I have multiple interfaces on the box and want to force the traffic through a particular interface using python.
This thread answers how to do that for HTTP traffic. But when I look at tcpdump, the DNS queries do not honor the interface setting. libcurl provides options to force DNS traffic through a particular interface using option CURLOPT_DNS_INTERFACE and CURLOPT_DNS_LOCAL_IP4
I tried using the same through C and it seems to honor the interface when libcurl is built with c-ares support.
But when the same options are used from the pycurl version result in the following errors:
AttributeError: DNS_INTERFACE
AttributeError: DNS_LOCAL_IP4
I am trying monkey patching suggested on this thread. But based on the comments, other people already reported that it's not working. Thanks.
[edit] Tested the above-mentioned monkey-patching with bind, tcpdump still shows traffic through a different interface. Fixed formatting.
The AttributeError happens since PycURL only supports curl options that it lists in src/module.c. One can add support for CURLOPT_DNS_INTERFACE by mirroring how it supports CURLOPT_INTERFACE -- by adding
insint_c(d, "DNS_INTERFACE", CURLOPT_DNS_INTERFACE);
and
case CURLOPT_DNS_INTERFACE:
in src/module.c and src/easyopt.c after the lines about CURLOPT_INTERFACE, I could build a version that supports DNS_INTERFACE. I used python setup.py install
for the build (see docs), running into two errors that were solved with this answer and make src/docstrings.c
(see GitHub).
Here the example from the docs with DNS_INTERFACE added:
import pycurl
from StringIO import StringIO
buffer = StringIO()
c = pycurl.Curl()
c.setopt(c.URL, 'http://pycurl.io/')
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.DNS_INTERFACE, "enp9s0")
c.perform()
c.close()
body = buffer.getvalue()
print(body)
It currently gives me pycurl.error: (4, '')
on the c.setopt(c.DNS_INTERFACE, "enp9s0")
, but this error would likely not happen for you since you built libcurl with c-ares support.