diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 7d5b80b2..0733b58a 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -299,6 +299,7 @@ func (t *tcp) call(saddr string, options interface{}, sintf string, upgrade *Tcp Timeout: time.Second * 5, } if sintf != "" { + dialer.Control = t.getContextWithBindToDevice(sintf) ief, err := net.InterfaceByName(sintf) if err != nil { return diff --git a/src/yggdrasil/tcp_linux.go b/src/yggdrasil/tcp_linux.go index 7eda3b5e..8d36f04c 100644 --- a/src/yggdrasil/tcp_linux.go +++ b/src/yggdrasil/tcp_linux.go @@ -29,3 +29,17 @@ func (t *tcp) tcpContext(network, address string, c syscall.RawConn) error { // Return nil because errors here are not considered fatal for the connection, it just means congestion control is suboptimal return nil } + +func (t *tcp) getContextWithBindToDevice(sintf string) func(string, string, syscall.RawConn) error { + return func(network, address string, c syscall.RawConn) error { + var err error + btd := func(fd uintptr) { + err = unix.BindToDevice(int(fd), sintf) + } + c.Control(btd) + if err != nil { + t.link.core.log.Debugln("Failed to set SO_BINDTODEVICE:", sintf) + } + return t.tcpContext(network, address, c) + } +}