mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-22 16:31:28 +02:00
* Feat add basic support for IPv6 networks Newly generated networks automatically generate an IPv6 prefix of size 64 within the ULA address range, devices obtain a randomly generated address within this prefix. Currently, this is Linux only and does not yet support all features (routes currently cause an error). * Fix firewall configuration for IPv6 networks * Fix routing configuration for IPv6 networks * Feat provide info on IPv6 support for specific client to mgmt server * Feat allow configuration of IPv6 support through API, improve stability * Feat add IPv6 support to new firewall implementation * Fix peer list item response not containing IPv6 address * Fix nftables breaking on IPv6 address change * Fix build issues for non-linux systems * Fix intermittent disconnections when IPv6 is enabled * Fix test issues and make some minor revisions * Fix some more testing issues * Fix more CI issues due to IPv6 * Fix more testing issues * Add inheritance of IPv6 enablement status from groups * Fix IPv6 events not having associated messages * Address first review comments regarding IPv6 support * Fix IPv6 table being created even when IPv6 is disabled Also improved stability of IPv6 route and firewall handling on client side * Fix IPv6 routes not being removed * Fix DNS IPv6 issues, limit IPv6 nameservers to IPv6 peers * Improve code for IPv6 DNS server selection, add AAAA custom records * Ensure IPv6 routes can only exist for IPv6 routing peers * Fix IPv6 network generation randomness * Fix a bunch of compilation issues and test failures * Replace method calls that are unavailable in Go 1.21 * Fix nil dereference in cleanUpDefaultForwardRules6 * Fix nil pointer dereference when persisting IPv6 network in sqlite * Clean up of client-side code changes for IPv6 * Fix nil dereference in rule mangling and compilation issues * Add a bunch of client-side test cases for IPv6 * Fix IPv6 tests running on unsupported environments * Fix import cycle in tests * Add missing method SupportsIPv6() for windows * Require IPv6 default route for IPv6 tests * Fix panics in routemanager tests on non-linux * Fix some more route manager tests concerning IPv6 * Add some final client-side tests * Add IPv6 tests for management code, small fixes * Fix linting issues * Fix small test suite issues * Fix linter issues and builds on macOS and Windows again * fix builds for iOS because of IPv6 breakage
175 lines
4.2 KiB
Go
175 lines
4.2 KiB
Go
package iface
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
"github.com/netbirdio/netbird/iface/bind"
|
|
)
|
|
|
|
const (
|
|
DefaultMTU = 1280
|
|
DefaultWgPort = 51820
|
|
)
|
|
|
|
// WGIface represents a interface instance
|
|
type WGIface struct {
|
|
tun wgTunDevice
|
|
userspaceBind bool
|
|
mu sync.Mutex
|
|
|
|
configurer wgConfigurer
|
|
filter PacketFilter
|
|
}
|
|
|
|
type WGStats struct {
|
|
LastHandshake time.Time
|
|
TxBytes int64
|
|
RxBytes int64
|
|
}
|
|
|
|
// IsUserspaceBind indicates whether this interfaces is userspace with bind.ICEBind
|
|
func (w *WGIface) IsUserspaceBind() bool {
|
|
return w.userspaceBind
|
|
}
|
|
|
|
// 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()
|
|
}
|
|
|
|
// Address6 returns the IPv6 interface address
|
|
func (w *WGIface) Address6() *WGAddress {
|
|
return w.tun.WgAddress6()
|
|
}
|
|
|
|
// Up configures a Wireguard interface
|
|
// The interface must exist before calling this method (e.g. call interface.Create() before)
|
|
func (w *WGIface) Up() (*bind.UniversalUDPMuxDefault, error) {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
return w.tun.Up()
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
// UpdateAddr6 updates the IPv6 address of the interface
|
|
func (w *WGIface) UpdateAddr6(newAddr6 string) error {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
var addr *WGAddress
|
|
if newAddr6 != "" {
|
|
parsedAddr, err := parseWGAddress(newAddr6)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addr = &parsedAddr
|
|
}
|
|
|
|
return w.tun.UpdateAddr6(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.WgAddress().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()
|
|
}
|
|
|
|
// GetStats returns the last handshake time, rx and tx bytes for the given peer
|
|
func (w *WGIface) GetStats(peerKey string) (WGStats, error) {
|
|
return w.configurer.getStats(peerKey)
|
|
}
|