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 5 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
// itself, like DNS stuff.
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
DNSDomains []string
SubnetRoutes []wgcfg.CIDR // subnets being advertised to other Tailscale nodes
@ -55,5 +55,5 @@ func (rs *RouteSettings) OnlyRelevantParts() string {
peers = append(peers, p.AllowedIPs)
}
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
import (
"errors"
"fmt"
"log"
"os/exec"
@ -55,14 +56,19 @@ func (r *freebsdRouter) Up() error {
}
func (r *freebsdRouter) SetRoutes(rs RouteSettings) error {
if rs.LocalAddr == (wgcfg.CIDR{}) {
if len(rs.LocalAddrs) == 0 {
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
// Update the address.
if rs.LocalAddr != r.local {
if localAddr != r.local {
// If the interface is already set, remove it.
if r.local != (wgcfg.CIDR{}) {
addrdel := []string{"ifconfig", r.tunname,
@ -78,7 +84,7 @@ func (r *freebsdRouter) SetRoutes(rs RouteSettings) error {
// Add the interface.
addradd := []string{"ifconfig", r.tunname,
"inet", rs.LocalAddr.String(), rs.LocalAddr.IP.String()}
"inet", localAddr.String(), localAddr.IP.String()}
out, err := cmd(addradd...).CombinedOutput()
if err != nil {
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.
r.local = rs.LocalAddr
r.local = localAddr
r.routes = newRoutes
if err := r.replaceResolvConf(rs.DNS, rs.DNSDomains); err != nil {

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

@ -6,6 +6,7 @@ package router
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"log"
@ -60,9 +61,15 @@ func (r *openbsdRouter) Up() 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
if rs.LocalAddr != r.local {
if localAddr != r.local {
if r.local != (wgcfg.CIDR{}) {
addrdel := []string{"ifconfig", r.tunname,
"inet", r.local.String(), "-alias"}
@ -86,7 +93,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
}
addradd := []string{"ifconfig", r.tunname,
"inet", rs.LocalAddr.String(), "alias"}
"inet", localAddr.String(), "alias"}
out, err := cmd(addradd...).CombinedOutput()
if err != nil {
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",
"add", "-inet", rs.LocalAddr.String(),
"-iface", rs.LocalAddr.IP.String()}
"add", "-inet", localAddr.String(),
"-iface", localAddr.IP.String()}
if out, err := cmd(routeadd...).CombinedOutput(); err != nil {
r.logf("route add failed: %v: %v\n%s", routeadd, err, out)
if errq == nil {
@ -119,7 +126,7 @@ func (r *openbsdRouter) SetRoutes(rs RouteSettings) error {
nstr := fmt.Sprintf("%v/%d", nip, route.Mask)
routedel := []string{"route", "-q", "-n",
"del", "-inet", nstr,
"-iface", rs.LocalAddr.IP.String()}
"-iface", localAddr.IP.String()}
out, err := cmd(routedel...).CombinedOutput()
if err != nil {
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)
routeadd := []string{"route", "-q", "-n",
"add", "-inet", nstr,
"-iface", rs.LocalAddr.IP.String()}
"-iface", localAddr.IP.String()}
out, err := cmd(routeadd...).CombinedOutput()
if err != nil {
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
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.
// Currently we never use more than one anyway.
var cidr wgcfg.CIDR
if len(cfg.Addresses) > 0 {
cidr = cfg.Addresses[0]
var addrs []wgcfg.CIDR
for _, addr := range cfg.Addresses {
addrs = append(addrs, wgcfg.CIDR{
IP: addr.IP,
// TODO(apenwarr): this shouldn't be hardcoded in the client
cidr.Mask = 10 // route the whole cgnat range
// 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{
LocalAddr: cidr,
LocalAddrs: addrs,
Cfg: cfg,
DNS: cfg.DNS,
DNSDomains: dnsDomains,
@ -403,7 +408,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string, local
rss := rs.OnlyRelevantParts()
if rss != e.lastRoutes {
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
err = e.router.SetRoutes(rs)
if err != nil {

Loading…
Cancel
Save