Skip to content

Instantly share code, notes, and snippets.

@atotto
Created September 26, 2019 01:30
Show Gist options
  • Select an option

  • Save atotto/dae840a49f20a0373b49bc1658bdc73b to your computer and use it in GitHub Desktop.

Select an option

Save atotto/dae840a49f20a0373b49bc1658bdc73b to your computer and use it in GitHub Desktop.

Revisions

  1. atotto created this gist Sep 26, 2019.
    54 changes: 54 additions & 0 deletions bind_to_device.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    package main

    import (
    "flag"
    "io"
    "log"
    "net"
    "net/http"
    "os"
    "syscall"
    )

    var (
    uri = flag.String("target", "https://google.com", "target url")
    netInterface = flag.String("interface", "eth0", "")
    )

    func main() {
    flag.Parse()

    client := &http.Client{
    Transport: Transport(*netInterface),
    }

    rc, err := client.Get(*uri)
    if err != nil {
    log.Fatal(err)
    }
    defer rc.Body.Close()

    if _, err := io.Copy(os.Stdout, rc.Body); err != nil {
    log.Fatal(err)
    }
    }

    func Transport(interfaceName string) *http.Transport {
    return &http.Transport{
    DialContext: (&net.Dialer{
    Control: func(network, address string, c syscall.RawConn) (err error) {
    err1 := c.Control(func(fd uintptr) {
    // need setcap cap_net_raw+ep
    err = syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, interfaceName)
    if err != nil {
    return
    }
    })
    if err != nil {
    return err
    }
    return err1
    },
    }).DialContext,
    }
    }