//go:build darwin package monitor import ( "net" "syscall" "golang.org/x/sys/unix" ) // bindControl returns a socket control hook that pins the connection to the // given interface with IP_BOUND_IF. On macOS a bound source address is not // enough: without this the kernel still routes the packets over the VPN's // default route, so traffic would not leave the interface we are measuring. func bindControl(iface string) func(network, address string, c syscall.RawConn) error { ifi, err := net.InterfaceByName(iface) if err != nil { return nil } idx := ifi.Index return func(_, _ string, c syscall.RawConn) error { var setErr error ctrlErr := c.Control(func(fd uintptr) { setErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, idx) }) if ctrlErr != nil { return ctrlErr } return setErr } }