ipn/ipnlocal: fix app connector route advertisements on exit nodes

If an app connector is also configured as an exit node, it should still
advertise discovered routes that are not covered by advertised routes,
excluding the exit node routes.

Updates tailscale/corp#16928

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker 2024-01-31 17:36:39 -08:00 committed by James Tucker
parent e1a4b89dbe
commit ba70cbb930
2 changed files with 19 additions and 6 deletions

View File

@ -5808,7 +5808,7 @@ func (b *LocalBackend) AdvertiseRoute(ipps ...netip.Prefix) error {
} }
// If the new prefix is already contained by existing routes, skip it. // If the new prefix is already contained by existing routes, skip it.
if coveredRouteRange(finalRoutes, ipp) { if coveredRouteRangeNoDefault(finalRoutes, ipp) {
continue continue
} }
@ -5829,10 +5829,13 @@ func (b *LocalBackend) AdvertiseRoute(ipps ...netip.Prefix) error {
return err return err
} }
// coveredRouteRange checks if a route is already included in a slice of // coveredRouteRangeNoDefault checks if a route is already included in a slice of
// prefixes. // prefixes, ignoring default routes in the range.
func coveredRouteRange(finalRoutes []netip.Prefix, ipp netip.Prefix) bool { func coveredRouteRangeNoDefault(finalRoutes []netip.Prefix, ipp netip.Prefix) bool {
for _, r := range finalRoutes { for _, r := range finalRoutes {
if r == tsaddr.AllIPv4() || r == tsaddr.AllIPv6() {
continue
}
if ipp.IsSingleIP() { if ipp.IsSingleIP() {
if r.Contains(ipp.Addr()) { if r.Contains(ipp.Addr()) {
return true return true

View File

@ -1218,7 +1218,7 @@ func TestObserveDNSResponse(t *testing.T) {
} }
} }
func TestCoveredRouteRange(t *testing.T) { func TestCoveredRouteRangeNoDefault(t *testing.T) {
tests := []struct { tests := []struct {
existingRoute netip.Prefix existingRoute netip.Prefix
newRoute netip.Prefix newRoute netip.Prefix
@ -1244,10 +1244,20 @@ func TestCoveredRouteRange(t *testing.T) {
newRoute: netip.MustParsePrefix("192.0.0.0/24"), newRoute: netip.MustParsePrefix("192.0.0.0/24"),
want: true, want: true,
}, },
{
existingRoute: netip.MustParsePrefix("0.0.0.0/0"),
newRoute: netip.MustParsePrefix("192.0.0.0/24"),
want: false,
},
{
existingRoute: netip.MustParsePrefix("::/0"),
newRoute: netip.MustParsePrefix("2001:db8::/32"),
want: false,
},
} }
for _, tt := range tests { for _, tt := range tests {
got := coveredRouteRange([]netip.Prefix{tt.existingRoute}, tt.newRoute) got := coveredRouteRangeNoDefault([]netip.Prefix{tt.existingRoute}, tt.newRoute)
if got != tt.want { if got != tt.want {
t.Errorf("coveredRouteRange(%v, %v) = %v, want %v", tt.existingRoute, tt.newRoute, got, tt.want) t.Errorf("coveredRouteRange(%v, %v) = %v, want %v", tt.existingRoute, tt.newRoute, got, tt.want)
} }