@ -54,13 +54,23 @@ type Impl struct {
// port other than accepting it and closing it.
// port other than accepting it and closing it.
ForwardTCPIn func ( c net . Conn , port uint16 )
ForwardTCPIn func ( c net . Conn , port uint16 )
// ProcessLocalIPs is whether netstack should handle incoming
// traffic directed at the Node.Addresses (local IPs).
// It can only be set before calling Start.
ProcessLocalIPs bool
// ProcessSubnets is whether netstack should handle incoming
// traffic destined to non-local IPs (i.e. whether it should
// be a subnet router).
// It can only be set before calling Start.
ProcessSubnets bool
ipstack * stack . Stack
ipstack * stack . Stack
linkEP * channel . Endpoint
linkEP * channel . Endpoint
tundev * tstun . Wrapper
tundev * tstun . Wrapper
e wgengine . Engine
e wgengine . Engine
mc * magicsock . Conn
mc * magicsock . Conn
logf logger . Logf
logf logger . Logf
onlySubnets bool // whether we only want to handle subnet relaying
// atomicIsLocalIPFunc holds a func that reports whether an IP
// atomicIsLocalIPFunc holds a func that reports whether an IP
// is a local (non-subnet) Tailscale IP address of this
// is a local (non-subnet) Tailscale IP address of this
@ -81,7 +91,7 @@ const nicID = 1
const mtu = 1500
const mtu = 1500
// Create creates and populates a new Impl.
// Create creates and populates a new Impl.
func Create ( logf logger . Logf , tundev * tstun . Wrapper , e wgengine . Engine , mc * magicsock . Conn , onlySubnets bool ) ( * Impl , error ) {
func Create ( logf logger . Logf , tundev * tstun . Wrapper , e wgengine . Engine , mc * magicsock . Conn ) ( * Impl , error ) {
if mc == nil {
if mc == nil {
return nil , errors . New ( "nil magicsock.Conn" )
return nil , errors . New ( "nil magicsock.Conn" )
}
}
@ -130,7 +140,6 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
e : e ,
e : e ,
mc : mc ,
mc : mc ,
connsOpenBySubnetIP : make ( map [ netaddr . IP ] int ) ,
connsOpenBySubnetIP : make ( map [ netaddr . IP ] int ) ,
onlySubnets : onlySubnets ,
}
}
ns . atomicIsLocalIPFunc . Store ( tsaddr . NewContainsIPFunc ( nil ) )
ns . atomicIsLocalIPFunc . Store ( tsaddr . NewContainsIPFunc ( nil ) )
return ns , nil
return ns , nil
@ -275,11 +284,11 @@ func (ns *Impl) updateIPs(nm *netmap.NetworkMap) {
isAddr [ ipp ] = true
isAddr [ ipp ] = true
}
}
for _ , ipp := range nm . SelfNode . AllowedIPs {
for _ , ipp := range nm . SelfNode . AllowedIPs {
if ns . onlySubnets && isAddr [ ipp ] {
local := isAddr [ ipp ]
continue
if local && ns . ProcessLocalIPs || ! local && ns . ProcessSubnets {
}
newIPs [ ipPrefixToAddressWithPrefix ( ipp ) ] = true
newIPs [ ipPrefixToAddressWithPrefix ( ipp ) ] = true
}
}
}
ipsToBeAdded := make ( map [ tcpip . AddressWithPrefix ] bool )
ipsToBeAdded := make ( map [ tcpip . AddressWithPrefix ] bool )
for ipp := range newIPs {
for ipp := range newIPs {
@ -446,11 +455,27 @@ func (ns *Impl) isLocalIP(ip netaddr.IP) bool {
return ns . atomicIsLocalIPFunc . Load ( ) . ( func ( netaddr . IP ) bool ) ( ip )
return ns . atomicIsLocalIPFunc . Load ( ) . ( func ( netaddr . IP ) bool ) ( ip )
}
}
// shouldProcessInbound reports whether an inbound packet should be
// handled by netstack.
func ( ns * Impl ) shouldProcessInbound ( p * packet . Parsed , t * tstun . Wrapper ) bool {
if ! ns . ProcessLocalIPs && ! ns . ProcessSubnets {
// Fast path for common case (e.g. Linux server in TUN mode) where
// netstack isn't used at all; don't even do an isLocalIP lookup.
return false
}
isLocal := ns . isLocalIP ( p . Dst . IP ( ) )
if ns . ProcessLocalIPs && isLocal {
return true
}
if ns . ProcessSubnets && ! isLocal {
return true
}
return false
}
func ( ns * Impl ) injectInbound ( p * packet . Parsed , t * tstun . Wrapper ) filter . Response {
func ( ns * Impl ) injectInbound ( p * packet . Parsed , t * tstun . Wrapper ) filter . Response {
if ns . onlySubnets && ns . isLocalIP ( p . Dst . IP ( ) ) {
if ! ns . shouldProcessInbound ( p , t ) {
// In hybrid ("only subnets") mode, bail out early if
// Let the host network stack (if any) deal with it.
// the traffic is destined for an actual Tailscale
// address. The real host OS interface will handle it.
return filter . Accept
return filter . Accept
}
}
var pn tcpip . NetworkProtocolNumber
var pn tcpip . NetworkProtocolNumber