From 9b8b3c478be6c9c4475109dda6ae88c0157951be Mon Sep 17 00:00:00 2001 From: forfuncsake Date: Mon, 10 Aug 2020 23:15:55 +1000 Subject: [PATCH] Support startup without a tun device (#269) This commit adds support for Nebula to be started without creating a tun device. A node started in this mode still has a full "control plane", but no effective "data plane". Its use is suited to a lighthouse that has no need to partake in the mesh VPN. Consequently, creation of the tun device is the only reason nebula neesd to be started with elevated privileged, so this example lighthouse can also be run as a non-root user. --- examples/config.yml | 2 ++ main.go | 9 ++++-- tun_disabled.go | 74 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 tun_disabled.go diff --git a/examples/config.yml b/examples/config.yml index 4236c70..0857885 100644 --- a/examples/config.yml +++ b/examples/config.yml @@ -124,6 +124,8 @@ punchy: # Configure the private interface. Note: addr is baked into the nebula certificate tun: + # When tun is disabled, a lighthouse can be started without a local tun interface (and therefore without root) + disabled: false # Name of the device dev: nebula1 # Toggles forwarding of local broadcast packets, the address of which depends on the ip/mask encoded in pki.cert diff --git a/main.go b/main.go index 09ad578..1c7cbb8 100644 --- a/main.go +++ b/main.go @@ -101,11 +101,14 @@ func Main(config *Config, configTest bool, block bool, buildVersion string, logg // tun config, listeners, anything modifying the computer should be below //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - var tun *Tun + var tun Inside if !configTest { config.CatchHUP() - if tunFd != nil { + switch { + case config.GetBool("tun.disabled", false): + tun = newDisabledTun(tunCidr, l) + case tunFd != nil: tun, err = newTunFromFd( *tunFd, tunCidr, @@ -114,7 +117,7 @@ func Main(config *Config, configTest bool, block bool, buildVersion string, logg unsafeRoutes, config.GetInt("tun.tx_queue", 500), ) - } else { + default: tun, err = newTun( config.GetString("tun.dev", ""), tunCidr, diff --git a/tun_disabled.go b/tun_disabled.go new file mode 100644 index 0000000..2d96b6a --- /dev/null +++ b/tun_disabled.go @@ -0,0 +1,74 @@ +package nebula + +import ( + "fmt" + "io" + "net" + "strings" + + log "github.com/sirupsen/logrus" +) + +type disabledTun struct { + block chan struct{} + cidr *net.IPNet + logger *log.Logger +} + +func newDisabledTun(cidr *net.IPNet, l *log.Logger) *disabledTun { + return &disabledTun{ + cidr: cidr, + block: make(chan struct{}), + logger: l, + } +} + +func (*disabledTun) Activate() error { + return nil +} + +func (t *disabledTun) CidrNet() *net.IPNet { + return t.cidr +} + +func (*disabledTun) DeviceName() string { + return "disabled" +} + +func (t *disabledTun) Read(b []byte) (int, error) { + <-t.block + return 0, io.EOF +} + +func (t *disabledTun) Write(b []byte) (int, error) { + t.logger.WithField("raw", prettyPacket(b)).Debugf("Disabled tun received unexpected payload") + return len(b), nil +} + +func (t *disabledTun) WriteRaw(b []byte) error { + _, err := t.Write(b) + return err +} + +func (t *disabledTun) Close() error { + if t.block != nil { + close(t.block) + t.block = nil + } + return nil +} + +type prettyPacket []byte + +func (p prettyPacket) String() string { + var s strings.Builder + + for i, b := range p { + if i > 0 && i%8 == 0 { + s.WriteString(" ") + } + s.WriteString(fmt.Sprintf("%02x ", b)) + } + + return s.String() +}