通过 Python 的 ftplib 在防火墙后连接到 FTP 时控制正在使用的端口号
Controlling port numbers in use when connecting to FTP via Python's ftplib behind a firewall
我正在尝试从仅接受端口范围 6100–6200 的输出的防火墙后面连接到 FTP 服务器。我(相当天真,但基于对 the documentation 的阅读)正在尝试:
from ftplib import FTP
host_address="the.ftp.ip.address"
ftp = FTP()
ftp.connect(host=hostaddress, source_address=("127.0.0.1", 6100))
但这给出了错误:
In [42]: ftp = FTP(host_address, source_address=('127.0.0.1', 6100))
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-42-071ac06087bd> in <module>
----> 1 ftp = FTP(destination, source_address=('127.0.0.1', 6100))
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/ftplib.py in __init__(self, host, user, passwd, acct, timeout, source_address, encoding)
117 self.timeout = timeout
118 if host:
--> 119 self.connect(host)
120 if user:
121 self.login(user, passwd, acct)
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/ftplib.py in connect(self, host, port, timeout, source_address)
154 self.source_address = source_address
155 sys.audit("ftplib.connect", self, self.host, self.port)
--> 156 self.sock = socket.create_connection((self.host, self.port), self.timeout,
157 source_address=self.source_address)
158 self.af = self.sock.family
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/socket.py in create_connection(address, timeout, source_address)
841 if err is not None:
842 try:
--> 843 raise err
844 finally:
845 # Break explicitly a reference cycle
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/socket.py in create_connection(address, timeout, source_address)
829 if source_address:
830 sock.bind(source_address)
--> 831 sock.connect(sa)
832 # Break explicitly a reference cycle
833 err = None
OSError: [Errno 22] Invalid argument
在同一台机器上,我可以使用 curl:
成功列出文件
curl --ftp-port :6100-6200 --list-only $ftpserver
如何使用 ftplib 绕过本地防火墙连接到常规(即端口 21)FTP 服务器?
curl --ftp-port
switch 启用 active 模式并设置本地 listening 端口用于 传入数据 个连接。
这不是您的代码所做的。您的代码使用 passive 模式并设置 source ports of outgoing control connection.
首先,如果您需要使用主动模式,这通常意味着您的 FTP 服务器或防火墙配置错误。主动模式实际上比被动模式需要更多的防火墙配置。你应该使用被动模式。这是一种工作量更少、功能更强大的解决方案。
请注意,在被动模式下,您无法控制使用的端口,因为那是服务器的决定,而不是客户端的。您必须配置本地防火墙(如果有)以允许服务器正在使用的数据连接端口。
如果确实需要使用主动模式,请使用FTP.set_pasv
。
ftp = FTP()
ftp.set_pasv(False)
ftp.connect(host=hostaddress)
ftplib 不允许您控制活动模式的端口。您必须在 ftplib FTP
class 中编辑 makeport
方法或在您的代码中覆盖它。让它监听 sock.bind
:
中的特定端口
- How can I specify the client's data port for a ftp server in active mode?
我正在尝试从仅接受端口范围 6100–6200 的输出的防火墙后面连接到 FTP 服务器。我(相当天真,但基于对 the documentation 的阅读)正在尝试:
from ftplib import FTP
host_address="the.ftp.ip.address"
ftp = FTP()
ftp.connect(host=hostaddress, source_address=("127.0.0.1", 6100))
但这给出了错误:
In [42]: ftp = FTP(host_address, source_address=('127.0.0.1', 6100))
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-42-071ac06087bd> in <module>
----> 1 ftp = FTP(destination, source_address=('127.0.0.1', 6100))
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/ftplib.py in __init__(self, host, user, passwd, acct, timeout, source_address, encoding)
117 self.timeout = timeout
118 if host:
--> 119 self.connect(host)
120 if user:
121 self.login(user, passwd, acct)
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/ftplib.py in connect(self, host, port, timeout, source_address)
154 self.source_address = source_address
155 sys.audit("ftplib.connect", self, self.host, self.port)
--> 156 self.sock = socket.create_connection((self.host, self.port), self.timeout,
157 source_address=self.source_address)
158 self.af = self.sock.family
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/socket.py in create_connection(address, timeout, source_address)
841 if err is not None:
842 try:
--> 843 raise err
844 finally:
845 # Break explicitly a reference cycle
~/SOFTWARE/anaconda3/envs/GDAL/lib/python3.9/socket.py in create_connection(address, timeout, source_address)
829 if source_address:
830 sock.bind(source_address)
--> 831 sock.connect(sa)
832 # Break explicitly a reference cycle
833 err = None
OSError: [Errno 22] Invalid argument
在同一台机器上,我可以使用 curl:
成功列出文件curl --ftp-port :6100-6200 --list-only $ftpserver
如何使用 ftplib 绕过本地防火墙连接到常规(即端口 21)FTP 服务器?
curl --ftp-port
switch 启用 active 模式并设置本地 listening 端口用于 传入数据 个连接。
这不是您的代码所做的。您的代码使用 passive 模式并设置 source ports of outgoing control connection.
首先,如果您需要使用主动模式,这通常意味着您的 FTP 服务器或防火墙配置错误。主动模式实际上比被动模式需要更多的防火墙配置。你应该使用被动模式。这是一种工作量更少、功能更强大的解决方案。
请注意,在被动模式下,您无法控制使用的端口,因为那是服务器的决定,而不是客户端的。您必须配置本地防火墙(如果有)以允许服务器正在使用的数据连接端口。
如果确实需要使用主动模式,请使用FTP.set_pasv
。
ftp = FTP()
ftp.set_pasv(False)
ftp.connect(host=hostaddress)
ftplib 不允许您控制活动模式的端口。您必须在 ftplib FTP
class 中编辑 makeport
方法或在您的代码中覆盖它。让它监听 sock.bind
:
- How can I specify the client's data port for a ftp server in active mode?