FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于FTP传输效率非常高,在网络上传输大的文件时,一般也采用该协议。
默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。但是,是否使用20作为传输数据的端口与FTP使用的传输模式有关,如果采用主动模式,那么数据传输端口就是20;如果采用被动模式,则具体最终使用哪个端口要服务器端配置决定。
运行FTP服务的许多站点都开放匿名服务,在这种设置下,用户不需要帐号就可以登录服务器,默认情况下,匿名用户的用户名是:“anonymous”。
支持网页浏览器和文件管理器
大多数最新的网页浏览器和文件管理器都能和FTP服务器创建连接。这使得在FTP上通过一个接口就可以操控远程文件,如同操控本地文件一样。这个功能通过给定一个FTP的URL实现,形如ftp://<服务器地址>(例如,ftp://ftp.gimp.org )。是否提供密码是可选择的,如果有密码,则形如ftp://<login>:<password>@<ftpserveraddress>。大部分网页浏览器要求使用被动FTP模式,然而并不是所有的FTP服务器都支持被动模式。
FTP状态码:
1xx-肯定的初步答复这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。
110重新启动标记答复。
120服务已就绪,在nnn分钟后开始。
125数据连接已打开,正在开始传输。
150文件状态正常,准备打开数据连接。
2xx-肯定的完成答复一项操作已经成功完成。客户端可以执行新命令。
200命令确定。
202未执行命令,站点上的命令过多。
211系统状态,或系统帮助答复。
212目录状态。
213文件状态。
214帮助消息。
215NAME系统类型,其中,NAME是AssignedNumbers文档中所列的正式系统名称。
220服务就绪,可以执行新用户的请求。
221服务关闭控制连接。如果适当,请注销。
225数据连接打开,没有进行中的传输。
226关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。
227进入被动模式(h1,h2,h3,h4,p1,p2)。
230用户已登录,继续进行。
250请求的文件操作正确,已完成。
257已创建“PATHNAME”。
3xx-肯定的中间答复该命令已成功,但服务器需要更多来自客户端的信息以完成对请求的处理。
331用户名正确,需要密码。
332需要登录帐户。
350请求的文件操作正在等待进一步的信息。
4xx-瞬态否定的完成答复该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。
421服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。
425无法打开数据连接。 426Connectionclosed;transferaborted.
450未执行请求的文件操作。文件不可用(例如,文件繁忙)。
451请求的操作异常终止:正在处理本地错误。
452未执行请求的操作。系统存储空间不够。
5xx-永久性否定的完成答复该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。
500语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。
501在参数中有语法错误。
502未执行命令。
503错误的命令序列。
504未执行该参数的命令。
530未登录。
532存储文件需要帐户。
550未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。
551请求的操作异常终止:未知的页面类型。
552请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。
553未执行请求的操作。不允许的文件名。
常见的FTP状态代码及其原因:
150-FTP使用两个端口:21用于发送命令,20用于发送数据。
状态代码150表示服务器准备在端口20上打开新连接,发送一些数据。
226-命令在端口20上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。
230-客户端发送正确的密码后,显示该状态代码。它表示用户已成功登录。
331-客户端发送用户名后,显示该状态代码。无论所提供的用户名是否为系统中的有效帐户,都将显示该状态代码。
426-命令打开数据连接以执行操作,但该操作已被取消,数据连接已关闭。
530-该状态代码表示用户无法登录,因为用户名和密码组合无效。如果使用某个用户帐户登录,可能键入错误的用户名或密码,也可能选择只允许匿名访问。如果使用匿名帐户登录,IIS的配置可能拒绝匿名访问。
550-命令未被执行,因为指定的文件不可用。例如,要GET的文件并不存在,或试图将文件PUT到您没有写入权限的目录。
常见的Ftp服务器:
linux:vsftp,FileZilla Server...
Windows:Server-U,FileZilla Server....
Ftp有两种工作模式:PORT 和 Passive
-
主动模式
ftp> put issue
local: issue remote: issue
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
29 bytes sent in 0.00 secs (480.0053 kB/s)
ftp>
22:33:38.185125 IP (tos 0x10, ttl 64, id 34867, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.106.53614 > 192.168.2.10.21: Flags [P.], cksum 0x8fa2 (correct), seq 30:38, ack 97, win 229, options [nop,nop,TS val 2979868386 ecr 6094179], length 8: FTP, length: 8
TYPE I "客户端通知进入 二进制模式 ===Type set to A表示的是字符模式;Type set to I表示的是二进制模式"
22:33:38.185286 IP (tos 0x0, ttl 64, id 3837, offset 0, flags [DF], proto TCP (6), length 83)
192.168.2.10.21 > 192.168.2.106.53614: Flags [P.], cksum 0x860a (incorrect -> 0xbd0a), seq 97:128, ack 38, win 227, options [nop,nop,TS val 6122503 ecr 2979868386], length 31: FTP, length: 31
200 Switching to Binary mode. "服务器通知,已切换到二进制模式"
22:33:38.185605 IP (tos 0x10, ttl 64, id 34868, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.53614 > 192.168.2.10.21: Flags [.], cksum 0xf2d7 (correct), ack 128, win 229, options [nop,nop,TS val 2979868387 ecr 6122503], length 0
22:33:38.185864 IP (tos 0x10, ttl 64, id 34869, offset 0, flags [DF], proto TCP (6), length 80)
192.168.2.106.53614 > 192.168.2.10.21: Flags [P.], cksum 0x3eda (correct), seq 38:66, ack 128, win 229, options [nop,nop,TS val 2979868387 ecr 6122503], length 28: FTP, length: 28
PORT 192,168,2,106,220,251 "客户端通知服务器自己打开的端口 是 200*256+251=56571"
22:33:38.185946 IP (tos 0x0, ttl 64, id 3838, offset 0, flags [DF], proto TCP (6), length 103)
192.168.2.10.21 > 192.168.2.106.53614: Flags [P.], cksum 0x861e (incorrect -> 0x475d), seq 128:179, ack 66, win 227, options [nop,nop,TS val 6122503 ecr 2979868387], length 51: FTP, length: 51
200 PORT command successful. Consider using PASV. "服务器回复:PORT命令成功。考虑使用PASV"
22:33:38.186495 IP (tos 0x10, ttl 64, id 34870, offset 0, flags [DF], proto TCP (6), length 64)
192.168.2.106.53614 > 192.168.2.10.21: Flags [P.], cksum 0x3981 (correct), seq 66:78, ack 179, win 229, options [nop,nop,TS val 2979868388 ecr 6122503], length 12: FTP, length: 12
STOR issue "客户端发送命令: 储存 issue"
"=====服务端使用21端口发起=====三次握手========="
22:33:38.186943 IP (tos 0x0, ttl 64, id 29344, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.10.20 > 192.168.2.106.56571: Flags [S], cksum 0x85f3 (incorrect -> 0xb801), seq 806100648, win 29200, options [mss 1460,sackOK,TS val 6122504 ecr 0,nop,wscale 7], length 0
22:33:38.187434 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.106.56571 > 192.168.2.10.20: Flags [S.], cksum 0x7ad8 (correct), seq 4031212861, ack 806100649, win 28960, options [mss 1460,sackOK,TS val 2979868389 ecr 6122504,nop,wscale 7], length 0
22:33:38.187448 IP (tos 0x0, ttl 64, id 29345, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.10.20 > 192.168.2.106.56571: Flags [.], cksum 0x85eb (incorrect -> 0x19df), ack 1, win 229, options [nop,nop,TS val 6122505 ecr 2979868389], length 0
22:33:38.187604 IP (tos 0x0, ttl 64, id 3839, offset 0, flags [DF], proto TCP (6), length 74)
"==========三次握手完成========="
192.168.2.10.21 > 192.168.2.106.53614: Flags [P.], cksum 0x8601 (incorrect -> 0xe02d), seq 179:201, ack 78, win 227, options [nop,nop,TS val 6122505 ecr 2979868388], length 22: FTP, length: 22
150 Ok to send data. "服务器通知客户端可以发数据了"
22:33:38.188605 IP (tos 0x8, ttl 64, id 62609, offset 0, flags [DF], proto TCP (6), length 81)
192.168.2.106.56571 > 192.168.2.10.20: Flags [P.], cksum 0x0854 (correct), seq 1:30, ack 1, win 227, options [nop,nop,TS val 2979868389 ecr 6122505], length 29
22:33:38.188618 IP (tos 0x8, ttl 64, id 62610, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.56571 > 192.168.2.10.20: Flags [F.], cksum 0x19c3 (correct), seq 30, ack 1, win 227, options [nop,nop,TS val 2979868389 ecr 6122505], length 0
22:33:38.188722 IP (tos 0x8, ttl 64, id 29346, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.10.20 > 192.168.2.106.56571: Flags [.], cksum 0x85eb (incorrect -> 0x19c1), ack 30, win 229, options [nop,nop,TS val 6122506 ecr 2979868389], length 0
22:33:38.188840 IP (tos 0x8, ttl 64, id 29347, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.10.20 > 192.168.2.106.56571: Flags [F.], cksum 0x85eb (incorrect -> 0x19bf), seq 1, ack 31, win 229, options [nop,nop,TS val 6122506 ecr 2979868389], length 0
22:33:38.189178 IP (tos 0x8, ttl 64, id 62611, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.56571 > 192.168.2.10.20: Flags [.], cksum 0x19c0 (correct), ack 2, win 227, options [nop,nop,TS val 2979868390 ecr 6122506], length 0
22:33:38.189319 IP (tos 0x0, ttl 64, id 3840, offset 0, flags [DF], proto TCP (6), length 76)
192.168.2.10.21 > 192.168.2.106.53614: Flags [P.], cksum 0x8603 (incorrect -> 0x234e), seq 201:225, ack 78, win 227, options [nop,nop,TS val 6122507 ecr 2979868388], length 24: FTP, length: 24
226 Transfer complete. "到此,传输完成"
22:33:38.189578 IP (tos 0x10, ttl 64, id 34871, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.53614 > 192.168.2.10.21: Flags [.], cksum 0xf248 (correct), ack 225, win 229, options [nop,nop,TS val 2979868391 ecr 6122505], length 0
-
被动模式
ftp> put issue
local: issue remote: issue
227 Entering Passive Mode (192,168,2,10,204,61).
150 Ok to send data.
226 Transfer complete.
29 bytes sent in 0.00 secs (449.5288 kB/s)
ftp>
23:08:14.730673 IP (tos 0x10, ttl 64, id 40034, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.106.54150 > 192.168.2.10.21: Flags [P.], cksum 0x8964 (correct), seq 42:50, ack 210, win 229, options [nop,nop,TS val 2981944932 ecr 8182778], length 8: FTP, length: 8
TYPE I "客户端通知进入 二进制模式 ===Type set to A表示的是字符模式;Type set to I表示的是二进制模式"
23:08:14.730825 IP (tos 0x0, ttl 64, id 36152, offset 0, flags [DF], proto TCP (6), length 83)
192.168.2.10.21 > 192.168.2.106.54150: Flags [P.], cksum 0x860a (incorrect -> 0xe5e2), seq 210:241, ack 50, win 227, options [nop,nop,TS val 8199048 ecr 2981944932], length 31: FTP, length: 31
200 Switching to Binary mode. "服务器通知,已切换到二进制模式"
23:08:14.731163 IP (tos 0x10, ttl 64, id 40035, offset 0, flags [DF], proto TCP (6), length 58)
192.168.2.106.54150 > 192.168.2.10.21: Flags [P.], cksum 0x6b01 (correct), seq 50:56, ack 241, win 229, options [nop,nop,TS val 2981944932 ecr 8199048], length 6: FTP, length: 6
PASV "客户端通知使用passive模式"
23:08:14.731321 IP (tos 0x0, ttl 64, id 36153, offset 0, flags [DF], proto TCP (6), length 102)
192.168.2.10.21 > 192.168.2.106.54150: Flags [P.], cksum 0x861d (incorrect -> 0x97f4), seq 241:291, ack 56, win 227, options [nop,nop,TS val 8199049 ecr 2981944932], length 50: FTP, length: 50
227 Entering Passive Mode (192,168,2,10,204,61). "服务器通知进入Passive模式,端口为:204*256*61=52285"
"=====客户端发起对服务器开启端口的=====三次握手========="
23:08:14.731819 IP (tos 0x0, ttl 64, id 35548, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.106.49672 > 192.168.2.10.52285: Flags [S], cksum 0x1608 (correct), seq 208867143, win 29200, options [mss 1460,sackOK,TS val 2981944933 ecr 0,nop,wscale 7], length 0
23:08:14.731840 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
192.168.2.10.52285 > 192.168.2.106.49672: Flags [S.], cksum 0x85f3 (incorrect -> 0xe8d9), seq 614067565, ack 208867144, win 28960, options [mss 1460,sackOK,TS val 8199049 ecr 2981944933,nop,wscale 7], length 0
23:08:14.732221 IP (tos 0x0, ttl 64, id 35549, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.49672 > 192.168.2.10.52285: Flags [.], cksum 0x87e1 (correct), ack 1, win 229, options [nop,nop,TS val 2981944933 ecr 8199049], length 0
23:08:14.732239 IP (tos 0x10, ttl 64, id 40036, offset 0, flags [DF], proto TCP (6), length 64)
"==========三次握手完成========="
192.168.2.106.54150 > 192.168.2.10.21: Flags [P.], cksum 0x6270 (correct), seq 56:68, ack 291, win 229, options [nop,nop,TS val 2981944933 ecr 8199049], length 12: FTP, length: 12
STOR issue "客户端发送命令: 储存 issue"
23:08:14.732644 IP (tos 0x0, ttl 64, id 36154, offset 0, flags [DF], proto TCP (6), length 74)
192.168.2.10.21 > 192.168.2.106.54150: Flags [P.], cksum 0x8601 (incorrect -> 0x091e), seq 291:313, ack 68, win 227, options [nop,nop,TS val 8199050 ecr 2981944933], length 22: FTP, length: 22
150 Ok to send data. "服务器通知客户端可以发数据了"
23:08:14.732927 IP (tos 0x8, ttl 64, id 35550, offset 0, flags [DF], proto TCP (6), length 81)
192.168.2.106.49672 > 192.168.2.10.52285: Flags [P.], cksum 0x7653 (correct), seq 1:30, ack 1, win 229, options [nop,nop,TS val 2981944934 ecr 8199049], length 29
23:08:14.732967 IP (tos 0x8, ttl 64, id 35551, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.49672 > 192.168.2.10.52285: Flags [F.], cksum 0x87c2 (correct), seq 30, ack 1, win 229, options [nop,nop,TS val 2981944934 ecr 8199049], length 0
23:08:14.733044 IP (tos 0x8, ttl 64, id 63204, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.10.52285 > 192.168.2.106.49672: Flags [.], cksum 0x85eb (incorrect -> 0x87c4), ack 30, win 227, options [nop,nop,TS val 8199050 ecr 2981944934], length 0
23:08:14.733234 IP (tos 0x8, ttl 64, id 63205, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.10.52285 > 192.168.2.106.49672: Flags [F.], cksum 0x85eb (incorrect -> 0x87c1), seq 1, ack 31, win 227, options [nop,nop,TS val 8199051 ecr 2981944934], length 0
23:08:14.734445 IP (tos 0x8, ttl 64, id 35552, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.49672 > 192.168.2.10.52285: Flags [.], cksum 0x87be (correct), ack 2, win 229, options [nop,nop,TS val 2981944935 ecr 8199051], length 0
23:08:14.734821 IP (tos 0x0, ttl 64, id 36155, offset 0, flags [DF], proto TCP (6), length 76)
192.168.2.10.21 > 192.168.2.106.54150: Flags [P.], cksum 0x8603 (incorrect -> 0x4c3e), seq 313:337, ack 68, win 227, options [nop,nop,TS val 8199052 ecr 2981944933], length 24: FTP, length: 24
226 Transfer complete. "到此,传输完成"
23:08:14.735454 IP (tos 0x10, ttl 64, id 40037, offset 0, flags [DF], proto TCP (6), length 52)
192.168.2.106.54150 > 192.168.2.10.21: Flags [.], cksum 0x1b38 (correct), ack 337, win 229, options [nop,nop,TS val 2981944937 ecr 8199050], length 0
这里存在一些问题:
如果使用主动模式,那么服务器会去主动连接客户端打开的随机端口,但如果有防火墙这将是不会允许的
如果使用被动模式,那么服务器端的防火墙又应该如何设置?
以下是ftp被动模式iptables规则
一、默认策略为ACCEPT
[root@centos6 ~]# modprobe nf_conntrack_ftp
[root@centos6 ~]# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
[root@centos6 ~]# iptables -A INPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
[root@centos6 ~]# iptables -A INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
[root@centos6 ~]# iptables -A INPUT -j DROP
二、默认策略为DROP
[root@centos6 ~]# modprobe nf_conntrack_ftp
[root@centos6 ~]# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
[root@centos6 ~]# iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
[root@centos6 ~]# iptables -P INPUT DROP
[root@centos6 ~]# iptables -P OUTPUT DROP
[root@centos6 ~]# iptables -A INPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT #在INPUT链上放行ftp命令端口
[root@centos6 ~]# iptables -A INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT #在INPUT链上放行ftp数据端口
[root@centos6 ~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT #在OUTPUT链上放行ftp连接,只要是已建立的连接都放行
如果防火墙只开启了21、20端口,又没有权限修改,又如何处理呢?可不可以将passive的数据端口限定在20呢?
测试后发现,vsftp的passive模式只能打开1024之上的端口,这样就只能在客户端设置使用主动模式连接了
在Centos 中使用的ftp服务器为vsftp
了解了Ftp的两种工作模式,下面来看看关于授权的问题
所有的网络共享服务用户的最终权限都取决于服务程序开放的权限和文件系统权限的交集
- 用户
系统用户
系统中passwd文件中存在的用户
在系统中直接使用useradd添加的用户
/etc/pam.d/vsftpd 控制用户登陆验证匿名用户
anonymous,用户不用提供用户名就能访问,最终会映射到ftp用户
/etc/pam.d/vsftpd 控制用户登陆验证虚拟用户
使用独立的账号和密码数据库来验证,最终也会映射到一个系统用户
需要使用自建一套pam来验证
相关的配置项
系统用户
系统用户登陆后,进入家目录,默认可以访问有限制的整个文件系统,使用chroot可以将其限制在"家目录"中
================================
ftp> pwd
257 "/home/test"
===============================
chroot_local_user=YES # 是否所有的系统用户登陆都chroot
chroot_list_enable=YES # 使用控制列表文件来指定哪些用户需要chroot(和chroot_local_user 不同时使用)
chroot_list_file=/etc/vsftpd/chroot_list # chroot控制列表文件,可自己指定
===============================
[root@localhost ~]# cat /etc/vsftpd/chroot_list
test
[root@localhost ~]# ftp 127.0.0.1
Connected to 127.0.0.1 (127.0.0.1).
220 (vsFTPd 3.0.2)
Name (127.0.0.1:root): test
331 Please specify the password.
Password:
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
Login failed.
421 Service not available, remote server has closed connection
ftp>
===============================
从2.3.5之后,vsftpd增强了安全检查,如果用户被限定在了其主目录下,则该用户的主目录不能再具有写权限了!
如果检查发现还有写权限,就会报该错误。 要修复这个错误,可以用命令chmod a-w /home/test去除用户主目录的写权限,注意把目录替换成你自己的。
或者你可以在vsftpd的配置文件中增加下列两项中的一项:
allow_writeable_chroot=YES
=============修改权限后==================
ftp> pwd
257 "/"
ftp>
===============================
匿名用户
anonymous_enable=YES # 启用匿名用户
anon_upload_enable=NO # YES 允许匿名用户上传
anon_mkdir_write_enable=NO # YES 允许匿名用户创建目录
anon_other_write_enable=NO # YES 删除和重命名。
no_anon_password=NO # YES 启用后,这将阻止vsftpd询问匿名密码-匿名用户将直接登录。
[root@localhost ~]# grep ftp /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@localhost ~]# ls -ld /var/ftp
drwxr-xr-x. 3 root root 17 Oct 15 19:02 /var/ftp
[root@localhost ~]# ls -ld /var/ftp/pub/
drwxr-xr-x. 2 root root 6 Oct 31 2018 /var/ftp/pub/
ftp(anonymous)用户的家目录为: /var/ftp,匿名用户登陆后会进入/var/ftp目录,并chroot。
而且该目录的属主为root,其它用户没有写权限,所以在配置中开启了写入权限也无法上传.
最好使用setfacl -m u:ftp:rwx /var/ftp/pub来添加一个ftp用户的权限,而不是使用chown来改用户和组。
"注意:不能修改 /var/ftp 目录的权限,否则会报错"
[root@localhost ~]# ftp 127.0.0.1
Connected to 127.0.0.1 (127.0.0.1).
220 (vsFTPd 3.0.2)
Name (127.0.0.1:root): ftp
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
Login failed.
421 Service not available, remote server has closed connection
===============================
虚拟用户
虚拟用户的上传和写权限也是受匿名anonymous用户的权限控制的如:
anon_upload_enable=YES
anon_mkdir_write_enable=YES
...
-
基于文件验证的vsftpd 虚拟用户
-
1. 生成密码数据库文件
vim /etc/vsftpd/vusers.txt
tom
1
jerry
1
奇数行为虚拟用户
偶数行为密码
cd /etc/vsftpd/
db_load -T -t hash -f vusers.txt vusers.db 编码文件为hash 格式
chmod 600 vusers.db 禁止非root 修改查看 处于安全性 -
2. 创建linux 系统用户及访问ftp目录
useradd -d /var/ftproot -s /sbin/nologin vuser
chmod +rx /var/ftproot/ 给予执行和读权限 使得可以ftp登陆
centos7 还需要执行以下操作:
chmod -w /var/ftproot/
mkdir /var/ftproot/upload
setfacl -m u:vuser:rwx /var/ftproot/upload 为vuser 设置 acl 权限 -
3. 创建pam配置文件
vim /etc/pam.d/vsftpd.db
auth required pam_userdb.so db=/etc/vsftpd/vusers
account required pam_userdb.so db=/etc/vsftpd/vusers -
4. 指定pam配置文件
vim /etc/vsftpd/vsftpd.conf
guest_enable=YES
guest_username=vuser
pam_service_name=vsftpd.db -
5. 禁用SELINUX 和 firewalld
iptables -F
setenforce 0 -
6 create a config file for vitual user
mdkir /etc/vsftpd/vusers.d/ 创建配置文件存放的路径
vim /etc/vsftpd/vsftpd.conf
user_config_dir=/etc/vsftpd/vusers.d/ 指定虚拟用户独立的配置目录
cd /etc/vsftpd/vusers.d/
vim tom
anon_upload_enable=YES 匿名上传
anon_mkdir_write_enable=YES
anon_other_write_enable=YES 允许匿名用户具有建立目录,上传之外的权限,如重命名,删除
-
1. 生成密码数据库文件
===============================
-
mysql验证的vsftpd 虚拟用户
1. 在数据库服务器上安装包:
Centos7:在数据库服务器上安装
yum –y install mariadb-server
systemctl start mariadb.service
systemctl enable mariadb
Centos6:在数据库服务器上安装
yum –y install mysql-server
-
2. 在FTP服务器上安装vsftpd和pam_mysql包
centos6:pam_mysql由epel6的源中提供
yum install vsftpd pam_mysql
centos7:无对应rpm包,需手动编译安装
yum -y groupinstall "Development Tools"
yum -y install mariadb-devel pam-devel vsftpd
下载pam_mysql-0.7RC1.tar.gz
https://sourceforge.net/projects/pam-mysql/
https://sourceforge.net/projects/pam-mysql/files/latest/download- 2.1 解压缩pam模块
tar -xf pam_mysql-0.7RC1.tar.gz
cd pam_mysql-0.7RC1/
- 2.2 编译
./configure --with-pam-mods-dir=/lib64/security
or
./configure --with-pam-mods-dir=/lib64/security --with-mysql=/usr --with-pam=/usr
=====================
make && make install
- 2.1 解压缩pam模块
3. 创建数据库和表
1)创建ftpuserdb数据库
MariaDB [(none)]> create database ftpuserdb;
2)授权一个用户可以连这个数据库(有读权限就行)
MariaDB [(none)]> grant select on ftpuserdb.* to vsftpd@'localhost' identified by 'vsftpdpass';
注意这里只授权了vsftpd用户的本地访问权限,如有需要自行增加
3)创建一个表
MariaDB [ftpdb]> create table users (id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, name VARCHAR(50) BINARY NOT NULL, password CHAR(48) BINARY NOT NULL );
4)往表里增加虚拟用户
MariaDB [ftpdb]> INSERT INTO users(name,password) values('tom',password('1'));
MariaDB [ftpdb]> INSERT INTO users(name,password) values('jerry',password('centos'));
4. 准备一个pam配置文件
vim /etc/pam.d/vsftpd.mysql
auth required pam_mysql.so user=vsftpd passwd=vsftpdpass host=localhost db=ftpdb table=users usercolumn=name passwdcolumn=password crypt=2
account required pam_mysql.so user=vsftpd passwd=vsftpdpass host=localhost db=ftpdb table=users usercolumn=name passwdcolumn=password crypt=2
5.配置使用pam文件和虚拟用户
vim /etc/vsftpd/vsftpd.conf
guest_enable=YES
guest_username=vftpuser
pam_service_name=vsftpd.mysql
6. 准备用户和目录
useradd -s /sbin/nologin vftpuser
chmod 500 /home/vftpuser/
把用户家目录的写权限去掉,家目录用户自己不能有写权限,不然登陆时chroot()就会出错,登陆失败
mkdir /home/vftpuser/upload
##创建上传用的文件夹
chown vftpuser /home/vftpuser/upload/
7. 虚拟用户的独立控制
修改配置文件,指明用户控制文件的位置
vim /etc/vsftpd/vsftpd.conf
user_config_dir=/etc/vsftpd/vftpuser.d/
=====
mkdir /etc/vsftpd/vftpuser.d/
# 创建目录
vim /etc/vsftpd/vftpuser.d/tom
# 编写tom用户的配置文件
anon_upload_enable=YES
anon_mkdir_write_enable=YES
=====
vim /etc/vsftpd/vftpuser.d/jerry
local_root=/data/jerry
这种设置要切两次根,第一次切vftpuser的根/home/vftpuser/,第二交再切到local_root
[root@localhost ~]# ls -ld /data/jerry/
drwxr-xr-x. 2 root root 23 Oct 16 00:19 /data/jerry/
备注1:要想 jerry 充当虚拟用户 jerry的根 jerry自己必须没有写权限
备注2:要想让 jerry用户有写权限,在/etc/vsftpd/vftpuser.d/jerry文件中加入
anon_upload_enable=YES
anon_mkdir_write_enable=YES
还要对/data/jerry/upload目录要有写权限
setfacl -m u:vftpuser:rwx /data/jerry/upload
==============================
-
更多的权限控制
- 1. user_list
userlist_deny
This option is examined if userlist_enable is activated. If you set this setting to NO,
then users will be denied login unless they are explicitly listed in the file specified by userlist_file. When login is denied, the denial is issued before the user is asked for a password.
Default: YES
userlist_enable
If enabled, vsftpd will load a list of usernames, from the filename given by userlist_file. If a user tries to log in using
a name in this file, they will be denied before they are asked for a password. This may be useful in preventing cleartext
passwords being transmitted. See also userlist_deny.
Default: NO
userlist_file
This option is the name of the file loaded when the userlist_enable option is active.
Default: /etc/vsftpd/user_list
userlist_deny=YES
默认的黑名单,user_list文件中的用户名不能登陆
如果设置为NO,则user_list就成为了白名单,只有文件中的用户名才能登陆
而且这个文件的定义,会在询问密码之前生效
-
2. ftpusers
这个是在默认pam中定义的
auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
定义在这个文件中的用户将禁止登陆ftp服务器 -
3. tcp_wrapper
使用tcp_wrapper=YES
可以调用tcp_wrapper来控制主机的访问
=============================
被动模式的端口限制
.......
pasv_min_port=port number
pasv_max_port=port number
设定在PASV模式下,建立数据传输所可以使用port范围的下界和上界,0 表示(1024 – 65535端口)。默认值为0。把端口范围设在比较高的一段范围内,比如50000-60000,将有助于安全性的提高。
=============================
问题(Centos 7)
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
系统用户可以控制是否chroot
匿名用户和虚拟用户默认会chroot
在chroot环境下,用户家(根)目录 用户自己不能有写权限,否则报错
如:jerry的根目录为/data/jerry 只要jerry用户没有写权限就OK
226 Transfer done (but failed to open directory).
登陆正常,但登入服务器后,ls都显示如上错误
- selinux问题,关闭
- 登陆的用户在文件系统中没有权限,文件夹的x权限
500 OOPS: bad bool value in config file for: anon_mkdir_write_enable
systemctl restart vsftpd
时报错,其实并不是配置写错了,而是anon_mkdir_write_enable=YES
后多了空格
550 Failed to open file.
上传文件正常,但不能下载文件
-rw------- 1 1001 1001 0 Oct 15 16:31 hello.txt #默认anon_umask=077情况下的上传文件
-rw-r--r-- 1 1001 1001 23 Oct 15 17:21 issue # anon_umask=022情况下的上传文件
get: Access failed: 550 Failed to open file. (hello.txt)
原因:默认anon_world_readable_only=YES
为开启状态
这个参数的意义:anonymous仅全局可读 开启
启用后,将仅允许匿名用户下载全局可读(other有读权限)的文件。 这是承认ftp用户可能拥有文件,尤其是在存在上传文件的情况下。
解决方案:
- 修改默认的anon_uamsk
anon_umask=022
默认为:077
- 修改默认的anon_uamsk
- 修改默认的anon_world_readable_only
anon_world_readable_only=NO
默认为:YES
- 修改默认的anon_world_readable_only