Python请求,如何指定传出流量的端口?

Python Requests, how to specify port for outgoing traffic?

我正在做一个项目,我们想为防火墙上的传入流量分配一个白名单数据包过滤器,我们正在使用 python 带有请求库的脚本向外部的某些服务器发出一些 https 请求那个网络。现在脚本使用临时端口连接到服务器,但我们想通过特定端口发出这些 https 请求。这将允许我们为这些端口创建严格的白名单。

如何指定发送请求的请求库端口?脚本当前正在使用以下类型的代码来发送必要的请求。

response = requests.post(data[0], data=query, headers=headers, timeout=10)

这可行,但我现在需要指定发送 http post 请求的端口,以允许在网络上进行更严格的数据包过滤。这个港口申报是怎么实现的呢?我已经从多个来源搜索了解决方案,但一无所获。

requests 建立在 urllib3 之上,它提供了为连接设置源地址的能力;当您将源地址设置为 ('', port_number) 时,您告诉它使用默认主机名但选择一个特定端口。

您可以在 pool manager, and you tell requests to use a different pool manager by creating a new transport adapter 上设置这些选项:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager


class SourcePortAdapter(HTTPAdapter):
    """"Transport adapter" that allows us to set the source port."""
    def __init__(self, port, *args, **kwargs):
        self._source_port = port
        super(SourcePortAdapter, self).__init__(*args, **kwargs)

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections, maxsize=maxsize,
            block=block, source_address=('', self._source_port))

在会话对象中使用此适配器,以下为 所有 HTTP 和 HTTPS 连接安装适配器,使用 54321 作为源端口:

s = requests.Session()
s.mount('http://', SourcePortAdapter(54321))
s.mount('https://', SourcePortAdapter(54321))

您只能设置一个源端口,一次只能使用一个活动连接。如果您需要在端口之间轮换,请注册多个适配器(每个 URL 一个)或每次重新注册 catch-all 安装。

有关 source_address 选项的详细信息,请参阅 create_connection() utility function documentation

If source_address is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default.