cmd/k8s-operator, net/netutil: support 4via6 in egress proxy and connector (#19863)

Add support for configuring egress to destinations reachable via 4via6
subnet routes. This change affects standalone egress proxy only- egress
ProxyGroup needs IPv6 support before being able to support 4via6. Egress may
be configured using either the synthesized 4via6 address or the MagicDNS
name (in the form
<IPv4-address-with-hyphens-instead-of-dots>-via-<siteid>[.*]).

Also update the Connector to validate and advertise 4via6 subnet routes.
Export net/netutil.ValidateViaPrefix so it can be reused by the Connector
validation logic.

Updates #19334

Signed-off-by: Becky Pauley <becky@tailscale.com>
This commit is contained in:
BeckyPauley
2026-05-27 10:54:35 +01:00
committed by GitHub
parent e5a8cf3b18
commit 0ed6da2826
4 changed files with 83 additions and 3 deletions
+7
View File
@@ -29,6 +29,8 @@ import (
tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes"
"tailscale.com/net/netutil"
"tailscale.com/net/tsaddr"
"tailscale.com/tstime"
"tailscale.com/util/clientmetric"
"tailscale.com/util/set"
@@ -356,6 +358,11 @@ func validateRoutes(routes tsapi.Routes) error {
if pfx.Masked() != pfx {
errs = append(errs, fmt.Errorf("route %s has non-address bits set; expected %s", pfx, pfx.Masked()))
}
if tsaddr.IsViaPrefix(pfx) {
if err := netutil.ValidateViaPrefix(pfx); err != nil {
errs = append(errs, err)
}
}
}
return errors.Join(errs...)
}
+16
View File
@@ -145,6 +145,22 @@ func TestConnector(t *testing.T) {
expectReconciled(t, cr, "", "test")
expectEqual(t, fc, expectedSTS(t, fc, opts), removeResourceReqs)
// Set an invalid 4via6 route (site ID too large).
mustUpdate[tsapi.Connector](t, fc, "", "test", func(conn *tsapi.Connector) {
conn.Spec.SubnetRouter.AdvertiseRoutes = []tsapi.Route{"fd7a:115c:a1e0:b1a:1:0:a2c:0/116"}
})
expectReconciled(t, cr, "", "test")
// STS should still have the previous valid route, unchanged.
expectEqual(t, fc, expectedSTS(t, fc, opts), removeResourceReqs)
// Set a valid 4via6 route.
mustUpdate[tsapi.Connector](t, fc, "", "test", func(conn *tsapi.Connector) {
conn.Spec.SubnetRouter.AdvertiseRoutes = []tsapi.Route{"fd7a:115c:a1e0:b1a:0:1:a2c:0/116"}
})
opts.subnetRoutes = "fd7a:115c:a1e0:b1a:0:1:a2c:0/116"
expectReconciled(t, cr, "", "test")
expectEqual(t, fc, expectedSTS(t, fc, opts), removeResourceReqs)
// Delete the Connector.
if err = fc.Delete(context.Background(), cn); err != nil {
t.Fatalf("error deleting Connector: %v", err)