From ce387c5b398f318470a174ea9f4ebf27fa539ca1 Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski Date: Fri, 31 Jan 2020 12:21:00 +0100 Subject: [PATCH 01/11] Rebase against upstream/master --- Makefile | 4 +++ go.mod | 1 + go.sum | 2 ++ tun_freebsd.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ udp_freebsd.go | 34 +++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 tun_freebsd.go create mode 100644 udp_freebsd.go diff --git a/Makefile b/Makefile index b71ff9270..320dfe31c 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ ALL_LINUX = linux-amd64 \ ALL = $(ALL_LINUX) \ darwin-amd64 \ + freebsd-amd64 \ windows-amd64 all: $(ALL:%=build/%/nebula) $(ALL:%=build/%/nebula-cert) @@ -31,6 +32,9 @@ bin-windows: build/windows-amd64/nebula.exe build/windows-amd64/nebula-cert.exe bin-darwin: build/darwin-amd64/nebula build/darwin-amd64/nebula-cert mv $? . +bin-freebsd: build/freebsd-amd64/nebula build/freebsd-amd64/nebula-cert + mv $? . + bin: go build -trimpath -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ${NEBULA_CMD_PATH} go build -trimpath -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert diff --git a/go.mod b/go.mod index aff1aeb6d..a26f1002c 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/stretchr/testify v1.4.0 github.com/vishvananda/netlink v1.0.1-0.20190522153524-00009fb8606a github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect + github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 diff --git a/go.sum b/go.sum index 1d655a682..b775ef61f 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,8 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c= github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= +github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 h1:YY9Pg2BEp0jeUVU60svTOaDr+fs1ySC9RbdC1Qc6wOw= +github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8/go.mod h1:R0SBCsugm+Sf1katgTb2t7GXMm+nRIv43tM4VDZbaOs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/tun_freebsd.go b/tun_freebsd.go new file mode 100644 index 000000000..068c383c5 --- /dev/null +++ b/tun_freebsd.go @@ -0,0 +1,67 @@ +package nebula + +import ( + "fmt" + "net" + "os/exec" + "strconv" + + "github.com/yggdrasil-network/water" +) + +type Tun struct { + Device string + Cidr *net.IPNet + MTU int + + *water.Interface +} + +func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, unsafeRoutes []route, txQueueLen int) (ifce *Tun, err error) { + if len(routes) > 0 { + return nil, fmt.Errorf("Route MTU not supported in FreeBSD") + } + if len(unsafeRoutes) > 0 { + return nil, fmt.Errorf("unsafeRoutes not supported in FreeBSD") + } + // NOTE: You cannot set the deviceName under FreeBSD, so you must check tun.Device after calling .Activate() + return &Tun{ + Cidr: cidr, + MTU: defaultMTU, + }, nil +} + +func (c *Tun) Activate() error { + var err error + c.Interface, err = water.New(water.Config{ + DeviceType: water.TUN, + }) + if err != nil { + return fmt.Errorf("Activate failed: %v", err) + } + + c.Device = c.Interface.Name() + + // TODO use syscalls instead of exec.Command + fmt.Println("command: ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()) + if err = exec.Command("ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { + return fmt.Errorf("failed to run 'ifconfig': %s", err) + } + /* This is not needed on FreeBSD + fmt.Println("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) + if err = exec.Command("route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { + return fmt.Errorf("failed to run 'route add': %s", err) + } + */ + fmt.Println("command: ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)) + if err = exec.Command("ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { + return fmt.Errorf("failed to run 'ifconfig': %s", err) + } + + return nil +} + +func (c *Tun) WriteRaw(b []byte) error { + _, err := c.Write(b) + return err +} diff --git a/udp_freebsd.go b/udp_freebsd.go new file mode 100644 index 000000000..88ff61829 --- /dev/null +++ b/udp_freebsd.go @@ -0,0 +1,34 @@ +package nebula + +// FreeBSD support is primarily implemented in udp_generic, besides NewListenConfig + +import ( + "fmt" + "net" + "syscall" + + "golang.org/x/sys/unix" +) + +func NewListenConfig(multi bool) net.ListenConfig { + return net.ListenConfig{ + Control: func(network, address string, c syscall.RawConn) error { + if multi { + var controlErr error + err := c.Control(func(fd uintptr) { + if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { + controlErr = fmt.Errorf("SO_REUSEPORT failed: %v", err) + return + } + }) + if err != nil { + return err + } + if controlErr != nil { + return controlErr + } + } + return nil + }, + } +} From 3f42be1ffee9b0055a1b0d52bb0e3d5f70c7b22a Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski Date: Tue, 17 Dec 2019 12:51:35 +0100 Subject: [PATCH 02/11] Make gofmt happy --- tun_freebsd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index 068c383c5..8f07c2f48 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -47,7 +47,7 @@ func (c *Tun) Activate() error { if err = exec.Command("ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } - /* This is not needed on FreeBSD + /* This is not needed on FreeBSD fmt.Println("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) if err = exec.Command("route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { return fmt.Errorf("failed to run 'route add': %s", err) From ec3b406bc0d719c714ff1f9eedd74cef60056bf5 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Tue, 7 Apr 2020 22:33:17 -0400 Subject: [PATCH 03/11] Use tap instead of tun The yggdrasil-network/water patch to make water work on bsd does some confusing things. One thing is that unless you set `Name`, it will create a tap device. Fix this by requiring the user set `tun.dev` in their config file to a name like `tun0` or `tun1` (the naming required by freebsd). We also need to add the `route` command back now that we are using a tun device. --- tun_freebsd.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index 8f07c2f48..34a3303ee 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -4,11 +4,15 @@ import ( "fmt" "net" "os/exec" + "regexp" "strconv" + "strings" "github.com/yggdrasil-network/water" ) +var deviceNameRE = regexp.MustCompile(`^/dev/tun[0-9]+$`) + type Tun struct { Device string Cidr *net.IPNet @@ -24,10 +28,16 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, if len(unsafeRoutes) > 0 { return nil, fmt.Errorf("unsafeRoutes not supported in FreeBSD") } - // NOTE: You cannot set the deviceName under FreeBSD, so you must check tun.Device after calling .Activate() + if !strings.HasPrefix(deviceName, "/dev/") { + deviceName = "/dev/" + deviceName + } + if !deviceNameRE.MatchString(deviceName) { + return nil, fmt.Errorf("tun.dev must match `tun[0-9]+`") + } return &Tun{ - Cidr: cidr, - MTU: defaultMTU, + Device: deviceName, + Cidr: cidr, + MTU: defaultMTU, }, nil } @@ -35,6 +45,9 @@ func (c *Tun) Activate() error { var err error c.Interface, err = water.New(water.Config{ DeviceType: water.TUN, + PlatformSpecificParams: water.PlatformSpecificParams{ + Name: c.Device, + }, }) if err != nil { return fmt.Errorf("Activate failed: %v", err) @@ -47,12 +60,10 @@ func (c *Tun) Activate() error { if err = exec.Command("ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } - /* This is not needed on FreeBSD fmt.Println("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) if err = exec.Command("route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { return fmt.Errorf("failed to run 'route add': %s", err) } - */ fmt.Println("command: ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)) if err = exec.Command("ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) From 2c24d993182e685af05c788d21920ea9ec4f203f Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Tue, 7 Apr 2020 22:57:52 -0400 Subject: [PATCH 04/11] add `release-freebsd` to the Makefile --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 320dfe31c..65b24f97b 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,8 @@ release: $(ALL:%=build/nebula-%.tar.gz) release-linux: $(ALL_LINUX:%=build/nebula-%.tar.gz) +release-freebsd: build/nebula-freebsd-amd64.tar.gz + bin-windows: build/windows-amd64/nebula.exe build/windows-amd64/nebula-cert.exe mv $? . From e1d638661e85b9dd41760c930203f65bc6ad80a1 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Tue, 7 Apr 2020 22:58:50 -0400 Subject: [PATCH 05/11] Build freebsd as part of the release --- .github/workflows/release.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c34ed6924..ed5fcc35c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Build run: | - make BUILD_NUMBER="${GITHUB_REF#refs/tags/v}" release-linux + make BUILD_NUMBER="${GITHUB_REF#refs/tags/v}" release-linux release-freebsd mkdir release mv build/*.tar.gz release @@ -278,3 +278,13 @@ jobs: asset_path: ./linux-latest/nebula-linux-mips64le.tar.gz asset_name: nebula-linux-mips64le.tar.gz asset_content_type: application/gzip + + - name: Upload freebsd-amd64 + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./linux-latest/nebula-freebsd-amd64.tar.gz + asset_name: nebula-freebsd-amd64.tar.gz + asset_content_type: application/gzip From f5661da7c70ad852f766738b9790918d617dd2a1 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Tue, 7 Apr 2020 23:02:40 -0400 Subject: [PATCH 06/11] debug logs instead of fmt.Println --- tun_freebsd.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index 34a3303ee..7f976f64b 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -56,15 +56,15 @@ func (c *Tun) Activate() error { c.Device = c.Interface.Name() // TODO use syscalls instead of exec.Command - fmt.Println("command: ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()) + l.Debug("command: ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()) if err = exec.Command("ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } - fmt.Println("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) + l.Debug("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) if err = exec.Command("route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { return fmt.Errorf("failed to run 'route add': %s", err) } - fmt.Println("command: ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)) + l.Debug("command: ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)) if err = exec.Command("ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } From 7751e9e1948773aa90b9a34658290b4d888e59d0 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Tue, 7 Apr 2020 23:28:19 -0400 Subject: [PATCH 07/11] use absolute paths --- tun_freebsd.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index 7f976f64b..ff6e7a2d0 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -57,15 +57,15 @@ func (c *Tun) Activate() error { // TODO use syscalls instead of exec.Command l.Debug("command: ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()) - if err = exec.Command("ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { + if err = exec.Command("/sbin/ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } l.Debug("command: route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device) - if err = exec.Command("route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { + if err = exec.Command("/sbin/route", "-n", "add", "-net", c.Cidr.String(), "-interface", c.Device).Run(); err != nil { return fmt.Errorf("failed to run 'route add': %s", err) } l.Debug("command: ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)) - if err = exec.Command("ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { + if err = exec.Command("/sbin/ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } From 660a455ce9fac6c16c8b8e700eadf764ecf35091 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Sat, 11 Apr 2020 06:54:33 -0400 Subject: [PATCH 08/11] we don't even need water The only thing the library is doing for freebsd is calling OpenFile. --- tun_freebsd.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index ff6e7a2d0..051287d35 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -2,23 +2,23 @@ package nebula import ( "fmt" + "io" "net" + "os" "os/exec" "regexp" "strconv" "strings" - - "github.com/yggdrasil-network/water" ) -var deviceNameRE = regexp.MustCompile(`^/dev/tun[0-9]+$`) +var deviceNameRE = regexp.MustCompile(`^tun[0-9]+$`) type Tun struct { Device string Cidr *net.IPNet MTU int - *water.Interface + io.ReadWriteCloser } func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, unsafeRoutes []route, txQueueLen int) (ifce *Tun, err error) { @@ -28,8 +28,8 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, if len(unsafeRoutes) > 0 { return nil, fmt.Errorf("unsafeRoutes not supported in FreeBSD") } - if !strings.HasPrefix(deviceName, "/dev/") { - deviceName = "/dev/" + deviceName + if strings.HasPrefix(deviceName, "/dev/") { + deviceName = strings.TrimPrefix(deviceName, "/dev/") } if !deviceNameRE.MatchString(deviceName) { return nil, fmt.Errorf("tun.dev must match `tun[0-9]+`") @@ -43,18 +43,11 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, func (c *Tun) Activate() error { var err error - c.Interface, err = water.New(water.Config{ - DeviceType: water.TUN, - PlatformSpecificParams: water.PlatformSpecificParams{ - Name: c.Device, - }, - }) + c.ReadWriteCloser, err = os.OpenFile("/dev/"+c.Device, os.O_RDWR, 0) if err != nil { return fmt.Errorf("Activate failed: %v", err) } - c.Device = c.Interface.Name() - // TODO use syscalls instead of exec.Command l.Debug("command: ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()) if err = exec.Command("/sbin/ifconfig", c.Device, c.Cidr.String(), c.Cidr.IP.String()).Run(); err != nil { From 70d6f49744764dd23c7013c82d1c5e5ab16d9826 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Sat, 11 Apr 2020 06:55:11 -0400 Subject: [PATCH 09/11] we don't even need water The only thing the library is doing for freebsd is calling OpenFile. --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index d79dde4d9..0449d4f8d 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,6 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c= github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= -github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 h1:YY9Pg2BEp0jeUVU60svTOaDr+fs1ySC9RbdC1Qc6wOw= -github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8/go.mod h1:R0SBCsugm+Sf1katgTb2t7GXMm+nRIv43tM4VDZbaOs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= From 580d177b51159f0cf4d627cd3523dbddba5b3e60 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Sat, 11 Apr 2020 06:55:37 -0400 Subject: [PATCH 10/11] we don't even need water The only thing the library is doing for freebsd is calling OpenFile. --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index e1d98a195..324d3a5fc 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,6 @@ require ( github.com/stretchr/testify v1.4.0 github.com/vishvananda/netlink v1.0.1-0.20190522153524-00009fb8606a github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect - github.com/yggdrasil-network/water v0.0.0-20190812103929-c83fe40250f8 golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 From 585dcfeedb8f63586c052bea6f7c4904d1c36184 Mon Sep 17 00:00:00 2001 From: Wade Simmons Date: Sat, 11 Apr 2020 07:21:57 -0400 Subject: [PATCH 11/11] support unsafe_routes --- tun_freebsd.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tun_freebsd.go b/tun_freebsd.go index 051287d35..957044339 100644 --- a/tun_freebsd.go +++ b/tun_freebsd.go @@ -14,9 +14,10 @@ import ( var deviceNameRE = regexp.MustCompile(`^tun[0-9]+$`) type Tun struct { - Device string - Cidr *net.IPNet - MTU int + Device string + Cidr *net.IPNet + MTU int + UnsafeRoutes []route io.ReadWriteCloser } @@ -25,9 +26,6 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, if len(routes) > 0 { return nil, fmt.Errorf("Route MTU not supported in FreeBSD") } - if len(unsafeRoutes) > 0 { - return nil, fmt.Errorf("unsafeRoutes not supported in FreeBSD") - } if strings.HasPrefix(deviceName, "/dev/") { deviceName = strings.TrimPrefix(deviceName, "/dev/") } @@ -35,9 +33,10 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, return nil, fmt.Errorf("tun.dev must match `tun[0-9]+`") } return &Tun{ - Device: deviceName, - Cidr: cidr, - MTU: defaultMTU, + Device: deviceName, + Cidr: cidr, + MTU: defaultMTU, + UnsafeRoutes: unsafeRoutes, }, nil } @@ -61,6 +60,13 @@ func (c *Tun) Activate() error { if err = exec.Command("/sbin/ifconfig", c.Device, "mtu", strconv.Itoa(c.MTU)).Run(); err != nil { return fmt.Errorf("failed to run 'ifconfig': %s", err) } + // Unsafe path routes + for _, r := range c.UnsafeRoutes { + l.Debug("command: route", "-n", "add", "-net", r.route.String(), "-interface", c.Device) + if err = exec.Command("/sbin/route", "-n", "add", "-net", r.route.String(), "-interface", c.Device).Run(); err != nil { + return fmt.Errorf("failed to run 'route add' for unsafe_route %s: %s", r.route.String(), err) + } + } return nil }