Fix: should not bind interface on local address
This commit is contained in:
parent
b1795b1e3d
commit
ba060bd0ee
2 changed files with 42 additions and 27 deletions
|
@ -5,22 +5,36 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type controlFn = func(network, address string, c syscall.RawConn) error
|
||||||
|
|
||||||
|
func bindControl(ifaceIdx int) controlFn {
|
||||||
|
return func(network, address string, c syscall.RawConn) error {
|
||||||
|
ipStr, _, err := net.SplitHostPort(address)
|
||||||
|
if err == nil {
|
||||||
|
ip := net.ParseIP(ipStr)
|
||||||
|
if ip != nil && !ip.IsGlobalUnicast() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Control(func(fd uintptr) {
|
||||||
|
switch network {
|
||||||
|
case "tcp4", "udp4":
|
||||||
|
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, ifaceIdx)
|
||||||
|
case "tcp6", "udp6":
|
||||||
|
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, ifaceIdx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error {
|
func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error {
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
iface, err := net.InterfaceByName(ifaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer.Control = func(network, address string, c syscall.RawConn) error {
|
dialer.Control = bindControl(iface.Index)
|
||||||
return c.Control(func(fd uintptr) {
|
|
||||||
switch network {
|
|
||||||
case "tcp4", "udp4":
|
|
||||||
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, iface.Index)
|
|
||||||
case "tcp6", "udp6":
|
|
||||||
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, iface.Index)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -31,16 +45,7 @@ func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.Control = func(network, address string, c syscall.RawConn) error {
|
lc.Control = bindControl(iface.Index)
|
||||||
return c.Control(func(fd uintptr) {
|
|
||||||
switch network {
|
|
||||||
case "tcp4", "udp4":
|
|
||||||
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, iface.Index)
|
|
||||||
case "tcp6", "udp6":
|
|
||||||
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, iface.Index)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,32 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error {
|
type controlFn = func(network, address string, c syscall.RawConn) error
|
||||||
dialer.Control = func(network, address string, c syscall.RawConn) error {
|
|
||||||
|
func bindControl(ifaceName string) controlFn {
|
||||||
|
return func(network, address string, c syscall.RawConn) error {
|
||||||
|
ipStr, _, err := net.SplitHostPort(address)
|
||||||
|
if err == nil {
|
||||||
|
ip := net.ParseIP(ipStr)
|
||||||
|
if ip != nil && !ip.IsGlobalUnicast() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return c.Control(func(fd uintptr) {
|
return c.Control(func(fd uintptr) {
|
||||||
syscall.BindToDevice(int(fd), ifaceName)
|
syscall.BindToDevice(int(fd), ifaceName)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error {
|
||||||
|
dialer.Control = bindControl(ifaceName)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error {
|
func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error {
|
||||||
lc.Control = func(network, address string, c syscall.RawConn) error {
|
lc.Control = bindControl(ifaceName)
|
||||||
return c.Control(func(fd uintptr) {
|
|
||||||
syscall.BindToDevice(int(fd), ifaceName)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue