Skip to content

Commit

Permalink
Support startup without a tun device (slackhq#269)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
forfuncsake authored Aug 10, 2020
1 parent 7b3f23d commit 9b8b3c4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 3 deletions.
2 changes: 2 additions & 0 deletions examples/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
74 changes: 74 additions & 0 deletions tun_disabled.go
Original file line number Diff line number Diff line change
@@ -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()
}

0 comments on commit 9b8b3c4

Please sign in to comment.