wgengine/router: add a setting to disable SNAT for subnet routes.

Part of #320.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson
2020-05-11 20:16:52 +00:00
parent 8eda667aa1
commit bfdc8175b1
9 changed files with 82 additions and 24 deletions

View File

@@ -54,6 +54,7 @@ type linuxRouter struct {
addrs map[netaddr.IPPrefix]bool
routes map[netaddr.IPPrefix]bool
subnetRoutes map[netaddr.IPPrefix]bool
noSNAT bool
ipt4 *iptables.IPTables
}
@@ -72,6 +73,7 @@ func newUserspaceRouter(logf logger.Logf, _ *device.Device, tunDev tun.Device) (
return &linuxRouter{
logf: logf,
tunname: tunname,
noSNAT: true,
ipt4: ipt4,
}, nil
}
@@ -193,9 +195,23 @@ func (r *linuxRouter) Set(rs Settings) error {
errq = err
}
switch {
case rs.NoSNAT == r.noSNAT:
// state already correct, nothing to do.
case rs.NoSNAT:
if err := r.delSNATRule(); err != nil && errq == nil {
errq = err
}
default:
if err := r.addSNATRule(); err != nil && errq == nil {
errq = err
}
}
r.addrs = newAddrs
r.routes = newRoutes
r.subnetRoutes = newSubnetRoutes
r.noSNAT = rs.NoSNAT
// TODO: this:
if false {
@@ -558,13 +574,12 @@ func (r *linuxRouter) addBaseNetfilter4() error {
return fmt.Errorf("adding %v in filter/ts-input: %v", args, err)
}
// Forward and masquerade packets that have the Tailscale subnet
// route bit set. The bit gets set by rules inserted into
// filter/FORWARD later on. We use packet marks here so both
// filter/FORWARD and nat/POSTROUTING can match on these packets
// of interest.
// Forward and mark packets that have the Tailscale subnet route
// bit set. The bit gets set by rules inserted into filter/FORWARD
// later on. We use packet marks here so both filter/FORWARD and
// nat/POSTROUTING can match on these packets of interest.
//
// In particular, we only want to apply masquerading in
// In particular, we only want to apply SNAT rules in
// nat/POSTROUTING to packets that originated from the Tailscale
// interface, but we can't match on the inbound interface in
// POSTROUTING. So instead, we match on the inbound interface and
@@ -579,11 +594,26 @@ func (r *linuxRouter) addBaseNetfilter4() error {
if err := r.ipt4.Append("filter", "ts-forward", args...); err != nil {
return fmt.Errorf("adding %v in filter/ts-forward: %v", args, err)
}
// TODO(danderson): this should be optional.
args = []string{"-m", "mark", "--mark", tailscaleSubnetRouteMark, "-j", "MASQUERADE"}
if err := r.ipt4.Append("nat", "ts-postrouting", args...); err != nil {
return fmt.Errorf("adding %v in nat/ts-postrouting: %v", args, err)
}
return nil
}
// addSNATRule adds a netfilter rule to SNAT traffic destined for
// local subnets.
func (r *linuxRouter) addSNATRule() error {
args := []string{"-m", "mark", "--mark", tailscaleSubnetRouteMark, "-j", "MASQUERADE"}
if err := r.ipt4.Append("nat", "ts-postrouting", args...); err != nil {
return fmt.Errorf("adding %v in nat/ts-postrouting: %v", args, err)
}
return nil
}
// delSNATRule removes the netfilter rule to SNAT traffic destined for
// local subnets. Fails if the rule does not exist.
func (r *linuxRouter) delSNATRule() error {
args := []string{"-m", "mark", "--mark", tailscaleSubnetRouteMark, "-j", "MASQUERADE"}
if err := r.ipt4.Delete("nat", "ts-postrouting", args...); err != nil {
return fmt.Errorf("deleting %v in nat/ts-postrouting: %v", args, err)
}
return nil
}