mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-23 08:54:25 +01:00
vhost
This commit is contained in:
@@ -26,11 +26,11 @@ func NewDeviceFromConfig(c *config.C, l *logrus.Logger, vpnNetworks []netip.Pref
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFdDeviceFromConfig(fd *int) DeviceFactory {
|
//func NewFdDeviceFromConfig(fd *int) DeviceFactory {
|
||||||
return func(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, routines int) (Device, error) {
|
// return func(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, routines int) (Device, error) {
|
||||||
return newTunFromFd(c, l, *fd, vpnNetworks)
|
// return newTunFromFd(c, l, *fd, vpnNetworks)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
func getAllRoutesFromConfig(c *config.C, vpnNetworks []netip.Prefix, initial bool) (bool, []Route, error) {
|
func getAllRoutesFromConfig(c *config.C, vpnNetworks []netip.Prefix, initial bool) (bool, []Route, error) {
|
||||||
if !initial && !c.HasChanged("tun.routes") && !c.HasChanged("tun.unsafe_routes") {
|
if !initial && !c.HasChanged("tun.routes") && !c.HasChanged("tun.unsafe_routes") {
|
||||||
|
|||||||
@@ -11,10 +11,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/gaissmai/bart"
|
"github.com/gaissmai/bart"
|
||||||
|
"github.com/hetznercloud/virtio-go/tuntap"
|
||||||
|
"github.com/hetznercloud/virtio-go/vhostnet"
|
||||||
|
"github.com/hetznercloud/virtio-go/virtio"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/slackhq/nebula/config"
|
"github.com/slackhq/nebula/config"
|
||||||
"github.com/slackhq/nebula/routing"
|
"github.com/slackhq/nebula/routing"
|
||||||
@@ -24,8 +28,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tun struct {
|
type tun struct {
|
||||||
io.ReadWriteCloser
|
dev *tuntap.Device
|
||||||
fd int
|
vdev *vhostnet.Device
|
||||||
Device string
|
Device string
|
||||||
vpnNetworks []netip.Prefix
|
vpnNetworks []netip.Prefix
|
||||||
MaxMTU int
|
MaxMTU int
|
||||||
@@ -65,68 +69,87 @@ type ifreqQLEN struct {
|
|||||||
pad [8]byte
|
pad [8]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTunFromFd(c *config.C, l *logrus.Logger, deviceFd int, vpnNetworks []netip.Prefix) (*tun, error) {
|
//func newTunFromFd(c *config.C, l *logrus.Logger, deviceFd int, vpnNetworks []netip.Prefix) (*tun, error) {
|
||||||
file := os.NewFile(uintptr(deviceFd), "/dev/net/tun")
|
// file := os.NewFile(uintptr(deviceFd), "/dev/net/tun")
|
||||||
|
//
|
||||||
t, err := newTunGeneric(c, l, file, vpnNetworks)
|
// t, err := newTunGeneric(c, l, file, vpnNetworks)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
t.Device = "tun0"
|
// t.Device = "tun0"
|
||||||
|
//
|
||||||
return t, nil
|
// return t, nil
|
||||||
}
|
//}
|
||||||
|
|
||||||
func newTun(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, multiqueue bool) (*tun, error) {
|
func newTun(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, multiqueue bool) (*tun, error) {
|
||||||
fd, err := unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
//fd, err := unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
// If /dev/net/tun doesn't exist, try to create it (will happen in docker)
|
// // If /dev/net/tun doesn't exist, try to create it (will happen in docker)
|
||||||
if os.IsNotExist(err) {
|
// if os.IsNotExist(err) {
|
||||||
err = os.MkdirAll("/dev/net", 0755)
|
// err = os.MkdirAll("/dev/net", 0755)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, fmt.Errorf("/dev/net/tun doesn't exist, failed to mkdir -p /dev/net: %w", err)
|
// return nil, fmt.Errorf("/dev/net/tun doesn't exist, failed to mkdir -p /dev/net: %w", err)
|
||||||
}
|
// }
|
||||||
err = unix.Mknod("/dev/net/tun", unix.S_IFCHR|0600, int(unix.Mkdev(10, 200)))
|
// err = unix.Mknod("/dev/net/tun", unix.S_IFCHR|0600, int(unix.Mkdev(10, 200)))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create /dev/net/tun: %w", err)
|
// return nil, fmt.Errorf("failed to create /dev/net/tun: %w", err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// fd, err = unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("created /dev/net/tun, but still failed: %w", err)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//var req ifReq
|
||||||
|
//req.Flags = uint16(unix.IFF_TUN | unix.IFF_NO_PI)
|
||||||
|
//if multiqueue {
|
||||||
|
// req.Flags |= unix.IFF_MULTI_QUEUE
|
||||||
|
//}
|
||||||
|
//copy(req.Name[:], c.GetString("tun.dev", ""))
|
||||||
|
//if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//name := strings.Trim(string(req.Name[:]), "\x00")
|
||||||
|
//
|
||||||
|
//file := os.NewFile(uintptr(fd), "/dev/net/tun")
|
||||||
|
|
||||||
fd, err = unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
name := strings.Trim(c.GetString("tun.dev", ""), "\x00")
|
||||||
if err != nil {
|
tundev, err := tuntap.NewDevice(
|
||||||
return nil, fmt.Errorf("created /dev/net/tun, but still failed: %w", err)
|
tuntap.WithName(name),
|
||||||
}
|
tuntap.WithDeviceType(tuntap.DeviceTypeTUN),
|
||||||
} else {
|
tuntap.WithVirtioNetHdr(true),
|
||||||
return nil, err
|
tuntap.WithOffloads(0x0), //todo
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
|
||||||
var req ifReq
|
|
||||||
req.Flags = uint16(unix.IFF_TUN | unix.IFF_NO_PI)
|
|
||||||
if multiqueue {
|
|
||||||
req.Flags |= unix.IFF_MULTI_QUEUE
|
|
||||||
}
|
|
||||||
copy(req.Name[:], c.GetString("tun.dev", ""))
|
|
||||||
if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
name := strings.Trim(string(req.Name[:]), "\x00")
|
|
||||||
|
|
||||||
file := os.NewFile(uintptr(fd), "/dev/net/tun")
|
|
||||||
t, err := newTunGeneric(c, l, file, vpnNetworks)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t, err := newTunGeneric(c, l, tundev.File(), vpnNetworks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t.dev = tundev
|
||||||
t.Device = name
|
t.Device = name
|
||||||
|
|
||||||
|
vdev, err := vhostnet.NewDevice(
|
||||||
|
vhostnet.WithBackendDevice(tundev),
|
||||||
|
vhostnet.WithQueueSize(8), //todo config
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t.vdev = vdev
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, vpnNetworks []netip.Prefix) (*tun, error) {
|
func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, vpnNetworks []netip.Prefix) (*tun, error) {
|
||||||
t := &tun{
|
t := &tun{
|
||||||
ReadWriteCloser: file,
|
|
||||||
fd: int(file.Fd()),
|
|
||||||
vpnNetworks: vpnNetworks,
|
vpnNetworks: vpnNetworks,
|
||||||
TXQueueLen: c.GetInt("tun.tx_queue", 500),
|
TXQueueLen: c.GetInt("tun.tx_queue", 500),
|
||||||
useSystemRoutes: c.GetBool("tun.use_system_route_table", false),
|
useSystemRoutes: c.GetBool("tun.use_system_route_table", false),
|
||||||
@@ -217,21 +240,22 @@ func (t *tun) reload(c *config.C, initial bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
|
func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
|
||||||
fd, err := unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
//fd, err := unix.Open("/dev/net/tun", os.O_RDWR, 0)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
|
//var req ifReq
|
||||||
|
//req.Flags = uint16(unix.IFF_TUN | unix.IFF_NO_PI | unix.IFF_MULTI_QUEUE)
|
||||||
|
//copy(req.Name[:], t.Device)
|
||||||
|
//if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//file := os.NewFile(uintptr(fd), "/dev/net/tun")
|
||||||
|
|
||||||
var req ifReq
|
//return file, nil
|
||||||
req.Flags = uint16(unix.IFF_TUN | unix.IFF_NO_PI | unix.IFF_MULTI_QUEUE)
|
return nil, syscall.ENOTSUP
|
||||||
copy(req.Name[:], t.Device)
|
|
||||||
if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
file := os.NewFile(uintptr(fd), "/dev/net/tun")
|
|
||||||
|
|
||||||
return file, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tun) RoutesFor(ip netip.Addr) routing.Gateways {
|
func (t *tun) RoutesFor(ip netip.Addr) routing.Gateways {
|
||||||
@@ -239,27 +263,33 @@ func (t *tun) RoutesFor(ip netip.Addr) routing.Gateways {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *tun) Read(p []byte) (int, error) {
|
||||||
|
_, out, err := t.vdev.ReceivePacket()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
p = p[:len(out)]
|
||||||
|
copy(p, out)
|
||||||
|
return len(out), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *tun) Write(b []byte) (int, error) {
|
func (t *tun) Write(b []byte) (int, error) {
|
||||||
var nn int
|
|
||||||
maximum := len(b)
|
maximum := len(b)
|
||||||
|
|
||||||
for {
|
hdr := virtio.NetHdr{ //todo
|
||||||
n, err := unix.Write(t.fd, b[nn:maximum])
|
Flags: 0,
|
||||||
if n > 0 {
|
GSOType: 0,
|
||||||
nn += n
|
HdrLen: 0,
|
||||||
|
GSOSize: 0,
|
||||||
|
CsumStart: 0,
|
||||||
|
CsumOffset: 0,
|
||||||
|
NumBuffers: 0,
|
||||||
}
|
}
|
||||||
if nn == len(b) {
|
err := t.vdev.TransmitPacket(hdr, b)
|
||||||
return nn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nn, err
|
return 0, err
|
||||||
}
|
|
||||||
|
|
||||||
if n == 0 {
|
|
||||||
return nn, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return maximum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tun) deviceBytes() (o [16]byte) {
|
func (t *tun) deviceBytes() (o [16]byte) {
|
||||||
@@ -674,8 +704,12 @@ func (t *tun) Close() error {
|
|||||||
close(t.routeChan)
|
close(t.routeChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ReadWriteCloser != nil {
|
if t.vdev != nil {
|
||||||
_ = t.ReadWriteCloser.Close()
|
_ = t.vdev.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.dev != nil {
|
||||||
|
_ = t.dev.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ioctlFd > 0 {
|
if t.ioctlFd > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user