Browse Source

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

Nate Brown 2 years ago
parent
commit
397fe5f879

+ 6 - 3
examples/config.yml

@@ -204,21 +204,24 @@ tun:
   tx_queue: 500
   # Default MTU for every packet, safe setting is (and the default) 1300 for internet based traffic
   mtu: 1300
+
   # Route based MTU overrides, you have known vpn ip paths that can support larger MTUs you can increase/decrease them here
   routes:
     #- mtu: 8800
     #  route: 10.0.0.0/16
+
   # 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
   # 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
-  # `metric` will default to 0 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
+  # `install`: will default to true, controls whether this route is installed in the systems routing table.
   unsafe_routes:
     #- route: 172.16.1.0/24
     #  via: 192.168.100.99
     #  mtu: 1300
     #  metric: 100
-
+    #  install: true
 
 # TODO
 # Configure logging level

+ 20 - 8
overlay/route.go

@@ -14,10 +14,11 @@ import (
 )
 
 type Route struct {
-	MTU    int
-	Metric int
-	Cidr   *net.IPNet
-	Via    *iputil.VpnIp
+	MTU     int
+	Metric  int
+	Cidr    *net.IPNet
+	Via     *iputil.VpnIp
+	Install bool
 }
 
 func makeRouteTree(l *logrus.Logger, routes []Route, allowMTU bool) (*cidr.Tree4, error) {
@@ -81,7 +82,8 @@ func parseRoutes(c *config.C, network *net.IPNet) ([]Route, error) {
 		}
 
 		r := Route{
-			MTU: mtu,
+			Install: true,
+			MTU:     mtu,
 		}
 
 		_, r.Cidr, err = net.ParseCIDR(fmt.Sprintf("%v", rRoute))
@@ -182,10 +184,20 @@ func parseUnsafeRoutes(c *config.C, network *net.IPNet) ([]Route, error) {
 
 		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{
-			Via:    &viaVpnIp,
-			MTU:    mtu,
-			Metric: metric,
+			Via:     &viaVpnIp,
+			MTU:     mtu,
+			Metric:  metric,
+			Install: install,
 		}
 
 		_, r.Cidr, err = net.ParseCIDR(fmt.Sprintf("%v", rRoute))

+ 17 - 5
overlay/route_test.go

@@ -92,6 +92,8 @@ func Test_parseRoutes(t *testing.T) {
 
 	tested := 0
 	for _, r := range routes {
+		assert.True(t, r.Install)
+
 		if r.MTU == 8000 {
 			assert.Equal(t, "10.0.0.1/32", r.Cidr.String())
 			tested++
@@ -205,35 +207,45 @@ func Test_parseUnsafeRoutes(t *testing.T) {
 	assert.Nil(t, routes)
 	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
 	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": "8000", "route": "1.0.0.1/32"},
+		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", "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"},
 	}}
 	routes, err = parseUnsafeRoutes(c, n)
 	assert.Nil(t, err)
-	assert.Len(t, routes, 3)
+	assert.Len(t, routes, 4)
 
 	tested := 0
 	for _, r := range routes {
 		if r.MTU == 8000 {
 			assert.Equal(t, "1.0.0.1/32", r.Cidr.String())
+			assert.False(t, r.Install)
 			tested++
 		} else if r.MTU == 9000 {
 			assert.Equal(t, 9000, r.MTU)
 			assert.Equal(t, "1.0.0.0/29", r.Cidr.String())
+			assert.True(t, r.Install)
 			tested++
 		} else {
 			assert.Equal(t, 1500, r.MTU)
 			assert.Equal(t, 1234, r.Metric)
 			assert.Equal(t, "1.0.0.2/32", r.Cidr.String())
+			assert.True(t, r.Install)
 			tested++
 		}
 	}
 
-	if tested != 3 {
-		t.Fatal("Did not see both unsafe_routes")
+	if tested != 4 {
+		t.Fatal("Did not see all unsafe_routes")
 	}
 }
 

+ 1 - 1
overlay/tun_darwin.go

@@ -287,7 +287,7 @@ func (t *tun) Activate() error {
 
 	// Unsafe path 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
 			continue
 		}

+ 1 - 1
overlay/tun_freebsd.go

@@ -86,7 +86,7 @@ func (t *tun) Activate() error {
 	}
 	// Unsafe path 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
 			continue
 		}

+ 4 - 0
overlay/tun_linux.go

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

+ 1 - 1
overlay/tun_water_windows.go

@@ -80,7 +80,7 @@ func (t *waterTun) Activate() error {
 	}
 
 	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
 			continue
 		}

+ 1 - 1
overlay/tun_wintun_windows.go

@@ -92,7 +92,7 @@ func (t *winTun) Activate() error {
 	routes := make([]*winipcfg.RouteData, 0, len(t.Routes)+1)
 
 	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
 			continue
 		}