掘金 后端 ( ) • 2024-04-18 09:56

简介

FTP (file transfer protocol)协议用于传输文件,客户端通过用户名密码连接到服务器,认证通过后可以从服务器下载文件到本地,也可以上传本地文件到服务器。

连接类型

  • 控制连接:服务端监听21端口,等待客户连接,建立在这个端口上的连接成为控制连接,控制连接用来传输控制信息,如连接请求、传送请求等。

  • 数据连接:服务器端在接收到FTP客户发来的文件传输请求后,就创建了数据连接,数据连接用来传输文件数据

数据传输模式

  • 主动模式:客户端打开一个端口等待服务端连接进行数据传输,服务器使用的源端口是20端口,因为是外部的服务端主动发起连接,可能会被防火墙拦截。

  • 被动模式:服务端收到客户端请求后,打开一个随机端口,告诉客户端去连接这个端口,这种连接是客户端主动发起的,所以没有防火墙拦截的问题,大部分默认使用这种模式。

服务端

使用vsftpd在linux搭建ftp服务端,号称是最安全、最快的FTP服务器。vsftpd官网,这个留给大家去自己体验下。

我这里介绍下嵌入式环境下常用的一种方式,通过tcpsvd来启动ftpd服务程序的方式搭建ftp服务端。

tcpsvd命令

[root@localhost ftp]# tcpsvd -h
BusyBox v1.36.0 (2023-03-29 17:04:41 CST) multi-call binary.

Usage: tcpsvd [-hEv] [-c N] [-C N[:MSG]] [-b N] [-u USER] [-l NAME] IP PORT PROG

Create TCP socket, bind to IP:PORT and listen for incoming connections.
Run PROG for each connection.

        IP PORT         IP:PORT to listen on
        PROG ARGS       Program to run
        -u USER[:GRP]   Change to user/group after bind
        -c N            Up to N connections simultaneously (default 30)
        -b N            Allow backlog of approximately N TCP SYNs (default 20)
        -C N[:MSG]      Allow only up to N connections from the same IP:
                        new connections from this IP address are closed
                        immediately, MSG is written to the peer before close
        -E              Don't set up environment
        -h              Look up peer's hostname
        -l NAME         Local hostname (else look up local hostname in DNS)
        -v              Verbose

Environment if no -E:
PROTO='TCP'
TCPREMOTEADDR='ip:port' ('[ip]:port' for IPv6)
TCPLOCALADDR='ip:port'
TCPORIGDSTADDR='ip:port' of destination before firewall
        Useful for REDIRECTed-to-local connections:
        iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080
TCPCONCURRENCY=num_of_connects_from_this_ip
If -h:
TCPLOCALHOST='hostname' (-l NAME is used if specified)
TCPREMOTEHOST='hostname'

ftpd命令

[root@localhost ftp]# ftpd --help
BusyBox v1.36.0 (2023-03-29 17:04:41 CST) multi-call binary.

Usage: ftpd [-wvS] [-a USER] [-t SEC] [-T SEC] [DIR]

FTP server. Chroots to DIR, if this fails (run by non-root), cds to it.
It is an inetd service, inetd.conf line:
        21 stream tcp nowait root ftpd ftpd /files/to/serve
Can be run from tcpsvd:
        tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve

        -w      Allow upload
        -A      No login required, client access occurs under ftpd's UID
        -a USER Enable 'anonymous' login and map it to USER
        -v      Log errors to stderr. -vv: verbose log
        -S      Log errors to syslog. -SS: verbose log
        -t,-T N Idle and absolute timeout

使用方式

tcpsvd -vE 0.0.0.0 21 ftpd -w /

  • tcpsvd 启动一个监听服务
  • -v 详细输出日志
  • -E 不使用指定环境变量
  • 0.0.0.0 指定监听的IP地址
  • 21 指定的监听端口号
  • ftpd 指定服务程序
  • -w 允许文件上传(ftpd参数)
  • / 指定ftp目录(ftpd参数)

客户端

使用MobaXterm作为客户端进行测试,当然也可以使用其他的ftp客户端软件,如filezillawinscp

连接ftp服务器

输入ftp服务器IP地址、用户、端口等信息。

image.png

下载文件

选择需要的文件,点击下载即可。

image.png

上传文件

点击上传,从本地选择文件,点击打开即可。

image.png

协议分析

  • 抓包:tcpdump -i eno2 -envv port 21 -w xf_ftp.pcap
  • wireshark通过追踪流得到ftp交互过程数据
  • 格式USER <SP> <username> <CRLF>空格分隔符,回车换行\r\n结束

连接认证

image.png

// 220	Service ready for new user.(服务端-对于新用户已经准备就绪)
220 Operation successful
// USER RFC 959 Authentication username. (客户端-认证用户名)
USER root
// 331 User name okay, need password. (服务端-用户名可以,需要密码)
331 Specify password
// PASS RFC 959 Authentication password. (客户端-认证密码)
PASS wisdom
// 230 User logged in, proceed. (服务端-用户登录成功)
230 Operation successful
// FEAT RFC 2389 Get the feature list implemented by the server. (客户端-获取服务端特性列表)
FEAT
// 211	System status, or system help reply.(服务端-系统状态回应)
211-Features:
// EPSV	RFC 2428	Enter extended passive mode.(服务端-进入扩展被动模式)
EPSV
// PASV	RFC 959	Enter passive mode.(进入被动模式)
PASV
// REST	RFC 3659	Restart transfer from the specified point.(从指定的点重新传输)
REST STREAM
// MDTM	RFC 3659	Return the last-modified time of a specified file.(返回文件最近修改时间)
MDTM
// SIZE	RFC 3659	Return the size of a file.(返回文件大小)
SIZE
// 211	System status, or system help reply.(服务端-成功)
211 Ok
// CWD	RFC 697	Change working directory.(客户端-改变工作目录)
CWD .
// 250	Requested file action okay, completed.(服务端-请求文件操作成功)
250 Operation successful
// PWD	RFC 959	Print working directory. Returns the current directory of the host.(客户端-打印当前目录)
PWD
// 257	"PATHNAME" created.(服务端-已经创建)
257 "/"
// CWD	RFC 697	Change working directory.(客户端-改变工作目录)
CWD /

250 Operation successful

PWD

257 "/"

PWD

257 "/"

CWD /

250 Operation successful
// TYPE	RFC 959	Sets the transfer mode (ASCII/Binary).(客户端-设置传输模式为ASCII)
TYPE A

200 Operation successful
// PASV	RFC 959	Enter passive mode.(客户端-进入被动模式)
PASV
// 227	Entering Passive Mode (h1,h2,h3,h4,p1,p2).(服务端-进入被动模式,指定了IP和端口)
227 PASV ok (192,168,13,174,165,9)
// LIST	RFC 959	Returns information of a file or directory if specified, else information of the current working directory is returned.(客户端-返回指定文件信息)
LIST
// 150	File status okay; about to open data connection.(服务端-文件状态OK,可以打开数据连接)
150 Directory listing
// 226	Closing data connection. Requested file action successful (for example, file transfer or file abort).(服务端-关闭数据连接)
226 Operation successful

CWD /

250 Operation successful

421 Timeout

文件下载

RETR 下载指定文件(RETR RFC 959 Retrieve a copy of the file image.png

参考

  • https://www.colasoft.com.cn/download/document/1-2.php
  • https://www.rfc-editor.org/rfc/rfc959
  • https://en.wikipedia.org/wiki/File_Transfer_Protocol
  • https://en.wikipedia.org/wiki/List_of_FTP_commands
  • https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes