一:简介

FTP是File Transfer Protocol(文件传输协议)的缩写,用来在两台计算机之间互相传送文件。相比于HTTP,FTP协议要复杂得多。复杂的原因,是因为FTP协议要用到两个TCP连接,一个是命令链路,用来在FTP客户端与服务器之间传递命令;另一个是数据链路,用来上传或下载数据。 

FTP协议有两种工作方式:PORT方式和PASV方式,中文意思为主动式和被动式。 

PORT(主动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。 当需要传送数据时,客户端在命令链路上用 PORT命令告诉服务器:“我打开了****端口,你过来连接我”。于是服务器从20端口向客户端的****端口发送连接请求,建立一条数据链路来传送数据。 

PASV(被动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。 当需要传送数据时,服务器在命令链路上用 PASV命令告诉客户端:“我打开了****端口,你过来连接我”。于是客户端向服务器的****端口发送连接请求,建立一条数据链路来传送数据。 

从上面可以看出,两种方式的命令链路连接方法是一样的,而数据链路的建立方法就完全不同。而FTP的复杂性就在于此。 

 vsftp提供3种远程的登录方式:

(1)匿名登录方式

  就是不需要用户名,密码。就能登录到服务器电脑里面

(2)本地用户方式

  需要帐户名和密码才能登录。而且,这个帐户名和密码,都是在你linux系统里面,已经有的用户。

(3)虚拟用户方式

  同样需要用户名和密码才能登录。但是和上面的区别就是,这个用户名和密码,在你linux系统中是没有的(没有该用户帐号)


二:安装

1、配置相关服务 

#安装vsftpd服务 
[root@localhost root]#yum install vsftpd
#启动服务,设置系统服务随着系统启动而启动
[root@localhost root]#/etc/init.d/vsftpd start 
[root@localhost root]#chkconfig --level 235 vsftpd on


配置相关文档: 

#vi /etc/vsftpd/vsftpd.conf 

######### 核心设置 ###########
local_enable=YES       # 允许本地用户登录
write_enable=YES       # 本地用户的写权限  
local_root=/home       #系统账户对应的ftp根目录
local_umask=027        #设置上传文件的权限(777减去此数的权限)
local_max_rate=3000000    #限制系统用户传输速率,单位bite
dirmessage_enable=YES     # 切换目录时,是否显示目录下.message的内容
dirlist_enable = NO
pam_service_name=vsftpd.vu  #vsftpd验证方式
connect_from_port_20=YES   #启用FTP数据端口的数据连接
listen=YES          #以独立的FTP服务运行
listen_port=21        # 修改连接端口,默认值为21。
ftp_data_port=20        # 修改数据端口,默认值为20。此参数用于PORT FTP模式。
port_enable=YES        #如果你要在数据连接时取消PORT模式时,设此选项为NO。默认值为YES
port_promiscuous=NO      #取消PORT安全检查。该检查确保外出的数据只能连接到客户端上。小心打开此选项
async_abor_enable=YES     #设定支持异步传输功能。
ascii_upload_enable=YES    #设定支持ASCII模式的上传功能。
ascii_download_enable=YES   #设定支持ASCII模式的下载功能。
TCP_wrappers=YES    #限制主机对VSFTP服务器的访问,不用改(通过/etc/hosts.deny和/etc/hosts.allow这两个文件来配置)

######### 匿名登录设置 ###########
anonymous_enable=NO     #禁止匿名 
anon_root=/data       #匿名账户对应的ftp根目录
anon_upload_enable=YES     #如果允许匿名登录,是否允许虚拟用户和匿名用户上传
anon_mkdir_write_enable=YES  #如果允许匿名登录,是否允许匿名建立文件夹并在文件夹内上传文件
anon_other_write_enable=YES  #如果允许匿名登录,允许虚拟用户和匿名用户修改文件名和删除文件
anon_max_rate=30000      #如果允许匿名登录,限制匿名用户传输速率,单位bite

######### 用户限制设置 ###########
#### 限制登录
userlist_enable=yes      # 用userlist来限制用户访问
userlist_deny=no             # YES禁止文件中的用户登录,NO,只允许在文件中的用户登录FTP服务器。
userlist_file=/etc/vsftpd.user_list    # 被读取的包含用户列表的文件
#### 限制目录
chroot_list_enable=NO            # 锁定某些用户在自家目录中,是否调用限制在家目录的用户名单
chroot_local_user=YES           # 禁止本地用户登出自己的FTP主目录
chroot_list_file=/etc/vsftpd/chroot_list    #限制在家目录的用户名单所在路径,文件格式为一行一用户
注:通过搭配能实现以下几种效果:①当chroot_list_enable=YES,chroot_local_user=YES时,在/etc/vsftpd.chroot_list文件中列出的用户,可以切换到其他目录;未在文件中列出的用户,不能切换到其他目录。②当chroot_list_enable=YES,chroot_local_user=NO时,在/etc/vsftpd.chroot_list文件中列出的用户,不能切换到其他目录;未在文件中列出的用户,可以切换到其他目录。③当chroot_list_enable=NO,chroot_local_user=YES时,所有的用户均不能切换到其他目录。④当chroot_list_enable=NO,chroot_local_user=NO时,所有的用户均可以切换到其他目录。

######### 日志设置 ###########
xferlog_enable=YES           #打开日志记录
xferlog_file=/var/log/vsftpd.log    #日志存放位置
xferlog_std_format=YES         #标准日志格式

######### 安全设置 ###########
idle_session_timeout=600      #用户空闲超时,单位秒
data_connection_timeout=120     #数据连接空闲超时,单位秒
accept_timeout=60          # 将客户端空闲1分钟后断开
connect_timeout=60         # 中断1分钟后重新连接
local_max_rate=50000        # 本地用户传输速率,单位bite
max_clients=200           # FTP的最大连接数
max_per_ip=5            # 每个IP允许的连接数,0表示没有限制,需要运行于独立模式方可

######### 被动模式设置 ###########
pasv_enable=NO           #是否使用PASV被动模式
pasv_min_port=5000         # 被动模式最小端口,0 表示任意。
pasv_max_port=6000         # 被动模式最大端口,0 表示任意。
pasv_promiscuous=NO         #PASV模式的安全检查,该检查确保数据连接和控制连接是来自同一个IP地址,小心打开此选项。

######### 其他设置 ###########
ftpd_banner=Welcome to Ftp Server!    #欢迎信息

######### 虚拟用户配置文件###########
guest_enable=YES               #允许虚拟用户
guest_username=ftpadmin           #指定虚拟用户的宿主用户
virtual_use_local_privs=YES          #设定虚拟用户的权限符合他们的宿主用户
user_config_dir=/etc/vsftpd/vconf   //设定虚拟用户个人Vsftp的配置文件存放路径。也就是说,这个被指定的目录里,将存放每个Vsftp虚拟用户个性的配置文件,一个需要注意的地方就是这些配置文件名必须和虚拟用户名相同


2、建立日志文件

touch /var/log/vsftpd.log
chown -R ftpadmin:ftpadmin /var/log/vsftpd.log

 

3、添加虚拟主机用户 
用户名virtual 将来会存放ftp数据,指定存放数据的位置:/data/ftp. 

/usr/sbin/adduser -d /data/ftp -s /sbin/nologin ftpadmin

注-s /sbin/nologin是让其不能登陆系统,-d 是指定用户目录为/data/ftp 
#passwd ftpadmin  设置密码 

chown -R ftpadmin:ftpadmin /data/ftp

注:将用户目录及其子目录的所有和所属的组权限设置为ftpadmin


4、创建虚拟用户文件

 mkdir /etc/vsftpd/vconf
 touch /etc/vsftpd/vconf/vir_user


5、建立虚拟用户

# vim /etc/vsftpd/vconf/vir_user
---------------------------------------------------
virtualuser           //用户名
12345678           //密码

注意:第一行用户名,第二行是上一行用户名的密码,其他人的以此类推


6、生成数据库

db_load -T -t hash -f /etc/vsftpd/vconf/vir_user /etc/vsftpd/vconf/vir_user.db


7、设置数据库文件的访问权限

chmod 600 /etc/vsftpd/vconf/vir_user.db
chmod 600 /etc/vsftpd/vconf/vir_user


8、建立认证文件

# vi /etc/pam.d/vsftpd.vu
#插入以下两行, 这里需要注意的是 vsftpd.vu可以其任何名字,关键是要跟配置文件pam一致,一定不能有空格

echo "auth required pam_userdb.so db=/etc/vsftpd/vconf/vir_user" > /etc/pam.d/vsftpd
echo "account required pam_userdb.so db=/etc/vsftpd/vconf/vir_user" >> /etc/pam.d/vsftpd


9、创建用户的配置文件

注意:用户配置文件的名字要和创建的“虚拟用户”名字对应。

前提配置文件中要开启:

tcp_wrappers=YES
mkdir -p /etc/vsftpd/vsftpd_user_conf
cd /etc/vsftpd/vsftpd_user_conf
vim /etc/vsftpd/vsftpd_user_conf/virtualuser

输入:

local_root=/data/ftp       #虚拟用户的个人目录路径
anonymous_enable=NO
write_enable=YES
local_umask=022
anon_upload_enable=NO
anon_mkdir_write_enable=NO
idle_session_timeout=600
data_connection_timeout=120
max_clients=10
max_per_ip=5
local_max_rate=1048576     #本地用户的最大传输速度,单位是Byts/s,我设定的是10M
cmds_allowed=MKD,LIST,PASV,ABOR,REST,NLST,RMD,RNFR,FNTO,SIZE,PORT,STOR,QUIT

 PS: vsftpd可以对每个用户特别限制.只要给那个用户建立一个设置文件,然后在文件里设置

cmds_allowed=XXXXX, 此用户可以使用的指令

# ABOR - abort a file transfer
# CWD - change working directory
# DELE - delete a remote file
# LIST - list remote files
# MDTM - return the modification time of a file
# MKD - make a remote directory
# NLST - name list of remote directory
# PASS - send password
# PASV - enter passive mode
# PORT - open a data port
# PWD - print working directory
# QUIT - terminate the connection
# RETR - retrieve a remote file
# RMD - remove a remote directory
# RNFR - rename from
# RNTO - rename to
# SITE - site-specific commands
# SIZE - return the size of a file
# STOR - store a file on the remote host
# TYPE - set transfer type
# USER - send username
#
# less common commands:
# ACCT* - send account information
# APPE - append to a remote file
# CDUP - CWD to the parent of the current directory
# HELP - return help on using the server
# MODE - set transfer mode
# NOOP - do nothing
# REIN* - reinitialize the connection
# STAT - return server status
# STOU - store a file uniquely
# STRU - set file transfer structure
# SYST - return system type

参数说明:

LIST 文件或目录列表

STOR 存储文件

MKD 创建目录

CWD 改变目录

ABOR 终止进程

REST 断点续传


10、建立虚拟用户目录

如果不建立虚拟用户的个人目录,那么所有的虚拟用户登录后所在的目录都是同一个目录下

# mkdir /data/ftp/virtualuser
# chown virtualuser:virtualuser /data/ftp/virtualuser
# chmod 600 /data/ftp/virtualuser


11、配置virtualuser用户访问权限

vim /etc/vsftpd.user_list   #设置用户白名单,,文件格式为一行一用户
vim /etc/vsftpd/chroot_list    #限制在家目录的用户名单所在路径,文件格式为一行一用户


12、开启防火墙20/21端口


13、限制ip访问

只使用hosts.allow文件即可,不用动hosts.deny文件

vsftpd:222.90.72.87 61.150.91.10:allow
vsftpd:all:deny


14、验证vsftp服务

Linux 验证:ftp 127.0.0.1  输入用户名:admin 密码:admin123

提示ftp:command not found  ,需要安装ftp服务:yum -y install ftp


遇到的问题:

    1、450:读取目录列表失败

在配置完第一台vsftp后(上面的配置就是)再用同样的过程做第二台,完成后用客户端和浏览器死活无法登录报错:

450:读取目录列表失败

只有在命令提示符和Termin下通过ftp 192.168.88.30后ls没有问题

对比了之前的配置,每一步都没错,难到是PASV问题,于是在vsftpd.conf加上了一句pasv_enable=NO,然后……没然后了,一切都正常了

    2、中文乱码

这个是老生常谈的问题,好象也一直没有什么好的解决办法,网上也有提出改i18n,不过客户提出不用改,他们公司主要都是英文档,也我也省事了,不过还是当个问题记录吧


    3、500 OOPS:cannot change directory:/home/pmfile

新建用户后登录报错,刚开始以为是selinux的问题,后来一想不对,其他的帐号都没事,肯定刚才己关闭了selinux(getenforce查看selinux,setenforce 0暂时关闭 ),那么就是权限问题了,果然是刚才忘了把权限给虚拟ftp宿主权限了:chown -R ftpuser.ftpuser /home/publicfile


    4、530错误:Login incorrect.

这是一个让我觉的搞笑的问题,第二台vsftp服务我用自己的本上的客户端(FileZilla)登录没问题,而客户用他的本登录就不行,用的软件都一样,不同的是我用的是Ubuntu,他用的是win7,但在win7的命令提示符下他却也能登录也能ls,不是权限问题,不是pam问题,这两块都着手试过,结果发现是客户在终端输入的密码错误,之前我还一再问他到底有没有输错密码,他也十分肯定的说没有,结果……


    5、外网无法登录,550错误,错误: 读取目录列表失败

这个问题很是挠头,在做完第二台服务器后让客户先从内网登录,一切都很正常,而从外网登录时就会出现“550 Permission denied.”“错误: 连接超时”“错误: 读取目录列表失败”,难到是权限?

试来试去什么PASV、什么权限更改全做了(这一步是我着实不想做的,要是登录用户权限有问题内网也该无法登录),最后让客户的网管带我去查了一下他们路由器的配置,我才发现他们的内网映射没有开放TCP20端口,开放后就OK了


附录:

FTP命令详解

  FTP的命令行格式为:ftp -v -d -i -n -g [主机名],其中

  -v显示远程服务器的所有响应信息;
  -n限制ftp的自动登录,即不使用;
  .n etrc文件;
  -d使用调试方式;
  -g取消全局文件名。
  
  ftp使用的内部命令如下(中括号表示可选项):
  1.![cmd[args]]:在本地机中执行交互shell,exit回到ftp环境,如:!ls*.zip.
  2.$ macro-ame[args]:执行宏定义macro-name.
  3.account[password]:提供登录远程系统成功后访问系统资源所需的补充口令。
  4.append local-file[remote-file]:将本地文件追加到远程系统主机,若未指定远程系统文件名,则使用本地文件名。
  5.ascii:使用ascii类型传输方式。
  6.bell:每个命令执行完毕后计算机响铃一次。
  7.bin:使用二进制文件传输方式。
  8.bye:退出ftp会话过程。
  9.case:在使用mget时,将远程主机文件名中的大写转为小写字母。
  10.cd remote-dir:进入远程主机目录。
  11.cdup:进入远程主机目录的父目录。
  12.chmod mode file-name:将远程主机文件file-name的存取方式设置为mode,如:chmod 777 a.out。
  13.close:中断与远程服务器的ftp会话(与open对应)。
  14.cr:使用asscii方式传输文件时,将回车换行转换为回行。
  15.delete remote-file:删除远程主机文件。
  16.debug[debug-value]:设置调试方式,显示发送至远程主机的每条命令,如:deb up 3,若设为0,表示取消debug。
  17.dir[remote-dir][local-file]:显示远程主机目录,并将结果存入本地文件local-file。
  18.disconnection:同close。
  19.form format:将文件传输方式设置为format,缺省为file方式。
  20.get remote-file[local-file]:将远程主机的文件remote-file传至本地硬盘的local-file。
  21.glob:设置mdelete,mget,mput的文件名扩展,缺省时不扩展文件名,同命令行的-g参数。
  22.hash:每传输1024字节,显示一个hash符号(#)。
  23.help[cmd]:显示ftp内部命令cmd的帮助信息,如:help get。
  24.idle[seconds]:将远程服务器的休眠计时器设为[seconds]秒。
  25.image:设置二进制传输方式(同binary)。
  26.lcd[dir]:将本地工作目录切换至dir。
  27.ls[remote-dir][local-file]:显示远程目录remote-dir,并存入本地文件local-file。
  28.macdef macro-name:定义一个宏,遇到macdef下的空行时,宏定义结束。
  29.mdelete[remote-file]:删除远程主机文件。
  30.mdir remote-files local-file:与dir类似,但可指定多个远程文件,如:mdir *.o.*.zipoutfile
  31.mget remote-files:传输多个远程文件。
  32.mkdir dir-name:在远程主机中建一目录。
  33.mls remote-file local-file:同nlist,但可指定多个文件名。
  34.mode[modename]:将文件传输方式设置为modename,缺省为stream方式。
  35.modtime file-name:显示远程主机文件的最后修改时间。
  36.mput local-file:将多个文件传输至远程主机。
  37.newer file-name:如果远程机中file-name的修改时间比本地硬盘同名文件的时间更近,则重传该文件。
  38.nlist[remote-dir][local-file]:显示远程主机目录的文件清单,并存入本地硬盘的local-file。
  39.nmap[inpattern outpattern]:设置文件名映射机制,使得文件传输时,文件中的某些字符相互转换,如:nmap $1.$2.$3[$1,$2].[$2,$3],则传输文件a1.a2.a3时,文件名变为a1,a2。该命令特别适用于远程主机为非UNIX机的情况。
  40.ntrans[inchars[outchars]]:设置文件名字符的翻译机制,如ntrans 1R,则文件名LLL将变为RRR。
  41.open host[port]:建立指定ftp服务器连接,可指定连接端口。
  42.passive:进入被动传输方式。
  43.prompt:设置多个文件传输时的交互提示。
  44.proxy ftp-cmd:在次要控制连接中,执行一条ftp命令,该命令允许连接两个ftp服务器,以在两个服务器间传输文件。第一条ftp命令必须为open,以首先建立两个服务器间的连接。
  45.put local-file[remote-file]:将本地文件local-file传送至远程主机。
  46.pwd:显示远程主机的当前工作目录。
  47.quit:同bye,退出ftp会话。
  48.quote arg1,arg2...:将参数逐字发至远程ftp服务器,如:quote syst.
  49.recv remote-file[local-file]:同get。
  50.reget remote-file[local-file]:类似于get,但若local-file存在,则从上次传输中断处续传。
  51.rhelp[cmd-name]:请求获得远程主机的帮助。
  52.rstatus[file-name]:若未指定文件名,则显示远程主机的状态,否则显示文件状态。
  53.rename[from][to]:更改远程主机文件名。
  54.reset:清除回答队列。
  55.restart marker:从指定的标志marker处,重新开始get或put,如:restart 130。
  56.rmdir dir-name:删除远程主机目录。
  57.runique:设置文件名唯一性存储,若文件存在,则在原文件后加后缀..1,.2等。
  58.send local-file[remote-file]:同put。
  59.sendport:设置PORT命令的使用。
  60.site arg1,arg2...:将参数作为SITE命令逐字发送至远程ftp主机。
  61.size file-name:显示远程主机文件大小,如:site idle 7200。
  62.status:显示当前ftp状态。
  63.struct[struct-name]:将文件传输结构设置为struct-name,缺省时使用stream结构。
  64.sunique:将远程主机文件名存储设置为唯一(与runique对应)。
  65.system:显示远程主机的操作系统类型。
  66.tenex:将文件传输类型设置为TENEX机的所需的类型。
  67.tick:设置传输时的字节计数器。
  68.trace:设置包跟踪。
  69.type[type-name]:设置文件传输类型为type-name,缺省为ascii,如:type binary,设置二进制传输方式。
  70.umask[newmask]:将远程服务器的缺省umask设置为newmask,如:umask 3。
  71.user user-name[password][account]:向远程主机表明自己的身份,需要口令时,必须输入口令,如:user anonymous my@email。
  72.verbose:同命令行的-v参数,即设置详尽报告方式,ftp服务器的所有响应都将显示给用户,缺省为on.
  73.?[cmd]:同help。


三、重启服务: 

/etc/init.d/vsftpd restart

到此,整个小巧的ftp服务器搭建成功。可以使用FileZilla FTP或FlashFXP等客户端软件登陆ftp server了。


四:相关的配置详解
匿名用户相关设置 

当virtual_use_local_privs=YES时,虚拟用户和本地用户有相同的权限;

当virtual_use_local_privs=NO时,虚拟用户和匿名用户有相同的权限,默认是NO。

当virtual_use_local_privs=YES,write_enable=YES时,虚拟用户具有写权限(上传、下载、删除、重命名)。

当virtual_use_local_privs=NO,write_enable=YES,anon_world_readable_only=YES,

anon_upload_enable=YES时,虚拟用户不能浏览目录,只能上传文件,无其他权限。

当virtual_use_local_privs=NO,write_enable=YES,anon_world_readable_only=NO,

anon_upload_enable=NO时,虚拟用户只能下载文件,无其他权限。

当virtual_use_local_privs=NO,write_enable=YES,anon_world_readable_only=NO,

anon_upload_enable=YES时,虚拟用户只能上传和下载文件,无其他权限。

当virtual_use_local_privs=NO,write_enable=YES,anon_world_readable_only=NO,

anon_mkdir_write_enable=YES时,虚拟用户只能下载文件和创建文件夹,无其他权限。

当virtual_use_local_privs=NO,write_enable=YES,anon_world_readable_only=NO,

anon_other_write_enable=YES时,虚拟用户只能下载、删除和重命名文件,无其他权限。