Implement networks routed through wesher

This adds an option for specifying a routed network. Every node route
that belongs to that routed network will be announced to the cluster and
every other node will direct traffic to that node for said route.
This commit is contained in:
kaiyou
2020-05-18 10:42:32 +02:00
parent e9aae4dc3b
commit 8637377cec
6 changed files with 104 additions and 8 deletions

View File

@ -94,7 +94,7 @@ func (s *State) DownInterface() error {
}
// SetUpInterface creates and sets up the associated network interface
func (s *State) SetUpInterface(nodes []common.Node) error {
func (s *State) SetUpInterface(nodes []common.Node, routedNet *net.IPNet) error {
if err := netlink.LinkAdd(&wireguard{LinkAttrs: netlink.LinkAttrs{Name: s.iface}}); err != nil && !os.IsExist(err) {
return errors.Wrapf(err, "could not create interface %s", s.iface)
}
@ -128,12 +128,45 @@ func (s *State) SetUpInterface(nodes []common.Node) error {
if err := netlink.LinkSetUp(link); err != nil {
return errors.Wrapf(err, "could not enable interface %s", s.iface)
}
for _, node := range nodes {
netlink.RouteAdd(&netlink.Route{
// first compute routes
currentRoutes, err := netlink.RouteList(link, netlink.FAMILY_ALL)
if err != nil {
return errors.Wrapf(err, "could not update the routing table for %s", s.iface)
}
routes := make([]netlink.Route, 0)
for index, node := range nodes {
// dev route
routes = append(routes, netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: &node.OverlayAddr,
Dst: &nodes[index].OverlayAddr,
Scope: netlink.SCOPE_LINK,
})
// via routes
for _, route := range node.Routes {
routes = append(routes, netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: &route,
Gw: node.OverlayAddr.IP,
Scope: netlink.SCOPE_SITE,
})
}
}
// then actually update the routing table
for _, route := range routes {
match := matchRoute(currentRoutes, route)
if match == nil {
netlink.RouteAdd(&route)
} else if match.Gw.String() != route.Gw.String() {
netlink.RouteReplace(&route)
}
}
for _, route := range routes {
// only delete a reoute if it is a site scope route that belongs to the routed net, mainly to
// avoid deleting otherwise manually set routes
if matchRoute(currentRoutes, route) == nil && route.Scope == netlink.SCOPE_LINK && routedNet.Contains(route.Dst.IP) {
netlink.RouteDel(&route)
}
}
return nil
@ -153,10 +186,20 @@ func (s *State) nodesToPeerConfigs(nodes []common.Node) ([]wgtypes.PeerConfig, e
IP: node.Addr,
Port: s.Port,
},
AllowedIPs: []net.IPNet{
node.OverlayAddr,
},
AllowedIPs: append([]net.IPNet{node.OverlayAddr}, node.Routes...),
}
}
return peerCfgs, nil
}
func matchRoute(set []netlink.Route, needle netlink.Route) *netlink.Route {
// routes are considered equal if they overlap and have the same prefix length
prefixn, _ := needle.Dst.Mask.Size()
for _, route := range set {
prefixr, _ := route.Dst.Mask.Size()
if prefixn == prefixr && route.Dst.Contains(needle.Dst.IP) {
return &route
}
}
return nil
}