Add an ability to specify metric for unsafe routes (#474)

This commit is contained in:
Donatas Abraitis 2021-11-04 04:53:28 +02:00 committed by GitHub
parent bcabcfdaca
commit b358bbab80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 11 deletions

View File

@ -18,7 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New config option `pki.disconnect_invalid` that will tear down tunnels when they become invalid (through expiry or
removal of root trust). Default is `false`. Note, this will not currently recognize if a remote has changed
certificates since the last handshake. (#370)
- New config option `unsafe_routes.<route>.metric` will set a metric for a specific unsafe route. It's useful if you have
more than one identical route and want to prefer one against the other.
### Changed
- Build against go 1.17. (#553)

View File

@ -165,10 +165,13 @@ tun:
# 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
unsafe_routes:
#- route: 172.16.1.0/24
# via: 192.168.100.99
# mtu: 1300 #mtu will default to tun mtu if this option is not sepcified
# mtu: 1300
# metric: 100
# TODO

View File

@ -2,6 +2,7 @@ package nebula
import (
"fmt"
"math"
"net"
"strconv"
@ -11,9 +12,10 @@ import (
const DEFAULT_MTU = 1300
type route struct {
mtu int
route *net.IPNet
via *net.IP
mtu int
metric int
route *net.IPNet
via *net.IP
}
func parseRoutes(c *config.C, network *net.IPNet) ([]route, error) {
@ -127,6 +129,23 @@ func parseUnsafeRoutes(c *config.C, network *net.IPNet) ([]route, error) {
return nil, fmt.Errorf("entry %v.mtu in tun.unsafe_routes is below 500: %v", i+1, mtu)
}
rMetric, ok := m["metric"]
if !ok {
rMetric = 0
}
metric, ok := rMetric.(int)
if !ok {
_, err = strconv.ParseInt(rMetric.(string), 10, 32)
if err != nil {
return nil, fmt.Errorf("entry %v.metric in tun.unsafe_routes is not an integer: %v", i+1, err)
}
}
if metric < 0 || metric > math.MaxInt32 {
return nil, fmt.Errorf("entry %v.metric in tun.unsafe_routes is not in range (0-%d) : %v", i+1, math.MaxInt32, metric)
}
rVia, ok := m["via"]
if !ok {
return nil, fmt.Errorf("entry %v.via in tun.unsafe_routes is not present", i+1)
@ -148,8 +167,9 @@ func parseUnsafeRoutes(c *config.C, network *net.IPNet) ([]route, error) {
}
r := route{
via: &nVia,
mtu: mtu,
via: &nVia,
mtu: mtu,
metric: metric,
}
_, r.route, err = net.ParseCIDR(fmt.Sprintf("%v", rRoute))

View File

@ -300,6 +300,7 @@ func (c Tun) Activate() error {
LinkIndex: link.Attrs().Index,
Dst: r.route,
MTU: r.mtu,
Priority: r.metric,
AdvMSS: c.advMSS(r),
Scope: unix.RT_SCOPE_LINK,
}

View File

@ -208,24 +208,30 @@ func Test_parseUnsafeRoutes(t *testing.T) {
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": "1500", "metric": 1234, "route": "1.0.0.2/32"},
}}
routes, err = parseUnsafeRoutes(c, n)
assert.Nil(t, err)
assert.Len(t, routes, 2)
assert.Len(t, routes, 3)
tested := 0
for _, r := range routes {
if r.mtu == 8000 {
assert.Equal(t, "1.0.0.1/32", r.route.String())
tested++
} else {
} else if r.mtu == 9000 {
assert.Equal(t, 9000, r.mtu)
assert.Equal(t, "1.0.0.0/29", r.route.String())
tested++
} else {
assert.Equal(t, 1500, r.mtu)
assert.Equal(t, 1234, r.metric)
assert.Equal(t, "1.0.0.2/32", r.route.String())
tested++
}
}
if tested != 2 {
if tested != 3 {
t.Fatal("Did not see both unsafe_routes")
}
}

View File

@ -92,7 +92,7 @@ func (c *Tun) Activate() error {
for _, r := range c.UnsafeRoutes {
err = exec.Command(
"C:\\Windows\\System32\\route.exe", "add", r.route.String(), r.via.String(), "IF", strconv.Itoa(iface.Index),
"C:\\Windows\\System32\\route.exe", "add", r.route.String(), r.via.String(), "IF", strconv.Itoa(iface.Index), "METRIC", strconv.Itoa(r.metric),
).Run()
if err != nil {
return fmt.Errorf("failed to add the unsafe_route %s: %v", r.route.String(), err)