本文将分为四个部分。第一部分阐述“什么是内网架设FTP”的问题。第二部分分析FTP协议的原理。第三部分阐述在内网中架设FTP服务器时会遇到的问题以及解决方法,使外网的用户能够访问位于内网的FTP服务器。第四部分为总结。建议读者能够将这五部分全部读完。如果只想要一个快速安装指南,那么请阅读第一部分和第四部分。
本文所使用的FTP服务器为proftpd。
内网FTP服务器的概念
设想下面的这种环境:几台计算机组成一个局域网,该局域网中拥有一台DHCP服务器负责为局域网中每台计算机分配IP地址。其中有一台计算机(或网络设备)作为网关(可以与DHCP服务器为同一台设备),网关通过拨号或其他方式连接到Internet,获取一个真实IP地址。局域网内的计算机通过网关的转发来实现与Internet的连接。我们定义该局域网内部为内网,相对地,定义Internet为外网。
举个例子,假设我们拥有两台计算机A、B和一个拥有拨号和DHCP功能的网关G。各自的网络配置如下:
网关G:
局域网IP地址:192.168.0.1(由网关硬件指定)
局域网子网掩码:255.255.255.0(由网关硬件指定)
广域网IP地址:12.34.56.78(拨号之后获得)
计算机A:
局域网IP地址:192.168.0.10(通过网关的DHCP功能获得)
局域网子网掩码:255.255.255.0(通过网关的DHCP功能获得)
网关:192.168.0.1(通过网关的DHCP功能获得)
计算机B:
局域网IP地址:192.168.0.11(通过网关的DHCP功能获得)
局域网子网掩码:255.255.255.0(通过网关的DHCP功能获得)
网关:192.168.0.1(通过网关的DHCP功能获得)
这样,从A、B发出的所有网络请求都会被发送到网关G(192.168.0.1),网关再将这些请求变换之后通过12.34.56.78发送到Internet,以实现A、B与Internet的连接。
需要提醒一点的是,你的网关必须拥有端口映射(Port Mapping)的功能(也称转发,Forwarding),这是下文架设服务器的先决条件。所谓端口映射功能,就是指网关能够将从外网发送到网关的指定端口的包转发到内网中指定的IP地址上。举个例子,假如我们定义了如下一条规则:将端口21映射到192.168.0.10上。那么
从外网发送到网关的一个包,其信息为
源地址:200.12.34.56:7890,目的地址:12.34.56.78:21
那么网关将修改该包的目的地址,结果为
源地址:200.12.34.56:7890,目的地址:192.168.0.10:21
并将该包发送到局域网中的192.168.0.10上。这样对于192.168.0.10来说,这个包仿佛是从Internet上直接发给自己的一样。
FTP协议原理
一般我们说,FTP协议使用TCP端口21。实际上这这并不准确;FTP协议使用TCP的21端口传送的是控制命令,同时使用随机端口来传送数据。也就是说,下载一个文件至少需要在客户端与服务器之间建立两个TCP连接,这两个连接分别称为控制连接和数据连接。
控制连接总是由客户端主动连接服务器的21端口来建立的;而数据连接则不一定。根据数据连接的建立方式的不同,FTP传送方式可分为主动方式和被动方式两种。主动方式下,服务器连接客户端的某个端口以建立数据连接;被动方式下,客户端连接服务器的某个端口来建立数据连接。
主动方式的连接过程如下:
- 客户端用随机端口连接服务器的21端口,建立控制连接,并发送用户名和密码进行登录。
- 客户端打开一个随机端口P进行监听,并通过控制连接将自己的IP地址和P端口的信息通知服务器。
- 服务器用自己的随机端口连接客户端的端口P,建立数据连接,并进行数据传送。
- 数据传送完毕之后,数据连接断开。
- 客户端通过控制连接发送结束命令,以断开控制连接,FTP交互过程结束。
被动方式的连接过程如下:
- 客户端用随机端口连接服务器的21端口,建立控制连接,并发送用户名和密码进行登录。(与主动方式相同)
- 客户端通过控制连接通知服务器使用被动方式。
- 服务器选择一个随机端口P进行监听,并通过控制连接将自己的IP地址和P端口的信息通知客户端。
- 客户端用自己的随机端口连接服务器的端口P,建立数据连接,并进行数据传送。
- 数据传送完毕之后,数据连接断开。(与主动方式相同)
- 客户端通过控制连接发送结束命令,以断开控制连接,FTP交互过程结束。(与主动方式相同)
举个实际的例子来说明。下文中以S:开头的为服务器返回的信息,C:开头的为客户端命令。 主动方式:
S: 220 ProFTPD 1.2.10 Server(控制连接建立,服务器返回欢迎信息)
C: USER foo(发送用户名)
S: 331 Password required for foo.
C: PASS mypassword (发送密码)
S: 230 User foo logged in. (登录成功)
C: SYST (获取服务器类型)
S: 215 UNIX Type: L8
C: PWD (获取当前目录)
S: 257 "/" is current directory.
C: PORT 192,168,0,11,10,171 (客户端监听端口2731,并将IP地址和端口2731通过PORT命令通知服务器。2731为10*256+171)
S: 200 PORT command successful
C: TYPE A (设置传输方式为文本方式)
S: 200 Type set to A
C: LIST (发出获取文件列表的命令)
S: 150 Opening ASCII mode data connection for file list (服务器尝试连接客户端的2731端口以建立数据连接)
(通过数据连接发送文件列表……)
S: 226 Transfer complete. (文件列表传送完毕,数据连接断开)
C: QUIT (退出命令)
被动方式:
S: 220 ProFTPD 1.2.10 Server(控制连接建立,服务器返回欢迎信息)
C: USER foo(发送用户名)
S: 331 Password required for foo.
C: PASS mypassword (发送密码)
S: 230 User foo logged in. (登录成功)
C: SYST (获取服务器类型)
S: 215 UNIX Type: L8
C: PWD (获取当前目录)
S: 257 "/" is current directory.
C: PASV (通知服务器使用被动方式)
S: 227 Entering Passive Mode (192,168,0,10,132,29).
(服务器监听端口33821,并将IP地址和端口33821通过PORT命令通知服务器。33821为132*256+29)
C: TYPE A (设置传输方式为文本方式)
S: 200 Type set to A
C: LIST (发出获取文件列表的命令)
S: 150 Opening ASCII mode data connection for file list (客户端尝试连接服务器的33821端口以建立数据连接)
(通过数据连接发送文件列表……)
S: 226 Transfer complete. (文件列表传送完毕,数据连接断开)
C: QUIT (退出命令)
内网FTP服务器的问题及解决方案
在这里我们沿用第一部分的网络实例,并假设FTP服务器架设在计算机A(192.168.0.10)上。
如何使外网的客户端能够与内网的FTP服务器建立控制连接
由于控制连接的服务器端端口为21,因此我们只需要在网关的端口映射上添加一条规则,将21端口映射到192.168.0.10即可。
如何建立数据连接
在主动方式下,数据连接由服务器发起,相当于内网的服务器主动去连接外网的客户端,这种连接可以穿过网关正常建立,因此不需要做任何特殊设置即可实现。问题是被动连接。由于被动方式下服务器会监听随机端口并需要将自己的IP地址和端口号通知客户端,这样就产生了以下两个问题:
- 服务器仅知道自己的内网IP地址(192.168.0.10),它会将这个IP地址通知给外网的客户端,而客户端从外网是无法连接这个内网IP地址的(客户端不知道该如何路由);
- 服务器需要监听随机端口,范围为1024-65535,出于安全起见,也考虑到可能存在其它的服务也使用该范围内的端口,因此不可能在网关上将这些端口全部映射给192.168.0.10。
由于以上的问题的存在,我们经常可以看到连接服务器时下方的连接日志停在
150 Opening ASCII mode data connection for file list
处迟迟不动,这就是因为被动数据连接无法建立。
对此proftpd提供了如下的解决方案。
-
通过MasqueradeAddress命令指定服务器通知给客户端的IP地址。即使得FTP服务器不再将自己的内网IP地址192.168.0.10通知给客户端,而是将MasqueradeAddress命令指定的IP地址通知给客户端。在proftpd.conf中添加如下命令:
MasqueradeAddress 12.34.56.78 (指定为网关的外网地址)
如果网关的外网地址不固定(例如通过拨号获取IP的情况),那么你需要为你的网关申请一个动态域名,并用MasqueradeAddress命令将域名指定给服务器。
MasqueradeAddress myftpserver.vicp.net
-
通过PassivePorts命令来限制被动方式下监听的端口的范围。例如
PassivePorts 60000 65535
这样服务器在被动方式下将仅使用60000-65535之间的端口,而不是原来的1024-65535。然后在网关上添加规则,将60000-65535的所有端口映射到192.168.0.10上。
这样,外网的客户端就可以正常访问FTP服务器了。
但是上面的方法并不是十全十美的。我们用MasqueradeAddress命令强制FTP通知网关的IP地址,这对于客户端位于外网的情况下是正确的,但是当客户端位于内网时,客户端可能会无法解析网关的IP地址,导致无法建立数据连接。
总结
内网架设FTP服务器的方法:
-
在proftpd.conf中利用MasqueradeAddress命令将网关的IP地址或域名指定给FTP服务器,例如
MasqueradeAddress myftpserver.vicp.net
或
MasqueradeAddress 12.34.56.78
然后通过PassivePorts命令来限制被动方式下监听的端口的范围,例如
PassivePorts 60000 65535
-
在网关的端口映射上将第一步中指定的端口范围(例中为60000-65535)以及FTP端口21映射到FTP服务器的内网地址上。
|