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) 配置vsftp配置
(3) 调试连接ldap配置
步骤1 安装基础包
# yum install nscd nss-pam-ldapd -y
# yum -y install vsftpd ftp openldap-clients
步骤2 配置vsftp配置
先贴出我的配置
# cat 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=compiler
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/anonymous # 没有授权的用户,统一的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
# 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
我先在/etc/vsftpd/vusers 创建一个测试账号文件,假定共享的目录为/opt
, 也就是所有授权的用户的root目录是/opt
# mkdir -p /etc/vsftpd/vusers
# cd /etc/vsftpd/vusers
# vim pcan1250
local_root=/opt
下面就是配置去连接LDAP了。
步骤3 配置,调试连接LDAP
直接启动vsftpd的话,现在访问ftp, 在操作系统日志里可以看到以下报错
# tail -f /var/log/secure
Sep 18 15:30:21 szvxl15487 vsftpd[311630]: pam_ldap(vsftpd:auth): Authentication failure; user=pcan1254
Sep 18 15:48:51 szvxl15487 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://xxx # 域控地址,根据自己实际情况填
#ldap_version 3
base DC=mydc,DC=xyz # 根据自己的实际情况填写
binddn CN=xxxx,OU=vApps,DC=mydc,DC=xyz # 可以理解为管理员账号(只读账号就可以), 根据自己实际情况填写
bindpw xxxx # 上面账号的密码
ssl no
filter passwd (objectClass=user) # 这里的话,根据自己的实际情况填写,其实我也不大懂,我是经过调试填的这个
map passwd uid sAMAccountName # 这里也是,配合上面fiter进行填写的,下面我会说一下 我是怎么调试的
(1) 没配置filter
和map
, 用正确的账号密码登录不了FTP
一开始我没有配置filter
和map
, 登录ftp,一直报账号密码错误,如下
# ftp localhost
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 Welcome to virtual FTP service.
Name (localhost:root): pcan1250
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp>
我知道自己的账号密码没错,问题肯定是映射问题,应该是vsftp是使用的账号与域控的映射不一致(也就是与我的预期不一致)引起的。 但是我看了操作系统日志,没有看到有相关的报错。问题一下子卡住了。
(2) 调试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 <nss-pam-ldapd-users@lists.arthurdejong.org>
先停掉,然后用 -d 启动到调试模式
# systemctl stop nslcd.service
# nslcd -d
nslcd: DEBUG: add_uri(ldap://XXX)
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 localhost
访问一次看看, 可以看到有日志输出了
# nslcd -d
nslcd: DEBUG: add_uri(ldap://XXXX)
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] <authc="pcan1250"> DEBUG: nslcd_pam_authc("pcan1250","vsftpd","***")
nslcd: DEBUG: accept() failed (ignored): Resource temporarily unavailable
nslcd: [8b4567] <authc="pcan1250"> DEBUG: myldap_search(base="DC=mydc,DC=xyz", filter="(&(objectClass=posixAccount)(uid=pcan1250))")
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_initialize(ldap://XXXX)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_rebind_proc()
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,3)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_DEREF,0)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_TIMELIMIT,0)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_TIMEOUT,0)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT,0)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_REFERRALS,LDAP_OPT_ON)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_set_option(LDAP_OPT_RESTART,LDAP_OPT_ON)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_simple_bind_s("CN=XXXX,OU=vApps,DC=mydc,DC=xyz","***") (uri="ldap://XXXX")
nslcd: [8b4567] <authc="pcan1250"> DEBUG: rebinding to ldap://DomainDnsZones.mydc.xyz/DC=DomainDnsZones,DC=mydc,DC=xyz
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_simple_bind_s("CN=XXXX,OU=vApps,DC=mydc,DC=xyz","***") (uri="ldap://DomainDnsZones.mydc.xyz/DC=DomainDnsZones,DC=mydc,DC=xyz")
nslcd: [8b4567] <authc="pcan1250"> DEBUG: rebinding to ldap://ForestDnsZones.mydc.xyz/DC=ForestDnsZones,DC=mydc,DC=xyz
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_simple_bind_s("CN=XXXX,OU=vApps,DC=mydc,DC=xyz","***") (uri="ldap://ForestDnsZones.mydc.xyz/DC=ForestDnsZones,DC=mydc,DC=xyz")
nslcd: [8b4567] <authc="pcan1250"> DEBUG: rebinding to ldap://mydc.xyz/CN=Configuration,DC=mydc,DC=xyz
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_simple_bind_s("CN=XXXX,OU=vApps,DC=mydc,DC=xyz","***") (uri="ldap://mydc.xyz/CN=Configuration,DC=mydc,DC=xyz")
nslcd: [8b4567] <authc="pcan1250"> DEBUG: ldap_result(): end of results (0 total)
nslcd: [8b4567] <authc="pcan1250"> DEBUG: "pcan1250": user not found: No such object
核心是这行 myldap_search(base="DC=mydc,DC=xyz", filter="(&(objectClass=posixAccount)(uid=pcan1250))")
, 我之前用python去连接ldap的时候,有一定的经验,所以我知道是这个fiter的问题,我这边不是用的uid, 而是用sAMAccountName
, 并且objectClass 也不对,因此我按照我的实际情况改成了如下
filter passwd (objectClass=user)
map passwd uid sAMAccountName
整个/etc/nslcd.conf
文件内容如上(步骤3开头已经列出来)所示, 再次访问ftp
# ftp localhost
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 Welcome to virtual FTP service.
Name (localhost:root): pcan1250
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): 11111111
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 当前没有权限访问该FTP.txt
226 Directory send OK.
ftp>
ftp> quit
221 Goodbye.
# ls /home/anonymous/
当前没有权限访问该FTP.txt
正是访问到了/home/anonymous/
(上面vsftpd.conf配置的)下。 至此,VSFTP + LDAP已完成。
后续与总结
后续有新的用户要授权的话,由于都是同样的local_root
, 因此,只需要用pcan1250文件做软链接就行,比如说,现在要加一个111111账号访问,只需要如下命令
# cd /etc/vsftpd/vusers
# ln -s pcan1250 111111
后续可以写一个脚本,用来批量添加或者删除用户。
这里的核心是调试nslcd连接到LDAP Server, 如果没有debug信息,可以需要耗费很多时间去慢慢调整....