Send http request through specific network interface

后端 未结 3 1453
春和景丽
春和景丽 2020-12-07 01:46

I have two network interfaces (wifi and ethernet) both with internet access. Let\'s say my interfaces are eth (ethernet) and wlp2 (wifi). I need sp

相关标签:
3条回答
  • 2020-12-07 02:02

    Here is the solution for Requests library without monkey-patching anything.

    This function will create a Session bound to the given IP address. It is up to you to determine IP address of the desired network interface.

    Tested to work with requests==2.23.0.

    import requests
    
    
    def session_for_src_addr(addr: str) -> requests.Session:
        """
        Create `Session` which will bind to the specified local address
        rather than auto-selecting it.
        """
        session = requests.Session()
        for prefix in ('http://', 'https://'):
            session.get_adapter(prefix).init_poolmanager(
                # those are default values from HTTPAdapter's constructor
                connections=requests.adapters.DEFAULT_POOLSIZE,
                maxsize=requests.adapters.DEFAULT_POOLSIZE,
                # This should be a tuple of (address, port). Port 0 means auto-selection.
                source_address=(addr, 0),
            )
    
        return session
    
    
    # usage example:
    s = session_for_src_addr('192.168.1.12')
    s.get('https://httpbin.org/ip')
    

    Be warned though that this approach is identical to curl's --interface option, and won't help in some cases. Depending on your routing configuration, it might happen that even though you bind to the specific IP address, request will go through some other interface. So if this answer does not work for you then first check if curl http://httpbin.org/ip --interface myinterface will work as expected.

    0 讨论(0)
  • 2020-12-07 02:09

    Try changing the internal IP (192.168.0.200) to the corresponding iface in the code below.

    import requests
    from requests_toolbelt.adapters import source
    
    def check_ip(inet_addr):
        s = requests.Session()
        iface = source.SourceAddressAdapter(inet_addr)
        s.mount('http://', iface)
        s.mount('https://', iface)
        url = 'https://emapp.cc/get_my_ip'
        resp = s.get(url)
        print(resp.text)
    
    if __name__ == '__main__':
        check_ip('192.168.0.200')
    
    0 讨论(0)
  • 2020-12-07 02:14

    I found a way using pycurl. This works like a charm.

    import pycurl
    from io import BytesIO
    import json
    
    
    def curl_post(url, data, iface=None):
        c = pycurl.Curl()
        buffer = BytesIO()
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.POST, True)
        c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json'])
        c.setopt(pycurl.TIMEOUT, 10)
        c.setopt(pycurl.WRITEFUNCTION, buffer.write)
        c.setopt(pycurl.POSTFIELDS, data)
        if iface:
            c.setopt(pycurl.INTERFACE, iface)
        c.perform()
    
        # Json response
        resp = buffer.getvalue().decode('UTF-8')
    
        #  Check response is a JSON if not there was an error
        try:
            resp = json.loads(resp)
        except json.decoder.JSONDecodeError:
            pass
    
        buffer.close()
        c.close()
        return resp
    
    
    if __name__ == '__main__':
        dat = {"id": 52, "configuration": [{"eno1": {"address": "192.168.1.1"}}]}
        res = curl_post("http://127.0.0.1:5000/network_configuration/", json.dumps(dat), "wlp2")
        print(res)
    

    I'm leaving the question opened hopping that someone can give an answer using requests.

    0 讨论(0)
提交回复
热议问题