vsftpd与PAM模块编译、安装及测试流程

背景:由于产品需求,需要在嵌入式 Linux 平台提供安全的内部 FTP 服务,所以尝试选择 vsftpd + PAM 的方式实现。


1 概述

  vsftpd的全名是“Very Secure FTP Daemon”,显然,vsftpd的发展理念就是构建一个以安全为重心的FTP服务器。

为什么“非常安全”?

(1)vsftpd尽量将服务取得的PID权限降低,使得服务即使不小心被入侵,入侵者也无法得到有效的系统管理权限,会使我们的系统较为安全。
(2)vsftpd支持chroot功能,也就是说它可以将某个特定的目录变成根目录,所以与该目录无关的其他目录就不会被误用。
(3)vsftpd可以通过配置文件(ftpusers和user_list)阻挡一些用户登录。
(4)vsftpd支持虚拟用户方式登录。
(5)vsftpd支持PAM认证模块插件,对登录账号和口令进行验证,并且可以根据需要扩展PAM认证模块。
(6)可通过支持SSL模块,增加对传输数据加密的功能。

2 可插拔认证模块PAM

2.1 PAM模块介绍

  可插拔认证模块PAM(Pluggable Authentication Modules)是一种认证机制,通过一些动态链接库和统一的API将系统提供的服务与认证方式分开,使得系统管理员可以根据需求灵活地调整服务程序的不同认证方式。简单来讲,PAM是一组安全机制的模块(插件),让系统管理员可以轻易地调整服务程序的认证方式,而不必对应用程序做任何修改。
  PAM采用分层设计思想,可分为应用程序层、应用接口层、鉴别模块层,如下图所示。

vsftpd与PAM模块编译、安装及测试流程_第1张图片

  PAM API 作为应用程序与鉴别模块层的连接纽带,让应用程序可以根据需求灵活地选择所需的鉴别功能模块。PAM 模块一般位于 /lib/security/ 目录下,PAM配置文件一般位于 /etc/pam.d/ 目录下。

2.2 编译及安装

  注意:编译PAM模块前需要更新flex,否则会出现“yywrap未定义”等错误。(我们这里由flex 2.5.37升级到flex 2.6.0)
  下面以Linux-PAM-1.1.1为例对PAM模块的编译与安装进行讲解。

(1)解压缩Linux-PAM-1.1.1.tar.bz2

# tar jxvf Linux-PAM-1.1.1.tar.bz2

(2)进入Linux-PAM-1.1.1目录

# cd Linux-PAM-1.1.1

(3)配置,生成Makefile

# ./configure --prefix=/usr  --sysconfdir=/etc  --libdir=/usr/lib  --disable-regenerate-docu  --enable-securedir=/lib/security  --docdir=/usr/share/doc/Linux-PAM-1.1.1

(4)编译

# make

(5)安装

# make install

  之后我们可以在 /usr/lib 目录下查看到如下库文件,它们就是上面所说的应用接口层。

root@imx6qrom5420:~# ls /usr/lib/libpam
libpam.la           libpam_misc.la          libpamc.la
libpam.so           libpam_misc.so          libpamc.so
libpam.so.0         libpam_misc.so.0        libpamc.so.0
libpam.so.0.82.2    libpam_misc.so.0.82.0   libpamc.so.0.82.1

  在 /lib/security目录下查看到如下库文件,它们就是上面所说的鉴别模块层。

root@imx6qrom5420:~# ls /lib/security/pam_
pam_access.la   pam_group.so    pam_motd.so         pam_succeed_if.so
pam_access.so   pam_issue.la    pam_namespace.la    pam_tally.la
pam_debug.la    pam_issue.so    pam_namespace.so    pam_tally.so
......

  如果没有 /etc/pam.d 目录,则创建,并从其他Linux设备上拷贝 /etc/pam.d/other 和 /etc/pam.d/vsftpd 到目标机器。

3 vsftpd服务

3.1 编译及安装

  vsftpd 的编译和安装步骤很简单,下面我们以 vsftpd-2.2.2 为例进行讲解。

(1)解压缩vsftpd-2.2.2.tar.gz

# tar zxvf vsftpd-2.2.2.tar.gz

(2)进入vsftpd-2.2.2目录

# cd vsftpd-2.2.2

(3)检查builddefs.h文件定义,选择是否支持tcp_wrappers、pam、ssl。

#undef VSF_BUILD_TCPWRAPPERS
#define VSF_BUILD_PAM
#undef VSF_BUILD_SSL

  我们这里支持 PAM 即可,故不作修改。实际上 builddefs.h 这个头文件是由 sysdeputil.c 包含,有兴趣的话可以跟踪一下。

(4)编译

# make

(5)检查相关库

# ./vsf_findlibs.sh

这里的执行结果输出如下:

-lpam
-ldl
-lnsl
-lresolv
-lutil
/lib/libcap.so.2

(6)安装

  可以执行 make install 进行安装,但是我的嵌入式平台不支持 install 命令,所以手动拷贝,如下:

# cp vsftpd /usr/sbin/
# cp xinetd.d/vsftpd /etc/xinetd.d/
# cp vsftpd.conf /etc/

3.2 启动前的准备工作

(1) vsftpd预设以 nobody 作为此一服务执行者的权限,保险起见,执行如下命令:

# useradd nobody
useradd: user nobody exists

从输出的信息看来,nobody已经存在,那就放心了。

(2)vsftpd 预设 secure_chroot_dir 为 /usr/share/empty,所以我们需要创建 /usr/share/empty 目录,如下:

# mkdir /usr/share/empty/
mkdir: cannot create directory `/usr/share/empty': File exists

显然,我们这里已经存在empty目录了。

(3)匿名访问需要ftp用户,并且有合理的家目录(拥有者不是ftp本身,并且不开放写权限),创建ftp用户如下:

# mkdir /var/ftp/
# useradd -d /var/ftp ftp

保险起见,执行如下命令修改属性:

# chown root.root /var/ftp
# chmod og-w /var/ftp

4 测试

4.1 匿名访问测试

  FTP匿名访问模式是一种不安全的服务模式,在真实的应用场合中一定要注意,敏感的数据千万不要存放,以免泄密。但是要注意,vsftpd默认是允许匿名访问模式的,也就是说要禁止匿名访问,一定要显式声明 anonymous_enable=NO,单纯注释掉 anonymous_enable=YES 是没有用的。
  下面我们通过匿名访问模式登录 vsftpd,打开 vsftpd 的配置文件 /etc/vsftpd.conf,添加或修改下面参数:

anonymous_enable=YES            (允许匿名访问模式)
anon_umask=022                  (匿名用户上传文件的umask值)
anon_upload_enable=YES          (允许匿名用户上传文件)
anon_mkdir_write_enable=YES     (允许匿名用户创建目录)
anon_other_write_enable=YES     (允许匿名用户修改目录或删除目录)

  保存并退出vsftpd.conf文件,并重启vsftpd服务。
  打开Windows的cmd命令行或者Linux的terminal,输入ftp回车,然后输入 open 进行连接。测试截图如下:

vsftpd与PAM模块编译、安装及测试流程_第2张图片

  说明:anonymous访问的目录就是ftp的家目录 /var/ftp。实际应用中如果确实要提供匿名访问功能,一定要注意权限的管理,如:anon_upload_enableanon_mkdir_write_enableanon_other_write_enable 配置项。

4.2 本地用户访问测试

  本地用户模式有一些要注意的文件: ftpusersvsftpd.user_listvsftpd.chroot_list。它们都是根据 vsftpd.conf 中相关配置提供一定的约束,有利于提高安全性。
  可以认为:先检查 /etc/vsftpd.user_list,再检查 /etc/ftpusers进行PAM验证。所以,只要这两个文件任意一个配置了root用户,都会导致root无法登录。

  本次测试的 vsftpd.conf 配置如下:

anonymous_enable=NO         (禁止匿名访问模式)
local_enable=YES            (允许本地用户模式)
write_enable=YES            (设置可写权限)
local_umask=022             (本地用户模式创建文件的umask值)
userlist_enable=YES         (配置禁止本地用户策略)
userlist_deny=YES
userlist_file=/etc/vsftpd.user_list
pam_service_name=vsftpd     (指定pam配置文件,即 /etc/pam.d/vsftpd)

  由于编译的时候选择了PAM,所以对于本地用户登录也需要指定PAM配置文件 /etc/pam.d/vsftpd,内容如下:

#%PAM-1.0
auth       required     /lib/security/pam_listfile.so item=user sense=deny file=/etc/vsftpd.ftpusers onerr=succeed
auth       required     /lib/security/pam_unix.so shadow nullok
auth       required     /lib/security/pam_shells.so
account    required     /lib/security/pam_unix.so
session    required     /lib/security/pam_unix.so  

  重启vsftpd服务,测试截图如下:

vsftpd与PAM模块编译、安装及测试流程_第3张图片

4.3 虚拟用户访问测试

  创建用户virtual,定义用户家目录并设置为不允许登录系统:

# useradd -d /var/ftproot -s /sbin/nologin virtual

  为保证其他用户可以访问,执行:

# chmod -Rf 755 /var/ftproot

  修改 /etc/vsftpd.conf 为:

anonymous_enable=NO         (禁止匿名访问模式)
local_enable=YES            (允许本地用户模式)
guest_enable=YES            (开启虚拟用户模式)
guest_username=virtual      (指定虚拟用户账号,也就是我们刚刚创建的virtual)
pam_service_name=vsftpd     (指定pam配置文件,即 /etc/pam.d/vsftpd)
allow_writeable_chroot=YES  (低版本vsftpd不需要)
#tcp_wrappers=YES           (注释掉)

  然后我们使用两个特殊的PAM模块来验证,分别是: pam_permit.sopam_deny.so,前者表示无条件允许,后者表示无条件拒绝。
  修改pam配置文件 /etc/pam.d/vsftpd为:

auth        required    pam_permit.so
account         required    pam_permit.so
session         required    pam_permit.so 
password        required    pam_permit.so

或者

auth        required    pam_deny.so
account         required    pam_deny.so
session         required    pam_deny.so 
password        required    pam_deny.so

  重新启动vsftpd,打开Windows的cmd命令行或者Linux的terminal,输入ftp回车,然后输入 open 进行连接。测试截图如下:

(1)/etc/pam.d/vsftpd配置为pam_permit.so无条件允许

vsftpd与PAM模块编译、安装及测试流程_第4张图片

(2)/etc/pam.d/vsftpd配置为pam_deny.so无条件拒绝

vsftpd与PAM模块编译、安装及测试流程_第5张图片

  通过这样的测试,可以确定vsftpd使用虚拟用户 + PAM认证的框架生效,接下来就可以根据需求编写自己的PAM认证模块了。

5 注意事项

可能出现的问题:

(1)“530 Login incorrect 登录失败”
  账号、密码出错,没有权限或该用户被强制禁止访问等原因。

(2)本地用户或虚拟用户登录,出现“500 OOPS: priv_sock_get_result远程主机关闭连接。”
  可能由于用户密码错误,或库链接不正确(比如原本希望调用pam,却链接到crypt了)导致的。

(3)“500 OOPS: vsftpd: refusing to run with writable root inside chroot() 远程主机关闭连接”
  配置文件vsftpd.conf中添加 allow_writeable_chroot=YES,这个问题猜测跟版本有关,低版本vsftpd不需要该配置项,而有些版本则是 allow_writable_chroot=YES。(注意:writeable和writable)

(4)“500 OOPS: priv_sock_get_cmd远程主机关闭连接”

(5)“500 OOPS: vsftpd: not found: directory given in ‘secure_chroot_dir’:/usr/share/empty”
  找不到/usr/share/empty目录,需要创建该目录,或者修改 secure_chroot_dir 配置项。

  注意:编译安装vsftpd,如果需要支持PAM模块,一定要先安装好PAM,否则会由于动态链接的问题造成异常。
  编译完 vsftpd,可以通过执行 vsftpd 源码包中的 vsf_findlibs.sh 脚本来检查,或者使用 ldd 命令来检查链接情况。

你可能感兴趣的:(Linux系统运维,Linux系统运维)