wg-quicker/wg.go

173 lines
4.1 KiB
Go
Raw Normal View History

2019-03-27 17:26:09 +01:00
package wgquick
2019-03-26 13:44:38 +01:00
import (
"github.com/mdlayher/wireguardctrl"
2019-03-26 13:57:33 +01:00
"github.com/sirupsen/logrus"
2019-03-26 13:44:38 +01:00
"github.com/vishvananda/netlink"
2019-03-27 17:26:09 +01:00
"syscall"
2019-03-26 13:44:38 +01:00
)
2019-03-27 17:40:06 +01:00
const (
defaultRoutingTable = 254
)
2019-03-26 13:57:33 +01:00
// Sync the config to the current setup for given interface
func (cfg *Config) Sync(iface string, logger logrus.FieldLogger) error {
log := logger.WithField("iface", iface)
2019-03-26 13:44:38 +01:00
link, err := netlink.LinkByName(iface)
if err != nil {
if _, ok := err.(netlink.LinkNotFoundError); !ok {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot read link")
2019-03-26 13:44:38 +01:00
return err
}
log.Info("link not found, creating")
wgLink := &netlink.GenericLink{
LinkAttrs: netlink.LinkAttrs{
Name: iface,
2019-03-26 13:58:26 +01:00
MTU: cfg.MTU,
2019-03-26 13:44:38 +01:00
},
LinkType: "wireguard",
}
if err := netlink.LinkAdd(wgLink); err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot create link")
2019-03-26 13:44:38 +01:00
return err
}
link, err = netlink.LinkByName(iface)
if err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot read link")
2019-03-26 13:44:38 +01:00
return err
}
}
if err := netlink.LinkSetUp(link); err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot set link up")
2019-03-26 13:44:38 +01:00
return err
}
2019-03-26 13:57:33 +01:00
log.Info("set device up")
2019-03-26 13:44:38 +01:00
cl, err := wireguardctrl.New()
if err != nil {
log.Error(err, "cannot setup wireguard device")
return err
}
if err := cl.ConfigureDevice(iface, cfg.Config); err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot configure device")
2019-03-26 13:44:38 +01:00
return err
}
2019-03-26 13:57:33 +01:00
if err := syncAddress(link, cfg, log); err != nil {
2019-03-26 13:44:38 +01:00
log.Error(err, "cannot sync addresses")
return err
}
2019-03-26 13:57:33 +01:00
if err := syncRoutes(link, cfg, log); err != nil {
2019-03-26 13:44:38 +01:00
log.Error(err, "cannot sync routes")
return err
}
2019-03-26 14:35:31 +01:00
log.Info("Successfully setup device")
2019-03-26 13:44:38 +01:00
return nil
}
2019-03-26 13:57:33 +01:00
func syncAddress(link netlink.Link, cfg *Config, log logrus.FieldLogger) error {
2019-03-26 13:44:38 +01:00
addrs, err := netlink.AddrList(link, syscall.AF_INET)
if err != nil {
log.Error(err, "cannot read link address")
return err
}
2019-03-27 17:40:06 +01:00
// nil addr means I've used it
presentAddresses := make(map[string]*netlink.Addr, 0)
2019-03-26 13:44:38 +01:00
for _, addr := range addrs {
2019-03-27 17:40:06 +01:00
presentAddresses[addr.IPNet.String()] = &addr
2019-03-26 13:44:38 +01:00
}
for _, addr := range cfg.Address {
2019-03-26 13:57:33 +01:00
log := log.WithField("addr", addr)
2019-03-26 13:44:38 +01:00
_, present := presentAddresses[addr.String()]
2019-03-27 17:40:06 +01:00
presentAddresses[addr.String()] = nil // mark as present
2019-03-26 13:44:38 +01:00
if present {
2019-03-26 13:57:33 +01:00
log.Info("address present")
2019-03-26 13:44:38 +01:00
continue
}
if err := netlink.AddrAdd(link, &netlink.Addr{
IPNet: addr,
}); err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot add addr")
2019-03-26 13:44:38 +01:00
return err
}
2019-03-26 13:57:33 +01:00
log.Info("address added")
2019-03-26 13:44:38 +01:00
}
2019-03-27 17:40:06 +01:00
for _, addr := range presentAddresses {
if addr == nil {
continue
}
log := log.WithField("addr", addr.IPNet.String())
if err := netlink.AddrDel(link, addr); err != nil {
log.WithError(err).Error("cannot delete addr")
return err
2019-03-26 13:44:38 +01:00
}
2019-03-27 17:40:06 +01:00
log.Info("addr deleted")
2019-03-26 13:44:38 +01:00
}
return nil
}
2019-03-26 13:57:33 +01:00
func syncRoutes(link netlink.Link, cfg *Config, log logrus.FieldLogger) error {
2019-03-26 13:44:38 +01:00
routes, err := netlink.RouteList(link, syscall.AF_INET)
if err != nil {
log.Error(err, "cannot read existing routes")
return err
}
2019-03-27 17:40:06 +01:00
presentRoutes := make(map[string]*netlink.Route, 0)
2019-03-26 13:44:38 +01:00
for _, r := range routes {
2019-03-26 14:35:31 +01:00
log := log.WithField("route", r.Dst.String())
2019-03-27 17:40:06 +01:00
if r.Table == cfg.Table || (cfg.Table == 0 && r.Table == defaultRoutingTable) {
presentRoutes[r.Dst.String()] = &r
2019-03-26 14:53:14 +01:00
log.WithField("table", r.Table).Debug("detected existing route")
2019-03-26 14:35:31 +01:00
} else {
log.Debug("wrong table for route, skipping")
2019-03-26 14:01:02 +01:00
}
2019-03-26 13:44:38 +01:00
}
for _, peer := range cfg.Peers {
for _, rt := range peer.AllowedIPs {
_, present := presentRoutes[rt.String()]
2019-03-27 17:40:06 +01:00
presentRoutes[rt.String()] = nil // mark as visited
2019-03-26 13:57:33 +01:00
log := log.WithField("route", rt.String())
2019-03-26 13:44:38 +01:00
if present {
2019-03-26 13:57:33 +01:00
log.Info("route present")
2019-03-26 13:44:38 +01:00
continue
}
if err := netlink.RouteAdd(&netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: &rt,
2019-03-26 14:01:02 +01:00
Table: cfg.Table,
2019-03-26 13:44:38 +01:00
}); err != nil {
2019-03-26 13:57:33 +01:00
log.WithError(err).Error("cannot setup route")
2019-03-26 13:44:38 +01:00
return err
}
2019-03-26 13:57:33 +01:00
log.Info("route added")
2019-03-26 13:44:38 +01:00
}
}
// Clean extra routes
2019-03-27 17:40:06 +01:00
for _, rt := range presentRoutes {
if rt == nil { // skip visited routes
continue
2019-03-26 13:44:38 +01:00
}
2019-03-27 17:40:06 +01:00
log := log.WithField("route", rt.Dst.String())
log.Info("extra manual route found")
if err := netlink.RouteDel(rt); err != nil {
log.WithError(err).Error("cannot setup route")
return err
2019-03-26 13:44:38 +01:00
}
2019-03-27 17:40:06 +01:00
log.Info("route deleted")
2019-03-26 13:44:38 +01:00
}
return nil
}