{"slug":"kernel-vs-netstack-subnet-routing-exit-nodes","title":"Kernel vs. netstack subnet routing & exit nodes","tags":["tailscale","routing","exit-nodes"],"agent_summary":"Last validated: Jan 5, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Kernel vs. netstack subnet routing & exit nodes\r\n\r\nLast validated: Jan 5, 2026\r\n\r\nTailscale can act as a subnet router or exit node in one of two\r\ndifferent modes:\r\n\r\n1. **kernel mode** (root on Linux)\r\n2. **userspace mode** (all non-Linux devices & non-root on Linux)\r\n\r\n## [Kernel mode](https://tailscale.com/docs/reference/kernel-vs-userspace-routers\\#kernel-mode)\r\n\r\nIn kernel mode, the operating system itself forwards the packets.\r\nEncrypted WireGuard UDP packets from peers arrive in the kernel, which\r\nforwards them to Tailscale to decrypt. Tailscale then returns the\r\ndecrypted packets to the kernel, to be forwarded to the relevant\r\ntarget.\r\n\r\nThis is the default mode of operation on Linux and was the first mode\r\nthat Tailscale supported.\r\n\r\nIn this mode, Tailscale doesn't rewrite the IP packets passing through\r\nit. TCP streams are end-to-end from the origin, through the Tailscale\r\nsubnet router or exit node, and on to the final destination. All IP\r\nprotocols are supported.\r\n\r\n## [Userspace (\"netstack\") mode](https://tailscale.com/docs/reference/kernel-vs-userspace-routers\\#userspace-netstack-mode)\r\n\r\nTailscale can also run subnet routers and exit nodes in\r\nuserspace, without the kernel forwarding packets. This happens when either:\r\n\r\n1. `tailscaled` is run with `--tun=userspace-networking` (used when running as a regular, non-root user)\r\n2. Tailscale is run on operating systems other than Linux, such as\r\nFreeBSD, macOS, or Windows. This is the only way to run subnet\r\nrouters and exit nodes on these operating systems.\r\n\r\nIn userspace mode, Tailscale uses the\r\n[gVisor](https://github.com/google/gvisor) [`netstack`](https://github.com/inetaf/netstack) library, implementing\r\n[networking in userspace](https://gvisor.dev/blog/2020/04/02/gvisor-networking-security).\r\n\r\nIn this mode, Tailscale terminates TCP and UDP connections\r\nfrom the origin Tailscale peer and makes new outbound connections\r\nto the target from the subnet router, stitching them together.\r\n\r\nFor ICMP pings, the Tailscale daemon does something similar to how it\r\nrelays TCP and UDP traffic. When a Tailscale subnet router or exit\r\nnode receives an ICMP ping request, it issues its own ping request to\r\nthe target (running the `ping` command if needed), replying to the\r\noriginal request if its relayed one succeeds. This can add a small\r\namount of apparent ping latency; it's supported primarily so people\r\ncan test connectivity using familiar tools.\r\n\r\nOther ICMP traffic is not relayed through Tailscale in userspace\r\nmode. Similarly, any IP protocol other than TCP or UDP (such as SCTP)\r\nis not supported in userspace mode.\r\n\r\n## [Performance](https://tailscale.com/docs/reference/kernel-vs-userspace-routers\\#performance)\r\n\r\nThe kernel mode and userspace mode have different CPU and memory\r\ncharacteristics.\r\n\r\nIn general, kernel mode (and thus only Linux, for now) should be used\r\nfor heavily used subnet routers, where \"heavy\" is some combination of\r\nnumber of users, number of flows, bandwidth.\r\n\r\nThe userspace mode should be more than sufficient for smaller numbers\r\nof users or low bandwidth. Even though Tailscale's userspace\r\nsubnet routing is not as optimized as the Linux kernel, it makes up for\r\nit slightly in being able to avoid some context switches to the\r\nkernel.\r\n\r\nIn any case, if you observe that `tailscaled` is using more CPU or memory than desired, consider switching to a kernel mode subnet router.\r\n\r\n## [Summary](https://tailscale.com/docs/reference/kernel-vs-userspace-routers\\#summary)\r\n\r\n| Feature | Kernel mode | Userspace mode |\r\n| --- | --- | --- |\r\n| Routing type | Layer 3 (IP) | Layer 4 (UDP, TCP) |\r\n| ICMP support | all | only ping (reconstructed) |\r\n| TCP end-to-end | yes | no (reconstructed) |\r\n| UDP end-to-end | yes | no (reconstructed) |\r\n| SCTP and support | yes (all IP protocols) | no (only TCP, UDP) |\r\n| Performance | best | acceptable |\r\n| Maturity | stable | new (in Tailscale) |\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Kernel vs. netstack subnet routing &#x26; exit nodes</h1>\n<p>Last validated: Jan 5, 2026</p>\n<p>Tailscale can act as a subnet router or exit node in one of two\r\ndifferent modes:</p>\n<ol>\n<li><strong>kernel mode</strong> (root on Linux)</li>\n<li><strong>userspace mode</strong> (all non-Linux devices &#x26; non-root on Linux)</li>\n</ol>\n<h2><a href=\"https://tailscale.com/docs/reference/kernel-vs-userspace-routers#kernel-mode\">Kernel mode</a></h2>\n<p>In kernel mode, the operating system itself forwards the packets.\r\nEncrypted WireGuard UDP packets from peers arrive in the kernel, which\r\nforwards them to Tailscale to decrypt. Tailscale then returns the\r\ndecrypted packets to the kernel, to be forwarded to the relevant\r\ntarget.</p>\n<p>This is the default mode of operation on Linux and was the first mode\r\nthat Tailscale supported.</p>\n<p>In this mode, Tailscale doesn't rewrite the IP packets passing through\r\nit. TCP streams are end-to-end from the origin, through the Tailscale\r\nsubnet router or exit node, and on to the final destination. All IP\r\nprotocols are supported.</p>\n<h2><a href=\"https://tailscale.com/docs/reference/kernel-vs-userspace-routers#userspace-netstack-mode\">Userspace (\"netstack\") mode</a></h2>\n<p>Tailscale can also run subnet routers and exit nodes in\r\nuserspace, without the kernel forwarding packets. This happens when either:</p>\n<ol>\n<li><code>tailscaled</code> is run with <code>--tun=userspace-networking</code> (used when running as a regular, non-root user)</li>\n<li>Tailscale is run on operating systems other than Linux, such as\r\nFreeBSD, macOS, or Windows. This is the only way to run subnet\r\nrouters and exit nodes on these operating systems.</li>\n</ol>\n<p>In userspace mode, Tailscale uses the\r\n<a href=\"https://github.com/google/gvisor\">gVisor</a> <a href=\"https://github.com/inetaf/netstack\"><code>netstack</code></a> library, implementing\r\n<a href=\"https://gvisor.dev/blog/2020/04/02/gvisor-networking-security\">networking in userspace</a>.</p>\n<p>In this mode, Tailscale terminates TCP and UDP connections\r\nfrom the origin Tailscale peer and makes new outbound connections\r\nto the target from the subnet router, stitching them together.</p>\n<p>For ICMP pings, the Tailscale daemon does something similar to how it\r\nrelays TCP and UDP traffic. When a Tailscale subnet router or exit\r\nnode receives an ICMP ping request, it issues its own ping request to\r\nthe target (running the <code>ping</code> command if needed), replying to the\r\noriginal request if its relayed one succeeds. This can add a small\r\namount of apparent ping latency; it's supported primarily so people\r\ncan test connectivity using familiar tools.</p>\n<p>Other ICMP traffic is not relayed through Tailscale in userspace\r\nmode. Similarly, any IP protocol other than TCP or UDP (such as SCTP)\r\nis not supported in userspace mode.</p>\n<h2><a href=\"https://tailscale.com/docs/reference/kernel-vs-userspace-routers#performance\">Performance</a></h2>\n<p>The kernel mode and userspace mode have different CPU and memory\r\ncharacteristics.</p>\n<p>In general, kernel mode (and thus only Linux, for now) should be used\r\nfor heavily used subnet routers, where \"heavy\" is some combination of\r\nnumber of users, number of flows, bandwidth.</p>\n<p>The userspace mode should be more than sufficient for smaller numbers\r\nof users or low bandwidth. Even though Tailscale's userspace\r\nsubnet routing is not as optimized as the Linux kernel, it makes up for\r\nit slightly in being able to avoid some context switches to the\r\nkernel.</p>\n<p>In any case, if you observe that <code>tailscaled</code> is using more CPU or memory than desired, consider switching to a kernel mode subnet router.</p>\n<h2><a href=\"https://tailscale.com/docs/reference/kernel-vs-userspace-routers#summary\">Summary</a></h2>\n<p>| Feature | Kernel mode | Userspace mode |\r\n| --- | --- | --- |\r\n| Routing type | Layer 3 (IP) | Layer 4 (UDP, TCP) |\r\n| ICMP support | all | only ping (reconstructed) |\r\n| TCP end-to-end | yes | no (reconstructed) |\r\n| UDP end-to-end | yes | no (reconstructed) |\r\n| SCTP and support | yes (all IP protocols) | no (only TCP, UDP) |\r\n| Performance | best | acceptable |\r\n| Maturity | stable | new (in Tailscale) |</p>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}