wgengine/router: alter API to support multiple addrs, and use on linux.

FreeBSD and OpenBSD will error out with a complaint if we pass >1 address
right now, but we don't yet so that's okay.
pull/361/head
David Anderson 4 years ago
parent 6802481bf5
commit 8861bb5a19

@ -41,7 +41,7 @@ func New(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (Router, err
// IP, etc in wgcfg.Config) plus the things that WireGuard doesn't do // IP, etc in wgcfg.Config) plus the things that WireGuard doesn't do
// itself, like DNS stuff. // itself, like DNS stuff.
type RouteSettings struct { type RouteSettings struct {
LocalAddr wgcfg.CIDR // TODO: why is this here? how does it differ from wgcfg.Config's info? LocalAddrs []wgcfg.CIDR
DNS []wgcfg.IP DNS []wgcfg.IP
DNSDomains []string DNSDomains []string
SubnetRoutes []wgcfg.CIDR // subnets being advertised to other Tailscale nodes SubnetRoutes []wgcfg.CIDR // subnets being advertised to other Tailscale nodes
@ -55,5 +55,5 @@ func (rs *RouteSettings) OnlyRelevantParts() string {
peers = append(peers, p.AllowedIPs) peers = append(peers, p.AllowedIPs)
} }
return fmt.Sprintf("%v %v %v %v %v", return fmt.Sprintf("%v %v %v %v %v",
rs.LocalAddr, rs.DNS, rs.DNSDomains, rs.SubnetRoutes, peers) rs.LocalAddrs, rs.DNS, rs.DNSDomains, rs.SubnetRoutes, peers)
} }

@ -5,6 +5,7 @@
package router package router
import ( import (
"errors"
"fmt" "fmt"
"log" "log"
"os/exec" "os/exec"
@ -55,14 +56,19 @@ func (r *freebsdRouter) Up() error {
} }
func (r *freebsdRouter) SetRoutes(rs RouteSettings) error { func (r *freebsdRouter) SetRoutes(rs RouteSettings) error {
if rs.LocalAddr == (wgcfg.CIDR{}) { if len(rs.LocalAddrs) == 0 {
return nil return nil
} }
// TODO: support configuring multiple local addrs on interface.
if len(rs.LocalAddrs) != 1 {
return errors.New("freebsd doesn't support setting multiple local addrs yet")
}
localAddr := rs.LocalAddrs[0]
var errq error var errq error
// Update the address. // Update the address.
if rs.LocalAddr != r.local { if localAddr != r.local {
// If the interface is already set, remove it. // If the interface is already set, remove it.
if r.local != (wgcfg.CIDR{}) { if r.local != (wgcfg.CIDR{}) {
addrdel := []string{"ifconfig", r.tunname, addrdel := []string{"ifconfig", r.tunname,
@ -78,7 +84,7 @@ func (r *freebsdRouter) SetRoutes(rs RouteSettings) error {
// Add the interface. // Add the interface.
addradd := []string{"ifconfig", r.tunname, addradd := []string{"ifconfig", r.tunname,
"inet", rs.LocalAddr.String(), rs.LocalAddr.IP.String()} "inet", localAddr.String(), localAddr.IP.String()}
out, err := cmd(addradd...).CombinedOutput() out, err := cmd(addradd...).CombinedOutput()
if err != nil { if err != nil {
r.logf("addr add failed: %v: %v\n%s", addradd, err, out) r.logf("addr add failed: %v: %v\n%s", addradd, err, out)
@ -132,7 +138,7 @@ func (r *freebsdRouter) SetRoutes(rs RouteSettings) error {
} }
// Store the interface and routes so we know what to change on an update. // Store the interface and routes so we know what to change on an update.
r.local = rs.LocalAddr r.local = localAddr
r.routes = newRoutes r.routes = newRoutes
if err := r.replaceResolvConf(rs.DNS, rs.DNSDomains); err != nil { if err := r.replaceResolvConf(rs.DNS, rs.DNSDomains); err != nil {

@ -51,7 +51,7 @@ const (
type linuxRouter struct { type linuxRouter struct {
logf func(fmt string, args ...interface{}) logf func(fmt string, args ...interface{})
tunname string tunname string
local wgcfg.CIDR addrs map[wgcfg.CIDR]bool
routes map[wgcfg.CIDR]bool routes map[wgcfg.CIDR]bool
subnetRoutes map[wgcfg.CIDR]bool subnetRoutes map[wgcfg.CIDR]bool
@ -117,8 +117,9 @@ func (r *linuxRouter) down() error {
return err return err
} }
r.routes = map[wgcfg.CIDR]bool{} r.addrs = nil
r.local = wgcfg.CIDR{} r.routes = nil
r.subnetRoutes = nil
return nil return nil
} }
@ -140,16 +141,26 @@ func (r *linuxRouter) Close() error {
func (r *linuxRouter) SetRoutes(rs RouteSettings) error { func (r *linuxRouter) SetRoutes(rs RouteSettings) error {
var errq error var errq error
if rs.LocalAddr != r.local { newAddrs := make(map[wgcfg.CIDR]bool)
if r.local != (wgcfg.CIDR{}) { for _, addr := range rs.LocalAddrs {
if err := r.delAddress(r.local); err != nil { newAddrs[addr] = true
r.logf("addr del failed: %v", err) }
if errq == nil { for addr := range r.addrs {
errq = err if newAddrs[addr] {
} continue
}
if err := r.delAddress(addr); err != nil {
r.logf("addr del failed: %v", err)
if errq == nil {
errq = err
} }
} }
if err := r.addAddress(rs.LocalAddr); err != nil { }
for addr := range newAddrs {
if r.addrs[addr] {
continue
}
if err := r.addAddress(addr); err != nil {
r.logf("addr add failed: %v", err) r.logf("addr add failed: %v", err)
if errq == nil { if errq == nil {
errq = err errq = err
@ -213,7 +224,7 @@ func (r *linuxRouter) SetRoutes(rs RouteSettings) error {
} }
} }
r.local = rs.LocalAddr r.addrs = newAddrs
r.routes = newRoutes r.routes = newRoutes
r.subnetRoutes = newSubnetRoutes r.subnetRoutes = newSubnetRoutes

@ -6,6 +6,7 @@ package router
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@ -60,9 +61,15 @@ func (r *openbsdRouter) Up() error {
} }
func (r *openbsdRouter) SetRoutes(rs RouteSettings) error { func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
// TODO: support configuring multiple local addrs on interface.
if len(rs.LocalAddrs) != 1 {
return errors.New("freebsd doesn't support setting multiple local addrs yet")
}
localAddr := rs.LocalAddrs[0]
var errq error var errq error
if rs.LocalAddr != r.local { if localAddr != r.local {
if r.local != (wgcfg.CIDR{}) { if r.local != (wgcfg.CIDR{}) {
addrdel := []string{"ifconfig", r.tunname, addrdel := []string{"ifconfig", r.tunname,
"inet", r.local.String(), "-alias"} "inet", r.local.String(), "-alias"}
@ -86,7 +93,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
} }
addradd := []string{"ifconfig", r.tunname, addradd := []string{"ifconfig", r.tunname,
"inet", rs.LocalAddr.String(), "alias"} "inet", localAddr.String(), "alias"}
out, err := cmd(addradd...).CombinedOutput() out, err := cmd(addradd...).CombinedOutput()
if err != nil { if err != nil {
r.logf("addr add failed: %v: %v\n%s", addradd, err, out) r.logf("addr add failed: %v: %v\n%s", addradd, err, out)
@ -96,8 +103,8 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
} }
routeadd := []string{"route", "-q", "-n", routeadd := []string{"route", "-q", "-n",
"add", "-inet", rs.LocalAddr.String(), "add", "-inet", localAddr.String(),
"-iface", rs.LocalAddr.IP.String()} "-iface", localAddr.IP.String()}
if out, err := cmd(routeadd...).CombinedOutput(); err != nil { if out, err := cmd(routeadd...).CombinedOutput(); err != nil {
r.logf("route add failed: %v: %v\n%s", routeadd, err, out) r.logf("route add failed: %v: %v\n%s", routeadd, err, out)
if errq == nil { if errq == nil {
@ -119,7 +126,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
nstr := fmt.Sprintf("%v/%d", nip, route.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Mask)
routedel := []string{"route", "-q", "-n", routedel := []string{"route", "-q", "-n",
"del", "-inet", nstr, "del", "-inet", nstr,
"-iface", rs.LocalAddr.IP.String()} "-iface", localAddr.IP.String()}
out, err := cmd(routedel...).CombinedOutput() out, err := cmd(routedel...).CombinedOutput()
if err != nil { if err != nil {
r.logf("route del failed: %v: %v\n%s", routedel, err, out) r.logf("route del failed: %v: %v\n%s", routedel, err, out)
@ -136,7 +143,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
nstr := fmt.Sprintf("%v/%d", nip, route.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Mask)
routeadd := []string{"route", "-q", "-n", routeadd := []string{"route", "-q", "-n",
"add", "-inet", nstr, "add", "-inet", nstr,
"-iface", rs.LocalAddr.IP.String()} "-iface", localAddr.IP.String()}
out, err := cmd(routeadd...).CombinedOutput() out, err := cmd(routeadd...).CombinedOutput()
if err != nil { if err != nil {
r.logf("addr add failed: %v: %v\n%s", routeadd, err, out) r.logf("addr add failed: %v: %v\n%s", routeadd, err, out)
@ -147,7 +154,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
} }
} }
r.local = rs.LocalAddr r.local = localAddr
r.routes = newRoutes r.routes = newRoutes
if err := r.replaceResolvConf(rs.DNS, rs.DNSDomains); err != nil { if err := r.replaceResolvConf(rs.DNS, rs.DNSDomains); err != nil {

@ -378,15 +378,20 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string, local
// TODO(apenwarr): only handling the first local address. // TODO(apenwarr): only handling the first local address.
// Currently we never use more than one anyway. // Currently we never use more than one anyway.
var cidr wgcfg.CIDR var addrs []wgcfg.CIDR
if len(cfg.Addresses) > 0 { for _, addr := range cfg.Addresses {
cidr = cfg.Addresses[0] addrs = append(addrs, wgcfg.CIDR{
// TODO(apenwarr): this shouldn't be hardcoded in the client IP: addr.IP,
cidr.Mask = 10 // route the whole cgnat range // TODO(apenwarr): this shouldn't be hardcoded in the client
// TODO(danderson): fairly sure we can make this a /32 or
// /128 based on address family. Need to check behavior on
// !linux OSes.
Mask: 10,
})
} }
rs := router.RouteSettings{ rs := router.RouteSettings{
LocalAddr: cidr, LocalAddrs: addrs,
Cfg: cfg, Cfg: cfg,
DNS: cfg.DNS, DNS: cfg.DNS,
DNSDomains: dnsDomains, DNSDomains: dnsDomains,
@ -403,7 +408,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string, local
rss := rs.OnlyRelevantParts() rss := rs.OnlyRelevantParts()
if rss != e.lastRoutes { if rss != e.lastRoutes {
e.logf("wgengine: Reconfig: reconfiguring router. la=%v dns=%v dom=%v; new routes: %v", e.logf("wgengine: Reconfig: reconfiguring router. la=%v dns=%v dom=%v; new routes: %v",
rs.LocalAddr, rs.DNS, rs.DNSDomains, rss) rs.LocalAddrs, rs.DNS, rs.DNSDomains, rss)
e.lastRoutes = rss e.lastRoutes = rss
err = e.router.SetRoutes(rs) err = e.router.SetRoutes(rs)
if err != nil { if err != nil {

Loading…
Cancel
Save