[TOC]

0x00 前言简述

描述: FTP只通过TCP连接,没有用于FTP的UDP组件.FTP不同于其他服务的是它使用了两个端口, 一个数据端口和一个命令端口(或称为控制端口)。通常21端口是命令端口,20端口是数据端口。当混入主动(Active)/被动模式(Passive)的概念时,数据端口就有可能不是20了。


1) FTP主动模式(Active)

描述: 该模式下FTP客户端从任意的非特殊的端口(N > 1023) -> 连接到FTP服务器的命令21端口, 然后客户端在 N+1(N+1 >= 1024)端口监听,并且通过N+1(N+1 >= 1024)端口发送命令给FTP服务器 -> 然后 FTP 服务器会返回并通过20端口进行传输数据。

示例: 以服务器端防火墙为立足点,要支持主动模式FTP需要打开如下交互中使用到的端口:

  • 1.FTP服务器命令(21)端口接受客户端任意端口(客户端初始连接)
  • 2.FTP服务器命令(21)端口到客户端端口(>1023)(服务器响应客户端命令)
  • 3.FTP服务器数据(20)端口到客户端端口(>1023)(服务器初始化数据连接到客户端数据端口)
  • 4.FTP服务器数据(20)端口接受客户端端口(>1023)(客户端发送ACK包到服务器的数据端口)

说明: 在第1步中客户端的命令端口与FTP服务器的命令端口建立连接,并发送命令“PORT 1027”。然后在第2步中,FTP服务器给客户端的命令端口返回一个”ACK”。在第3步中,FTP服务器发起一个从它自己的数据端口(20)到客户端先前指定的数据端口(1027)的连接,最后客户端在第4步中给服务器端返回一个”ACK”。

WeiyiGeek.主动模式

WeiyiGeek.主动模式

Tips : 在连接FTP服务器时如果没有指定模式它默认使用的是主动模式。

Tips : 主动方式FTP的主要问题实际上在于客户端。FTP的客户端并没有实际建立一个到服务器数据端口的连接,它只是简单的告诉服务器自己监听的端口号,服务器再回来连接客户端这个指定的端口。对于客户端的防火墙来说,这是从外部系统建立到内部客户端的连接,这是通常会被阻塞的。


2) FTP被动模式 (Passive)

描述: 在被动方式FTP中命令连接和数据连接都由客户端控制,该模式是解决了服务器发起到客户的连接的问题, 即被动方式或者叫做PASV,当客户端通知服务器它处于被动模式时才启用。

当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(N > 1024和 N+1),第一个端口连接服务器的21端口,但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连它的数据端口而是提交PASV命令。这样做的结果是服务器会开启一个任意的非特权端口(P > 1024)并发送PORT命令给客户端, 然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。

示例: 对于服务器端的防火墙来说,必须允许下面的通讯才能支持被动方式的FTP:

  • 1.FTP服务器命令(21)端口接受客户端任意端口(客户端初始连接 PASV) 例如 1026
  • 2.FTP服务器命令(21)端口到客户端端口(>1023)(服务器响应客户端命令)
  • 3.FTP服务器数据端口(>1023)接受客户端端口(>1023)(客户端初始化数据连接到服务器指定的任意端口)例如 1027 -> 2024
  • 4.FTP服务器数据端口(>1023)到客户端端口(>1023)(服务器发送ACK响应和数据到客户端的数据端口) 例如 2024 -> 1027

说明: 在第1步中,客户端的命令端口与服务器的命令端口建立连接,并发送命令“PASV”。然后在第2步中,服务器返回命令”PORT 2024”,告诉客户端(服务器)用哪个端口侦听数据连接。在第3步中,客户端初始化一个从自己的数据端口到服务器端指定的数据端口的数据连接。最后服务器在第4 步中给客户端的数据端口返回一个”ACK”响应。

WeiyiGeek.被动模式

WeiyiGeek.被动模式

Tips : 该模式解决了客户端的许多问题但同时给服务器端带来了更多的问题,例如需要允许从任意远程终端到服务器高位端口的连接。幸运的是许多FTP守护程序,包括流行的WU-FTPD允许管理员指定FTP服务器使用的端口范围。其次是客户端有的支持被动模式,有的不支持被动模式。


总结:

Tips :有读者指出当NAT(Network Address Translation)设备以主动模式访问FTP服务器时,由于NAT设备不会聪明的变更FTP包中的IP地址,从而导致无法访问服务器。


简单FTP工作连接方式:

  • 主动FTP:
    1
    2
    命令连接:客户端 >1023端口 -> 服务器 21端口
    数据连接:客户端 >1024端口 <- 服务器 20端口
  • 被动FTP:
    1
    2
    命令连接:客户端 >1023端口 -> 服务器 21端口
    数据连接:客户端 >1024端口 -> 服务器 > nnnn 端口


主动与被动FTP优缺点的简要总结:

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

折中方式: 既然FTP服务器的管理员需要他们的服务器有最多的客户连接,那么必须得支持被动FTP。我们可以通过为FTP服务器指定一个有限的端口范围来减小服务器高位端口的暴露, 这样不在这个范围的任何端口会被服务器的防火墙阻塞,虽然这没有消除所有针对服务器的危险,但它大大减少了危险。


0x01 vsftpd 服务

1.安装说明

安装环境:

1
2
* CentOS7
* Vsftpd


Centos7部署vsftpd

  1. 配置防火墙开启FTP服务器需要的端口CentOS 7.0默认使用的是firewall作为防火墙这里改为iptables防火墙(也可以不改)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1) 关闭firewall:
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动

2) 安装iptables防火墙
yum install iptables-services #安装
vi /etc/sysconfig/iptables #编辑防火墙配置文件
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 10060:10090 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
:wq! #保存退出

# firewalld-cmd简单明了
# [[email protected] ROOT]# firewall-cmd --add-service=ftp --permanent
# success
# [[email protected] ROOT]# firewall-cmd --reload
# success

3) 启动iptables服务和自启
systemctl restart iptables.service #最后重启防火墙使配置生效
systemctl enable iptables.service #设置防火墙开机启动

说明:21端口是ftp服务端口;10060到10090是Vsftpd被动模式需要的端口,可自定义一段大于1024的tcp端口。

  1. 关闭SELINUX
    1
    2
    3
    4
    5
    6
    7
    8
    9
    vi /etc/selinux/config
    #SELINUX=enforcing #注释掉
    #SELINUXTYPE=targeted #注释掉
    SELINUX=disabled #增加

    :wq! #保存退出

    #或者
    setenforce 0 #使配置立即生效(临时)
  1. 安装vsftpd

    1
    2
    3
    4
    5
    6
    yum install -y vsftpd #安装vsftpd
    yum install -y psmisc net-tools systemd-devel libdb-devel perl-DBI #安装vsftpd虚拟用户配置依赖包

    #启动和自启
    systemctl start vsftpd.service #启动
    systemctl enable vsftpd.service #设置vsftpd开机启动
  2. 配置vsftp服务器

    cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf-bak #备份默认配置文件

执行以下命令进行设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sed -i "s/anonymous_enable=YES/anonymous_enable=NO/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#anon_upload_enable=YES/anon_upload_enable=NO/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#anon_mkdir_write_enable=YES/anon_mkdir_write_enable=NO/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#chown_uploads=YES/chown_uploads=NO/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#async_abor_enable=YES/async_abor_enable=YES/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#ascii_upload_enable=YES/ascii_upload_enable=YES/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#ascii_download_enable=YES/ascii_download_enable=YES/g" '/etc/vsftpd/vsftpd.conf'
sed -i "s/#ftpd_banner=Welcome to blah FTP service./ftpd_banner=Welcome to FTP service.Thanks/g" '/etc/vsftpd/vsftpd.conf'

#下面是关键点guest_username
echo -e "use_localtime=YES\nlisten_port=21\nchroot_local_user=YES\nidle_session_timeout=300
\ndata_connection_timeout=1\nguest_enable=YES\nguest_username=vsftpd
\nuser_config_dir=/etc/vsftpd/vconf\nvirtual_use_local_privs=YES
\npasv_min_port=10000\npasv_max_port=10100
\naccept_timeout=5\nconnect_timeout=1" >> /etc/vsftpd/vsftpd.conf

  1. 建立虚拟用户名单文件
1
2
3
4
5
6
7
8
9
10
11
12
13
touch /etc/vsftpd/virtusers
#编辑虚拟用户名单文件:(第一行账号,第二行密码,注意:不能使用root做用户名,系统保留)
vi /etc/vsftpd/virtusers
web1
123456
web2
123456
web3
123456
:wq! #保存退出
#或者
echo web > /etc/vsftpd/virtusers
echo 123456 > /etc/vsftpd/virtusers
  1. 生成虚拟用户数据文件

    1
    2
    db_load -T -t hash -f /etc/vsftpd/virtusers /etc/vsftpd/virtusers.db
    chmod 600 /etc/vsftpd/virtusers.db #设定PAM验证文件,并指定对虚拟用户数据库文件进行读取
  2. 在/etc/pam.d/vsftpd的文件头部加入以下信息(在后面加入无效
    修改前先备份 cp /etc/pam.d/vsftpd /etc/pam.d/vsftpdbak

    1
    2
    3
    vi /etc/pam.d/vsftpd
    auth sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/virtusers
    account sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/virtusers

    注意:如果系统为32位,上面改为lib,否则配置失败

  3. 新建系统用户vsftpd,用户目录为/home/wwwroot, 用户登录终端设为/bin/false(即使之不能登录系统)

    1
    2
    3
    useradd vsftpd -d /home/wwwroot -s /bin/false
    chown vsftpd:vsftpd /home/wwwroot -R
    chown vsftpd:nginx /home/wwwroot -R #如果虚拟用户的宿主用户为www,需要这样设置。(Nginx服务)
  4. 建立虚拟用户个人Vsftp的配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    mkdir /etc/vsftpd/vconf && cd /etc/vsftpd/vconf
    touch web1 web2 web3 #这里创建三个虚拟用户配置文件
    mkdir -p /home/wwwroot/web1/http/

    vi web1 #编辑用户web1配置文件,其他的跟这个配置文件类似
    local_root=/home/wwwroot/web1/http/
    write_enable=YES
    anon_world_readable_only=NO
    anon_upload_enable=YES
    anon_mkdir_write_enable=YES
    anon_other_write_enable=YES
    allow_writeable_chroot=YES
  5. 最后重启vsftpd服务器

    systemctl restart vsftpd.service

备注:

  • guest_username=vsftpd #指定虚拟用户的宿主用户(就是我们前面新建的用户)
  • guest_username=www #如果ftp目录是指向网站根目录,用来上传网站程序,可以指定虚拟用户的宿主用户为nginx运行账户www,可以避免很多权限设置问题
  • 至此,CentOS 7.0安装配置Vsftp服务器配置完成。


Ubuntu安装vsftpd

本文在Ubuntu Server 14.04 amd64系统测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#安装ftp
sudo apt-get install vsftpd
#配置vsftpd.conf
sudo vi /etc/vsftpd.conf
sudo gedit /etc/vsftpd.conf

#禁止匿名访问
anonymous_enable=NO
#接受本地用户
local_enable=YES
#允许上传
write_enable=YES
#用户只能访问限制的目录
chroot_local_user=YES
#设置固定目录,在结尾添加。如果不添加这一行,各用户对应自己的目录,当然这个文件夹自己建
local_root=/home/ftp

注意:pam_service_name=vsftpd,主要是进行认证的

添加ftp登录用户

1
2
3
4
5
6
7
8
9
10
11
12
sudo useradd -d /home/ftp -M ftpuser
sudo passwd ftpuser
#调整文件夹权限,这个是避免“500 OOPS: vsftpd: refusing to run with writable root inside chroot()”
sudo chmod a-w /home/ftp #所有用户取消写入权限(安全)
sudo mkdir /home/ftp/data

#这时候直接用useradd的帐号登录ftp会530 login incorrect
sudo nano /etc/pam.d/vsftpd
#auth required pam_shells.so #注释掉,貌似不是必须的

#重启vsftpd
sudo service vsftpd restart


2.配置文件

  1. vsftpd的配置文件说明:
1
2
3
* vsftpd.ftpusers:位于/etc目录下。它指定了哪些用户账户不能访问FTP服务器,例如root等。
* vsftpd.user_list:位于/etc目录下。该文件里的用户账户在默认情况下也不能访问FTP服务器,仅当vsftpd.conf配置文件里启用userlist_enable=NO选项时才允许访问。
* vsftpd.conf:位于/etc/vsftpd目录下。来自定义用户登录控制、用户权限控制、超时设置、服务器功能选项、服务器性能选项、服务器响应消息等FTP服务器的配置。
  • (1)用户登录控制
    • anonymous_enable=YES,允许匿名用户登录。
    • no_anon_password=YES,匿名用户登录时不需要输入密码。
    • local_enable=YES,允许本地用户登录。
    • deny_email_enable=YES,可以创建一个文件保存某些匿名电子邮件的黑名单,以防止这些人使用Dos攻击。
    • banned_email_file=/etc/vsftpd.banned_emails,当启用deny_email_enable功能时,所需的电子邮件黑名单保存路径(默认为/etc/vsftpd.banned_emails)。
  • (2)用户权限控制
    • write_enable=YES,开启全局上传权限。
    • local_umask=022,本地用户的上传文件的umask设为022(系统默认是077,一般都可以改为022)。anon_upload_enable=YES,允许匿名用户具有上传权限,很明显必须启用write_enable=YES,才可以使用此项。同时我们还必须建立一个允许ftp用户可以读写的目录(前面说过,ftp是匿名用户的映射用户账号)。
    • anon_mkdir_write_enable=YES,允许匿名用户有创建目录的权利。
    • chown_uploads=YES,启用此项,匿名上传文件的属主用户将改为别的用户账户,注意,这里建议不要指定root账号为匿名上传文件的属主用户!
    • chown_username=whoever,当启用chown_uploads=YES时,所指定的属主用户账号,此处的whoever自然要用合适的用户账号来代替。
    • chroot_list_enable=YES,可以用一个列表限定哪些本地用户只能在自己目录下活动,如果chroot_local_user=YES,那么这个列表里指定的用户是不受限制的。
    • chroot_list_file=/etc/vsftpd.chroot_list,如果chroot_local_user=YES,则指定该列表(chroot_local_user)的保存路径(默认是/etc/vsftpd.chroot_list)。
    • nopriv_user=ftpsecure,指定一个安全用户账号,让FTP服务器用作完全隔离和没有特权的独立用户。这是vsftpd系统推荐选项。
    • async_abor_enable=YES,强烈建议不要启用该选项,否则将可能导致出错!
    • ascii_upload_enable=YES;
    • ascii_download_enable=YES,默认情况下服务器会假装接受ASCⅡ模式请求但实际上是忽略这样的请求,启用上述的两个选项可以让服务器真正实现ASCⅡ模式的传输。

注意:启用ascii_download_enable选项会让恶意远程用户们在ASCⅡ模式下用“SIZE/big/file”这样的指令大量消耗FTP服务器的I/O资源。
这些ASCⅡ模式的设置选项分成上传和下载两个,这样我们就可以允许ASCⅡ模式的上传(可以防止上传脚本等恶意文件而导致崩溃),而不会遭受拒绝服务攻击的危险。

  • (3)用户连接和超时选项

    • idle_session_timeout=600,可以设定默认的空闲超时时间,用户超过这段时间不动作将被服务器踢出。
    • data_connection_timeout=120,设定默认的数据连接超时时间。
  • (4)服务器日志和欢迎信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
dirmessage_enable=YES,允许为目录配置显示信息,显示每个目录下面的message_file文件ftpd_banner=Welcome to blah FTP service,可以自定义FTP用户登录到服务器所看到的欢迎信息。 
xferlog_enable=YES,启用记录上传/下载活动日志功能。
xferlog_file=/var/log/vsftpd.log,可以自定义日志文件的保存路径和文件名,默认是/var/log/vsftpd.log。
anonymous_enable=YES 允许匿名登录
local_enable=YES 允许本地用户登录
write_enable=YES 开放本地用户写权限
local_umask=022 设置本地用户生成文件的掩码为022
#anon_upload_enable=YES 此项设置允许匿名用户上传文件
#anon_mkdir_write_enable=YES 开启匿名用户的写和创建目录的权限
dirmessage_enable=YES 当切换到目录时,显示该目录下的.message隐藏文件的内容
xferlog_enable=YES 激活上传和下载日志
connect_from_port_20=YES 启用FTP数据端口的连接请求
#chown_uploads=YES 是否具有上传权限. 用户由chown_username参数指定。
#chown_username=whoever 指定拥有上传文件权限的用户。此参数与chown_uploads联用。
#xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES 使用标准的ftpd xferlog日志格式
#idle_session_timeout=600 此设置将在用户会话空闲10分钟后被中断
#data_connection_timeout=120 将在数据连接空闲2分钟后被中断
#ascii_upload_enable=YES 启用上传的ASCII传输方式
#ascii_download_enable=YES 启用下载的ASCII传输方式
#ftpd_banner=Welcome to blah FTP service 设置用户连接服务器后显示消息
#deny_email_enable=NO 此参数默认值为NO。当值为YES时,拒绝使用banned_email_file参数指定文件中所列出的e-mail地址用户登录。
#banned_email_file=/etc/vd.banned_emails 指定包含拒绝的e-mail地址的文件.
#chroot_list_enable=YES 设置本地用户登录后不能切换到自家目录以外的别的目录
#chroot_list_file=/etc/vsftpd.chroot_list
#ls_recurse_enable=YES
pam_service_name=vsftpd 设置PAM认证服务的配置文件名称,该文件存放在/etc/pam.d/
userlist_enable=YES 此项配置/etc/vsftpd.user_list中指定的用户也不能访问服务器,若添加userlist_deny=No,则仅仅/etc/vsftpd.user_list文件中的用户可以访问,其他用户都不可以访问服务器。如过userlist_enable=NO,userlist_deny=YES,则指定使文件/etc/vsftpd.user_list中指定的用户不可以访问服务器,其他本地用户可以访问服务器。
listen=YES 指明VSFTPD以独立运行方式启动
tcp_wrappers=YES 在VSFTPD中使用TCP_Wrappers远程访问控制机制,默认值为YES


3.安全配置

  • vsftpd配置文件:/etc/vsftpd/vsftpd.conf
  • vsftpd默认匿名用户上传目录:/var/ftp/pub
    1
    ftp的密码为空,anonymous的密码为空或者guest

安全配置必须选项:

1
2
3
4
5
6
#不允许匿名访问登录的以及权限的管控(匿名用户的文件夹必须是777权限)))
anonymous_enable=NO
anon_world_readable_only=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO

本地用户登陆ftp

1
2
3
4
5
6
7
8
#接受本地用户
local_enable=YES
#允许上传
write_enable=YES
#用户只能访问限制的目录
chroot_local_user=YES
#设置固定目录在结尾添加。如果不添加这一行各用户对应自己的目录,当然这个文件夹自己建
local_root=/home/ftp

由于本地用户登陆ftp会出现信息泄露的问题,本地用户不止可以访问ftp站点的内容,还可以访问ftp服务器上的其他目录,解决办法就是用虚拟用户、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#创建FTP根目录及虚拟用户映射的系统用户
useradd -d /home/vftpuser -s /sbin/nologin vftpuser
#为保证其他用户可以访问,给予rwxr-xr-x权限:
chmod 755 /home/vftpuser
#建立虚拟FTP用户数据库文件。
db_load -T -t hash -f vuser_login.txt vuser_login.db
#找到认证文件的路径
Find / -name pam_userdb.so

#以下这些是关于vsftpd虚拟用户支持的重要配置项,
#默认vsftpd.conf中不包含这些设定项目,需要自己手动添加
guest_enable=YES #设定启用虚拟用户功能
guest_username=vsftpd #指定虚拟用户的宿主用户
user_config_dir=/etc/vsftpd/vuser_conf #设定虚拟用户个人vsftp的CentOS FTP服务文件存放路径
#为虚拟用户设置不同的权限
#指定用户独立的权限配置文件存放的目录:vim /etc/vsftpd/vsftpd.conf
user_config_dir=/etc/vsftpd/vsftpd_user_conf
#切换进入到该目录中:cd /etc/vsftpd/vsftpd_user_conf
#比如设置web默认是可读权限
anon_mkdir_write_enable=YES #允许用户创建文件
anon_world_readable_only=YES #只读
anon_upload_enable=YES #允许wang用户上传文件
anon_other_write_enable=YES #用户就具有修改和删除文件的权限了


4.入坑&出坑

  1. FTP登录时报错500 OOPS: chroot
    解决方法:关闭SElinux

    setenforce 0 #临时


  1. 500 OOPS: vsftpd: refusing to run with writable root inside chroot()
    解决方法:修改配置文件/etc/vsftpd/vsftpd.conf或者个人配置文件添加参数:

    allow_writeable_chroot=YES

从2.3.5之后,vsftpd增强了安全检查,如果用户被限定在了其主目录下,则该用户的主目录不能再具有写权限了!如果检查发现还有写权限,就会报该错误。
要修复这个错误,可以用命令chmod a-w /home/user去除用户主目录的写权限,注意把目录替换成你自己的。或者你可以在vsftpd的配置文件中增加下列项:allow_writeable_chroot=YES


0x02 命令解析&状态码

1.ftp 命令

描述:ftp 服务主要用于文件传输到服务器默认服务端口21进行命令传递, FTP命令是Internet用户使用最频繁的命令之一,熟悉并灵活应用FTP的内部命令,可以大大方便使用者并收到事半功倍之效。

基础语法:
描述: 将文件传送到运行 FTP 服务器服务(经常称为后台程序)的计算机以及将文件从该计算机传出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 语法
FTP [-v] [-d] [-i] [-n] [-g] [-s:filename] [-a] [-A] [-x:sendbuffer] [-r:recvbuffer] [-b:asyncbuffers] [-w:windowsize] [host]

# 参数
-v 显示远程服务器的全部响应,并提供数据传输的统计信息,即在程序运行时显示详细的处理信息。
-n 禁止在初始连接时自动登录。否则ftp 命令会搜索 $HOME/.netrc 登录项,该登录项描述了远程主机的登录和初始化过程。
-i 关闭多文件传输过程中的交互式提示。
-d 启用调试(但必须编辑 /etc/syslog.conf 文件并添加以下中的一项:user.info FileName 或 user.debug FileName)。
-g 禁用文件名通配(禁用文件名中的元字符拓展,即取消全局文件名)。
-s:filename 指定包含 FTP 命令的文本文件;命令在 FTP 启动后自动运行。
-a 在绑字数据连接时使用所有本地接口。
-A 匿名登录。
-x:send sockbuf 覆盖默认的 SO_SNDBUF 大小 8192。
-r:recv sockbuf 覆盖默认的 SO_RCVBUF 大小 8192。
-b:async count 覆盖默认的异步计数 3
-w:windowsize 覆盖默认的传输缓冲区大小 65535。
host 指定主机名称或要连接到的远程主机的 IP 地址。

Tips: 使用 Ctrl-C 中止命令。


FTP使用的内部命令如下(中括号表示可选项):

  • 0.?[cmd]:同help.
  • 23.help[cmd]:显示ftp内部命令cmd的帮助信息,如:help get。
  • 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类型传输方式。
  • 7.binary:使用二进制文件传输方式。
    • 【如果选择binary来传输数据,发送方与接送方不能改变文件的内容】
    • 【如果选择asciiL来传输数据,发送方将文本从字符集转换成标准的Ascii码后发送数据,而接收方将接受到的Ascii码转换成本方的计算机的字符集】
  • 6.bell:每个命令执行完毕后计算机响铃一次。
  • 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]:显示远程主机目录,并将结果存入本地文件。
  • 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符号(#)。
  • 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:将多个文件传输至远程主机(将所在文件夹下所有文件上传到FTP上)。
  • 37.newer file-name: 如果远程机中file-name的修改时间比本地硬盘同名文件的时间更近,则重传该文件。
  • 38.nlist[remote-dir][local-file]:显示远程主机目录的文件清单,并存入本地硬盘的local-file。
  • 40.ntrans[inchars[outchars]]:设置文件名字符的翻译机制,如ntrans1R,则文件名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 [email protected]
  • 72.verbose:同命令行的-v参数,即设置详尽报告方式,ftp 服务器的所有响 应都将显示给用户,缺省为on.


实际案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1.利用Explorer资源管理器进行登录FTP以及文件下载
ftp://username:[email protected]/path/file
ftp://weiyigeektemp:@192.168.12.31/application-prod.yml

# 2.交互式命令登录
ftp
> open ip 端口 # 默认为ASCII格式传送(文本文件时)
> 输入账号密码
> bin # bin指用二进制方式传送(可执行文件进)
> get pull.txt
> put push.txt
> bye

# 3.采用-s选项进行执行交换中的命令
# 格式
echo "ftp ip port" >>download.bat
echo "user" >>download.bat
echo "password" >>download.bat
echo "bin" >>download.bat
echo "get back.exe" >>download.bat
echo "bye" >>download.bat
ftp -s:download.bat
# 实例
echo open 192.168.1.31 21212 > ftp.tmp
echo weiyigeek >> ftp.tmp
echo password >> ftp.tmp
echo bin >> ftp.tmp
echo mkdir %currentday% >> ftp.tmp
echo cd %currentday% >> ftp.tmp
echo put %Backupfile% >> ftp.tmp
echo quit >> ftp.tmp
ftp -i -s:ftp.tmp

Tips : FTP文件传输类型有:ascii、binary、ebcdic、image、local M 和 tenex
– ascii:将文件传输类型设置为网络 ASCII。此类型为缺省值,即默认使用ascii方式进行传输。
– binary:将文件传输类型设置为二进制映像。需要使用binary方式传输的文件类型有ISO文件、可执行文件、压缩文件、图片等。此类型可能比 ASCII 传送更有效。
– ebcdic:将文件传输类型设为 EBCDIC。
– image:将文件传输类型设置为二进制映像。此类型可能比 ASCII 传送更有效。
– local M:将文件传输类型设置为本地。M 参数定义每计算机字位的十进制数。此参数没有缺省值。
– tenex:将文件传输类型设为 TENEX 机器需要的类型。

Tips : << 是使用即时文件重定向输入, EOF是即时文件的标志它必须成对出现,以标识即时文件的开始和结尾。值得注意的是EOF只是一个分界符标志,完全可以用abc, ! 等替换也一样的功能,只是大家都习惯用EOF来表示。
Tips : << 用法当shell看到<<的时候,它就会知道下一个词是一个分界符。在该分界符以后的内容都被当作输入,直到shell又看到该分界符(位于单独的一行)。因此分界符可以是定义的任何字符串。


2.tftp 命令

基础语法:

1
-i 指以二进制模式传送,如传送exe文件时用,如不加-i 则以ASCII模式(传送文本文件模式)进行传送

基础实例:

1
2
3
4
5
# 1.登陆后将“IP”服务器中server.exe下载到目标主机c:server.exe 
tftp -i 服务器IP get server.exe c:server.exe

# 2.登陆后上传本地c:server.exe文件至IP服务器
tftp -i 服务器IP put c:server.exe


3.状态码

  • 1xx - 肯定的初步答复 : 这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。
    • 110 重新启动标记答复。
    • 120 服务已就绪,在 nnn 分钟后开始。
    • 125 数据连接已打开,正在开始传输。
    • 150 文件状态正常,准备打开数据连接。

  • 2xx - 肯定的完成答复: 一项操作已经成功完成。客户端可以执行新命令。
    • 200 命令确定。
    • 202 未执行命令,站点上的命令过多。
    • 211 系统状态,或系统帮助答复。
    • 212 目录状态。
    • 213 文件状态。
    • 214 帮助消息。
    • 215 NAME 系统类型,其中,NAME 是 Assigned Numbers 文档中所列的正式系统名称。
    • 220 服务就绪,可以执行新用户的请求。
    • 221 服务关闭控制连接。如果适当,请注销。
    • 225 数据连接打开,没有进行中的传输。
    • 226 关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。
    • 227 进入被动模式 (h1,h2,h3,h4,p1,p2)。
    • 230 用户已登录,继续进行。
    • 250 请求的文件操作正确,已完成。
    • 257 已创建“PATHNAME”。

  • 3xx - 肯定的中间答复: 该命令已成功但服务器需要更多来自客户端的信息以完成对请求的处理。
    • 331 用户名正确,需要密码。
    • 332 需要登录帐户。
    • 350 请求的文件操作正在等待进一步的信息。

  • 4xx - 瞬态否定的完成答复: 该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。
    • 421 服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。
    • 425 无法打开数据连接。
    • 426 Connection closed; transferaborted.
    • 450 未执行请求的文件操作。文件不可用(例如,文件繁忙)。
    • 451 请求的操作异常终止:正在处理本地错误。
    • 452 未执行请求的操作。系统存储空间不够。

  • 5xx - 永久性否定的完成答复: 该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。
    • 500 语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。
    • 501 在参数中有语法错误。
    • 502 未执行命令。
    • 503 错误的命令序列。
    • 504 未执行该参数的命令。
    • 530 未登录。
    • 532 存储文件需要帐户。
    • 550 未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。
    • 551 请求的操作异常终止:未知的页面类型。
    • 552 请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。
    • 553 未执行请求的操作。不允许的文件名。


Q: 常见的 FTP 状态代码及其原因?
• 150 - FTP 使用两个端口:21 用于发送命令,20 用于发送数据。状态代码 150 表示服务器准备在端口 20 上打开新连接发送一些数据。
• 226 - 命令在端口 20 上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。
• 230 - 客户端发送正确的密码后,显示该状态代码。它表示用户已成功登录。
• 331 - 客户端发送用户名后,显示该状态代码。无论所提供的用户名是否为系统中的有效帐户,都将显示该状态代码。
• 426 - 命令打开数据连接以执行操作,但该操作已被取消,数据连接已关闭。
• 530 - 该状态代码表示用户无法登录,因为用户名和密码组合无效。如果使用某个用户帐户登录,可能键入错误的用户名或密码,也可能选择只允许匿名访问。如果使用匿名帐户登录,IIS 的配置可能拒绝匿名访问。
• 550 - 命令未被执行,因为指定的文件不可用。例如要 GET 的文件并不存在或试图将文件 PUT 到您没有写入权限的目录。


0x03 常用脚本

1) 实现FTP上传下载文件

描述: 在Linux中我们可以采用FTP进行文件得批量得上传和下载。

示例1.从FTP上单独或者批量下载文件到本地
环境说明:

  • FTP服务器:192.168.0.199
  • FTP路径:/ftphome/data
  • 本地路径:/local/data
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/sh
    ftp -v -n 192.168.0.199<<EOF
    user ftpuser ftppwd
    binary
    cd /ftphome/downloadData
    lcd /local/getDownloadData
    prompt
    get test.txt
    mget *
    bye
    EOF
    echo "download from ftp successfully"


示例2.从FTP上单独或者批量上传本地文件到服务器
环境说明:

  • FTP服务器:192.168.0.199
  • FTP路径:/ftphome/uploadData
  • 本地路径:/local/getUploadData
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/bin/sh
    PUTFILE = test.txt # 此处规定要上传得文件
    ftp -v -n 192.168.0.199<<EOF
    user ftpuser ftppwd
    binary
    hash
    cd /ftphome/uploadData
    lcd /ftphome/getUploadData
    prompt
    put $PUTFILE
    mput *
    bye
    #here document
    EOF
    echo "commit to ftp successfully"


示例3.sftp脚本自定登陆上传以及变量调用

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
FLAG=1
export backfile="text.json"
# $(ls --time=atime /home/weiyigeek-gitlab/logs/gitlab-backup/ | head -n 1)
if [[ ${FLAG} -eq 1 ]];then
lftp -u "gitlab","weiyigeekgitlab" sftp://192.168.12.31<<EOF
lcd /home/weiyigeek-gitlab/logs/gitlab-backup/
put ${backfile}
quit
bye
EOF
fi


0x04 入坑出坑

问题1.使用FTP报ftp: bind: Address already in use错误。

  • 问题描述: 使用ftp命令上传文件时出现如下错误Server cannot accept argument.ftp: bind: Address already in use
  • 问题原因:ftp使用了主动模式,导致防火墙将服务器到客户端的连接阻塞。(主动模式下,ftp服务器数据端口20要去连接客户端指定的数据端口。而,一般来讲外部系统到内部的端口连接会被防火墙阻塞)
  • 问题解决:使用ftp被动模式即可(被动模式下,服务器会启动一个监听数据的端口。让客户端的数据端口,去连接服务器监听数据的端口。)
    1
    2
    3
    # 开启被动模式 
    ftp -p -n ipadress port
    # -p enable passive mode (default for pftp)


问题2.使用FTPftp:500 Illegal PORT command.

  • 问题描述:ftp登录后使用ls命令出现如下提示
    1
    2
    ftp:500 Illegal PORT command.
    ftp: bind: Address already in use
  • 问题原因: 造成这个原因主要是是由于iptables防火墙不支持ip_nat_ftp/ip_conntrack_ftp模块。
  • 解决方式:
    1
    2
    3
    # 1.在linux的ftp服务器上执行下列命令即可解决
    modprobe ip_nat_ftp
    modprobe ip_conntrack_ftp