mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-27 10:47:35 +00:00
cmd/tailscaled, wgengine/netstack: always wire up netstack
Even if not in use. We plan to use it for more stuff later. (not for iOS or macOS-GUIs yet; only tailscaled) Change-Id: Idaef719d2a009be6a39f158fd8f57f8cca68e0ee Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
ff597e773e
commit
5dc5bd8d20
@ -289,10 +289,14 @@ func run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ns *netstack.Impl
|
ns, err := newNetstack(logf, e)
|
||||||
if useNetstack || wrapNetstack {
|
if err != nil {
|
||||||
onlySubnets := wrapNetstack && !useNetstack
|
return fmt.Errorf("newNetstack: %w", err)
|
||||||
ns = mustStartNetstack(logf, e, onlySubnets)
|
}
|
||||||
|
ns.ProcessLocalIPs = useNetstack
|
||||||
|
ns.ProcessSubnets = useNetstack || wrapNetstack
|
||||||
|
if err := ns.Start(); err != nil {
|
||||||
|
log.Fatalf("failed to start netstack: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if socksListener != nil || httpProxyListener != nil {
|
if socksListener != nil || httpProxyListener != nil {
|
||||||
@ -453,19 +457,12 @@ func runDebugServer(mux *http.ServeMux, addr string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustStartNetstack(logf logger.Logf, e wgengine.Engine, onlySubnets bool) *netstack.Impl {
|
func newNetstack(logf logger.Logf, e wgengine.Engine) (*netstack.Impl, error) {
|
||||||
tunDev, magicConn, ok := e.(wgengine.InternalsGetter).GetInternals()
|
tunDev, magicConn, ok := e.(wgengine.InternalsGetter).GetInternals()
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatalf("%T is not a wgengine.InternalsGetter", e)
|
return nil, fmt.Errorf("%T is not a wgengine.InternalsGetter", e)
|
||||||
}
|
}
|
||||||
ns, err := netstack.Create(logf, tunDev, e, magicConn, onlySubnets)
|
return netstack.Create(logf, tunDev, e, magicConn)
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("netstack.Create: %v", err)
|
|
||||||
}
|
|
||||||
if err := ns.Start(); err != nil {
|
|
||||||
log.Fatalf("failed to start netstack: %v", err)
|
|
||||||
}
|
|
||||||
return ns
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustStartTCPListener(name, addr string) net.Listener {
|
func mustStartTCPListener(name, addr string) net.Listener {
|
||||||
|
@ -202,9 +202,14 @@ func startIPNServer(ctx context.Context, logid string) error {
|
|||||||
dev.Close()
|
dev.Close()
|
||||||
return nil, fmt.Errorf("engine: %w", err)
|
return nil, fmt.Errorf("engine: %w", err)
|
||||||
}
|
}
|
||||||
onlySubnets := true
|
ns, err := newNetstack(logf, eng)
|
||||||
if wrapNetstack {
|
if err != nil {
|
||||||
mustStartNetstack(logf, eng, onlySubnets)
|
return nil, fmt.Errorf("newNetstack: %w", err)
|
||||||
|
}
|
||||||
|
ns.ProcessLocalIPs = false
|
||||||
|
ns.ProcessSubnets = wrapNetstack
|
||||||
|
if err := ns.Start(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to start netstack: %w", err)
|
||||||
}
|
}
|
||||||
return wgengine.NewWatchdog(eng), nil
|
return wgengine.NewWatchdog(eng), nil
|
||||||
}
|
}
|
||||||
|
@ -127,10 +127,11 @@ func (s *Server) start() error {
|
|||||||
return fmt.Errorf("%T is not a wgengine.InternalsGetter", eng)
|
return fmt.Errorf("%T is not a wgengine.InternalsGetter", eng)
|
||||||
}
|
}
|
||||||
|
|
||||||
ns, err := netstack.Create(logf, tunDev, eng, magicConn, false)
|
ns, err := netstack.Create(logf, tunDev, eng, magicConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("netstack.Create: %w", err)
|
return fmt.Errorf("netstack.Create: %w", err)
|
||||||
}
|
}
|
||||||
|
ns.ProcessLocalIPs = true
|
||||||
ns.ForwardTCPIn = s.forwardTCP
|
ns.ForwardTCPIn = s.forwardTCP
|
||||||
if err := ns.Start(); err != nil {
|
if err := ns.Start(); err != nil {
|
||||||
return fmt.Errorf("failed to start netstack: %w", err)
|
return fmt.Errorf("failed to start netstack: %w", err)
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user