FTP服务器简介

FTP服务器是提供文件存储和访问服务的服务器,通过ftp(文件传输协议)实现数据传输,而且FTP是仅基于TCP的服务,不支持UDP。FTP应用是一种C/S架构的应用,客户端和服务器端都需要安装相关的软件才能实现相互之间的数据传输。常见的软件套件有FileZilla,Server-U,VsFTP,Pure-FTPd ProFTPD等,其中VsFTP,Pure-FTPd ProFTPD是单纯的服务器程序,常见客户端程序有ftp,lftp。本文实验环境中采用的服务器程序是vsftp。


工作模式

FTP的服务基于两个端口:命令端口和数据端口。命令端口用于建立命令连接,命令连接主要用来传输文件管理类命令,一但用户连接上FTP服务器,命令连接就一直在线,直到用户退出。数据端口用于建立数据连接,用于传输数据,数据连接是按需创建的,数据传输完毕,连接就会拆除。FTP的数据传输格式是根据文件类型来选择的,它既支持文本传输也支持二进制传输。一般而言,数据基于什么编码,就基于什么格式来传输,所以不应该人为的限定FTP的传输格式。

FTP的工作模式也非常独特,有两种工作模式,主动模式和被动模式。这两者主要区别在于当需要传输数据时,主动模式是由服务器端向客户端发起连接请求,而后建立数据连接。而被动模式,连接请求是由客户端发起。一般而言都是采用被动模式。


1)主动模式

在主动模式下,客户端从一个非特权端口N(随机端口,N>1024),连接到FTP服务器的命令端口(21号端口),然后客户端开始监听端口N+1,并发送FTP命令“port N+1”到FTP服务器(告诉服务器端用于数据传输的端口)。然后服务器从数据端口(20)连接到客户端指定的数据端口(N+1)。

在主动模式下,由于是服务器端去主动连接客户端的随机端口(N+1),所以往往这个连接请求会被客户端的防火墙过滤掉。若需要支持这种连接,每个各户端都需要对iptables进行规则的改写,对于客户端而言很不方便。然后就有了被动模式。

wKiom1Wea2LxaWlqAABlKh2Vepw218.jpg

2)被动模式

在被动模式下,当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(N > 1024和N+1)。第一个端口用于命令连接(连接服务器的21号端口),当需要数据传输时,客户端提交PASV命令,服务器端收到命令后,开启一个任意的非特权端口(P > 1024),并发送PORT P命令给客户端(告诉客户端用于数据连接的端口),然后客户端从本地的N+1端口连接到服务器端的P端口开始数据传输。

服务器端的防火墙需要允许客户端发起的数据连接请求。被动模式的好处在于客户端不需要再去修改iptables的规则即可直接连接FTP服务器。

wKioL1WebWGDq0-XAAB7AV6Az8E263.jpg


FTP服务器安装配置

直接使用yum源安装即可(192.168.1.104为FTP服务器ip)

[root@www ~]# yum install vsftpd -y
.......

来看一下vsftpd的相关文件:

[root@www ~]# rpm -ql vsftpd
/etc/logrotate.d/vsftpd
/etc/pam.d/vsftpd
/etc/rc.d/init.d/vsftpd
/etc/vsftpd
/etc/vsftpd/ftpusers
/etc/vsftpd/user_list
/etc/vsftpd/vsftpd.conf
/etc/vsftpd/vsftpd_conf_migrate.sh
/usr/sbin/vsftpd
........

/etc/logrotate.d/vsftpd          #实现日志滚动的服务程序

/etc/pam.d/vsftpd                  #用户认证的配置文件,调用pam模块完成认证

/etc/rc.d/init.d/vsftpd            #服务脚本

/etc/vsftpd/ftpusers              #用户的访问控制       

/etc/vsftpd/user_list

/etc/vsftpd/vsftpd.conf         #主配置文件

/usr/sbin/vsftpd                    #主程序


一般而言能够访问FTP服务器的用户有3类:系统用户,匿名用户,虚拟用户

1)系统用户:系统上存在的用户,其默认访问的资源位置为该用户的家目录。

2)匿名用户:不需要账号密码即可登录的用户,这一类用户会被映射成一个系统用户(默认ftp用户),访问的资源位置为ftp用户用户的家目录(默认为/var/ftp)。

3)虚拟用户:这一类用户需要在FTP服务器中创建,也会映射成一个系统用户。


关于匿名用户的配置

# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=YES                          #匿名用户是否启用
......
# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
anon_upload_enable=YES                        #是否允许匿名用户上传
#
# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.
anon_mkdir_write_enable=YES                     #是否允许匿名用户创建目录

分别开启这3项之后重启服务,进行测试。

[root@www ~]# lftp 192.168.1.104
lftp 192.168.1.104:~> put install.log
put: Access failed: 553 Could not create file. (install.log)
lftp 192.168.1.104:/> bye

由于运行vsftpd程序的是ftp用户,而/var/ftp/这个目录ftp用户没有写权限,所以即使在配置文件中设置了允许上传,也无法写入文件。

wKioL1WegzqQX5PzAAJMtH4bSSo156.jpg


出于安全的考虑不能直接对/var/ftp目录直接进行权限的修改,在该目录下创建专门用于上传的目录,并授权。

[root@www ftp]# mkdir anonData
[root@www ftp]# setfacl -R -m u:ftp:rwx anonData/

在另外一台虚拟机上进行测试:

[root@www ~]# lftp 192.168.1.104 
lftp 192.168.1.104:~> cd anonData/
lftp 192.168.1.104:/anonData> put install.log
27312 bytes transferred                 
lftp 192.168.1.104:/anonData> pwd
ftp://192.168.1.104/anonData
lftp 192.168.1.104:/anonData> mkdir test
mkdir ok, `test' created
lftp 192.168.1.104:/anonData> ls
-rw-------    1 14       50          27312 Jul 09 14:41 install.log
drwx------    2 14       50           4096 Jul 09 14:44 test
lftp 192.168.1.104:/anonData> rm -fr install.log 
lftp 192.168.1.104:/anonData> ls
-rw-------    1 14       50          27312 Jul 09 14:41 install.log
drwx------    2 14       50           4096 Jul 09 14:44 test

上传成功,创建文件也没问题!!!但此时依旧无法删除自己上传的文件。这是需要在配置文件中添加anon_ohter_write_enable=YES,允许匿名用户的其他写权限(包括删除)。重新加载服务。

[root@www ~]# lftp 192.168.1.104 
lftp 192.168.1.104:~> cd anonData/
lftp 192.168.1.104:/anonData> ls
-rw-------    1 14       50          27312 Jul 09 14:41 install.log
drwx------    2 14       50           4096 Jul 09 14:44 test
lftp 192.168.1.104:/anonData> rm -fr install.log 
rm ok, `install.log' removed
lftp 192.168.1.104:/anonData> ls
drwx------    2 14       50           4096 Jul 09 14:44 test

完成删除!!!


关于系统用户的配置

# Uncomment this to allow local users to log in.
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES
#
# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)
local_umask=022

local_enable=YES      #是否允许系统用户登录

write_enable=YES     #是否允许系统用户写操作(包括删除)

local_umask=022      #本地用户上传文件之后默认的权限

配置完成后,用系统用户登录,进行测试。上传、创建、删除均没有问题。也可以看到上传的文件的权限为644。

wKiom1WejHfSYrYjAAKllu4MMtw275.jpg


由于是系统用户登录,系统用户可以切换到其他的目录(只要有权限),又由于ftp是明文传输,这样非常的不安全。可以通过chroot_local_user=YES,将系统用户禁锢在家目录中。而对于匿名用户不存在这个问题,匿名用户只能浏览映射的系统用户的家目录(/var/ftp/)

lftp baby@192.168.1.104:~> cd /etc
cd ok, cwd=/etc                  
lftp baby@192.168.1.104:/etc> ls
drwxr-xr-x    5 0        0            4096 May 29 08:19 ConsoleKit
-rw-r--r--    1 0        0            4439 Oct 17  2013 DIR_COLORS
-rw-r--r--    1 0        0            5139 Oct 17  2013 DIR_COLORS.256color
-rw-r--r--    1 0        0            4113 Oct 17  2013 DIR_COLORS.lightbgcolor
.........


修改配置文件,重新加载服务。wKioL1WekJiQYUKAAAFU4Qcj5mU891.jpg


[root@www ~]# lftp -u baby 192.168.1.104
Password: 
lftp baby@192.168.1.104:~> pwd        
ftp://baby@192.168.1.104
lftp baby@192.168.1.104:~> cd /etc
cd: Access failed: 550 Failed to change directory. (/etc)
lftp baby@192.168.1.104:/>

目录已无法切换。启用下面的两个属性chroot_list_enable=YES,chroot_list_file=/etc/vsftpd/chroot_list,就可以动态的在/etc/vsftpd/chroot_list中指定将哪些系统用户登录之后禁锢在其家目录中。


其他配置信息

简单介绍下其他的一些比较常用的配置属性,不做演示。

改变上传文件的属主:

chown_uploads=YES                   #是否改变上传文件的属主

chown_username=whoever        #上传文件的属主

local_root=dirname                     #系统用户的资源访问路径,默认是系统用户的家目录。

anon_root=dirname                    #匿名用户的资源访问路径,默认是/var/ftp


userlist_enable=YES           #是否启用控制用户登录的列表文件,列表文件由userlist_file指定

userlist_file=dirname         #指定列表文件,默认文件为/etc/vsftpd/user_list

userlist_deny=YES|NO       #这个参数控制/etc/vsftpd/user_list这个文件中的用户能否登录yes表示黑名单,no表

                                           #示白名单(没有出现在文件上的用户都不能登录)


vsftpd使用pam完成用户认证,其用到的pam配置文件:

pam_service_name=vsftpd      #指明/etc/pam.d下用哪一个配置文件来完成基于pam对vsftp进行用户认证


日志相关的配置:

xferlog_enable=YES                       #是否打开传输日志

xferlog_std_format=YES                #传输日志是否使用标准格式

xferlog_file=/var/log/xferlog         #传输日志记录位置


idle_session_timeout=600                #会话空闲超时时长时常

data_connection_timeout=120        #数据连接超时时长

ascii_upload_enable=YES                 #是否支持文本格式的上传下载,这两项不建议启用

ascii_download_enable=YES            #用文本格式上传下载)


连接限制:

max_clients=num                 #最大并发连接数;0表示不限制,默认2000

max_per_ip=num                 #每个IP可同时发起的并发请求数;0表示不限制,默认50


传输速率限制:

anon_max_rate=num           #匿名用户的最大传输速率(所有的匿名用户加起来), 单位是“字节/秒“,默认为

                                             #0,默认不限制;

local_max_rate=num            #系统用户.......

更详细的配置信息请参考man 5 vsftpd.conf!!!


FTP基于MariaDB实现访问控制

实验环境:

vsftp服务器:192.168.1.104

mariaDB数据库:192.168.1.113

基于MariaDB实现访问控制,就是将虚拟用户的用户名、密码存放在mariaDB数据库中。

1)首先安装pam_mysql模块,vsftpd通过这个模块来连接mariaDB/mysql数据库,并完成查询验证。

[root@www guest]# yum install pam_mysql -y
.....
[root@www guest]# rpm -ql pam_mysql
/lib64/security/pam_mysql.so
/usr/share/doc/pam_mysql-0.7
/usr/share/doc/pam_mysql-0.7/COPYING
/usr/share/doc/pam_mysql-0.7/CREDITS
/usr/share/doc/pam_mysql-0.7/ChangeLog
/usr/share/doc/pam_mysql-0.7/NEWS
/usr/share/doc/pam_mysql-0.7/README

pam_mysql其实就提供了一个共享库文件/lib64/security/pam_mysql.so。这个文件的路径需要在vsftpd的配置文件中用到。


2)在数据库中创建虚拟用户,然后插入baby,shaw两个用户,密码和用户名相同。

MariaDB [(none)]> create database vsftpd_data;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> grant select on vsftpd_data.* to vsftpd@'192.168.%.%' identified by 'vsftpd';
Query OK, 0 rows affected (0.03 sec)
MariaDB [(none)]> use vsftpd_data;
Database changed
MariaDB [vsftpd_data]> create table users (
    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> name CHAR(20) BINARY NOT NULL,
    -> password CHAR(48) BINARY NOT NULL );
Query OK, 0 rows affected (0.02 sec)
MariaDB [vsftpd_data]> insert into users(name,password) values('baby',password('baby'));
Query OK, 1 row affected (0.00 sec)
MariaDB [vsftpd_data]> insert into users(name,password) values('shaw',password('shaw'));
Query OK, 1 row affected (0.00 sec)


3)建立pam认证所需文件

在/etc/pam.d/目录下创建对应的认证文件。

[root@www ~]# vim /etc/pam.d/vsftpd.mysql
auth required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=192.168.1.113 db=vsftpd_data table=users usercolumn=name passwdcolumn=password crypt=2
account required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=192.168.1.113 db=vsftpd_data table=users usercolumn=name passwdcolumn=password crypt=2

第一行是对用户身份的认证,第二行是对用户的有效性验证,例如账号是否过期。由于在mariaDB数据库中对密码采用了内置的函数加密,所以crypt=2。关于这里的具体参数的含义及配置方法可以参考pam_mysql包提供的文档/usr/share/doc/pam_mysql-0.7/README。


4)修改vsftpd的配置文件,使其能够使用通过数据库认证

建立虚拟用户映射的系统用户及对应的目录

[root@www data]# useradd -s /sbin/nologin -d /data/guest ftp_user
[root@www data]# chmod go+rx /data/guest/


配置/etc/vsftpd.conf,确保其中的下面的几项已开启,若需要开启上传,创建等功能还需要开启这两项anon_upload_enable,anon_mkdir_write_enable。

vim /etc/vsftpd/vsftpd.conf 
anonymous_enable=YES
local_enable=YES
chroot_local_user=YES
.....

允许来宾账号访问,并将来宾账号映射为本地的系统账号,并把认证文件改为vsftpd.mysql。由于系统用户的认证是通过/etc/pam.d/vsftpd这个模块来完成,所以修改之后只能对匿名用户认证。

vim /etc/vsftpd/vsftpd.conf 
guest_enable=YES
guest_username=ftp_user
pam_service_name=vsftpd.mysql


配置完成之后重新加载服务,进行测试。

[root@www ~]# lftp -u shaw 192.168.1.104
Password: 
lftp shaw@192.168.1.104:~> ls         
-rw-r--r--    1 0        0            1471 Jul 09 23:57 fstab
lftp shaw@192.168.1.104:/> put install.log
27312 bytes transferred                            
lftp shaw@192.168.1.104:/> ls
-rw-r--r--    1 0        0            1471 Jul 09 23:57 fstab
-rw-------    1 501      501         27312 Jul 10 00:33 install.log

已可以用数据库中的用户名正常访问.................^_^


5)配置虚拟用户具有不同的访问权限

vsftpd可以在配置文件目录中为每个用户提供单独的配置文件以定义其ftp服务访问权限,每个虚拟用户的配置文件名同虚拟用户的用户名。配置文件目录可以是任意未使用目录,只需要在vsftpd.conf指定其路径及名称即可。

1、配置vsftpd为虚拟用户使用配置文件目录,该目录下存放了每个用户单独使用的配置文件

[root@www ~]# vim /etc/vsftpd/vsftpd.conf 
.....
user_config_dir=/etc/vsftpd/users_config


2、创建所需要目录,并为虚拟用户提供配置文件(创建的用户首先需要在数据库中存在)

[root@www ~]# mkdir /etc/vsftpd/users_config/
[root@www ~]# cd /etc/vsftpd/users_config
[root@www ~]# touch hello


3、配置虚拟用户的访问权限

虚拟用户对vsftpd服务的访问权限是通过匿名用户的相关指令进行的。修改某一用户的权限,创建/etc/vsftpd/users_config/username,添加如下选项即可。

anon_upload_enable={YES|NO}

anon_mkdir_write_enable={YES|NO}

anon_other_write_enable={YES|NO}