allow configuring extra routes

Useful for routing IPv6 subnets through a WireGuard tunnel.

related to https://github.com/rtr7/router7/issues/52
This commit is contained in:
Michael Stapelberg 2022-06-06 14:17:44 +02:00
parent f52deeed03
commit 7d936f4844
2 changed files with 40 additions and 2 deletions

View File

@ -53,6 +53,12 @@ const goldenInterfaces = `
"addr": "fe80::1/64", "addr": "fe80::1/64",
"extra_addrs": [ "extra_addrs": [
"10.22.100.1/24" "10.22.100.1/24"
],
"extra_routes": [
{
"destination": "2a02:168:4a00:22::/64",
"gateway": "fe80::2"
}
] ]
} }
] ]
@ -475,6 +481,16 @@ peer: AVU3LodtnFaFnJmMyNNW7cUk4462lqnVULTFkjWYvRo=
t.Errorf("regexp %s does not match %s", addr6Re, string(out)) t.Errorf("regexp %s does not match %s", addr6Re, string(out))
} }
out, err = exec.Command("ip", "-netns", ns, "-6", "route", "show", "dev", "wg0").Output()
if err != nil {
t.Fatal(err)
}
extraRouteRe := regexp.MustCompile(`(?m)^\s*2a02:168:4a00:22::/64 via fe80::2 metric 1024 pref medium\s*$`)
if !extraRouteRe.MatchString(string(out)) {
t.Errorf("regexp %s does not match %s", extraRouteRe, string(out))
}
}) })
opts := []cmp.Option{ opts := []cmp.Option{

View File

@ -191,12 +191,18 @@ func applyDhcp6(dir string) error {
return nil return nil
} }
type Route struct {
Destination string `json:"destination"` // e.g. 2a02:168:4a00:22::/64
Gateway string `json:"gateway"` // e.g. fe80::1
}
type InterfaceDetails struct { type InterfaceDetails struct {
HardwareAddr string `json:"hardware_addr"` // e.g. dc:9b:9c:ee:72:fd HardwareAddr string `json:"hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
SpoofHardwareAddr string `json:"spoof_hardware_addr"` // e.g. dc:9b:9c:ee:72:fd SpoofHardwareAddr string `json:"spoof_hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
Name string `json:"name"` // e.g. uplink0, or lan0 Name string `json:"name"` // e.g. uplink0, or lan0
Addr string `json:"addr"` // e.g. 192.168.42.1/24 Addr string `json:"addr"` // e.g. 192.168.42.1/24
ExtraAddrs []string `json:"extra_addrs"` // e.g. ["192.168.23.1/24"] ExtraAddrs []string `json:"extra_addrs"` // e.g. ["192.168.23.1/24"]
ExtraRoutes []Route `json:"extra_routes"`
} }
type BridgeDetails struct { type BridgeDetails struct {
@ -402,6 +408,7 @@ func applyInterfaces(dir, root string) error {
} }
for _, addr := range details.ExtraAddrs { for _, addr := range details.ExtraAddrs {
log.Printf("replacing extra address %v on %v", addr, attr.Name)
addr, err := netlink.ParseAddr(addr) addr, err := netlink.ParseAddr(addr)
if err != nil { if err != nil {
return fmt.Errorf("ParseAddr(%q): %v", addr, err) return fmt.Errorf("ParseAddr(%q): %v", addr, err)
@ -412,8 +419,23 @@ func applyInterfaces(dir, root string) error {
} }
} }
// TODO: allow static route configuration (ExtraRoutes) for _, route := range details.ExtraRoutes {
// 2a02:168:4a00:22::/64 via fe80::2 dev wg0 _, dst, err := net.ParseCIDR(route.Destination)
if err != nil {
return fmt.Errorf("ParseCIDR(%q): %v", route.Destination, err)
}
r := &netlink.Route{Dst: dst}
if route.Gateway != "" {
r.Gw = net.ParseIP(route.Gateway)
}
r.LinkIndex = attr.Index
log.Printf("replacing extra route %v on %v", r, attr.Name)
if err := netlink.RouteReplace(r); err != nil {
return fmt.Errorf("RouteReplace(%v): %v", r, err)
}
}
} }
return nil return nil
} }