Add ability to skip installing unsafe routes on the os routing table (#831)

This commit is contained in:
Nate Brown 2023-04-10 12:32:37 -05:00 committed by GitHub
parent 9b03053191
commit 397fe5f879
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 20 deletions

View File

@ -204,21 +204,24 @@ tun:
tx_queue: 500 tx_queue: 500
# Default MTU for every packet, safe setting is (and the default) 1300 for internet based traffic # Default MTU for every packet, safe setting is (and the default) 1300 for internet based traffic
mtu: 1300 mtu: 1300
# Route based MTU overrides, you have known vpn ip paths that can support larger MTUs you can increase/decrease them here # Route based MTU overrides, you have known vpn ip paths that can support larger MTUs you can increase/decrease them here
routes: routes:
#- mtu: 8800 #- mtu: 8800
# route: 10.0.0.0/16 # route: 10.0.0.0/16
# Unsafe routes allows you to route traffic over nebula to non-nebula nodes # Unsafe routes allows you to route traffic over nebula to non-nebula nodes
# Unsafe routes should be avoided unless you have hosts/services that cannot run nebula # Unsafe routes should be avoided unless you have hosts/services that cannot run nebula
# NOTE: The nebula certificate of the "via" node *MUST* have the "route" defined as a subnet in its certificate # NOTE: The nebula certificate of the "via" node *MUST* have the "route" defined as a subnet in its certificate
# `mtu` will default to tun mtu if this option is not specified # `mtu`: will default to tun mtu if this option is not specified
# `metric` will default to 0 if this option is not specified # `metric`: will default to 0 if this option is not specified
# `install`: will default to true, controls whether this route is installed in the systems routing table.
unsafe_routes: unsafe_routes:
#- route: 172.16.1.0/24 #- route: 172.16.1.0/24
# via: 192.168.100.99 # via: 192.168.100.99
# mtu: 1300 # mtu: 1300
# metric: 100 # metric: 100
# install: true
# TODO # TODO
# Configure logging level # Configure logging level

View File

@ -18,6 +18,7 @@ type Route struct {
Metric int Metric int
Cidr *net.IPNet Cidr *net.IPNet
Via *iputil.VpnIp Via *iputil.VpnIp
Install bool
} }
func makeRouteTree(l *logrus.Logger, routes []Route, allowMTU bool) (*cidr.Tree4, error) { func makeRouteTree(l *logrus.Logger, routes []Route, allowMTU bool) (*cidr.Tree4, error) {
@ -81,6 +82,7 @@ func parseRoutes(c *config.C, network *net.IPNet) ([]Route, error) {
} }
r := Route{ r := Route{
Install: true,
MTU: mtu, MTU: mtu,
} }
@ -182,10 +184,20 @@ func parseUnsafeRoutes(c *config.C, network *net.IPNet) ([]Route, error) {
viaVpnIp := iputil.Ip2VpnIp(nVia) viaVpnIp := iputil.Ip2VpnIp(nVia)
install := true
rInstall, ok := m["install"]
if ok {
install, err = strconv.ParseBool(fmt.Sprintf("%v", rInstall))
if err != nil {
return nil, fmt.Errorf("entry %v.install in tun.unsafe_routes is not a boolean: %v", i+1, err)
}
}
r := Route{ r := Route{
Via: &viaVpnIp, Via: &viaVpnIp,
MTU: mtu, MTU: mtu,
Metric: metric, Metric: metric,
Install: install,
} }
_, r.Cidr, err = net.ParseCIDR(fmt.Sprintf("%v", rRoute)) _, r.Cidr, err = net.ParseCIDR(fmt.Sprintf("%v", rRoute))

View File

@ -92,6 +92,8 @@ func Test_parseRoutes(t *testing.T) {
tested := 0 tested := 0
for _, r := range routes { for _, r := range routes {
assert.True(t, r.Install)
if r.MTU == 8000 { if r.MTU == 8000 {
assert.Equal(t, "10.0.0.1/32", r.Cidr.String()) assert.Equal(t, "10.0.0.1/32", r.Cidr.String())
tested++ tested++
@ -205,35 +207,45 @@ func Test_parseUnsafeRoutes(t *testing.T) {
assert.Nil(t, routes) assert.Nil(t, routes)
assert.EqualError(t, err, "entry 1.mtu in tun.unsafe_routes is below 500: 499") assert.EqualError(t, err, "entry 1.mtu in tun.unsafe_routes is below 500: 499")
// bad install
c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "9000", "route": "1.0.0.0/29", "install": "nope"}}}
routes, err = parseUnsafeRoutes(c, n)
assert.Nil(t, routes)
assert.EqualError(t, err, "entry 1.install in tun.unsafe_routes is not a boolean: strconv.ParseBool: parsing \"nope\": invalid syntax")
// happy case // happy case
c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{ c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{
map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "9000", "route": "1.0.0.0/29"}, map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "9000", "route": "1.0.0.0/29", "install": "t"},
map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "8000", "route": "1.0.0.1/32"}, map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "8000", "route": "1.0.0.1/32", "install": 0},
map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "1500", "metric": 1234, "route": "1.0.0.2/32", "install": 1},
map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "1500", "metric": 1234, "route": "1.0.0.2/32"}, map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "1500", "metric": 1234, "route": "1.0.0.2/32"},
}} }}
routes, err = parseUnsafeRoutes(c, n) routes, err = parseUnsafeRoutes(c, n)
assert.Nil(t, err) assert.Nil(t, err)
assert.Len(t, routes, 3) assert.Len(t, routes, 4)
tested := 0 tested := 0
for _, r := range routes { for _, r := range routes {
if r.MTU == 8000 { if r.MTU == 8000 {
assert.Equal(t, "1.0.0.1/32", r.Cidr.String()) assert.Equal(t, "1.0.0.1/32", r.Cidr.String())
assert.False(t, r.Install)
tested++ tested++
} else if r.MTU == 9000 { } else if r.MTU == 9000 {
assert.Equal(t, 9000, r.MTU) assert.Equal(t, 9000, r.MTU)
assert.Equal(t, "1.0.0.0/29", r.Cidr.String()) assert.Equal(t, "1.0.0.0/29", r.Cidr.String())
assert.True(t, r.Install)
tested++ tested++
} else { } else {
assert.Equal(t, 1500, r.MTU) assert.Equal(t, 1500, r.MTU)
assert.Equal(t, 1234, r.Metric) assert.Equal(t, 1234, r.Metric)
assert.Equal(t, "1.0.0.2/32", r.Cidr.String()) assert.Equal(t, "1.0.0.2/32", r.Cidr.String())
assert.True(t, r.Install)
tested++ tested++
} }
} }
if tested != 3 { if tested != 4 {
t.Fatal("Did not see both unsafe_routes") t.Fatal("Did not see all unsafe_routes")
} }
} }

View File

@ -287,7 +287,7 @@ func (t *tun) Activate() error {
// Unsafe path routes // Unsafe path routes
for _, r := range t.Routes { for _, r := range t.Routes {
if r.Via == nil { if r.Via == nil || !r.Install {
// We don't allow route MTUs so only install routes with a via // We don't allow route MTUs so only install routes with a via
continue continue
} }

View File

@ -86,7 +86,7 @@ func (t *tun) Activate() error {
} }
// Unsafe path routes // Unsafe path routes
for _, r := range t.Routes { for _, r := range t.Routes {
if r.Via == nil { if r.Via == nil || !r.Install {
// We don't allow route MTUs so only install routes with a via // We don't allow route MTUs so only install routes with a via
continue continue
} }

View File

@ -279,6 +279,10 @@ func (t tun) Activate() error {
// Path routes // Path routes
for _, r := range t.Routes { for _, r := range t.Routes {
if !r.Install {
continue
}
nr := netlink.Route{ nr := netlink.Route{
LinkIndex: link.Attrs().Index, LinkIndex: link.Attrs().Index,
Dst: r.Cidr, Dst: r.Cidr,

View File

@ -80,7 +80,7 @@ func (t *waterTun) Activate() error {
} }
for _, r := range t.Routes { for _, r := range t.Routes {
if r.Via == nil { if r.Via == nil || !r.Install {
// We don't allow route MTUs so only install routes with a via // We don't allow route MTUs so only install routes with a via
continue continue
} }

View File

@ -92,7 +92,7 @@ func (t *winTun) Activate() error {
routes := make([]*winipcfg.RouteData, 0, len(t.Routes)+1) routes := make([]*winipcfg.RouteData, 0, len(t.Routes)+1)
for _, r := range t.Routes { for _, r := range t.Routes {
if r.Via == nil { if r.Via == nil || !r.Install {
// We don't allow route MTUs so only install routes with a via // We don't allow route MTUs so only install routes with a via
continue continue
} }