0

I'm trying to make an HTTP request using a specific interface on my machine. My actual code is:

package main

import (
    "context"
    "fmt"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    "time"
)

func PanicErr(err error) {
    if err != nil {
        panic(err)
    }
}

func main() {

    ief, err := net.InterfaceByName("usb0")
    if err != nil {
        log.Fatal(err)
    }
    addrs, err := ief.Addrs()
    if err != nil {
        log.Fatal(err)
    }

    tcpAddr := &net.TCPAddr{
        IP: addrs[0].(*net.IPNet).IP,
    }

    dialer := net.Dialer{LocalAddr: tcpAddr}

    dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) {
        contextTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
        defer cancel()
        conn, err := dialer.DialContext(contextTimeout, network, addr)
        return conn, err
    }

    transport := &http.Transport{DialContext: dialContext}
    client := &http.Client{
        Transport: transport,
    }

    // http request
    response, err := client.Get("https://ipinfo.io/")
    PanicErr(err)

    data, err := ioutil.ReadAll(response.Body)
    PanicErr(err)

    fmt.Println(string(data))
}

But it doesn't work. Once started, as output, I have:

> go run req.go 
panic: Get "https://ipinfo.io/": dial tcp 192.168.8.100:0->34.117.59.81:443: i/o timeout

But if I attempt the same request with curl, it works and the IP address is the one the interface have right now:

> curl --interface usb0 https://ipinfo.io/
{
  "ip": "31.*.*.*",
  ...
}

Actual ifconfig output:

usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.8.100  netmask 255.255.255.0  broadcast 192.168.8.255
        inet6 fe80::21d5:1667:629c:7e91  prefixlen 64  scopeid 0x20<link>
        ether 62:ef:7f:**:**:**  txqueuelen 1000  (Ethernet)
        RX packets 281  bytes 57933 (56.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 73  bytes 8688 (8.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0 

Output of lsusb:

Bus 001 Device 009: ID 12d1:14db Huawei Technologies Co., Ltd. E353/E3131

What's wrong with my code?

Rockietto
  • 109
  • 1
  • 11
  • 1
    Unix systems don't choose the interface based on the address, that is a routing decision. There is [`syscall.BindToDevice`](https://pkg.go.dev/syscall#BindToDevice) for `SO_BINDTODEVICE`. See also https://stackoverflow.com/questions/563235/linux-how-do-i-force-a-specific-network-interface-to-be-used and https://stackoverflow.com/questions/335607/how-do-i-make-an-outgoing-socket-to-a-specific-network-interface – JimB Jul 12 '22 at 20:05
  • Actually this option worked! Thanks – Rockietto Jul 12 '22 at 20:37

0 Answers0