基于Linux构建FTP服务器

一、vsftpd

vsftpd(Very Secure ftp deamon,非常安全的FTP守护进程)是一款灵活、安全、开源的FTP服务程序。特点是具有高安全性、高传输速度、支持虚拟用户认证。vsftpd的服务端口在21/tcp。

二、安装vsftpd

Ubuntu2204默认没有安装vsftpd,需要手动安装。

sudo apt-get install vsftpd #安装vsftpd

三、用户&用户主目录

1、用户

Vsftpd可以创建三种用户,分别是匿名用户、本地用户、虚拟用户。以下是三种用户的定义和特性:

  • 匿名用户:安装完vsftpd后自动生成的账户。

  • 本地用户:基于Linux本地文件系统中的用户。Linux创建完本地用户后,一般会在/etc/passwd和/etc/shadow中找到相关信息。账户名即本地用户账户,有shell登录权限。

  • 虚拟用户:vsftpd创建的用户,此类用户只能用于登录FTP服务,用于传输文件和数据,无法登录Linux。

2、用户主目录

用户主目录即FTP用户可以上传/下载文件的绝对位置。匿名用户ftp默认主目录是/srv/ftp;本地用户默认主目录是自己的家目录;虚拟用户默认主目录也是自己的家目录。

用户主目录的权限限制。为了系统安全,vsftpd增加了Chroot机制,目的就是防止登录用户访问用户主目录的上级目录,造成访问越权的情况发生。Chroot机制即默认不允许用户主目录具备w权限,否则该用户无法登录。为了避免因用户主目录的不可写限制,常规做法就是在用户主目录下创建一个属组和属主都是登录用户的可写目录

四、登录认证模式

Vsftpd根据用户类别,采用了三种登录认证模式,分别是匿名开放模式、本地用户模式、虚拟用户模式。以下是对三种登录认证模式的解释:

  • 匿名开放模式:任何人只需要凭借ftp用户即可登录FTP服务器。

  • 本地用户模式:攻击者可以通过口令爆破等方式对FTP进行密码猜解,一旦成功即可获取系统登录权限。

  • 虚拟用户模式:尽管攻击者可以通过口令爆破FTP用户,但是无法获取系统登录权限。

五、配置文件参数解析

vsftpd的配置文件是/etc/vsftpd.conf,以下是配置文件参数解析。

端口相关
listen= {YES|NO}       #是否以独立运行的方式监听服务
listen_address=IP地址	 #设置要监听的IP地址
listen_port=21	     #设置FTP服务的监听端口

工作模式
pasv_enable= YES/NO  #被动模式/主动模式
pasv_min_port=30000   #被动模式数据端口最小端口号
pasv_max_port=30099   #被动模式数据端口最大端口号
pasv_address=x.x.x.x #被动模式返回给客户端IP地址,一般用于服务器内网穿透时用,地址填写服务器外网IP

登录模式
1)	匿名模式
anonymous_enable={YES|NO}   #是否允许匿名用户访问
anon_root=/srv/ftp  #主目录
anon_upload_enable={YES|NO}  #是否允许上传文件
anon_world_readable_only={YES|NO}  #是否允许下载可读(下载到本机可读)
anon_mkdir_write_enable={YES|NO}   #是否允许创建目录(前提需要write_enable=YES)
anon_other_write_enable={YES|NO}   #是否开放其他写入权限(重命名、删除等操作)
anon_umask=022   #上传文件的umask值,比如创建一个权限为666的文件,文件的实际权限为666-022=644
anon_max_rate=0   #最大传输速率(字节/秒),0为不限制
匿名模式只设置和使用默认的ftp用户
2)	本地模式
local_enable={YES|NO}  #是否允许本地用户访问
local_root=/var/ftp
local_umask=022 
local_max_rate=0	本地用户最大传输速率(字节/秒)
设置不允许哪些本地用户登录:
userlist_enable={YES|NO}   #是否启用控制用户登录的列表文件,默认/etc/vsftpd.user_list
userlist_deny={YES|NO}	 #是否拒绝userlist指定的列表文件中存在的用户登录FTP

用户主目录&chroot
1)	主目录设置&权限
前面说到vsftpd为了安全,默认chroot机制不允许主目录可写,那么怎么使得用户登录上来后能够下载和上传文件呢?以本地用户epiol为例,为该用户创建根目录:
sudo useradd epiol -s /sbin/nologin
sudo passwd epiol
sudo mkdir /home/epiol && chmod -w /home/epiol
sudo chown root:epiol /home/epiol && mkdir /home/epiol/upload
sudo chown epiol:epiol /home/epiol/upload && chmod 777 /home/epiol/upload
sudo vim /etc/vsftpd.conf && local_root=/home/epiol
2)	chroot
chroot_local_user=YES  #是否锁死所有本地用户在主目录内,无法回溯
chroot_list_enable=YES  #是否开启锁死特例
chroot_list_file=/etc/vsftpd.chroot_list  #锁死特例文件指定,默认该文件不存在需要创建
allow_writeable_chroot=YES  #是否允许主目录可写登录
文件或目录操作权限(针对所有登录模式下的所有用户)
write_enable=YES	 #允许登录用户对FTP服务器文件具有写权限
更多全局操作
dirmessage_enable = YES  #激活目录欢迎信息功能(默认开启)
xferlog_enable = YES      #开启FTP日志
xferlog_file=/var/log/vsftpd.log  #存放FTP日志的目录
idle_session_timeout=600       #会话超时时长
hide_ids=YES   #显示属主/属组名   
#最大客户端连接数,0为不限制, 同一IP地址的最大连接数,0为不限制
max_clients=0
max_per_ip=0
ftpd_banner= “Welcom”  #设置banner信息,登录时自动显示	
ls_recurse_enable=NO #禁止用户登录FTP后使用ls -R,该命令会对服务器性能造成巨大影响
tcp_wrappers=YES  #设置支持TCP wrappers

六、FTP最佳实践

1、匿名开放模式FTP

该模式适合公开分享文件,我们需要做的就是开放匿名用户上传、下载文件的权限,以及让匿名用户创建、删除、更名文件的权限,vsftpd默认禁用匿名开放模式。不建议设置为匿名开放模式!

Step1. 修改主配置文件/etc/vsftpd.conf有关匿名开放模式的参数:

anonymous_enable=YES  #开启匿名用户模式
local_enable=NO        #关闭本地用户模式
anon_upload_enable=YES 
anon_umask=022  
anon_mkdir_write_enable=YES 
anon_other_write_enable=YES
write_enable=YES
pasv_enable= YES 
pasv_min_port=30000   
pasv_max_port=30999 

Step2. 重启服务:systemctl restart vsftpd.service

Step3. 开机自启:systemctl enable vsftpd

Step4. 防火墙设置:

  • sudo firewall-cmd --add-port=21/tcp --permanent

  • sudo firewall-cmd --add-port=30000-30999/tcp --permanent && firewall-cmd --reload

Step5. 客户端登录

在匿名开放认证模式下,其账户统一为ftp,密码为空。并且连接到FTP服务器后默认访问的是/srv/ftp目录。但是默认只有root才对/srv/ftp目录有w权限。就算我们对配置文件修改有w权限,但是也没有任何用。

使匿名用户可以上传文件,在/srv/ftp目录下新建一个目录,给这个新建的目录允许上传文件的权限:

sudo mkdir /srv/ftp/upload
sudo chown ftp:ftp /srv/ftp/upload/
sudo chmod 777 /srv/ftp/upload/
sudo chown root:ftp /srv/ftp

2、本地用户模式FTP

本地用户模式特点就是默认不能上传、只能下载、可回溯到根目录(可看到整个服务器的目录树结构,造成严重的安全隐患),出于使用和安全性考虑,需要让本地用户登录后能够上传、不可回溯到根目录(将用户添加至vsftpd.chroot_list)!

Step1. 创建本地用户&用户主目录

sudo mkdir /home/test && sudo chown test:test /home/test/ && sudo chmod -w test
sudo useradd test -s /sbin/nologin -d /home/test 
sudo passwd test 
sudo mkdir /home/test/file && sudo chown test:test /home/test/file && sudo chmod 777 file

Step2. 修改主配置文件/etc/vsftpd.conf有关本地用户模式的参数:

anonymous_enable=NO  #关闭匿名用户模式
local_enable=YES        #开启本地用户模式
local_umask=022        # 本地用户模式创建文件的umask值
local_root=/home/test   #本地用户主目录
#userlist_enable=YES     
#userlist_deny=YES   #默认禁止登录的用户文件在/etc/vsftpd.user_list中
#userlist_file=/etc/vsftpd.user_list
chroot_local_user=YES  
chroot_list_enable=YES    
chroot_list_file=/etc/vsftpd.chroot_list   
write_enable=YES      
pasv_enable= YES
pasv_min_port=30000   
pasv_max_port=30999 

注意:

1、vsftpd.user_list和vsftpd.chroot_list必须创建!

2、vsftpd为了让FTP更安全,默认是禁止root用户登录的!

Step3. 重启服务:sudo systemctl restart vsftpd.service

Step4. 查看服务:sudo systemctl status vsftpd.service

Step5. 开机自启:systemctl enable vsftpd

Step6. 防火墙配置:

  • sudo firewall-cmd --add-port=21/tcp

  • sudo firewall-cmd --add-port=30000-30099/tcp --permanent && sudo firewall-cmd --reload

Step7. 客户端登录

3、虚拟用户模式FTP

虚拟用户是指在FTP服务器上拥有账号,并且用户账户只能用于FTP服务的用户,也称为Guest用户。该类用户可以通过输入账号以及口令来进行授权登录,登录系统后根目录只能是指定的目录,拥有上传和下载权限,没有删除和重命名权限。

vsftpd的虚拟用户的账户和口令单独被存放在一个数据库,与系统本地用户(/etc/passwd、/etc/shadow)分开,大大增强了系统的安全性。vsftpd可以采用数据库文件存放账户和口令也可使用专门的数据库服务器(Mysql)来存放。

数据库文件或者数据库服务器中存放的账户和口令独立于本地系统用户

vsftpd验证虚拟用户采用PAM方式,即使用guest用户来读取数据库文件或者数据库服务器完成验证,Guset用户可以被认为是映射虚拟用户。

PAM:PAM登录认证模块是一种认证机制,不会直接使用系统用户,而是用自己的用户数据库,但是由于vsftpd必须要存取操作系统上的文件,所以离不开系统用户,那么就通过不直接登录,只是做映射,只要用自己的用户登录后和系统用户做映射就安全很多。,通过一个动态链接库和统一的API把系统提供的服务与认证方式分开,得系统管理员可以根据需求灵活调整服务程序的不同认证方式。

1)生成虚拟用户数据库文件

Step1. 创建虚拟用户账户文件:vim /etc/vuser.list

用户名A(奇数行)
密码A(偶数行)
用户名B(奇数行)
密码B(偶数行)
……

Step2. 生成虚拟用户数据库文件:db5.3_load -T -t hash -f vuser.list vuser.db

Step3. 删除原始明文数据库文件:sudo rm -rf vuser.list

Step4. 查看虚拟用户数据库文件文件属性:file vuser.db

Step5. 修改数据库文件权限(权限最小化原则):chmod 600 vuser.db

如果没有db_load命令,则需要安装db5.3-util

2)创建认证文件

sudo vim /etc/pam.d/vsftpd 编辑虚拟用户所需要的PAM配置,加入以下两行内容:

auth     required   pam_userdb.so  db=/etc/vuser
account  required   pam_userdb.so  db=/etc/vuser

注意是vuser而不是vuser.db

3)指定虚拟用户的FTP根目录和权限

本地用户(即vuser)登录后的根目录(即/home/vuser),以及配置相应权限提高安全性:

sudo useradd -d /home/vuser -s /sbin/nologin vuser && sudo mkdir /home/vuser
sudo chmod -w /home/vuser && chown vuser:vuser /home/vuser

4)修改主配置文件

anonymous_enable=NO
local_enable=YES #PAM必须为YES,因为需要映射本地用户,否则所有虚拟用户无法访问
local_umask=022 
write_enable=YES

chroot_local_user=YES #所有本地用户限制在自己的FTP根目录中
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list

guest_enable=YES             #开启虚拟用户模式
guest_username=vuser         #指定虚拟用户需要映射的本地用户
pam_service_name=/etc/pam.d/vsftpd      #指定虚拟用户存在的文件 
virtual_use_local_privs=YES  #设定虚拟用户的权限符合他们的宿主用户

pasv_enable= YES
pasv_min_port=30000   
pasv_max_port=30999 

5)重启服务并测试

Step1. 重启服务:sudo systemctl restart vsftpd.service

Step2. 查看服务:sudo systemctl status vsftpd.service

Step3. 开机自启:systemctl enable vsftpd

Step4. 防火墙配置:

  • sudo firewall-cmd --add-port=21/tcp

  • sudo firewall-cmd --add-port=30000-30099/tcp --permanent && sudo firewall-cmd --reload

创建vsftpd服务程序用于存储文件的根目录以及虚拟用户映射的系统本地用户。由于linux系统中的每一个文件都有属主、属组属性。例如使用虚拟账户“张三”新建了一个文件,但是系统中找不到账户“张三”,就会导致这个文件的权限出现错误。所以需要创建一个可以映射到虚拟用户的系统本地用户。

简单的说:让虚拟用户默认登录到与之有映射关系的系统本地用户的家目录中,虚拟用户创建的文件属性也都归属于该系统本地用户,从而避免了linux系统无法处理虚拟用户所创建的属性权限。

为了方便管理FTP服务器上的数据,可以把系统本地用户的家目录设置为/var目录,并且为了安全起见,我们将这个系统本地用户设置为不允许登录FTP服务器,这不会影响虚拟用户登录,而且还可以避免何可通过该系统本地用户进行登录。