Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python FTP应用程序中的代理_Python_Proxy_Ftp_Ftplib - Fatal编程技术网

Python FTP应用程序中的代理

Python FTP应用程序中的代理,python,proxy,ftp,ftplib,Python,Proxy,Ftp,Ftplib,我正在用Python ftplib开发一个FTP客户端。如何向其添加代理支持(我见过的大多数FTP应用程序似乎都有代理支持)?我特别考虑袜子代理,但也考虑其他类型。。。FTP,HTTP(甚至可以在FTP程序中使用HTTP代理吗?) 有什么办法吗?标准模块ftplib不支持代理。似乎唯一的解决方案是根据源代码编写自己的自定义版本的ftplib 取决于代理,但常用的方法是ftp到代理,然后使用 目标服务器的用户名和密码 例如,对于ftp.example.com: 服务器地址:proxyserver(

我正在用Python ftplib开发一个FTP客户端。如何向其添加代理支持(我见过的大多数FTP应用程序似乎都有代理支持)?我特别考虑袜子代理,但也考虑其他类型。。。FTP,HTTP(甚至可以在FTP程序中使用HTTP代理吗?)


有什么办法吗?

标准模块
ftplib
不支持代理。似乎唯一的解决方案是根据源代码编写自己的自定义版本的
ftplib

取决于代理,但常用的方法是ftp到代理,然后使用 目标服务器的用户名和密码

例如,对于ftp.example.com:

服务器地址:proxyserver(或使用ftp从打开proxyserver)
用户:anonymous@ftp.example.com
密码:密码
在Python代码中:

from ftplib import FTP
site = FTP('my_proxy')
site.set_debuglevel(1)
msg = site.login('anonymous@ftp.example.com', 'password')
site.cwd('/pub')
您可以在
urllib2
中使用

ph = urllib2.ProxyHandler( { 'ftp' : proxy_server_url } )
server= urllib2.build_opener( ph )

我也遇到了同样的问题,需要使用ftplib模块(而不是用URLlib2重写所有脚本)

我已经成功地编写了一个脚本,在套接字层(由ftplib使用)上安装透明的HTTP隧道

现在,我可以透明地通过HTTP进行FTP了

你可以在那里买到:

修补内置套接字库肯定不是每个人都可以选择的,但我的解决方案是修补
套接字。创建\u connection()
在主机名与白名单匹配时使用HTTP代理:

from base64 import b64encode
from functools import wraps
import socket

_real_create_connection = socket.create_connection
_proxied_hostnames = {}  # hostname: (proxy_host, proxy_port, proxy_auth)


def register_proxy (host, proxy_host, proxy_port, proxy_username=None, proxy_password=None):
    proxy_auth = None
    if proxy_username is not None or proxy_password is not None:
        proxy_auth = b64encode('{}:{}'.format(proxy_username or '', proxy_password or ''))
    _proxied_hostnames[host] = (proxy_host, proxy_port, proxy_auth)


@wraps(_real_create_connection)
def create_connection (address, *args, **kwds):
    host, port = address
    if host not in _proxied_hostnames:
        return _real_create_connection(address, *args, **kwds)

    proxy_host, proxy_port, proxy_auth = _proxied_hostnames[host]
    conn = _real_create_connection((proxy_host, proxy_port), *args, **kwds)
    try:
        conn.send('CONNECT {host}:{port} HTTP/1.1\r\nHost: {host}:{port}\r\n{auth_header}\r\n'.format(
            host=host, port=port,
            auth_header=('Proxy-Authorization: basic {}\r\n'.format(proxy_auth) if proxy_auth else '')
        ))
        response = ''
        while not response.endswith('\r\n\r\n'):
            response += conn.recv(4096)
        if response.split()[1] != '200':
            raise socket.error('CONNECT failed: {}'.format(response.strip()))
    except socket.error:
        conn.close()
        raise

    return conn


socket.create_connection = create_connection
我还必须创建ftplib.FTP的子类,该子类忽略由
PASV
EPSV
FTP命令返回的
host
。用法示例:

from ftplib import FTP
import paramiko  # For SFTP
from proxied_socket import register_proxy

class FTPIgnoreHost (FTP):
    def makepasv (self):
        # Ignore the host returned by PASV or EPSV commands (only use the port).
        return self.host, FTP.makepasv(self)[1]

register_proxy('ftp.example.com', 'proxy.example.com', 3128, 'proxy_username', 'proxy_password')

ftp_connection = FTP('ftp.example.com', 'ftp_username', 'ftp_password')

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # If you don't care about security.
ssh.connect('ftp.example.com', username='sftp_username', password='sftp_password')
sftp_connection = ssh.open_sftp()

以下是使用
请求
的解决方法,使用不支持连接隧道的squid代理进行测试:

def ftp_fetch_file_through_http_proxy(host, user, password, remote_filepath, http_proxy, output_filepath):
    """
    This function let us to make a FTP RETR query through a HTTP proxy that does NOT support CONNECT tunneling.
    It is equivalent to: curl -x $HTTP_PROXY --user $USER:$PASSWORD ftp://$FTP_HOST/path/to/file
    It returns the 'Last-Modified' HTTP header value from the response.

    More precisely, this function sends the following HTTP request to $HTTP_PROXY:
        GET ftp://$USER:$PASSWORD@$FTP_HOST/path/to/file HTTP/1.1
    Note that in doing so, the host in the request line does NOT match the host we send this packet to.

    Python `requests` lib does not let us easily "cheat" like this.
    In order to achieve what we want, we need:
    - to mock urllib3.poolmanager.parse_url so that it returns a (host,port) pair indicating to send the request to the proxy
    - to register a connection adapter to the 'ftp://' prefix. This is basically a HTTP adapter but it uses the FULL url of
    the resource to build the request line, instead of only its relative path.
    """
    url = 'ftp://{}:{}@{}/{}'.format(user, password, host, remote_filepath)
    proxy_host, proxy_port = http_proxy.split(':')

    def parse_url_mock(url):
        return requests.packages.urllib3.util.url.parse_url(url)._replace(host=proxy_host, port=proxy_port, scheme='http')

    with open(output_filepath, 'w+b') as output_file, patch('requests.packages.urllib3.poolmanager.parse_url', new=parse_url_mock):
        session = requests.session()
        session.mount('ftp://', FTPWrappedInFTPAdapter())
        response = session.get(url)
        response.raise_for_status()
        output_file.write(response.content)
        return response.headers['last-modified']


class FTPWrappedInFTPAdapter(requests.adapters.HTTPAdapter):
    def request_url(self, request, _):
        return request.url

上面答案中的链接是404。可能是这个意思:“匿名ftp.download.com”部分纯属虚构。据我所知,任何RFC中都没有提到过这样的内容,也没有任何服务器实现/支持这样的内容。在本机上,FTP协议不支持代理。好的,代理FTP的唯一方法是使用SOCKS,在这种情况下,客户端应该连接到SOCKS,后者应该被告知真正的FTP服务器是什么。示例中“urlli2”的键入不能编辑,因为“编辑必须至少6个字符”。谢谢,这是迄今为止我发现的唯一一种可行的解决方案,但对我来说仍然不起作用。在添加了一些.encode和.decode以使Python 3兼容之后,我现在可以通过代理建立到ftp服务器的连接,但是当我运行一个LIST命令时,例如,我得到了
ftplib.error\u temp:425无法打开数据连接
,并且没有返回任何数据。有什么想法吗?@JordanDimov你能把你做的事发出来吗?我正试图找到解决这个问题的方法,但这里提到的代码片段都不适合我。