CentOS7でvsftpdをLDAP(ドメインコントローラ)と連携させる設定

背景と要件

社内でFTPによるファイル共有を行っており、以前は共通アカウントを使用していましたが、これによりアカウントとパスワードが広く共有され、権限管理が困難になっていました。そのため、FTPサービスをLDAP(社内のドメインコントローラ)と連携させ、個人ドメインアカウントでのログインを実現することを計画しました。

具体的な要件

  • ドメインアカウントでのログイン
  • 未承認のユーザーはFTPにログインできるが、共有コンテンツへのアクセス権がない

環境構成

オペレーティングシステム

# lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description:    CentOS Linux release 7.9.2009 (Core)
Release:        7.9.2009
Codename:       Core

実装手順

手順概要

  1. 基本パッケージのインストール
  2. vsftpdの設定
  3. LDAP接続設定のデバッグ

手順1: 基本パッケージのインストール

# yum install nscd nss-pam-ldapd -y
# yum -y install vsftpd ftp openldap-clients

手順2: vsftpdの設定

まず、設定ファイルを示します。

# cat /etc/vsftpd/vsftpd.conf
use_localtime=YES
listen=YES
connect_from_port_20=YES
ftpd_banner=Welcome to virtual FTP service.
anonymous_enable=NO
local_enable=YES
write_enable=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO
chroot_local_user=YES
local_umask=022
guest_enable=YES
guest_username=ftpuser

tcp_wrappers=YES

use_localtime=yes
max_per_ip=20

pasv_enable=YES
pasv_min_port=3001
pasv_max_port=5100

idle_session_timeout=600
allow_writeable_chroot=YES

pam_service_name=vsftpd                     # ここが重要な設定で、/etc/pam.d/vsftpdファイルに対応
xferlog_enable=YES
xferlog_file=/var/log/vsftpd/xferlog.log
dual_log_enable=yes

# 仮想ユーザーとローカルユーザーは同じ権限を持つ
virtual_use_local_privs=YES
user_sub_token=$USER
local_root=/home/noaccess                  # 未承認ユーザーの共通rootディレクトリ(中身なし)
user_config_dir=/etc/vsftpd/vusers          # ここに承認済みユーザーの設定を配置し、ユーザーのrootディレクトリを制御

anon_world_readable_only=YES
anon_upload_enable=NO
anon_mkdir_write_enable=YES
anon_other_write_enable=NO

次に、PAM設定ファイルです。

# cat /etc/pam.d/vsftpd            # LDAP認証を使用する設定
#%PAM-1.0
auth required /usr/lib64/security/pam_ldap.so
account required /usr/lib64/security/pam_ldap.so

承認済みユーザー用の設定ディレクトリを作成し、テストアカウントファイルを作成します。共有ディレクトリを`/opt`と仮定します。

# mkdir -p /etc/vsftpd/vusers
# cd /etc/vsftpd/vusers
# testuser 
local_root=/opt

手順3: LDAP接続設定とデバッグ

vsftpdを直接起動すると、FTPアクセス時にシステムログに以下のエラーが表示されます。

# tail -f /var/log/secure
Sep 18 15:30:21 server vsftpd[311630]: pam_ldap(vsftpd:auth): Authentication failure; user=testuser
Sep 18 15:48:51 server vsftpd[316172]: pam_ldap(vsftpd:auth): error opening connection to nslcd: No such file or directory

この問題を解決するために、nslcdサービスを使用する必要があります。設定ファイルは`/etc/nslcd.conf`です。

# cat /etc/nslcd.conf
uid nslcd
gid ldap
uri ldap://domain-controller.example.com         # ドメインコントローラーのアドレスを実際の環境に合わせて設定
base DC=example,DC=com                            # 実際の環境に合わせて設定
binddn  CN=service-account,OU=Services,DC=example,DC=com  # 読み取り専用アカウント(管理者アカウントでも可)
bindpw password                                  # 上記アカウントのパスワード
ssl no
filter passwd (objectClass=user)                  # 実際の環境に合わせて設定
map    passwd uid sAMAccountName                  # 上記filterと連携して設定

問題と解決策

  1. フィルタとマッピングの未設定
    フィルタとマッピングを設定しない場合、正しいアカウントとパスワードでFTPにログインできません。
# ftp localhost
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 Welcome to virtual FTP service.
Name (localhost:root): testuser
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp>

アカウントとパスワードが正しいにもかかわらずログインできない場合、FTPサーバーが使用するアカウントとドメインコントローラーの間のマッピングが不一致である可能性があります。

  1. nslcdサービスのデバッグ
    /var/log/secureからnslcdサービスがLDAPにアクセスしていることがわかります。nslcdのヘルプオプションにdebugオプションがあるので、これを使用します。
# nslcd --help
Usage: nslcd [OPTION]...
Name Service LDAP connection daemon.
  -c, --check        check if the daemon already is running
  -d, --debug        don't fork and print debugging to stderr
      --help         display this help and exit
      --version      output version information and exit

Report bugs to 

サービスを停止し、デバッグモードで起動します。

# systemctl stop nslcd.service
# nslcd -d
nslcd: DEBUG: add_uri(ldap://domain-controller.example.com)
nslcd: version 0.8.13 starting
nslcd: DEBUG: unlink() of /var/run/nslcd/socket failed (ignored): No such file or directory
nslcd: DEBUG: initgroups("nslcd",55) done
nslcd: DEBUG: setgid(55) done
nslcd: DEBUG: setuid(65) done
nslcd: accepting connections

この状態でFTPにアクセスすると、詳細なログが表示されます。

# nslcd -d
nslcd: DEBUG: add_uri(ldap://domain-controller.example.com)
nslcd: version 0.8.13 starting
nslcd: DEBUG: unlink() of /var/run/nslcd/socket failed (ignored): No such file or directory
nslcd: DEBUG: initgroups("nslcd",55) done
nslcd: DEBUG: setgid(55) done
nslcd: DEBUG: setuid(65) done
nslcd: accepting connections
nslcd: [8b4567] DEBUG: connection from pid=321676 uid=0 gid=0
nslcd: [8b4567]  DEBUG: nslcd_pam_authc("testuser","vsftpd","***")
nslcd: DEBUG: accept() failed (ignored): Resource temporarily unavailable
nslcd: [8b4567]  DEBUG: myldap_search(base="DC=example,DC=com", filter="(&(objectClass=posixAccount)(uid=testuser))")
nslcd: [8b4567]  DEBUG: ldap_initialize(ldap://domain-controller.example.com)
nslcd: [8b4567]  DEBUG: ldap_set_rebind_proc()
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,3)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_DEREF,0)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_TIMELIMIT,0)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_TIMEOUT,0)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT,0)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_REFERRALS,LDAP_OPT_ON)
nslcd: [8b4567]  DEBUG: ldap_set_option(LDAP_OPT_RESTART,LDAP_OPT_ON)
nslcd: [8b4567]  DEBUG: ldap_simple_bind_s("CN=service-account,OU=Services,DC=example,DC=com","***") (uri="ldap://domain-controller.example.com")
nslcd: [8b4567]  DEBUG: rebinding to ldap://DomainDnsZones.example.com/DC=DomainDnsZones,DC=example,DC=com
nslcd: [8b4567]  DEBUG: ldap_simple_bind_s("CN=service-account,OU=Services,DC=example,DC=com","***") (uri="ldap://DomainDnsZones.example.com/DC=DomainDnsZones,DC=example,DC=com")
nslcd: [8b4567]  DEBUG: rebinding to ldap://ForestDnsZones.example.com/DC=ForestDnsZones,DC=example,DC=com
nslcd: [8b4567]  DEBUG: ldap_simple_bind_s("CN=service-account,OU=Services,DC=example,DC=com","***") (uri="ldap://ForestDnsZones.example.com/DC=ForestDnsZones,DC=example,DC=com")
nslcd: [8b4567]  DEBUG: rebinding to ldap://example.com/CN=Configuration,DC=example,DC=com
nslcd: [8b4567]  DEBUG: ldap_simple_bind_s("CN=service-account,OU=Services,DC=example,DC=com","***") (uri="ldap://example.com/CN=Configuration,DC=example,DC=com")
nslcd: [8b4567]  DEBUG: ldap_result(): end of results (0 total)
nslcd: [8b4567]  DEBUG: "testuser": user not found: No such object

重要なのはこの行です:myldap_search(base="DC=example,DC=com", filter="(&(objectClass=posixAccount)(uid=testuser))")。以前にLDAPに接続する際の経験から、このフィルターが問題であることがわかります。この環境ではuidではなくsAMAccountNameを使用し、objectClassも異なるため、実際の環境に合わせて以下のように変更しました。

filter passwd (objectClass=user)
map    passwd uid sAMAccountName

設定を更新した後、再度FTPにアクセスします。

# ftp localhost
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 Welcome to virtual FTP service.
Name (localhost:root): testuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (127,0,0,1,13,225).
150 Here comes the directory listing.
-rw-r--r--    1 0        0               0 Sep 18 09:50 a

# ls -alrt /opt
total 4
dr-xr-xr-x. 21 root root 4096 Sep 18 09:50 ..
-rw-r--r--   1 root root    0 Sep 18 09:50 a
drwxr-xr-x   2 root root   15 Sep 18 09:50 .

正常にログインできていることが確認できます。次に、未承認のアカウントでテストします。

# ftp localhost
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 Welcome to virtual FTP service.
Name (localhost:root): unauthuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (127,0,0,1,14,172).
150 Here comes the directory listing.
-rw-r--r--    1 0        0               0 Sep 18 15:29 アクセス権限なし.txt
226 Directory send OK.
ftp>
ftp> quit
221 Goodbye.

# ls /home/noaccess/
アクセス権限なし.txt

未承認ユーザーは`/home/noaccess/`ディレクトリ(vsftpd.confで設定された)にアクセスしていることが確認できます。これで、VSFTP + LDAPの連携は完了です。

今後の運用とまとめ

新しいユーザーを承認する必要がある場合、すべてのユーザーが同じ`local_root`を使用するため、testuserファイルのシンボリックリンクを作成するだけで済みます。例えば、新しいユーザー"newuser"を追加するには、以下のコマンドを実行します。

# cd /etc/vsftpd/vusers
# ln -s testuser newuser

今後、ユーザーの一括追加または削除を行うスクリプトを作成することも可能です。

この設定の核心は、nslcdをLDAPサーバーに接続する際のデバッグです。デバッグ情報がない場合、多くの時間をかけて設定を調整する必要があるかもしれません。

タグ: centos7 vsftpd LDAP 認証 ドメインコントローラ

6月29日 20:15 投稿