0

I have multiple network interfaces and want to send data using a specific interface.

Here's my code using pycurl:

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')

    try:
        resp = json.loads(resp)
    except json.decoder.JSONDecodeError:
        pass

    buffer.close()
    c.close()
    return resp

dat = {"id": 52, "configuration": [{"eno1": {"address": "192.168.1.1"}}]}

res = curl_post("https://emapp.cc/get_my_ip", json.dumps(dat), "enp0s20u1u3")

print(res)

The code works when run with sudo, but times out if I run it as a standard user.

It fails the same way using bash without sudo:

curl --interface enp0s20u1u3 google.com

My default interface is enp4s0f2 and when I set this to my code there is no need to use sudo.

stevieb
  • 9,065
  • 3
  • 26
  • 36
javadfarah
  • 46
  • 5

1 Answers1

3

From curl man page:

           curl --interface eth0:1 https://www.example.com/

          If this option is used several times, the last one will be used.

          On  Linux  it  can  be  used  to  specify  a VRF, but the binary needs to either have CAP_NET_RAW or to be ran as root. More information about Linux VRF:
          https://www.kernel.org/doc/Documentation/networking/vrf.txt

In other words to enable curl to run on all interfaces without sudo run the following command once:

sudo setcap CAP_NET_RAW+ep /usr/bin/curl

To revert this setting run:

sudo setcap CAP_NET_RAW-ep /usr/bin/curl

More info see https://security.stackexchange.com/questions/128958/security-implications-of-using-setcap-cap-net-raw

AAber
  • 1,562
  • 10
  • 14