我正在尝试连接到防火墙后面的 FTP 服务器,该服务器仅允许 6100-6200 范围内的传入连接。我已经成功连接到该服务器,如下所示curl
:
curl --ftp-port :6100-6200 --list-only ftp.server
但我想通过 Python 更友好地使用其他客户端来重现此curl 命令的行为。原则上是 Linux 的ftp
,但如果有人提出一个好的选择,我愿意接受其他选择。我尝试了 ftplib 但似乎该库不允许您选择端口;我试过了不成功。
目前我无法让它工作ftp
:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive
Passive mode on.
ftp> ls
227 Entering Passive Mode (XXX,XXX,XXX,XXX,202,251).
ftp: connect: Connection refused
同一组命令在我的笔记本电脑上运行,因此很明显问题出在防火墙上。
如何强制ftp
协商 6100-6200 范围内的端口中的数据连接,从而模拟 的行为curl
?
答案1
当您以被动模式使用 FTP 时,服务器告诉客户端要使用哪个(服务器端)数据端口。众所周知的 FTP 协议无法让客户端向服务器端表达要使用哪个端口范围的请求。可能有一些扩展可以改变这种情况,但这些扩展不一定得到广泛支持。
在您的示例中,消息
227 Entering Passive Mode (XXX,XXX,XXX,XXX,202,251).
直接来自 FTP 服务器,因为它告诉客户端:“我正在侦听来自您的 IP 地址 XXX.XXX.XXX.XXX,端口 51683 的数据连接”(= 202
*256 + 251
)。
每个 TCP 连接都有两个端口号:本地端口号和远程端口号。通常,传出连接仅选择操作系统指定的端口范围中的第一个空闲本地端口用于传出连接,并且根据正在使用的服务指定远程端口。在被动 FTP 的情况下,服务器将根据其配置选择远程端口,并以 FTP 227 响应的形式告诉客户端。
在防火墙中处理被动FTP通常有两种方法:
a) 防火墙和 FTP 服务器需要协同配置,以接受/使用特定范围的端口进行被动 FTP 数据连接,因此服务器甚至不会尝试选择防火墙不允许通过的端口,
b) 防火墙需要侦听 FTP 命令通道流量,确定用于每个数据连接的端口号,并使用命令通道上声明的端口号动态允许 FTP 客户端和服务器之间的被动 FTP 数据连接。
如果您使用的是 Linux iptables
/netfilter
防火墙,这正是 FTP 协议特定的 conntrack 扩展模块的作用。你只需要告诉它允许监听哪些控制连接,因为以前监听通过防火墙系统的所有 FTP 控制连接的策略结果被坏人利用,现在这样的扩展将不再被利用。自动使用。详情请参阅此页面或者这个问题在 U&L SE 上。
curl
实际上使用FTP被动模式默认情况下,但是当您使用该--ftp-port
选项时,它会切换为主动模式。从手册页(突出显示我的):
-P, --ftp 端口
(FTP) 在使用 FTP 连接时反转默认发起者/侦听者角色。该选项使curl 使用主动模式。然后,curl 告诉服务器连接回客户端指定的地址和端口,而被动模式则要求服务器设置要连接的 IP 地址和端口。
关于 Python 和ftplib
,请注意你提到的问题已经有 10 多年历史了,现在 Marcus Müller 添加了一个新答案:
从 Python 3.3 开始,
ftplib
建立连接的函数带有一个source_addr
参数,允许您准确地执行此操作。