mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-12 18:00:49 +01:00
c9b2ce08eb
In case the 53 UDP port is not an option to bind then we hijack the DNS traffic with eBPF, and we forward the traffic to the listener on a custom port. With this implementation, we should be able to listen to DNS queries on any address and still set the local host system to send queries to the custom address on port 53. Because we tried to attach multiple XDP programs to the same interface, I did a refactor in the WG traffic forward code also.
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
package iface
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/netbirdio/netbird/iface/bind"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
const (
|
|
DefaultMTU = 1280
|
|
DefaultWgPort = 51820
|
|
)
|
|
|
|
// WGIface represents a interface instance
|
|
type WGIface struct {
|
|
tun *tunDevice
|
|
configurer wGConfigurer
|
|
mu sync.Mutex
|
|
userspaceBind bool
|
|
filter PacketFilter
|
|
}
|
|
|
|
// IsUserspaceBind indicates whether this interfaces is userspace with bind.ICEBind
|
|
func (w *WGIface) IsUserspaceBind() bool {
|
|
return w.userspaceBind
|
|
}
|
|
|
|
// GetBind returns a userspace implementation of WireGuard Bind interface
|
|
func (w *WGIface) GetBind() *bind.ICEBind {
|
|
return w.tun.iceBind
|
|
}
|
|
|
|
// Name returns the interface name
|
|
func (w *WGIface) Name() string {
|
|
return w.tun.DeviceName()
|
|
}
|
|
|
|
// Address returns the interface address
|
|
func (w *WGIface) Address() WGAddress {
|
|
return w.tun.WgAddress()
|
|
}
|
|
|
|
// Configure configures a Wireguard interface
|
|
// The interface must exist before calling this method (e.g. call interface.Create() before)
|
|
func (w *WGIface) Configure(privateKey string, port int) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
log.Debugf("configuring Wireguard interface %s", w.tun.DeviceName())
|
|
return w.configurer.configureInterface(privateKey, port)
|
|
}
|
|
|
|
// UpdateAddr updates address of the interface
|
|
func (w *WGIface) UpdateAddr(newAddr string) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
addr, err := parseWGAddress(newAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return w.tun.UpdateAddr(addr)
|
|
}
|
|
|
|
// UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist
|
|
// Endpoint is optional
|
|
func (w *WGIface) UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
log.Debugf("updating interface %s peer %s, endpoint %s ", w.tun.DeviceName(), peerKey, endpoint)
|
|
return w.configurer.updatePeer(peerKey, allowedIps, keepAlive, endpoint, preSharedKey)
|
|
}
|
|
|
|
// RemovePeer removes a Wireguard Peer from the interface iface
|
|
func (w *WGIface) RemovePeer(peerKey string) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
log.Debugf("Removing peer %s from interface %s ", peerKey, w.tun.DeviceName())
|
|
return w.configurer.removePeer(peerKey)
|
|
}
|
|
|
|
// AddAllowedIP adds a prefix to the allowed IPs list of peer
|
|
func (w *WGIface) AddAllowedIP(peerKey string, allowedIP string) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
log.Debugf("adding allowed IP to interface %s and peer %s: allowed IP %s ", w.tun.DeviceName(), peerKey, allowedIP)
|
|
return w.configurer.addAllowedIP(peerKey, allowedIP)
|
|
}
|
|
|
|
// RemoveAllowedIP removes a prefix from the allowed IPs list of peer
|
|
func (w *WGIface) RemoveAllowedIP(peerKey string, allowedIP string) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
log.Debugf("removing allowed IP from interface %s and peer %s: allowed IP %s ", w.tun.DeviceName(), peerKey, allowedIP)
|
|
return w.configurer.removeAllowedIP(peerKey, allowedIP)
|
|
}
|
|
|
|
// Close closes the tunnel interface
|
|
func (w *WGIface) Close() error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
return w.tun.Close()
|
|
}
|
|
|
|
// SetFilter sets packet filters for the userspace implementation
|
|
func (w *WGIface) SetFilter(filter PacketFilter) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
if w.tun.wrapper == nil {
|
|
return fmt.Errorf("userspace packet filtering not handled on this device")
|
|
}
|
|
|
|
w.filter = filter
|
|
w.filter.SetNetwork(w.tun.address.Network)
|
|
|
|
w.tun.wrapper.SetFilter(filter)
|
|
return nil
|
|
}
|
|
|
|
// GetFilter returns packet filter used by interface if it uses userspace device implementation
|
|
func (w *WGIface) GetFilter() PacketFilter {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
return w.filter
|
|
}
|
|
|
|
// GetDevice to interact with raw device (with filtering)
|
|
func (w *WGIface) GetDevice() *DeviceWrapper {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
return w.tun.wrapper
|
|
}
|