FTP主动模式和被动模式学习笔记

时间:2023-02-15 15:09:39

关于FTP,有被动模式和主动模式两种,有人说是验证模式,我不太认同,但懒得查资料,不想咬文嚼字,纠结这种事情。下面简单从自己理解的角度来记录一下两种模式的学习笔记。

1、被动模式

代码流程:
客户端:发PASV\r\n命令到21端口
服务器:通过21端口向客户端发数据通道端口(数据通道端口由服务器生产)
客户端:使用数据通道端口重新连接服务器,connect会创建新的socket,之后数据通道使用该socket

PASV客户端实例:

latelee@localhost:~$ ftp 192.168.18.88
Connected to 192.168.18.88.
220 Serv-U FTP Server v6.0 for WinSock ready...
Name (192.168.18.88:latelee): latelee
331 User name okay, need password.
Password:
230 User logged in, proceed.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive // pasv模式
Passive mode on.
ftp> ls
227 Entering Passive Mode (192,168,18,88,25,172)
150 Opening ASCII mode data connection for /bin/ls.
drw-rw-rw-   1 user     group           0 May  4 18:04 .
drw-rw-rw-   1 user     group           0 May  4 18:04 ..
drw-rw-rw-   1 user     group           0 May  4 18:22 test
226 Transfer complete.
ftp> LIST // 无此命令
?Invalid command
ftp> list // 无此命令
?Invalid command

服务器对应命令:

Connected to 192.168.18.111 (Local address 192.168.18.88)
220 Serv-U FTP Server v6.0 for WinSock ready...
USER latelee
331 User name okay, need password.
PASS xxxxx
User LATELEE logged in
230 User logged in, proceed.
SYST
215 UNIX Type: L8
PASV
227 Entering Passive Mode (192,168,18,88,44,213)
LIST
150 Opening ASCII mode data connection for /bin/ls.
226 Transfer complete.
QUIT
221 Goodbye!
Closing connection for user LATELEE (00:00:15 connected)

二、主动模式

代码流程:
客户端:生成随机的大于1024的端口NUM,发PORT A,B,C,D,n,m\r\n命令到21端口(其中A,B,C,D为本机IP,n=NUM/256,m=NUM%256)
服务器:通过21端口向客户端发送是否成功的信息(成功:200 PORT Command successful.)
客户端:监听上面生成的NUM端口,如有连接,则Accept得到新的socket,数据通道即使用该socket。
注:资料2的文章说在监听NUM+1的端口,但我实际测试使用NUM也可以。另外,“PORT A,B,C,D,n,m\r\n”最后的回车换行和之前的字符是不能有空格的!因为写代码时是用sprintf组装字段的,习惯性多带个空格。正确的是示例如下:

sprintf(buffer, "PORT %d,%d,%d,%d,%d,%d\r\n", ip1, ip2, ip3, ip4, port>>8, port&0xFF);

这个问题搞了差不多半个钟头才意识到。

实然想起上个月搞网络问题打印PHY寄存器,就是因为没有使能网络设备直接访问寄存器挂掉,当时是晚上7点,大多数人都回家吃饭了,心又急,脑子一时短路,来回验证超过半小时后才发现是这样原因。程序员对细节不能不注意。我相信有很多工程会因为将“==”误写为“=”或者因为某些括号等等问题导致debug花费大量时间。

主动模式客户端实例

latelee@localhost:~$ ftp 192.168.18.88
Connected to 192.168.18.88.
220 Serv-U FTP Server v6.0 for WinSock ready...
Name (192.168.18.88:latelee): latelee
331 User name okay, need password.
Password:
230 User logged in, proceed.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT Command successful.
150 Opening ASCII mode data connection for /bin/ls.
drw-rw-rw-   1 user     group           0 May  4 18:04 .
drw-rw-rw-   1 user     group           0 May  4 18:04 ..
drw-rw-rw-   1 user     group           0 May  6 11:24 test
226 Transfer complete.
ftp> LIST
?Invalid command
ftp> list
?Invalid command
ftp> 

服务器对应命令:

Connected to 192.168.18.111 (Local address 192.168.18.88)
220 Serv-U FTP Server v6.0 for WinSock ready...
USER latelee
331 User name okay, need password.
PASS xxxxx
User LATELEE logged in
230 User logged in, proceed.
SYST
215 UNIX Type: L8
PORT 192,168,18,111,175,229
200 PORT Command successful.
LIST
150 Opening ASCII mode data connection for /bin/ls.
226 Transfer complete.
QUIT
221 Goodbye!

三、命令一览

下面命令是从网上一个开源工程头文件找到的,我觉得很简洁,记录于此。其中<CRLF>对应代码“\r\n”,<SP>表示有空格,其它没有出现<SP>说明是没有空格的。一般FTP命令由实际命令字符和回车换行组成,这两部分是没有空格的。但以前搞的时候,发现PASV命令与“\r\n”有无空格都能正常执行,不过为了不出意外,最好不带空格。

FTP commands - Overview

simple commands
  CDUP <CRLF>
  QUIT <CRLF>
  REIN <CRLF>
  PASV <CRLF>
  STOU <CRLF>
  ABOR <CRLF>
  PWD  <CRLF>
  SYST <CRLF>
  NOOP <CRLF>
  PORT <SP> <host-port> <CRLF>
  TYPE <SP> <type-code> <CRLF>
  CWD  <SP> <pathname> <CRLF>
  MKD  <SP> <pathname> <CRLF>
  SITE <SP> <string> <CRLF>
  HELP [<SP> <string>] <CRLF>
  DELE <SP> <pathname> <CRLF>
  RMD  <SP> <pathname> <CRLF>
  STRU <SP> <structure-code> <CRLF>
  MODE <SP> <mode-code> <CRLF>
  STAT [<SP> <pathname>] <CRLF>
  ALLO <SP> <decimal-integer>
      [<SP> R <SP> <decimal-integer>] <CRLF>
  SMNT <SP> <pathname> <CRLF>

commands for logon sequence
  USER <SP> <username> <CRLF>
  PASS <SP> <> password <CRLF>
  ACCT <SP> <account-information> <CRLF>

commands for renaming
  RNFR <SP> <pathname> <CRLF>
  RNTO <SP> <pathname> <CRLF>

  RETR <SP> <pathname> <CRLF>
  STOR <SP> <pathname> <CRLF>
  APPE <SP> <pathname> <CRLF>
  REST <SP> <marker> <CRLF>
  LIST [<SP> <pathname>] <CRLF>
  NLST [<SP> <pathname>] <CRLF>

non RFC-Commands
  SIZE <SP> <pathname> <CRLF>
  MDTM <SP> <pathname> <CRLF>

FTP命令注解可参考:http://www.nsftools.com/tips/RawFTP.htm


参考资料: