【问题标题】:Making Python Requests through specific network interface通过特定的网络接口发出 Python 请求
【发布时间】:2020-11-18 23:06:01
【问题描述】:

我的 Raspberry Pi 上有多个网络接口,它们都具有相同的 IP 地址(192.168.3.1),但命名如下:eth1、eth2 等。

有没有办法通过特定的网络接口发出请求,即使 IP 地址相同?例如,运行eth2

这是我要运行的代码:

class Modem(object):
  BASE_URL = 'http://{host}'
  TOKEN_URL = '/api/webserver/SesTokInfo'
  session = None

  def __init__(self,host='192.168.3.1'):
    self.host = host
    self.base_url = self.BASE_URL.format(host=host)
    self.session = requests.Session()

  def switch_modem(self, state='02'):
    try:
      # Get session and verification tokens from the modem
      r = self.session.get(self.base_url + self.TOKEN_URL, timeout=10)
      _dict = xmltodict.parse(r.text).get('response', None)

【问题讨论】:

  • 你为什么要这样做?我想不出在多个接口上使用相同 IP 的任何正当理由。

标签: python linux python-requests raspberry-pi


【解决方案1】:

有了足够新鲜的请求和 urllib,您可以传递额外的套接字选项。见:https://*.com/a/35278688/745924

在发出请求之前,您可以使用它在套接字上设置SO_BINDTODEVICE。例如:

import requests
import socket

class HTTPAdapterWithSocketOptions(requests.adapters.HTTPAdapter):
    def __init__(self, *args, **kwargs):
        self.socket_options = kwargs.pop("socket_options", None)
        super(HTTPAdapterWithSocketOptions, self).__init__(*args, **kwargs)

    def init_poolmanager(self, *args, **kwargs):
        if self.socket_options is not None:
            kwargs["socket_options"] = self.socket_options
        super(HTTPAdapterWithSocketOptions, self).init_poolmanager(*args, **kwargs)

interface = 'veth0'
adapter = HTTPAdapterWithSocketOptions(socket_options=[(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, interface.encode('utf-8'))])
session = requests.session()
session.mount("http://", adapter)
session.mount("https://", adapter)
session.get('http://192.168.3.1')

这样做会破坏链接和 ip 层的分离。它确实需要 root 并且可能由于许多其他原因无法正常工作。

【讨论】:

    最近更新 更多