Linux下FTP虚拟账号环境部署记录 (vsftpd)

 

一、FTP协议的两种工作方式
port方式:主动模式
port(主动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。当需要传送数据时,服务器从20端口向客户端的空闲端口发送连接请求,建立一条数据链路来传送数据。[即当需要传送数据时,客户端在命令链路上用PORT命令告诉服务器"我打开了***X端口,你过来连接我"。于是服务器从20端口向客户端的***X端口发送连接请求,建立一条数据链路来传送数据。]
pasv方式:被动模式
pasv(被动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。当需要传送数据时,客户端向服务器的空闲端口发送连接请求,建立一条数据链路来传送数据。[即当需要传送数据时,服务器在命令链路上用PASV命令告诉客户端"我打开了***X端口,你过来连接我"。于是客户端向服务器的***X端口发送连接请求,建立一条数据链 路来传送数据。]

FTP是仅基于tcp的服务,不支持udp。FTP使用2个端口,一个数据端口和一个命令端口(也可叫做控制端口)。通常来说这两个端口是21(命令端口)和20(数据端口)。但FTP工作方式的不同,数据端口并不总是20,这就是主动与被动FTP的最大不同之处。

主动模式的FTP工作流程:客户端从一个任意的非特权端口N(N>1024)连接到FTP服务器的命令端口,也就是21端口。然后客户端开始监听端口N+1,并发送FTP命令"portN+1"到FTP服务器。接着服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1)。针对FTP服务器前面的防火墙来说,必须允许以下通讯才能支持主动方式FTP:
1)任何大于1024的端口到FTP服务器的21端口。(客户端初始化的连接)
2)FTP服务器的21端口到大于1024的端口。(服务器响应客户端的控制端口)
3)FTP服务器的20端口到大于1024的端口。(服务器端初始化数据连接到客户端的数据端口)
4)大于1024端口到FTP服务器的20端口(客户端发送ACK响应到服务器的数据端口)

被动模式的FTP工作流程 (有效解决了服务器发起到客户的连接问题) 当客户端通知服务器它处于被动模式时才启用。在被动方式FTP中,命令连接和数据连接都由客户端发起,这样就可以解决从服务器到客户端的数据端口的入方向连接被防火墙过滤掉的问题。当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(N>1024和N+1)。第一个端口连接服务器的21端口,但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连它的数据端口,而是提交PASV命令。这样做的结果是服务器会开启一个任意的非特权端口(P>1024),并发送PORTP命令给客户端。然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。对于服务器端的防火墙来说,必须允许下面的通讯才能支持被动方式的FTP:
1)从任何大于1024的端口到服务器的21端口(客户端初始化的连接)
2)服务器的21端口到任何大于1024的端口(服务器响应到客户端的控制端口的连接)
3)从任何大于1024端口到服务器的大于1024端口(客户端初始化数据连接到服务器指定的任意端口)
4)服务器的大于1024端口到远程的大于1024的端口(服务器发送ACK响应和数据到客户端的数据端口)

主动FTP:
命令连接:客户端>1024端口  --> 服务器 21端口
数据连接:客户端>1024端口 <-- 服务器 20端口

被动FTP:
命令连接:客户端>1024端口 --> 服务器 21端口
数据连接:客户端>1024端口 --> 服务器>1023端口

主动与被动FTP优缺点:
主动FTP对FTP服务器的管理有利,但对客户端的管理不利。因为FTP服务器企图与客户端的高位随机端口建立连接,而这个端口很有可能被客户端的防火墙阻塞掉。
被动FTP对FTP客户端的管理有利,但对服务器端的管理不利。因为客户端要与服务器端建立两个连接,其中一个连到一个高位随机端口,而这个端口很有可能被服务器端的防火墙阻塞掉。

随着WWW的广泛流行,许多人习惯用web浏览器作为FTP客户端。大多数浏览器只在访问ftp://这样的URL时才支持被动模式。这到底是好还是坏取决于服务器和防火墙的配置。通常情况下会选用被动模式的FTP。

二、FTP登录的用户类型
FTP的用户有三种类型:匿名用户、系统用户、虚拟用户
匿名登录:在登录FTP时使用默认的用户名,一般是ftp或anonymous。
本地用户登录:使用系统用户登录,在/etc/passwd中。
虚拟用户登录:这是FTP专有用户,有两种方式实现虚拟用户,本地数据文件和数据库服务器。

FTP虚拟用户是FTP服务器的专有用户,使用虚拟用户账号可以提供集中管理的FTP根目录,方便了管理员的管理,同时将用于FTP登录的用户名、密码与系统用户账号区别开,进一步增强了FTP服务器的安全性。某种意义上来说,匿名用户也是系统用户,只是系统用户的一个映射。公开的FTP都不会使用系统用户作为FTP帐号,而更多的采用了虚拟用户,这样能保证系统的安全性。

使用虚拟用户登录FTP服务器,可以避免使用操作系统帐号作为FTP用户带来的一些安全问题,也便于通过数据库或其它程序来进行管理。虚拟用户的特点是只能访问服务器为其提供的FTP服务,而不能访问系统的其它资源。所以,如果想让用户对FTP服务器站内具有写权限,但又不允许访问系统其它资源,可以使用虚拟用户来提高系统的安全性。

在VSFTP中,认证这些虚拟用户使用的是单独的口令库文件(pam_userdb),由可插入认证模块(PAM)认证。使用这种方式更加安全,并且配置更加灵活。基本流程:FTP用户访问->PAM配置文件(由vsftpd.conf中pam_service_name指定)->PAM论证->区别用户读取配置文件(由vsftpd.conf中user_config_dir指定配置文件路径,文件名即用户名)。有两种方式建立FTP的虚拟用户,分别是:本地数据文件方式、数据库服务器(MySQL)方式

三、FTP虚拟用户环境部署记录
下面记录在CentOS6版本下采用本地数据文件方式部署FTP虚拟账号登陆环境的过程及其中遇到的问题:

1)yum安装vsftpd
[root@i-f658wfj6 ~]# yum install -y vsftpd
[root@i-f658wfj6 ~]# yum install -y db4
          
[root@cms_web vsftpd]# pwd
/etc/vsftpd
          
2)配置vsftpd(将vsftpd.conf文件备份,然后将配置内容直接粘贴下面内容)
[root@cms_web vsftpd]# cat vsftpd.conf|grep -v "^#"
anonymous_enable=NO        # 不允许匿名账号访问
local_enable=YES           # 本地用户可以访问(采用虚拟账号访问时,这个参数也要开启(虚拟账号要寄宿本地账号),虽然开启但是本地账号是不可以登陆的)
write_enable=YES           # 可写可上传。这个参数是全局配置,否则上传和下载都会报错550!
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
xferlog_std_format=YES
ascii_upload_enable=YES
ascii_download_enable=YES
ftpd_banner=Welcome to FTP service   # 登陆FTP时显示的欢迎信息
listen=YES
chroot_local_user=NO           # 限制所有的本地用户在自家目录,即用户登陆系统后锁定在自家目录。虚拟主机配置下,在下面两个chroot配置后,这个参数必须为NO,否则登陆FTP后还可以访问其他目录!
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list  # 指定不能离开家目录的用户列表文件,一行一个用户。使用此方法时必须chroot_local_user=NO。说明这个列表里面的用户登陆ftp后都只能访问其主目录,其他目录都不能访问!
pam_service_name=vsftpd        # 指定PAM配置文件,即下面的/etc/pam.d/vsftpd文件要和这里指定的一致。
userlist_enable=YES
tcp_wrappers=YES
virtual_use_local_privs=YES    # 这个参数一定要加上,虚拟用户和本地用户有相同的权限;否则ftp连上后不能上传,报错550权限拒绝!
guest_enable=YES               # 启用虚拟用户
guest_username=nobody          # 将虚拟用户映射为本地nobody用户(前提是local_enable=YES)
user_config_dir=/etc/vsftpd/vuser_conf      # 指定不同虚拟用户配置文件的存放路径
          
connect_from_port_20=YES       # 通过20端口传输数据
listen_port=2021               # 监听的ftp端口
pasv_min_port=40001            # 分配给ftp账号的最小端口。被动模式下的配置
pasv_max_port=40100            # 分配给ftp账号的最大端口。每个账号分配一个端口,即最大允许100个ftp账号连接。
max_clients=150                # 客户端的最大连接数
accept_timeout=5
connect_timeout=1
max_per_ip=5                   # 每个ip最大连接数
          
=============================================================================================
温馨提示:
上面的ftp是被动模式下的配置,配置后需要在iptables防火墙开通ftp访问
[root@cms_web vsftpd]# cat /etc/sysconfig/iptables
............
-A INPUT -s 10.68.250.13 -m state --state NEW -m tcp -p tcp --dport 2021 -j ACCEPT
-A INPUT -s 10.68.250.13 -m state --state NEW -m tcp -p tcp --dport 40001:40100 -j ACCEPT
..........
============================================================================================
          
设置登陆ftp的虚拟账号文件(格式依次是:第一行是账户名,次行是该账号的密码;即奇数行是账户名,偶数行是对应上一行的账户密码)。
这个虚拟账号是不需要手动创建的,它不是真实存在于系统中的,即/etc/passwd文件里没有的,它是借助于宿主账号nobody。
[root@cms_web vsftpd]# cat vuser_passwd.txt
hqsbcms
hqsbcms_2016@huanqiu.com
          
生成虚拟用户口令认证的db文件(该文件设定600权限),这是本地数据库文件
[root@cms_web vsftpd]# db_load -T -t hash -f /etc/vsftpd/vuser_passwd.txt /etc/vsftpd/vuser_passwd.db
[root@cms_web vsftpd]# chmod 600 /etc/vsftpd/vuser_passwd.db
          
[root@cms_web vsftpd]# cat /etc/vsftpd/chroot_list     # 将虚拟用户放在这个列表文件里,说明这些用户登陆后都只能锁定到对应主目录内
hqsbcms
     
[root@cms_web vsftpd]# mkdir vuser_conf                # 此目录名是在vsftpd.conf配置中指定的,里面是虚拟用户配置文件(文件名是虚拟用户名)
[root@cms_web vsftpd]# cat vuser_conf/hqsbcms
local_root=/hqsb/ftp/          # 指定虚拟账号登陆后的主目录,目录权限要是宿主账号nobody,这样就可以实现账号映射
write_enable=YES               # 写权限
anon_umask=022
anon_world_readable_only=NO    # 下载权限(当其他四项的YES为NO时,则此账号登陆FTP后只有可读和下载权限了)
anon_upload_enable=YES         # 上传权限
anon_mkdir_write_enable=YES    # 创建目录权限
anon_other_write_enable=YES    # 删除和重命名权限
        
[root@bastion-IDC vsftpd]# ll /lib64/security/pam_userdb.so
-rwxr-xr-x. 1 root root 10280 May 11  2016 /lib64/security/pam_userdb.so
[root@cms_web vsftpd]# cat /etc/pam.d/vsftpd       # 注释掉文件中原来的内容,添加下面两行内容
#%PAM-1.0
#session optional pam_keyinit.so force revoke
#auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
#auth required pam_shells.so
#auth include password-auth
#account include password-auth
#session required pam_loginuid.so
#session include password-auth
# 32-bit
#auth required /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser_passwd
#account required /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser_passwd
# 64-bit
auth sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser_passwd          # 这个vuser_passwd根据的是vuser_passwd.db
account sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser_passwd       # 这里64bit系统,必须用sufficient,否则上面vuser_conf目录下的虚拟主机配置文件无效!
          
[root@bastion-IDC ~]# cat /etc/passwd|grep nobody          # 宿主账号nobody的信息不用做任何修改,shell类型是不是/sbin/nologin都可以,不影响ftp登陆限制到主目录下,因为vsfprd里配置了三个chroot。
nobody:x:99:99:Nobody:/:/sbin/nologin          

[root@cms_web vsftpd]# chown -R nobody.nobody /hqsb/ftp    # 设置虚拟账号hqsbcms指定的主目录的权限为nobody,这样就可以映射到宿主账号nobody
[root@cms_web vsftpd]# chmod -R 700 /hqsb/ftp
          
[root@cms_web vsftpd]# /etc/init.d/vsftpd start
  
[root@bastion-IDC vsftpd]# ll /hqsb/ftp/
total 4
-rwxrwxrwx. 1 nobody nobody    0 Mar 29 12:53 aaa
drwxrwxrwx. 2 nobody nobody 4096 Mar 29 12:53 test

                                                                                                                                                    
vsftpd进程启动报错:
starting vsftpd for vsftpd: 500 OOPS: bad bool value in config file for: anonymous_enable

处理办法:要保证vsftpd.conf文件里每行的配置后面都不要有空格。
解决:vim编辑/etc/vsftpd/vsftpd.conf文件,在尾行模式下输入":%s/\s\+$",然后回车即可。

                                                                                                                                                    
vim删除行首行尾空格和tab的命令如下(非编辑状态下输入):
:%s/^\s\+         删除行首的空格和tab
:%s/\s\+$         删除行尾的空格和tab

上面两条命令的解释:
%s          表示全局搜索
/             为分隔符。
^            代表行首
\s            代表空格和tab
\+           代表匹配一个或多个
$             匹配行尾
                                                                                                                                                   

问题0500 OOPS: vsftpd: refusing to run with writable root inside chroot()

解决办法在/etc/vsftpd/vsftpd.conf文件添加:allow_writeable_chroot=YES

然后重启vsftpd服务即可!!!!

                                                                                                                                                   

问题一在ftp客户端(比如FileZilla)进行连接,发现连接失败,无法连接到服务器!如下(例如*.*.186.5为上面ftp服务器外网ip)

原因及解决:由于上面ftp配置中采用的是被动模式,而客户端连接默认的是主动模式。所以需要手动修改下客户端的默认配置。修改如下:
依次点击FileZilla客户端左上角的"文件"->"站点管理器"->"新建站点"

这样,就能正常连接上FTP服务器了。以后每次连接的时候,就依次打开左上角"文件"->"站点管理器"里之前设置并保存好的站点就行(如上面的185.5-ftp站点)。使用上诉虚拟账号登陆ftp后,只能登陆到其设置的主目录/hqsb/ftp下,服务器上的其他目录资源都不能访问!

问题二登陆ftp时出现下面报错

500 OOPS: cannot change directory:/hqsb/ftp  
Login failed.  
421 Service not available, remote server has closed connection 

解决办法:通常为Selinux导致,关闭Selinux即可。

                                                                                                                                                  
需要注意
浏览器访问只支持FTP的被动模式,也就是说只有在FTP配置成被动模式时,才能在远程浏览器里通过url访问。比如上面配置后,可以通过web访问ftp://111.111.111.115:2021/

                                                                                                                                                               

ftp命令行登录(ftp或\ftp):
# ftp ip port
# \ftp 111.111.111.115 2021

如果不使用ftp命令,还可以通过wget命令下载,使用示例如下:
# wget ftp://111.111.111.115:2021/kevin/source_1209-0-1/201801251520-test.tar.gz --ftp-user=kevin --ftp-password=kevin@123

                                                                                                                                                              
FTP数据安全:使用SSL加密传输(不再使用明文传输)
按照上面的配置后,FTP连接后的数据传输严格来说是不太安全的,因为是使用明文传输。如下截图,客户端连接过程中会提示“不安全的服务器,...”

这种情况下,我们可以使用SSL加密传输,配置过程如下:

[root@bastion-IDC ~]# mkdir /etc/vsftpd/sslkey
[root@bastion-IDC ~]# cd /etc/vsftpd/sslkey
[root@bastion-IDC sslkey]# openssl req -new -x509 -nodes -out vsftpd.pem -keyout vsftpd.pem
Generating a 2048 bit RSA private key
.........................................................................................+++
...................................+++
writing new private key to 'vsftpd.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:huanqiu
Organizational Unit Name (eg, section) []:technology
Common Name (eg, your name or your server's hostname) []:huanqiu
Email Address []:wangshibo@huanqiu.cn

[root@bastion-IDC sslkey]# ls
vsftpd.pem
 
[root@bastion-IDC sslkey]# vim /etc/vsftpd/vsftpd.conf    //在文件最底部添加下面几行
ssl_enable=YES
ssl_sslv2=NO
ssl_sslv3=NO
ssl_tlsv1=YES
ssl_ciphers=HIGH
require_ssl_reuse=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
rsa_cert_file=/etc/vsftpd/sslkey/vsftpd.pem

[root@bastion-IDC sslkey]# /etc/init.d/vsftpd restart
Shutting down vsftpd:                                      [  OK  ]
Starting vsftpd for vsftpd:                                [  OK  ]

然后再次在客户端连接FTP(注意FTP客户端配置中的加密类型中要支持"FTP over TLS"),发现就就会建立TLS安装连接了。(连接中,会出现是否信任证书的提示,信任即可)

注意:FTP做了SSL加密传输后,ftp命令将不能再登陆,FTP浏览器方式访问也会受阻。需使用支持SSL的客户端来验证vsftp,这里还可以推荐使用flashFXP客户端,如下:

如果flashFXP客户端不好用的话,可以采用lftp工具进行登陆:

# yum install -y lftp
# lftp ip -u username -p 2021

注意:lftp命令可以支持ssl加密方式的连接,ftp命令不支持ssl加密方式的连接。
如果远程客户机lftp登录进去操作报错"Fatal error: Certificate verification: Not trusted"
[root@kevin ~]# lftp 172.16.60.214 -u myftp -p 20021
Password:
lftp myftp@172.16.60.214:~> ls     
ls: Fatal error: Certificate verification: Not trusted
  
[root@kevin ~]# cp /etc/lftp.conf /etc/lftp.conf.bak
[root@kevin ~]# vim /etc/lftp.conf
set ssl:verify-certificate no           #在文本最后添加
  
然后就可以正常登录并操作了
[root@kevin ~]# lftp 172.16.60.214 -u myftp -p 20021
Password:
lftp myftp@172.16.60.214:~> ls     
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 OPS
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 DEV
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XDCF

登陆后执行ls,如果出现一直请求连接的情况,多数是因为pasv的端口范围在防火墙上没有配置。ftp协议数据传输和命令传输是不同的端口,这个例子下要开40001~40100端口。

                                                                                                                                                             
添加FTP虚拟账号

比如添加账号ops(密码为ops@123),指定目录为/mnt/ops,操作如下:
[root@bastion-IDC vsftpd]# pwd
/etc/vsftpd
[root@bastion-IDC vsftpd]# cat chroot_list
hqsbcms
ops

[root@bastion-IDC vsftpd]# cat vuser_passwd.txt
hqsbcms
hqsbcms_2016@huanqiu.com
ops
ops@123

[root@bastion-IDC vsftpd]# db_load -T -t hash -f /etc/vsftpd/vuser_passwd.txt /etc/vsftpd/vuser_passwd.db

[root@bastion-IDC vsftpd]# cat vuser_conf/ops
local_root=/mnt/ops/
write_enable=YES
anon_umask=022
anon_world_readable_only=NO
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES

[root@bastion-IDC vsftpd]# chown -R nobody.nobody /mnt/ops
[root@bastion-IDC vsftpd]# chmod -R 777 /mnt/ops

照此操作就可以添加FTP虚拟账号了,每个虚拟账号可以对应一个主目录,并且限定到只能ftp访问该主目录
====================================================================================

如果想让虚拟账号ops权限为只读以及只能下载(没有上传、删除、重命名、创建文件目录等写权限),那么它的配置修改如下:
[root@bastion-IDC vsftpd]# cat vuser_conf/ops
local_root=/mnt/ops/
write_enable=NO
anon_umask=022
anon_world_readable_only=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO

                                                                                                                                                              
自动添加FTP虚拟账号的脚本

下面脚本可用于自动添加vsftp虚拟账号,脚本中的kevin账号是已经存在的vsftp虚拟账号,用这个kevin账号配置拷贝给新账号,然后再更新配置。

[root@localhost ~]# vim /opt/scripts/AddVirtualFtpUser.sh
#! /bin/sh
#-----------------------------------------------
# Usage:
#        Add a new virtual user for FTP
# Example:
#        AddVirtualFtpUser.sh Syscode(Capital letter) password
#-----------------------------------------------
 
SysCode=$1
Password=$2
 
FTP_User_DB_TXT="/etc/vsftpd/vuser_passwd.txt"
FTP_User_DB="/etc/vsftpd/vuser_passwd.db"
FTP_User_List="/etc/vsftpd/chroot_list"
Virtual_User_Dir="/etc/vsftpd/vuser_conf"
 
if [ $# -ne 2 ];then
        echo "[Error]: Please input correct parameters."
        echo "[Example]: AddVirtualFtpUser.sh kevin password"
        exit 1
fi
 
SysCode=`echo ${SysCode} | tr '[a-z]' '[A-Z]'`
 
echo ${SysCode} >> ${FTP_User_DB_TXT}
echo ${Password} >> ${FTP_User_DB_TXT}
echo ${SysCode} >> ${FTP_User_List}
 
UpdateDB=`db_load -T -t hash -f ${FTP_User_DB_TXT}  ${FTP_User_DB} 2>&1`
if [ $? -ne 0 ];then
   echo ${UpdateDB}
   exit 1
fi

#用之前的虚拟账号kevin的配置拷贝到新账号下,然后替换更新
cp "${Virtual_User_Dir}/kevin" "${Virtual_User_Dir}/${SysCode}"
sed -i "s/kevin/${SysCode}/g" "${Virtual_User_Dir}/${SysCode}"
if [ $? -eq 0 ];then
   echo "Success | 0"
else
   echo "Failed | 1"
fi

授予脚本执行权限
[root@localhost ~]# chmod 755 /opt/scripts/AddVirtualFtpUser.sh

比如相加新ftp账号rubao,密码为rubao@123,做法:
[root@localhost ~]# sh /opt/scripts/AddVirtualFtpUser.sh rubao rubao@123

                                                                                                                                                              
Haproxy代理层配置上面Ftp虚拟账号登陆环境的访问
下面配置表示本机haproxy的2021端口代理到10.68.250.198(这是后端的ftp服务器)的2021端口(ftp服务端口)。本机的iptables防火墙里开放2021和40001:40100;而10.68.250.198机器的2021和40001:40100端口要对haproxy代理机开放。

Haproxy配置方法一

[root@mysql-master ~]# cat /etc/haproxy/haproxy.cfg
.......

listen ftp_198 0.0.0.0:2021
mode tcp
option tcplog
balance roundrobin
server 10.68.250.198 10.68.250.198 check port 2021 inter 10s rise 1 fall 2

listen ftp_date_198 0.0.0.0:40001-40100
mode tcp
option tcplog
balance roundrobin
server 10.68.250.198 10.68.250.198 check port 2021 inter 10s rise 1 fall 2

Haproxy配置方法二

[root@mysql-master ~]# cat /etc/haproxy/haproxy.cfg
.......
frontend ftp_198 0.0.0.0:2021                       
   mode tcp
   bind *:2021
   default_backend ftp_server
frontend ftp_date_198 0.0.0.0:40001-40100
   mode tcp
   bind *:40001-40100
   default_backend ftp_server_data
backend ftp_server
   mode tcp
   server ftp 10.68.250.198 check port 2021 inter 10s rise 1 fall 2
backend ftp_server_data
   mode tcp
   server ftp 10.68.250.198 check port 2021 inter 10s rise 1 fall 2

                                                                                                                                                         
附上vsftpd配置参数

################################## 基本设定 #########################################
#接受匿名用户
anonymous_enable=YES

#匿名用户login时不询问口令
no_anon_password=YES

#匿名用户主目录
anon_root=(none)

#接受本地用户
local_enable=YES

#本地用户主目录
local_root=(none)

#如果匿名用户需要密码,那么使用banned_email_file里面的电子邮件地址的用户不能登录
deny_email_enable=YES

#仅在没有pam验证版本时有用,是否检查用户有一个有效的shell来登录
check_shell=YES

#若启用此选项,userlist_deny选项才被启动
userlist_enable=YES

#若为YES,则userlist_file中的用户将不能登录,为NO则只有userlist_file的用户可以登录
userlist_deny=NO

#如果和chroot_local_user一起开启,那么用户锁定的目录来自/etc/passwd每个用户指定的目录(这个不是很清楚,很哪位熟悉的指点一下)
passwd_chroot_enable=NO

#定义匿名登入的使用者名称。默认值为ftp。
ftp_username=FTP

################################### 用户权限控制 ####################################
#可以上传(全局控制).
write_enable=YES

#本地用户上传文件的umask
local_umask=022

#上传文件的权限配合umask使用
#file_open_mode=0666

#匿名用户可以上传
anon_upload_enable=NO

#匿名用户可以建目录
anon_mkdir_write_enable=NO

匿名用户其它的写权利(更改权限?)
anon_other_write_enable=NO

如果设为YES,匿名登入者会被允许下载可阅读的档案。默认值为YES。
anon_world_readable_only=YES

#如果开启,那么所有非匿名登陆的用户名都会被切换成guest_username指定的用户名
#guest_enable=NO

所有匿名上传的文件的所属用户将会被更改成chown_username
chown_uploads=YES

匿名上传文件所属用户名
chown_username=lightwiter

#如果启动这项功能,则所有列在chroot_list_file之中的使用者不能更改根目录
chroot_list_enable=YES

#允许使用"async ABOR"命令,一般不用,容易出问题
async_abor_enable=YES

管控是否可用ASCII 模式上传。默认值为NO。
ascii_upload_enable=YES

#管控是否可用ASCII 模式下载。默认值为NO。
ascii_download_enable=YES

#这个选项必须指定一个空的数据夹且任何登入者都不能有写入的权限,当vsftpd 不需要file system 的权限时,就会将使用者限制在此数据夹中。默认值为/usr/share/empty
secure_chroot_dir=/usr/share/empty

############################### 超时设置 ###############################
#空闲连接超时
idle_session_timeout=600

#数据传输超时
data_connection_timeout=120

#P***S请求超时
ACCEPT_TIMEOUT=60

#PROT模式连接超时
connect_timeout=60

############################### 服务器功能选项 #############################
#开启日记功能
xferlog_enable=YES

#使用标准格式
xferlog_std_format=YES

#当xferlog_std_format关闭且本选项开启时,记录所有ftp请求和回复,当调试比较有用.
#log_ftp_protocol=NO

#允许使用pasv模式
pasv_enable=YES

#关闭安全检查,小心呀.
#pasv_promiscuous=NO

#允许使用port模式
#port_enable=YES

#关闭安全检查
#prot_promiscuous

#开启tcp_wrappers支持
tcp_wrappers=YES

#定义PAM 所使用的名称,预设为vsftpd。
pam_service_name=vsftpd

#当服务器运行于最底层时使用的用户名
nopriv_user=nobody

#使vsftpd在pasv命令回复时跳转到指定的IP地址.(服务器联接跳转?)
pasv_address=(none)

########################### 服务器性能选项 ###########################
#是否能使用ls -R命令以防止浪费大量的服务器资源。是否允许递归查询。默认为关闭,以防止远程用户造成过量的I/O
ls_recurse_enable=YES

#是否使用单进程模式。这个设定项目比较危险一点~当设定为YES时,表示每个建立的连线都会拥有一支process在负责,可以增加vsftpd的效能。
#不过,除非您的系统比较安全,而且硬体配备比较高,否则容易耗尽系统资源喔!一般建议设定为NO的啦!
one_process_model=NO

#绑定到listen_port指定的端口,既然都绑定了也就是每时都开着的,就是那个什么standalone模式
listen=YES

#当使用者登入后使用ls -al 之类的指令查询该档案的管理权时,预设会出现拥有者的UID,而不是该档案拥有者的名称。
#若是希望出现拥有者的名称,则将此功能开启。
text_userdb_names=NO

#显示目录清单时是用本地时间还是GMT时间,可以通过mdtm命令来达到一样的效果
use_localtime=NO

#测试平台优化
#use_sendfile=YES 

########################### 信息类设置  ############################
login时显示欢迎信息.如果设置了banner_file则此设置无效
ftpd_banner="欢迎登录kevin的ftp服务"

#允许为目录配置显示信息,显示每个目录下面的message_file文件的内容
dirmessage_enable=YES

#显示会话状态信息
#setproctitle_enable=YES

############################ 文件定义 #############################
#定义不能更改用户主目录的文件
chroot_list_file=/etc/vsftpd/vsftpd.chroot_list

#定义限制/允许用户登录的文件
userlist_file=/etc/vsftpd/vsftpd.user_list

#定义登录信息文件的位置
banner_file=/etc/vsftpd/banner

#禁止使用的匿名用户登陆时作为密码的电子邮件地址
#如果deny_email_enable=YES时,可以利用这个设定项目来规定哪个email address不可登入我们的vsftpd喔!在上面设定的档案内,一行输入一个email address即可!
banned_email_file=/etc/vsftpd.banned_emails

#日志文件位置
xferlog_file=/var/log/vsftpd.log

#目录信息文件
#当进入一个新目录的时候,会查找这个文件并显示文件里的内容给远程用户。dirmessage_enable需启用。默认值:.message 
message_file=.message

########################### 目录定义 #############################
#定义用户配置文件的目录
user_config_dir=/etc/vsftpd/userconf

#定义本地用户登陆的根目录,注意定义根目录可以是相对路径也可以是绝对路径
相对路径是针对用户家目录来说的
local_root=webdisk

#此项设置每个用户登陆后其根目录为/home/username/webdisk#匿名用户登陆后的根目录
anon_root=/var/ftp 

########################## 用户连接选项 ##########################
#可接受的最大client数目
max_clients=100

#每个ip的最大client数目
max_per_ip=5

#使用标准的20端口来连接ftp
connect_from_port_20=YES

#绑定到某个IP,其它IP不能访问
listen_address=192.168.0.2

#绑定到某个端口
listen_port=2121

#数据传输端口
ftp_data_port=2020

#pasv连接模式时可以使用port 范围的上界,0 表示任意。默认值为0。
pasv_max_port=100010

#pasv连接模式时可以使用port 范围的下界,0 表示任意。默认值为0。
pasv_min_port=100050

######################### 数据传输选项 ##########################
#匿名用户的传输比率(b/s)
# 这个设定值后面接的数值单位为bytes/秒,限制anonymous的传输速度,如果是0则不限制(由最大频宽所限制),
# 如果您想让anonymous仅有30 KB/s的速度,可以设定『anon_max_rate=30000』
anon_max_rate=51200

#本地用户的传输比率(b/s)
local_max_rate=5120000

#限制anonymous的权限!如果是077则anonymous传送过来的档案权限会是-rw
anon_umask=077


重点注意的细节
=============================================================================================================
1》限制vsftpd最大连接数和传输速率
在FTP服务器的管理中,无论对本地用户还是匿名用户,对于FTP服务器资源的使用都需要进行控控制,避免由于负担过大造成FTP服务器运行异常,
可以添加以下配置项对FTP客户机使用FTP服务器资源进行控制:

max_client设置项 
用于设置FTP服务器所允许的最大客户端连接数,值为0时表示不限制。
例如max_client=100表示FTP服务器的所有客户端最大连接数不超过100个。

max_per_ip设置项 
用于设置对于同一IP地址允许的最大客户端连接数,值为0时表示不限制。
例如max_per_ip=5表示同一IP地址的FTP客户机与FTP服务器建立的最大连接数不超过5个。

local_max_rate设置项 
用于设置本地用户的最大传输速率,单位为B/s,值为0时表示不限制。
例如local_max_rate=500000表示FTP服务器的本地用户最大传输速率设置为500KB/s.

anon_max_rate设置项 
用于设置匿名用户的最大传输速率,单位为B/s,值为0表示不限制。
例如ano_max_rate=200000,表示FTP服务器的匿名用户最大传输速率设置为200KB/s.

=============================================================================================================
2》指定用户的权限设置

vsftpd.user_list文件需要与vsftpd.conf文件中的配置项结合来实现对于vsftpd.user_list文件中指定用户账号的访问控制:

a)设置禁止登录的用户账号
当vsftpd.conf配置文件中包括以下设置时,vsftpd.user_list文件中的用户账号被禁止进行FTP登录:
userlist_enable=YES
userlist_deny=YES 

userlist_enable设置项设置使用vsftpd.user_list文件,userlist_deny设置为YES表示vsftpd.user_list文件用于设置禁止的用户账号。

b)设置只允许登录的用户账号
当vsftpd.conf配置文件中包括以下设置时,只有vsftpd.user_list文件中的用户账号能够进行FTP登录:
userlist_enable=YES
userlist_deny=NO 


userlist_enable设置项设置使用vsftpd.user_list文件,
userlist _deny设置为NO表示vsftpd.usre_list文件用于设置只允许登录的用户账号,文件中未包括的用户账号被禁止FTP登录。

userlist_deny和userlist_enable选项限制用户登录FTP服务器

注意:使用userlist_deny选项和user_list文件一起能有效阻止root,apache,www等系统用户登录FTP服务器,从而保证FTP服务器的分级安全性。

以下是两个选项的具体表现形式和两种搭配使用方式的效果:
Userlist_enable=YES   表示:Ftpusers中用户允许访问;User_list中用户允许访问
Userlist_enable=NO    表示:Ftpusers中用户禁止访问;User_list中用户允许访问
Userlist_deny=YES     表示:Ftpusers中用户禁止访问(登录时可以看到密码输入提示,但仍无法访问);User_list 中用户禁止访问
Userlist_deny=NO      表示:Ftpusers中用户禁止访问;User_list中用户允许访问

Userlist_enable=YES 并且 Userlist_deny=YES  表示:Ftpusers中用户禁止访问;User_list中用户禁止访问(登录时不会出现密码提示,直接被服务器拒绝)
Userlist_enable=YES 并且 Userlist_deny=NO   表示:Ftpusers中用户禁止访问;User_list中用户允许访问

                                                                                                                                                         
FTP/LFTP在Shell脚本中的用法

1)从FTP上批量下载文件到本地
[root@Kevin test]# pwd
/tmp/test
[root@Kevin test]# ls
ftp.sh  test.file
  
[root@Kevin test]# cat ftp.sh
#!/bin/sh
ftp -v -n 192.168.10.10 20021 << EOF       # ip,port
user kevinftp ftp1@3$                      # user后面跟的是ftp连接的用户名和密码
binary                                     # 文件传输类型
cd IFS/Pay/iOS/                            # cd是登录到远程ftp后的路径(在ftp根目录下的cd切换)
lcd /tmp/test/                             # lcd是在本地主机目录操作的命令
prompt                                     # 取消交互
mget *                                     # mget是批量的下载文件,*表示下载当前ftp目录下的所有文件,可以是一个或多个文件,中间使用空格隔开。
bye
EOF                                      
echo "download from ftp successfully"
  
2)从本地向FTP批量上传文件
[root@Kevin test]# cat ftp.sh
#!/bin/sh
ftp -v -n 192.168.10.10 20021 << EOF  
user kevinftp ftp1@3$
binary
cd IFS/Pay/iOS/             
lcd /tmp/test/                             # 也可以使用"lcd ./"表示在本地当前目录下                          
prompt
mput test.file ftp.sh                      # mput是批量上传的文件,可以是一个或多个文件,中间用空格隔开。也可以使用*表示上传本地当前目录下的所有文件。
bye
EOF                                      
echo "upload to ftp successfully"
  
=====================================================================================
lftp在shell中的用法(去掉交互) (ftp登录的用户名是kevinftp,密码是ftp1@3$)
 
[root@Kevin ~]# lftp 192.168.10.10 -u kevinftp -p 20021
Password:
lftp kevinftp@192.168.10.10:~> ls     
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 BOBO
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 GRACE
drwxrwxr-x    4 500      500          4096 Aug 27 03:18 RUBAO
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XIAOAN
drwxr-xr-x    3 500      500          4096 Mar 28 11:45 HEHUO
  
lftp在命令行里非交互模式直接登录使用
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;ls;"               
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 BOBO
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 GRACE
drwxrwxr-x    4 500      500          4096 Aug 27 03:18 RUBAO
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XIAOAN
drwxr-xr-x    3 500      500          4096 Mar 28 11:45 HEHUO
  
上传a.log和a.txt文件(put)
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;put a.log;put a.txt;" >/dev/null 2>&1
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;ls;"
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 BOBO
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 GRACE
drwxrwxr-x    4 500      500          4096 Aug 27 03:18 RUBAO
-rw-r--r--    1 500      500        231498 Aug 30 10:28 a.log
-rw-r--r--    1 500      500           906 Aug 30 10:28 a.txt
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XIAOAN
drwxr-xr-x    3 500      500          4096 Mar 28 11:45 HEHUO
  
删除(rm)(注意:ftp登录后的删除命令是delete,lftp登录后的删除命令是rm)
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;rm -f a.log;rm -f a.txt;" >/dev/null 2>&1            
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;ls;"
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 BOBO
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 GRACE
drwxrwxr-x    4 500      500          4096 Aug 27 03:18 RUBAO
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XIAOAN
drwxr-xr-x    3 500      500          4096 Mar 28 11:45 HEHUO
  
下载(get)
[root@Kevin ~]# lftp -c "open 192.168.10.10.20021 ;user kevinftp ftp1@3$;get a.log;get a.txt;" >/dev/null 2>&1

                                                                                                                                                                         
FTP登录后操作出现227错误

部署了FTP的PASV的被动模式,远程客户机连接ftp后进行操作,一直出现227错误,如下:

[root@Kevin ~]# ftp 192.168.10.10 20021
Connected to 192.168.10.10 (192.168.10.10).
220 Welcome to aiops FTPs service.PLS use Passive mode.
Name (192.168.10.10:root): mpsftp
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 (h1,h2,h3,h4,p1,p2). 
就一直卡在这里了.......

这里就要分析下FTP的两种工作模式,PORT主动模式和PASV被动模式 (文章开头已经详细介绍了)
参考并尝试网上解决办法都不好使,最后无奈将被动模式改为主动模式,并将ftp端口给位默认的21端口,问题得已解决。

需要修改的配置如下:
[root@Kevin ~]# cat /etc/vsftpd/vsftpd.conf
........
#修改FTP监听端口
#listen_port=20021
listen_port=21

#使用被动模式,指定数据端口及安全检查(被动模式配置都注释了)
#pasv_enable=YES
#pasv_min_port=40001
#pasv_max_port=40100
#pasv_promiscuous=NO
#max_clients=150
#accept_timeout=5
#connect_timeout=1
#max_per_ip=5

最后重启ftp服务
[root@Kevin ~]# /etc/init.d/vsftpd restart

再次连接ftp进行操作就可以了(默认连接的就是21端口)
[root@Kevin ~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 Welcome to aiops FTPs service.PLS use Passive mode.
Name (192.168.10.10:root): mpsftp
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   (10,4,87,254,216,234).
150 Here comes the directory listing.
drwxr-xr-x    5 500      500          4096 Aug 27 02:54 BOBO
drwxr-xr-x    4 500      500          4096 Jun 18 08:19 GRACE
drwxrwxr-x    4 500      500          4096 Aug 27 03:18 RUBAO
drwxr-xr-x    3 500      500          4096 Mar 29 02:24 XIAOAN
drwxr-xr-x    3 500      500          4096 Mar 28 11:45 HEHUO
226 Directory send OK.
ftp>

                                                                                                                                            
FTP上传文件前后大小改变
1)对比文件上传前后的MD5值("md5sum filename"),MD5值不一样,则文件肯定是有变化的了。
2) "\ftp ip port"登录ftp后,在使用put/get命令进行上传/下载操作前,先输入"binary",即将传输模式设为二进制(默认是ASCII方式传输),这样可以防止windows下的文件传到
linux上出现文件损坏的情况。

                                                                                                                                            

FTP登陆报错: 500 OOPS: vsftpd: refusing to run with writable root inside chroot()
这个问题发生在最新的vsftpd版本里。从2.3.5之后,vsftpd增强了安全检查,如果用户被限定在了其主目录下,则该用户的主目录不能再具有写权限了!如果检查发现还有写权限,就会报该错误。
[root@ftp01 ftp]# ftp 192.168.10.22 2021
Connected to 192.168.10.22 (192.168.10.22).
220 Welcome to FTP service
Name (192.168.10.22:root): haftp
331 Please specify the password.
Password:
500 OOPS: vsftpd: refusing to run with writable root inside chroot()

解决办法:在/etc/vsftpd/vsftpd.conf文件里添加下面一行内容,并重启vsftpd服务即可:
allow_writeable_chroot=YES

                                                                                                                                            
FTP日常操作命令

ftp> ascii       # 设定以ASCII方式传送文件(缺省值) 。
ftp> bell        # 每完成一次文件传送,报警提示。 
ftp> binary      # 设定以二进制方式传送文件。 
ftp> bye         # 终止主机FTP进程,并退出FTP管理方式。 
ftp> case        # 当为ON时,用MGET命令拷贝的文件名到本地机器中,全部转换为小写字母。 
ftp> cd          # 同UNIX的CD命令。 
ftp> cdup        # 返回上一级目录。(同理:ftp> cd 。。/)
ftp> chmod       # 改变远端主机的文件权限。 
ftp> close       # 终止远端的FTP进程,返回到FTP命令状态, 所有的宏定义都被删除。 
ftp> delete      # 删除远端主机中的文件。 
ftp> dir [remote-directory] [local-file]    # 列出当前远端主机目录中的文件。如果有本地文件,就将结果写至本地文件。 
ftp> get [remote-file] [local-file]         # 从远端主机中传送至本地主机中。 
ftp> help [command]                         # 输出命令的解释。 
ftp> lcd                                    # 改变当前本地主机的工作目录,如果缺省,就转到当前用户的HOME目录。 
ftp> ls [remote-directory] [local-file]     # 同DIR。列出当前远端主机目录中的文件。如果有本地文件,就将结果写至本地文件
ftp> macdef                                 # 定义宏命令。 
ftp> mdelete [remote-files]                 # 删除一批文件。 
ftp> mget [remote-files]                    # 从远端主机接收一批文件至本地主机。 
ftp> mkdir directory-name                   # 在远端主机中建立目录。 
ftp> mput local-files                       # 将本地主机中一批文件传送至远端主机。 
ftp> open host [port]                       # 重新建立一个新的连接。 
ftp> prompt                                 # 交互提示模式。 
ftp> put local-file [remote-file]           # 将本地一个文件传送至远端主机中。 
ftp> pwd                                    # 列出当前远端主机目录。 
ftp> quit                                   # 同BYE。即终止主机FTP进程,并退出FTP管理方式。 
ftp> recv remote-file [local-file]          # 同GET。从远端主机中传送至本地主机中。
ftp> rename [from] [to]                     # 改变远端主机中的文件名。 
ftp> rmdir directory-name                   # 删除远端主机中的目录。 
ftp> send local-file [remote-file]          # 同PUT。将本地一个文件传送至远端主机中。
ftp> status                                 # 显示当前FTP的状态。 
ftp> system                                 # 显示远端主机系统类型。 
ftp> user user-name [password] [account]    # 重新以别的用户名登录远端主机。 
ftp> ? [command]                            # 同HELP。 [command]指定需要帮助的命令名称。如果没有指定 command,ftp 将显示全部命令的列表。
ftp> !                                      # 从 ftp 子系统退出到外壳。 

1)关闭FTP连接
ftp> bye
ftp> exit
ftp> quit

2)下载文件
ftp> get readme.txt  # 下载 readme.txt 文件
ftp> mget *.txt      # 下载

3)上传文件
ftp> put /path/readme.txt   # 上传 readme.txt 文件
ftp> mput *.txt             # 可以上传多个文件

4)状态码
•230 - 登录成功
•200 - 命令执行成功
•150 - 文件状态正常,开启数据连接端口
•250 - 目录切换操作完成
•226 - 关闭数据连接端口,请求的文件操作成功
posted @ 2016-06-15 13:24  散尽浮华  阅读(5088)  评论(4编辑  收藏  举报