ts-2024-005
Vulnerability from tailscale

Description: Insufficient inbound packet filtering in subnet routers and exit nodes

What happened?

In Tailscale versions earlier than 1.66.0, exit nodes, subnet routers, and app connectors, could allow inbound connections to other tailnet nodes from their local area network (LAN). This vulnerability only affects Linux exit nodes, subnet routers, and app connectors in tailnets where ACLs allow "src": "*", such as with default ACLs.

Tailscale version 1.66.0 fixes the vulnerability. Additionally, a server-side update changes the interpretation of "src": "*" to mitigate the issue specifically for exit nodes.

Special thanks to Hakan Ergan for reporting a similar concern that led us to discover this vulnerability.

Who was affected?

This affected the following nodes using Tailscale version 1.65 or earlier:

  • Exit nodes on Linux
  • Subnet routers on Linux
  • App connectors on Linux
  • Regular nodes on all platforms connecting to the above nodes

Tailnets with custom ACLs that do not use "src": "*" or any other value that includes external IPs were not affected.

We are not aware of any active exploitation of this vulnerability.

What was the impact?

Devices outside of the tailnet, but on the same LAN as an exit node, subnet router, or app connector could connect to ports on tailnet nodes that are allowed by ACLs.

What do I need to do?

Upgrade the following nodes to 1.66.0 or later:

We recommend enabling auto-updates and updating all nodes to the latest version, but it is not required to mitigate this vulnerability.

A server-side change mitigated this vulnerability for other types of affected nodes.

Technical details

Below, we refer to exit nodes, subnet routers, and app connectors as packet-forwarding nodes, because the details apply to all of them. Specific types of packet-forwarding nodes are mentioned explicitly where their behavior is different.

Before 1.66.0, packets between regular nodes and destination hosts behind packet-forwarding nodes were filtered based on source/destination IP as specified in tailnet ACLs. Specifying "src": "*" in ACLs is equivalent to "src": ["0.0.0.0/0", "::/0"], meaning any IP address. This allowed source IPs outside of the tailnet to send packets to tailnet nodes via a packet-forwarding node. This could be abused by malicious LAN hosts to connect into the tailnet using a known tailnet node IP.

The attack only works on a LAN because:

  • it relies on next-hop routing, which only works in a LAN
  • destination IPs are in the subnet router's approved range, or in the CGNAT range 100.64.0.0/10, which are not routable over the Internet.
Attacks

Here are several attack scenarios.

Packet-forwarding node on an untrusted LAN.

diagram showing a LAN machine connecting to a victim node

A malicious host 10.0.0.1 on the same LAN as the packet-forwarding node 10.0.0.2 could craft packets with destination IP of a tailnet node 100.64.0.1 (using a command like ip route add 100.64.0.1/32 via 10.0.0.2 dev eth0) and send them to the packet-forwarding node. The packet-forwarding node would accept them and forward them to the victim node. The victim node would see a packet from 10.0.0.1 and accept it if the tailnet ACLs allow this source IP.

This scenario is very similar to a legitimate use-case of site-to-site networking, where two subnets are bridged using Tailscale subnet routers and the flag --snat-subnet-routes=false.

Malicious shared exit node

diagram showing a malicious exit node connecting a the victim node

A malicious exit node 100.64.0.4 from tailnet A could craft packets with destination IP of tailnet B node 100.64.0.3 and any source IP other than 100.64.0.4. Due to the built-in quarantining of shared nodes, packets from 100.64.0.4 are rejected.

Mitigations

We implemented 3 separate mitigations for these attacks.

Redefine "src": "*" in ACLs

While * is a convenient shorthand in ACLs, Tailscale users almost never need to allow connections from any IP. In most cases users intend * as "all other nodes in my tailnet". As a mitigation for this vulnerability, we redefined * in src section of ACLs to include:

  • all tailnet nodes
  • all IPs from approved subnet routes

The inclusion of IPs from approved subnet routes is needed for the site-to-site networking setup.

For users that need the old semantics of * we added a new autogroup:danger-all, which matches the old definition of *.

Stateful packet filtering on packet-forwarding nodes

On Linux packet-forwarding nodes we added stateful packet filtering. This means that these nodes keep track of forwarded connections and only allow return packets for existing outbound connections. Inbound packets that don't belong to an existing connection are dropped.

Because routing is implemented differently on non-Linux platforms, this mitigation is only necessary on Linux.

Stateful filtering is enabled by default, except for existing subnet routers that set --snat-subnet-routes=false. You can disable stateful filtering using tailscale up --stateful-filtering=false.

Client-side quarantining of shared nodes

Quarantining of shared nodes was implemented by a packet filter sent from the Tailscale control plane. This packet filter instructs nodes to drop any inbound connections from the source IP of the shared node. To prevent malicious shared exit nodes from crafting packets with different source IPs, additional client-side quarantining logic was added. The 1.66.0 and later clients reject all inbound connections from quarantined nodes, regardless of their source IP. This is similar to how the "shields up" mode works within the tailnet.

Show details on source website


{
  "guidislink": false,
  "id": "https://tailscale.com/security-bulletins/#ts-2024-005",
  "link": "https://tailscale.com/security-bulletins/#ts-2024-005",
  "links": [
    {
      "href": "https://tailscale.com/security-bulletins/#ts-2024-005",
      "rel": "alternate",
      "type": "text/html"
    }
  ],
  "published": "Wed, 08 May 2024 00:00:00 GMT",
  "summary": "\u003cp\u003e\u003cstrong\u003e\u003cem\u003eDescription\u003c/em\u003e\u003c/strong\u003e: Insufficient inbound packet filtering in subnet routers and exit nodes\u003c/p\u003e\n\u003ch5\u003eWhat happened?\u003c/h5\u003e\n\u003cp\u003eIn Tailscale versions earlier than 1.66.0, \u003ca href=\"https://tailscale.com/kb/1103/exit-nodes\"\u003eexit nodes\u003c/a\u003e, \u003ca href=\"https://tailscale.com/kb/1019/subnets\"\u003esubnet\nrouters\u003c/a\u003e, and \u003ca href=\"https://tailscale.com/kb/1281/app-connectors\"\u003eapp connectors\u003c/a\u003e, could\nallow inbound connections to other tailnet nodes from their local area network\n(LAN). This vulnerability only affects Linux exit nodes, subnet routers, and\napp connectors in tailnets where \u003ca href=\"https://tailscale.com/kb/1018/acls\"\u003eACLs\u003c/a\u003e allow \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e, such as\nwith \u003ca href=\"https://tailscale.com/kb/1192/acl-samples#allow-all-default-acl\"\u003edefault ACLs\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eTailscale version 1.66.0 fixes the vulnerability. Additionally, a server-side\nupdate changes the interpretation of \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e to mitigate the issue\nspecifically for exit nodes.\u003c/p\u003e\n\u003cp\u003eSpecial thanks to \u003ca href=\"https://www.linkedin.com/in/hakan-ergan/\"\u003eHakan Ergan\u003c/a\u003e for reporting a similar\nconcern that led us to discover this vulnerability.\u003c/p\u003e\n\u003ch5\u003eWho was affected?\u003c/h5\u003e\n\u003cp\u003eThis affected the following nodes using Tailscale version 1.65 or earlier:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExit nodes on Linux\u003c/li\u003e\n\u003cli\u003eSubnet routers on Linux\u003c/li\u003e\n\u003cli\u003eApp connectors on Linux\u003c/li\u003e\n\u003cli\u003eRegular nodes on all platforms connecting to the above nodes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTailnets with custom ACLs that do not use \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e or any other value that\nincludes external IPs were not affected.\u003c/p\u003e\n\u003cp\u003eWe are not aware of any active exploitation of this vulnerability.\u003c/p\u003e\n\u003ch5\u003eWhat was the impact?\u003c/h5\u003e\n\u003cp\u003eDevices outside of the tailnet, but on the same LAN as an exit node, subnet\nrouter, or app connector could connect to ports on tailnet nodes that are\nallowed by ACLs.\u003c/p\u003e\n\u003ch5\u003eWhat do I need to do?\u003c/h5\u003e\n\u003cp\u003eUpgrade the following nodes to 1.66.0 or later:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSubnet routers on Linux\u003c/li\u003e\n\u003cli\u003eApp connectors on Linux\u003c/li\u003e\n\u003cli\u003eRegular nodes on all platforms that use exit nodes \u003ca href=\"https://tailscale.com/kb/1084/sharing#sharing--exit-nodes\"\u003eshared from other\ntailnets\u003c/a\u003e or \u003ca href=\"https://tailscale.com/kb/1258/mullvad-exit-nodes\"\u003eMullvad exit nodes\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWe recommend enabling auto-updates and updating all nodes to the latest\nversion, but it is not required to mitigate this vulnerability.\u003c/p\u003e\n\u003cp\u003eA server-side change mitigated this vulnerability for other types of affected\nnodes.\u003c/p\u003e\n\u003ch5\u003eTechnical details\u003c/h5\u003e\n\u003cp\u003eBelow, we refer to exit nodes, subnet routers, and app connectors as\n\u003cem\u003epacket-forwarding nodes\u003c/em\u003e, because the details apply to all of them. Specific\ntypes of packet-forwarding nodes are mentioned explicitly where their behavior\nis different.\u003c/p\u003e\n\u003cp\u003eBefore 1.66.0, packets between regular nodes and destination hosts behind\npacket-forwarding nodes were filtered based on source/destination IP as\nspecified in tailnet ACLs. Specifying \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e in ACLs is equivalent to\n\u003ccode\u003e\"src\": [\"0.0.0.0/0\", \"::/0\"]\u003c/code\u003e, meaning any IP address. This allowed source IPs\noutside of the tailnet to send packets to tailnet nodes via a packet-forwarding\nnode. This could be abused by malicious LAN hosts to connect into the tailnet\nusing a known tailnet node IP.\u003c/p\u003e\n\u003cp\u003eThe attack only works on a LAN because:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eit relies on next-hop routing, which only works in a LAN\u003c/li\u003e\n\u003cli\u003edestination IPs are in the subnet router\u0027s approved range, or in the \u003ca href=\"https://tailscale.com/kb/1015/100.x-addresses\"\u003eCGNAT\nrange\u003c/a\u003e \u003ccode\u003e100.64.0.0/10\u003c/code\u003e, which are not routable over the Internet.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch6\u003eAttacks\u003c/h6\u003e\n\u003cp\u003eHere are several attack scenarios.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ePacket-forwarding node on an untrusted LAN.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"diagram showing a LAN machine connecting to a victim node\" src=\"https://tailscale.com/files/images/security-bulletins/2024-05-08-01.svg\" /\u003e\u003c/p\u003e\n\u003cp\u003eA malicious host \u003ccode\u003e10.0.0.1\u003c/code\u003e on the same LAN as the packet-forwarding node\n\u003ccode\u003e10.0.0.2\u003c/code\u003e could craft packets with destination IP of a tailnet node\n\u003ccode\u003e100.64.0.1\u003c/code\u003e (using a command like \u003ccode\u003eip route add 100.64.0.1/32 via 10.0.0.2 dev eth0\u003c/code\u003e) and send them to the packet-forwarding node. The packet-forwarding node\nwould accept them and forward them to the victim node. The victim node would\nsee a packet from \u003ccode\u003e10.0.0.1\u003c/code\u003e and accept it if the tailnet ACLs allow this\nsource IP.\u003c/p\u003e\n\u003cp\u003eThis scenario is very similar to a legitimate use-case of\n\u003ca href=\"https://tailscale.com/kb/1214/site-to-site\"\u003esite-to-site\u003c/a\u003e networking, where two subnets are bridged using\nTailscale subnet routers and the flag \u003ccode\u003e--snat-subnet-routes=false\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eMalicious shared exit node\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"diagram showing a malicious exit node connecting a the victim node\" src=\"https://tailscale.com/files/images/security-bulletins/2024-05-08-02.svg\" /\u003e\u003c/p\u003e\n\u003cp\u003eA malicious exit node \u003ccode\u003e100.64.0.4\u003c/code\u003e from tailnet A could craft packets with\ndestination IP of tailnet B node \u003ccode\u003e100.64.0.3\u003c/code\u003e and any source IP other than\n\u003ccode\u003e100.64.0.4\u003c/code\u003e. Due to the built-in \u003ca href=\"https://tailscale.com/kb/1084/sharing#quarantine\"\u003equarantining\u003c/a\u003e of shared\nnodes, packets from \u003ccode\u003e100.64.0.4\u003c/code\u003e are rejected.\u003c/p\u003e\n\u003ch6\u003eMitigations\u003c/h6\u003e\n\u003cp\u003eWe implemented 3 separate mitigations for these attacks.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRedefine \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e in ACLs\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhile \u003ccode\u003e*\u003c/code\u003e is a convenient shorthand in ACLs, Tailscale users almost never need\nto allow connections from any IP. In most cases users intend \u003ccode\u003e*\u003c/code\u003e as \"all other\nnodes in my tailnet\". As a mitigation for this vulnerability, we redefined \u003ccode\u003e*\u003c/code\u003e\nin \u003ccode\u003esrc\u003c/code\u003e section of ACLs to include:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eall tailnet nodes\u003c/li\u003e\n\u003cli\u003eall IPs from approved subnet routes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe inclusion of IPs from approved subnet routes is needed for the site-to-site\nnetworking setup.\u003c/p\u003e\n\u003cp\u003eFor users that need the old semantics of \u003ccode\u003e*\u003c/code\u003e we added a new\n\u003ca href=\"https://tailscale.com/kb/1337/acl-syntax#src\"\u003e\u003ccode\u003eautogroup:danger-all\u003c/code\u003e\u003c/a\u003e, which matches the old definition of \u003ccode\u003e*\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStateful packet filtering on packet-forwarding nodes\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eOn Linux packet-forwarding nodes we added stateful packet filtering. This means\nthat these nodes keep track of forwarded connections and only allow return\npackets for existing outbound connections. Inbound packets that don\u0027t belong to\nan existing connection are dropped.\u003c/p\u003e\n\u003cp\u003eBecause routing is implemented differently on non-Linux platforms, this\nmitigation is only necessary on Linux.\u003c/p\u003e\n\u003cp\u003eStateful filtering is enabled by default, except for existing subnet routers\nthat set \u003ccode\u003e--snat-subnet-routes=false\u003c/code\u003e. You can disable stateful filtering using\n\u003ccode\u003etailscale up --stateful-filtering=false\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eClient-side quarantining of shared nodes\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://tailscale.com/kb/1084/sharing#quarantine\"\u003eQuarantining\u003c/a\u003e of shared nodes was implemented by a packet\nfilter sent from the Tailscale control plane. This packet filter instructs\nnodes to drop any inbound connections from the source IP of the shared node. To\nprevent malicious shared exit nodes from crafting packets with different source\nIPs, additional client-side quarantining logic was added. The 1.66.0 and later\nclients reject all inbound connections from quarantined nodes, regardless of\ntheir source IP. This is similar to how the \u003ca href=\"https://tailscale.com/kb/1072/client-preferences#allow-incoming-connections\"\u003e\"shields up\"\u003c/a\u003e mode\nworks within the tailnet.\u003c/p\u003e",
  "summary_detail": {
    "base": "https://tailscale.com/security-bulletins/index.xml",
    "language": null,
    "type": "text/html",
    "value": "\u003cp\u003e\u003cstrong\u003e\u003cem\u003eDescription\u003c/em\u003e\u003c/strong\u003e: Insufficient inbound packet filtering in subnet routers and exit nodes\u003c/p\u003e\n\u003ch5\u003eWhat happened?\u003c/h5\u003e\n\u003cp\u003eIn Tailscale versions earlier than 1.66.0, \u003ca href=\"https://tailscale.com/kb/1103/exit-nodes\"\u003eexit nodes\u003c/a\u003e, \u003ca href=\"https://tailscale.com/kb/1019/subnets\"\u003esubnet\nrouters\u003c/a\u003e, and \u003ca href=\"https://tailscale.com/kb/1281/app-connectors\"\u003eapp connectors\u003c/a\u003e, could\nallow inbound connections to other tailnet nodes from their local area network\n(LAN). This vulnerability only affects Linux exit nodes, subnet routers, and\napp connectors in tailnets where \u003ca href=\"https://tailscale.com/kb/1018/acls\"\u003eACLs\u003c/a\u003e allow \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e, such as\nwith \u003ca href=\"https://tailscale.com/kb/1192/acl-samples#allow-all-default-acl\"\u003edefault ACLs\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eTailscale version 1.66.0 fixes the vulnerability. Additionally, a server-side\nupdate changes the interpretation of \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e to mitigate the issue\nspecifically for exit nodes.\u003c/p\u003e\n\u003cp\u003eSpecial thanks to \u003ca href=\"https://www.linkedin.com/in/hakan-ergan/\"\u003eHakan Ergan\u003c/a\u003e for reporting a similar\nconcern that led us to discover this vulnerability.\u003c/p\u003e\n\u003ch5\u003eWho was affected?\u003c/h5\u003e\n\u003cp\u003eThis affected the following nodes using Tailscale version 1.65 or earlier:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExit nodes on Linux\u003c/li\u003e\n\u003cli\u003eSubnet routers on Linux\u003c/li\u003e\n\u003cli\u003eApp connectors on Linux\u003c/li\u003e\n\u003cli\u003eRegular nodes on all platforms connecting to the above nodes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTailnets with custom ACLs that do not use \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e or any other value that\nincludes external IPs were not affected.\u003c/p\u003e\n\u003cp\u003eWe are not aware of any active exploitation of this vulnerability.\u003c/p\u003e\n\u003ch5\u003eWhat was the impact?\u003c/h5\u003e\n\u003cp\u003eDevices outside of the tailnet, but on the same LAN as an exit node, subnet\nrouter, or app connector could connect to ports on tailnet nodes that are\nallowed by ACLs.\u003c/p\u003e\n\u003ch5\u003eWhat do I need to do?\u003c/h5\u003e\n\u003cp\u003eUpgrade the following nodes to 1.66.0 or later:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSubnet routers on Linux\u003c/li\u003e\n\u003cli\u003eApp connectors on Linux\u003c/li\u003e\n\u003cli\u003eRegular nodes on all platforms that use exit nodes \u003ca href=\"https://tailscale.com/kb/1084/sharing#sharing--exit-nodes\"\u003eshared from other\ntailnets\u003c/a\u003e or \u003ca href=\"https://tailscale.com/kb/1258/mullvad-exit-nodes\"\u003eMullvad exit nodes\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWe recommend enabling auto-updates and updating all nodes to the latest\nversion, but it is not required to mitigate this vulnerability.\u003c/p\u003e\n\u003cp\u003eA server-side change mitigated this vulnerability for other types of affected\nnodes.\u003c/p\u003e\n\u003ch5\u003eTechnical details\u003c/h5\u003e\n\u003cp\u003eBelow, we refer to exit nodes, subnet routers, and app connectors as\n\u003cem\u003epacket-forwarding nodes\u003c/em\u003e, because the details apply to all of them. Specific\ntypes of packet-forwarding nodes are mentioned explicitly where their behavior\nis different.\u003c/p\u003e\n\u003cp\u003eBefore 1.66.0, packets between regular nodes and destination hosts behind\npacket-forwarding nodes were filtered based on source/destination IP as\nspecified in tailnet ACLs. Specifying \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e in ACLs is equivalent to\n\u003ccode\u003e\"src\": [\"0.0.0.0/0\", \"::/0\"]\u003c/code\u003e, meaning any IP address. This allowed source IPs\noutside of the tailnet to send packets to tailnet nodes via a packet-forwarding\nnode. This could be abused by malicious LAN hosts to connect into the tailnet\nusing a known tailnet node IP.\u003c/p\u003e\n\u003cp\u003eThe attack only works on a LAN because:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eit relies on next-hop routing, which only works in a LAN\u003c/li\u003e\n\u003cli\u003edestination IPs are in the subnet router\u0027s approved range, or in the \u003ca href=\"https://tailscale.com/kb/1015/100.x-addresses\"\u003eCGNAT\nrange\u003c/a\u003e \u003ccode\u003e100.64.0.0/10\u003c/code\u003e, which are not routable over the Internet.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch6\u003eAttacks\u003c/h6\u003e\n\u003cp\u003eHere are several attack scenarios.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ePacket-forwarding node on an untrusted LAN.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"diagram showing a LAN machine connecting to a victim node\" src=\"https://tailscale.com/files/images/security-bulletins/2024-05-08-01.svg\" /\u003e\u003c/p\u003e\n\u003cp\u003eA malicious host \u003ccode\u003e10.0.0.1\u003c/code\u003e on the same LAN as the packet-forwarding node\n\u003ccode\u003e10.0.0.2\u003c/code\u003e could craft packets with destination IP of a tailnet node\n\u003ccode\u003e100.64.0.1\u003c/code\u003e (using a command like \u003ccode\u003eip route add 100.64.0.1/32 via 10.0.0.2 dev eth0\u003c/code\u003e) and send them to the packet-forwarding node. The packet-forwarding node\nwould accept them and forward them to the victim node. The victim node would\nsee a packet from \u003ccode\u003e10.0.0.1\u003c/code\u003e and accept it if the tailnet ACLs allow this\nsource IP.\u003c/p\u003e\n\u003cp\u003eThis scenario is very similar to a legitimate use-case of\n\u003ca href=\"https://tailscale.com/kb/1214/site-to-site\"\u003esite-to-site\u003c/a\u003e networking, where two subnets are bridged using\nTailscale subnet routers and the flag \u003ccode\u003e--snat-subnet-routes=false\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eMalicious shared exit node\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"diagram showing a malicious exit node connecting a the victim node\" src=\"https://tailscale.com/files/images/security-bulletins/2024-05-08-02.svg\" /\u003e\u003c/p\u003e\n\u003cp\u003eA malicious exit node \u003ccode\u003e100.64.0.4\u003c/code\u003e from tailnet A could craft packets with\ndestination IP of tailnet B node \u003ccode\u003e100.64.0.3\u003c/code\u003e and any source IP other than\n\u003ccode\u003e100.64.0.4\u003c/code\u003e. Due to the built-in \u003ca href=\"https://tailscale.com/kb/1084/sharing#quarantine\"\u003equarantining\u003c/a\u003e of shared\nnodes, packets from \u003ccode\u003e100.64.0.4\u003c/code\u003e are rejected.\u003c/p\u003e\n\u003ch6\u003eMitigations\u003c/h6\u003e\n\u003cp\u003eWe implemented 3 separate mitigations for these attacks.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRedefine \u003ccode\u003e\"src\": \"*\"\u003c/code\u003e in ACLs\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWhile \u003ccode\u003e*\u003c/code\u003e is a convenient shorthand in ACLs, Tailscale users almost never need\nto allow connections from any IP. In most cases users intend \u003ccode\u003e*\u003c/code\u003e as \"all other\nnodes in my tailnet\". As a mitigation for this vulnerability, we redefined \u003ccode\u003e*\u003c/code\u003e\nin \u003ccode\u003esrc\u003c/code\u003e section of ACLs to include:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eall tailnet nodes\u003c/li\u003e\n\u003cli\u003eall IPs from approved subnet routes\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe inclusion of IPs from approved subnet routes is needed for the site-to-site\nnetworking setup.\u003c/p\u003e\n\u003cp\u003eFor users that need the old semantics of \u003ccode\u003e*\u003c/code\u003e we added a new\n\u003ca href=\"https://tailscale.com/kb/1337/acl-syntax#src\"\u003e\u003ccode\u003eautogroup:danger-all\u003c/code\u003e\u003c/a\u003e, which matches the old definition of \u003ccode\u003e*\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStateful packet filtering on packet-forwarding nodes\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eOn Linux packet-forwarding nodes we added stateful packet filtering. This means\nthat these nodes keep track of forwarded connections and only allow return\npackets for existing outbound connections. Inbound packets that don\u0027t belong to\nan existing connection are dropped.\u003c/p\u003e\n\u003cp\u003eBecause routing is implemented differently on non-Linux platforms, this\nmitigation is only necessary on Linux.\u003c/p\u003e\n\u003cp\u003eStateful filtering is enabled by default, except for existing subnet routers\nthat set \u003ccode\u003e--snat-subnet-routes=false\u003c/code\u003e. You can disable stateful filtering using\n\u003ccode\u003etailscale up --stateful-filtering=false\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eClient-side quarantining of shared nodes\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://tailscale.com/kb/1084/sharing#quarantine\"\u003eQuarantining\u003c/a\u003e of shared nodes was implemented by a packet\nfilter sent from the Tailscale control plane. This packet filter instructs\nnodes to drop any inbound connections from the source IP of the shared node. To\nprevent malicious shared exit nodes from crafting packets with different source\nIPs, additional client-side quarantining logic was added. The 1.66.0 and later\nclients reject all inbound connections from quarantined nodes, regardless of\ntheir source IP. This is similar to how the \u003ca href=\"https://tailscale.com/kb/1072/client-preferences#allow-incoming-connections\"\u003e\"shields up\"\u003c/a\u003e mode\nworks within the tailnet.\u003c/p\u003e"
  },
  "title": "TS-2024-005",
  "title_detail": {
    "base": "https://tailscale.com/security-bulletins/index.xml",
    "language": null,
    "type": "text/plain",
    "value": "TS-2024-005"
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.