mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-12 17:59:06 +02:00
[client] Scope the iOS file drop dial to the tunnel interface
A Network Extension's own unscoped sockets bypass its tunnel and leave on the physical interface, so the file drop dial to a peer address died on the local network. Bind the socket to the overlay address and the tunnel interface index, the same way the iOS DNS upstream client dials. Other platforms keep the plain dialer: Android and the desktops route the client's own traffic into the tunnel already.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
//go:build !ios
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/filedrop"
|
||||
)
|
||||
|
||||
func fileDropOSDial(WGIface) filedrop.DialFunc {
|
||||
dialer := &net.Dialer{}
|
||||
return dialer.DialContext
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//go:build ios
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/filedrop"
|
||||
)
|
||||
|
||||
// fileDropOSDial scopes the dial to the tunnel interface, since a Network
|
||||
// Extension's own unscoped sockets bypass its tunnel and leave on the
|
||||
// physical interface.
|
||||
func fileDropOSDial(wgIface WGIface) filedrop.DialFunc {
|
||||
return func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
addrPort, err := netip.ParseAddrPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
osIface, err := net.InterfaceByName(wgIface.Name())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("lookup interface %q: %w", wgIface.Name(), err)
|
||||
}
|
||||
|
||||
wgAddr := wgIface.Address()
|
||||
bindIP := wgAddr.IP
|
||||
proto, opt := unix.IPPROTO_IP, unix.IP_BOUND_IF
|
||||
if addrPort.Addr().Is6() {
|
||||
if !wgAddr.HasIPv6() {
|
||||
return nil, fmt.Errorf("no IPv6 address on %s", wgIface.Name())
|
||||
}
|
||||
bindIP = wgAddr.IPv6
|
||||
proto, opt = unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF
|
||||
}
|
||||
|
||||
dialer := &net.Dialer{
|
||||
LocalAddr: net.TCPAddrFromAddrPort(netip.AddrPortFrom(bindIP, 0)),
|
||||
Control: func(_, _ string, c syscall.RawConn) error {
|
||||
var operr error
|
||||
if err := c.Control(func(s uintptr) {
|
||||
operr = unix.SetsockoptInt(int(s), proto, opt, osIface.Index)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return operr
|
||||
},
|
||||
}
|
||||
return dialer.DialContext(ctx, network, addr)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user