Skip to content

Commit e1e8fb8

Browse files
committed
linux: opt out of naming your tun device yourself
1 parent 071589f commit e1e8fb8

1 file changed

Lines changed: 40 additions & 5 deletions

File tree

overlay/tun_linux.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package overlay
55

66
import (
7+
"errors"
78
"fmt"
89
"io"
910
"net"
@@ -101,12 +102,18 @@ func newTun(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, multiqueu
101102
}
102103
}
103104

105+
tunNameTemplate := c.GetString("tun.dev", "nebula%d")
106+
tunName, err := findNextTunName(tunNameTemplate)
107+
if err != nil {
108+
return nil, err
109+
}
110+
104111
var req ifReq
105112
req.Flags = uint16(unix.IFF_TUN | unix.IFF_NO_PI)
106113
if multiqueue {
107114
req.Flags |= unix.IFF_MULTI_QUEUE
108115
}
109-
copy(req.Name[:], c.GetString("tun.dev", ""))
116+
copy(req.Name[:], tunName)
110117
if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil {
111118
return nil, err
112119
}
@@ -123,6 +130,38 @@ func newTun(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, multiqueu
123130
return t, nil
124131
}
125132

133+
func findNextTunName(tunName string) (string, error) {
134+
if !strings.HasSuffix(tunName, "%d") {
135+
return tunName, nil
136+
}
137+
if len(tunName) == 2 {
138+
return "", errors.New("please don't name your tun device '%d'")
139+
}
140+
tunNameTemplate := tunName[:len(tunName)-2]
141+
links, err := netlink.LinkList()
142+
if err != nil {
143+
return "", err
144+
}
145+
var candidateName string
146+
for i := 0; i < 100000; i++ {
147+
candidateName = fmt.Sprintf("%s%d", tunNameTemplate, i)
148+
good := true
149+
for _, link := range links {
150+
if candidateName == link.Attrs().Name {
151+
good = false
152+
break
153+
}
154+
}
155+
if good {
156+
if len(candidateName) > 16 {
157+
return "", errors.New("you have too many nebula networks")
158+
}
159+
return candidateName, nil
160+
}
161+
}
162+
return "", errors.New("failed to find a tun device name")
163+
}
164+
126165
func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, vpnNetworks []netip.Prefix) (*tun, error) {
127166
t := &tun{
128167
ReadWriteCloser: file,
@@ -582,9 +621,7 @@ func (t *tun) isGatewayInVpnNetworks(gwAddr netip.Addr) bool {
582621
}
583622

584623
func (t *tun) getGatewaysFromRoute(r *netlink.Route) routing.Gateways {
585-
586624
var gateways routing.Gateways
587-
588625
link, err := netlink.LinkByName(t.Device)
589626
if err != nil {
590627
t.l.WithField("Devicename", t.Device).Error("Ignoring route update: failed to get link by name")
@@ -633,9 +670,7 @@ func (t *tun) getGatewaysFromRoute(r *netlink.Route) routing.Gateways {
633670
}
634671

635672
func (t *tun) updateRoutes(r netlink.RouteUpdate) {
636-
637673
gateways := t.getGatewaysFromRoute(&r.Route)
638-
639674
if len(gateways) == 0 {
640675
// No gateways relevant to our network, no routing changes required.
641676
t.l.WithField("route", r).Debug("Ignoring route update, no gateways")

0 commit comments

Comments
 (0)