feat: support via gateway for v6 multihop for v4 routes (#1521)

Co-authored-by: Nate Brown <nbrown.us@gmail.com>
This commit is contained in:
Bryan Lee
2025-11-19 20:21:03 -08:00
committed by GitHub
parent a5ee928990
commit 12cf348c80

View File

@@ -586,48 +586,42 @@ func (t *tun) isGatewayInVpnNetworks(gwAddr netip.Addr) bool {
} }
func (t *tun) getGatewaysFromRoute(r *netlink.Route) routing.Gateways { func (t *tun) getGatewaysFromRoute(r *netlink.Route) routing.Gateways {
var gateways routing.Gateways var gateways routing.Gateways
link, err := netlink.LinkByName(t.Device) link, err := netlink.LinkByName(t.Device)
if err != nil { if err != nil {
t.l.WithField("Devicename", t.Device).Error("Ignoring route update: failed to get link by name") t.l.WithField("deviceName", t.Device).Error("Ignoring route update: failed to get link by name")
return gateways return gateways
} }
// If this route is relevant to our interface and there is a gateway then add it // If this route is relevant to our interface and there is a gateway then add it
if r.LinkIndex == link.Attrs().Index && len(r.Gw) > 0 { if r.LinkIndex == link.Attrs().Index {
gwAddr, ok := netip.AddrFromSlice(r.Gw) gwAddr, ok := getGatewayAddr(r.Gw, r.Via)
if !ok { if ok {
t.l.WithField("route", r).Debug("Ignoring route update, invalid gateway address") if t.isGatewayInVpnNetworks(gwAddr) {
} else {
gwAddr = gwAddr.Unmap()
if !t.isGatewayInVpnNetworks(gwAddr) {
// Gateway isn't in our overlay network, ignore
t.l.WithField("route", r).Debug("Ignoring route update, not in our network")
} else {
gateways = append(gateways, routing.NewGateway(gwAddr, 1)) gateways = append(gateways, routing.NewGateway(gwAddr, 1))
} else {
// Gateway isn't in our overlay network, ignore
t.l.WithField("route", r).Debug("Ignoring route update, gateway is not in our network")
} }
} else {
t.l.WithField("route", r).Debug("Ignoring route update, invalid gateway or via address")
} }
} }
for _, p := range r.MultiPath { for _, p := range r.MultiPath {
// If this route is relevant to our interface and there is a gateway then add it // If this route is relevant to our interface and there is a gateway then add it
if p.LinkIndex == link.Attrs().Index && len(p.Gw) > 0 { if p.LinkIndex == link.Attrs().Index {
gwAddr, ok := netip.AddrFromSlice(p.Gw) gwAddr, ok := getGatewayAddr(p.Gw, p.Via)
if !ok { if ok {
t.l.WithField("route", r).Debug("Ignoring multipath route update, invalid gateway address") if t.isGatewayInVpnNetworks(gwAddr) {
} else {
gwAddr = gwAddr.Unmap()
if !t.isGatewayInVpnNetworks(gwAddr) {
// Gateway isn't in our overlay network, ignore
t.l.WithField("route", r).Debug("Ignoring route update, not in our network")
} else {
// p.Hops+1 = weight of the route
gateways = append(gateways, routing.NewGateway(gwAddr, p.Hops+1)) gateways = append(gateways, routing.NewGateway(gwAddr, p.Hops+1))
} else {
// Gateway isn't in our overlay network, ignore
t.l.WithField("route", r).Debug("Ignoring route update, gateway is not in our network")
} }
} else {
t.l.WithField("route", r).Debug("Ignoring route update, invalid gateway or via address")
} }
} }
} }
@@ -636,10 +630,27 @@ func (t *tun) getGatewaysFromRoute(r *netlink.Route) routing.Gateways {
return gateways return gateways
} }
func getGatewayAddr(gw net.IP, via netlink.Destination) (netip.Addr, bool) {
// Try to use the old RTA_GATEWAY first
gwAddr, ok := netip.AddrFromSlice(gw)
if !ok {
// Fallback to the new RTA_VIA
rVia, ok := via.(*netlink.Via)
if ok {
gwAddr, ok = netip.AddrFromSlice(rVia.Addr)
}
}
if gwAddr.IsValid() {
gwAddr = gwAddr.Unmap()
return gwAddr, true
}
return netip.Addr{}, false
}
func (t *tun) updateRoutes(r netlink.RouteUpdate) { func (t *tun) updateRoutes(r netlink.RouteUpdate) {
gateways := t.getGatewaysFromRoute(&r.Route) gateways := t.getGatewaysFromRoute(&r.Route)
if len(gateways) == 0 { if len(gateways) == 0 {
// No gateways relevant to our network, no routing changes required. // No gateways relevant to our network, no routing changes required.
t.l.WithField("route", r).Debug("Ignoring route update, no gateways") t.l.WithField("route", r).Debug("Ignoring route update, no gateways")