@ -462,7 +462,7 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logid string) (_ *ip
socksListener , httpProxyListener := mustStartProxyListeners ( args . socksAddr , args . httpProxyAddr )
dialer := & tsdial . Dialer { Logf : logf } // mutated below (before used)
e , use Netstack, err := createEngine ( logf , linkMon , dialer )
e , only Netstack, err := createEngine ( logf , linkMon , dialer )
if err != nil {
return nil , fmt . Errorf ( "createEngine: %w" , err )
}
@ -482,10 +482,10 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logid string) (_ *ip
if err != nil {
return nil , fmt . Errorf ( "newNetstack: %w" , err )
}
ns . ProcessLocalIPs = use Netstack
ns . ProcessSubnets = useNetstack || shouldWrap Netstack( )
ns . ProcessLocalIPs = only Netstack
ns . ProcessSubnets = onlyNetstack || handleSubnetsIn Netstack( )
if use Netstack {
if only Netstack {
dialer . UseNetstackForIP = func ( ip netip . Addr ) bool {
_ , ok := e . PeerForIP ( ip )
return ok
@ -540,16 +540,21 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logid string) (_ *ip
return lb , nil
}
func createEngine ( logf logger . Logf , linkMon * monitor . Mon , dialer * tsdial . Dialer ) ( e wgengine . Engine , useNetstack bool , err error ) {
// createEngine tries to the wgengine.Engine based on the order of tunnels
// specified in the command line flags.
//
// onlyNetstack is true if the user has explicitly requested that we use netstack
// for all networking.
func createEngine ( logf logger . Logf , linkMon * monitor . Mon , dialer * tsdial . Dialer ) ( e wgengine . Engine , onlyNetstack bool , err error ) {
if args . tunname == "" {
return nil , false , errors . New ( "no --tun value specified" )
}
var errs [ ] error
for _ , name := range strings . Split ( args . tunname , "," ) {
logf ( "wgengine.NewUserspaceEngine(tun %q) ..." , name )
e , use Netstack, err = tryEngine ( logf , linkMon , dialer , name )
e , only Netstack, err = tryEngine ( logf , linkMon , dialer , name )
if err == nil {
return e , use Netstack, nil
return e , only Netstack, nil
}
logf ( "wgengine.NewUserspaceEngine(tun %q) error: %v" , name , err )
errs = append ( errs , err )
@ -557,8 +562,12 @@ func createEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer)
return nil , false , multierr . New ( errs ... )
}
func shouldWrapNetstack ( ) bool {
if v , ok := envknob . LookupBool ( "TS_DEBUG_WRAP_NETSTACK" ) ; ok {
// handleSubnetsInNetstack reports whether netstack should handle subnet routers
// as opposed to the OS. We do this if the OS doesn't support subnet routers
// (e.g. Windows) or if the user has explicitly requested it (e.g.
// --tun=userspace-networking).
func handleSubnetsInNetstack ( ) bool {
if v , ok := envknob . LookupBool ( "TS_DEBUG_NETSTACK_SUBNETS" ) ; ok {
return v
}
if distro . Get ( ) == distro . Synology {
@ -575,15 +584,15 @@ func shouldWrapNetstack() bool {
var tstunNew = tstun . New
func tryEngine ( logf logger . Logf , linkMon * monitor . Mon , dialer * tsdial . Dialer , name string ) ( e wgengine . Engine , useNetst ack bool , err error ) {
func tryEngine ( logf logger . Logf , linkMon * monitor . Mon , dialer * tsdial . Dialer , name string ) ( e wgengine . Engine , onlyNets ack bool , err error ) {
conf := wgengine . Config {
ListenPort : args . port ,
LinkMonitor : linkMon ,
Dialer : dialer ,
}
useNetst ack = name == "userspace-networking"
netns . SetEnabled ( ! useNetst ack)
onlyNets ack = name == "userspace-networking"
netns . SetEnabled ( ! onlyNets ack)
if args . birdSocketPath != "" && createBIRDClient != nil {
log . Printf ( "Connecting to BIRD at %s ..." , args . birdSocketPath )
@ -592,7 +601,7 @@ func tryEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer, na
return nil , false , fmt . Errorf ( "createBIRDClient: %w" , err )
}
}
if useNetst ack {
if onlyNets ack {
if runtime . GOOS == "linux" && distro . Get ( ) == distro . Synology {
// On Synology in netstack mode, still init a DNS
// manager (directManager) to avoid the health check
@ -631,15 +640,15 @@ func tryEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer, na
}
conf . DNS = d
conf . Router = r
if shouldWrap Netstack( ) {
if handleSubnetsIn Netstack( ) {
conf . Router = netstack . NewSubnetRouterWrapper ( conf . Router )
}
}
e , err = wgengine . NewUserspaceEngine ( logf , conf )
if err != nil {
return nil , useNetst ack, err
return nil , onlyNets ack, err
}
return e , useNetst ack, nil
return e , onlyNets ack, nil
}
func newDebugMux ( ) * http . ServeMux {