mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-19 05:02:34 +00:00
ipn/ipnlocal: make IPv6 OS routes be a single /48 for our ULA space
And if we have over 10,000 CGNAT routes, just route the entire CGNAT range. (for the hello test server) Fixes #1450 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
a6d098c750
commit
82edf94df7
@ -1362,6 +1362,41 @@ var (
|
|||||||
ipv6Default = netaddr.MustParseIPPrefix("::/0")
|
ipv6Default = netaddr.MustParseIPPrefix("::/0")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// peerRoutes returns the routerConfig.Routes to access peers.
|
||||||
|
// If there are over cgnatThreshold CGNAT routes, one big CGNAT route
|
||||||
|
// is used instead.
|
||||||
|
func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netaddr.IPPrefix) {
|
||||||
|
tsULA := tsaddr.TailscaleULARange()
|
||||||
|
cgNAT := tsaddr.CGNATRange()
|
||||||
|
var didULA bool
|
||||||
|
var cgNATIPs []netaddr.IPPrefix
|
||||||
|
for _, peer := range peers {
|
||||||
|
for _, aip := range peer.AllowedIPs {
|
||||||
|
aip = unmapIPPrefix(aip)
|
||||||
|
// Only add the Tailscale IPv6 ULA once, if we see anybody using part of it.
|
||||||
|
if aip.IP.Is6() && aip.IsSingleIP() && tsULA.Contains(aip.IP) {
|
||||||
|
if !didULA {
|
||||||
|
didULA = true
|
||||||
|
routes = append(routes, tsULA)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if aip.IsSingleIP() && cgNAT.Contains(aip.IP) {
|
||||||
|
cgNATIPs = append(cgNATIPs, aip)
|
||||||
|
} else {
|
||||||
|
routes = append(routes, aip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(cgNATIPs) > cgnatThreshold {
|
||||||
|
// Probably the hello server. Just append one big route.
|
||||||
|
routes = append(routes, cgNAT)
|
||||||
|
} else {
|
||||||
|
routes = append(routes, cgNATIPs...)
|
||||||
|
}
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
// routerConfig produces a router.Config from a wireguard config and IPN prefs.
|
// routerConfig produces a router.Config from a wireguard config and IPN prefs.
|
||||||
func routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router.Config {
|
func routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router.Config {
|
||||||
rs := &router.Config{
|
rs := &router.Config{
|
||||||
@ -1369,10 +1404,7 @@ func routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router.Config {
|
|||||||
SubnetRoutes: unmapIPPrefixes(prefs.AdvertiseRoutes),
|
SubnetRoutes: unmapIPPrefixes(prefs.AdvertiseRoutes),
|
||||||
SNATSubnetRoutes: !prefs.NoSNAT,
|
SNATSubnetRoutes: !prefs.NoSNAT,
|
||||||
NetfilterMode: prefs.NetfilterMode,
|
NetfilterMode: prefs.NetfilterMode,
|
||||||
}
|
Routes: peerRoutes(cfg.Peers, 10_000),
|
||||||
|
|
||||||
for _, peer := range cfg.Peers {
|
|
||||||
rs.Routes = append(rs.Routes, unmapIPPrefixes(peer.AllowedIPs)...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check: we expect the control server to program both a v4
|
// Sanity check: we expect the control server to program both a v4
|
||||||
@ -1409,10 +1441,14 @@ func routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router.Config {
|
|||||||
return rs
|
return rs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmapIPPrefix(ipp netaddr.IPPrefix) netaddr.IPPrefix {
|
||||||
|
return netaddr.IPPrefix{IP: ipp.IP.Unmap(), Bits: ipp.Bits}
|
||||||
|
}
|
||||||
|
|
||||||
func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) {
|
func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) {
|
||||||
for _, ipps := range ippsList {
|
for _, ipps := range ippsList {
|
||||||
for _, ipp := range ipps {
|
for _, ipp := range ipps {
|
||||||
ret = append(ret, netaddr.IPPrefix{IP: ipp.IP.Unmap(), Bits: ipp.Bits})
|
ret = append(ret, unmapIPPrefix(ipp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
package ipnlocal
|
package ipnlocal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
|
"tailscale.com/wgengine/wgcfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNetworkMapCompare(t *testing.T) {
|
func TestNetworkMapCompare(t *testing.T) {
|
||||||
@ -171,3 +173,95 @@ func TestShrinkDefaultRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPeerRoutes(t *testing.T) {
|
||||||
|
pp := netaddr.MustParseIPPrefix
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
peers []wgcfg.Peer
|
||||||
|
want []netaddr.IPPrefix
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "small_v4",
|
||||||
|
peers: []wgcfg.Peer{
|
||||||
|
{
|
||||||
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
|
pp("100.101.102.103/32"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []netaddr.IPPrefix{
|
||||||
|
pp("100.101.102.103/32"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "big_v4",
|
||||||
|
peers: []wgcfg.Peer{
|
||||||
|
{
|
||||||
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
|
pp("100.101.102.103/32"),
|
||||||
|
pp("100.101.102.104/32"),
|
||||||
|
pp("100.101.102.105/32"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []netaddr.IPPrefix{
|
||||||
|
pp("100.64.0.0/10"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "has_1_v6",
|
||||||
|
peers: []wgcfg.Peer{
|
||||||
|
{
|
||||||
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
|
pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b240/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []netaddr.IPPrefix{
|
||||||
|
pp("fd7a:115c:a1e0::/48"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "has_2_v6",
|
||||||
|
peers: []wgcfg.Peer{
|
||||||
|
{
|
||||||
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
|
pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b240/128"),
|
||||||
|
pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b241/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []netaddr.IPPrefix{
|
||||||
|
pp("fd7a:115c:a1e0::/48"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "big_v4_big_v6",
|
||||||
|
peers: []wgcfg.Peer{
|
||||||
|
{
|
||||||
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
|
pp("100.101.102.103/32"),
|
||||||
|
pp("100.101.102.104/32"),
|
||||||
|
pp("100.101.102.105/32"),
|
||||||
|
pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b240/128"),
|
||||||
|
pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b241/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: []netaddr.IPPrefix{
|
||||||
|
pp("fd7a:115c:a1e0::/48"),
|
||||||
|
pp("100.64.0.0/10"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := peerRoutes(tt.peers, 2)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("got = %v; want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user