mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-22 08:03:30 +01:00
[client] Eliminate UDP proxy in user-space mode (#2712)
In the case of user space WireGuard mode, use in-memory proxy between the TURN/Relay connection and the WireGuard Bind. We keep the UDP proxy and eBPF proxy for kernel mode. The key change is the new wgproxy/bind and the iface/bind/ice_bind changes. Everything else is just to fulfill the dependencies.
This commit is contained in:
parent
0106a95f7a
commit
30ebcf38c7
@ -1,142 +0,0 @@
|
|||||||
package bind
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/pion/stun/v2"
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
|
||||||
)
|
|
||||||
|
|
||||||
type receiverCreator struct {
|
|
||||||
iceBind *ICEBind
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc receiverCreator) CreateIPv4ReceiverFn(msgPool *sync.Pool, pc *ipv4.PacketConn, conn *net.UDPConn) wgConn.ReceiveFunc {
|
|
||||||
return rc.iceBind.createIPv4ReceiverFn(msgPool, pc, conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ICEBind struct {
|
|
||||||
*wgConn.StdNetBind
|
|
||||||
|
|
||||||
muUDPMux sync.Mutex
|
|
||||||
|
|
||||||
transportNet transport.Net
|
|
||||||
udpMux *UniversalUDPMuxDefault
|
|
||||||
|
|
||||||
filterFn FilterFn
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewICEBind(transportNet transport.Net, filterFn FilterFn) *ICEBind {
|
|
||||||
ib := &ICEBind{
|
|
||||||
transportNet: transportNet,
|
|
||||||
filterFn: filterFn,
|
|
||||||
}
|
|
||||||
|
|
||||||
rc := receiverCreator{
|
|
||||||
ib,
|
|
||||||
}
|
|
||||||
ib.StdNetBind = wgConn.NewStdNetBindWithReceiverCreator(rc)
|
|
||||||
return ib
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetICEMux returns the ICE UDPMux that was created and used by ICEBind
|
|
||||||
func (s *ICEBind) GetICEMux() (*UniversalUDPMuxDefault, error) {
|
|
||||||
s.muUDPMux.Lock()
|
|
||||||
defer s.muUDPMux.Unlock()
|
|
||||||
if s.udpMux == nil {
|
|
||||||
return nil, fmt.Errorf("ICEBind has not been initialized yet")
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.udpMux, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ICEBind) createIPv4ReceiverFn(ipv4MsgsPool *sync.Pool, pc *ipv4.PacketConn, conn *net.UDPConn) wgConn.ReceiveFunc {
|
|
||||||
s.muUDPMux.Lock()
|
|
||||||
defer s.muUDPMux.Unlock()
|
|
||||||
|
|
||||||
s.udpMux = NewUniversalUDPMuxDefault(
|
|
||||||
UniversalUDPMuxParams{
|
|
||||||
UDPConn: conn,
|
|
||||||
Net: s.transportNet,
|
|
||||||
FilterFn: s.filterFn,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return func(bufs [][]byte, sizes []int, eps []wgConn.Endpoint) (n int, err error) {
|
|
||||||
msgs := ipv4MsgsPool.Get().(*[]ipv4.Message)
|
|
||||||
defer ipv4MsgsPool.Put(msgs)
|
|
||||||
for i := range bufs {
|
|
||||||
(*msgs)[i].Buffers[0] = bufs[i]
|
|
||||||
}
|
|
||||||
var numMsgs int
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
numMsgs, err = pc.ReadBatch(*msgs, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg := &(*msgs)[0]
|
|
||||||
msg.N, msg.NN, _, msg.Addr, err = conn.ReadMsgUDP(msg.Buffers[0], msg.OOB)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
numMsgs = 1
|
|
||||||
}
|
|
||||||
for i := 0; i < numMsgs; i++ {
|
|
||||||
msg := &(*msgs)[i]
|
|
||||||
|
|
||||||
// todo: handle err
|
|
||||||
ok, _ := s.filterOutStunMessages(msg.Buffers, msg.N, msg.Addr)
|
|
||||||
if ok {
|
|
||||||
sizes[i] = 0
|
|
||||||
} else {
|
|
||||||
sizes[i] = msg.N
|
|
||||||
}
|
|
||||||
|
|
||||||
addrPort := msg.Addr.(*net.UDPAddr).AddrPort()
|
|
||||||
ep := &wgConn.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
|
||||||
wgConn.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
|
||||||
eps[i] = ep
|
|
||||||
}
|
|
||||||
return numMsgs, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ICEBind) filterOutStunMessages(buffers [][]byte, n int, addr net.Addr) (bool, error) {
|
|
||||||
for i := range buffers {
|
|
||||||
if !stun.IsMessage(buffers[i]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := s.parseSTUNMessage(buffers[i][:n])
|
|
||||||
if err != nil {
|
|
||||||
buffers[i] = []byte{}
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
muxErr := s.udpMux.HandleSTUNMessage(msg, addr)
|
|
||||||
if muxErr != nil {
|
|
||||||
log.Warnf("failed to handle STUN packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
buffers[i] = []byte{}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ICEBind) parseSTUNMessage(raw []byte) (*stun.Message, error) {
|
|
||||||
msg := &stun.Message{
|
|
||||||
Raw: raw,
|
|
||||||
}
|
|
||||||
if err := msg.Decode(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg, nil
|
|
||||||
}
|
|
5
client/iface/bind/endpoint.go
Normal file
5
client/iface/bind/endpoint.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package bind
|
||||||
|
|
||||||
|
import wgConn "golang.zx2c4.com/wireguard/conn"
|
||||||
|
|
||||||
|
type Endpoint = wgConn.StdNetEndpoint
|
276
client/iface/bind/ice_bind.go
Normal file
276
client/iface/bind/ice_bind.go
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pion/stun/v2"
|
||||||
|
"github.com/pion/transport/v3"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
wgConn "golang.zx2c4.com/wireguard/conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RecvMessage struct {
|
||||||
|
Endpoint *Endpoint
|
||||||
|
Buffer []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type receiverCreator struct {
|
||||||
|
iceBind *ICEBind
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc receiverCreator) CreateIPv4ReceiverFn(msgPool *sync.Pool, pc *ipv4.PacketConn, conn *net.UDPConn) wgConn.ReceiveFunc {
|
||||||
|
return rc.iceBind.createIPv4ReceiverFn(msgPool, pc, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICEBind is a bind implementation with two main features:
|
||||||
|
// 1. filter out STUN messages and handle them
|
||||||
|
// 2. forward the received packets to the WireGuard interface from the relayed connection
|
||||||
|
//
|
||||||
|
// ICEBind.endpoints var is a map that stores the connection for each relayed peer. Fake address is just an IP address
|
||||||
|
// without port, in the format of 127.1.x.x where x.x is the last two octets of the peer address. We try to avoid to
|
||||||
|
// use the port because in the Send function the wgConn.Endpoint the port info is not exported.
|
||||||
|
type ICEBind struct {
|
||||||
|
*wgConn.StdNetBind
|
||||||
|
RecvChan chan RecvMessage
|
||||||
|
|
||||||
|
transportNet transport.Net
|
||||||
|
filterFn FilterFn
|
||||||
|
endpoints map[netip.Addr]net.Conn
|
||||||
|
endpointsMu sync.Mutex
|
||||||
|
// every time when Close() is called (i.e. BindUpdate()) we need to close exit from the receiveRelayed and create a
|
||||||
|
// new closed channel. With the closedChanMu we can safely close the channel and create a new one
|
||||||
|
closedChan chan struct{}
|
||||||
|
closedChanMu sync.RWMutex // protect the closeChan recreation from reading from it.
|
||||||
|
closed bool
|
||||||
|
|
||||||
|
muUDPMux sync.Mutex
|
||||||
|
udpMux *UniversalUDPMuxDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewICEBind(transportNet transport.Net, filterFn FilterFn) *ICEBind {
|
||||||
|
b, _ := wgConn.NewStdNetBind().(*wgConn.StdNetBind)
|
||||||
|
ib := &ICEBind{
|
||||||
|
StdNetBind: b,
|
||||||
|
RecvChan: make(chan RecvMessage, 1),
|
||||||
|
transportNet: transportNet,
|
||||||
|
filterFn: filterFn,
|
||||||
|
endpoints: make(map[netip.Addr]net.Conn),
|
||||||
|
closedChan: make(chan struct{}),
|
||||||
|
closed: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
rc := receiverCreator{
|
||||||
|
ib,
|
||||||
|
}
|
||||||
|
ib.StdNetBind = wgConn.NewStdNetBindWithReceiverCreator(rc)
|
||||||
|
return ib
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ICEBind) Open(uport uint16) ([]wgConn.ReceiveFunc, uint16, error) {
|
||||||
|
s.closed = false
|
||||||
|
s.closedChanMu.Lock()
|
||||||
|
s.closedChan = make(chan struct{})
|
||||||
|
s.closedChanMu.Unlock()
|
||||||
|
fns, port, err := s.StdNetBind.Open(uport)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
fns = append(fns, s.receiveRelayed)
|
||||||
|
return fns, port, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ICEBind) Close() error {
|
||||||
|
if s.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s.closed = true
|
||||||
|
|
||||||
|
close(s.closedChan)
|
||||||
|
|
||||||
|
return s.StdNetBind.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetICEMux returns the ICE UDPMux that was created and used by ICEBind
|
||||||
|
func (s *ICEBind) GetICEMux() (*UniversalUDPMuxDefault, error) {
|
||||||
|
s.muUDPMux.Lock()
|
||||||
|
defer s.muUDPMux.Unlock()
|
||||||
|
if s.udpMux == nil {
|
||||||
|
return nil, fmt.Errorf("ICEBind has not been initialized yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.udpMux, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ICEBind) SetEndpoint(peerAddress *net.UDPAddr, conn net.Conn) (*net.UDPAddr, error) {
|
||||||
|
fakeUDPAddr, err := fakeAddress(peerAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// force IPv4
|
||||||
|
fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4())
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("failed to convert IP to netip.Addr")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.endpointsMu.Lock()
|
||||||
|
b.endpoints[fakeAddr] = conn
|
||||||
|
b.endpointsMu.Unlock()
|
||||||
|
|
||||||
|
return fakeUDPAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ICEBind) RemoveEndpoint(fakeUDPAddr *net.UDPAddr) {
|
||||||
|
fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4())
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("failed to convert IP to netip.Addr")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.endpointsMu.Lock()
|
||||||
|
defer b.endpointsMu.Unlock()
|
||||||
|
delete(b.endpoints, fakeAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error {
|
||||||
|
b.endpointsMu.Lock()
|
||||||
|
conn, ok := b.endpoints[ep.DstIP()]
|
||||||
|
b.endpointsMu.Unlock()
|
||||||
|
if !ok {
|
||||||
|
log.Infof("failed to find endpoint for %s", ep.DstIP())
|
||||||
|
return b.StdNetBind.Send(bufs, ep)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, buf := range bufs {
|
||||||
|
if _, err := conn.Write(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ICEBind) createIPv4ReceiverFn(ipv4MsgsPool *sync.Pool, pc *ipv4.PacketConn, conn *net.UDPConn) wgConn.ReceiveFunc {
|
||||||
|
s.muUDPMux.Lock()
|
||||||
|
defer s.muUDPMux.Unlock()
|
||||||
|
|
||||||
|
s.udpMux = NewUniversalUDPMuxDefault(
|
||||||
|
UniversalUDPMuxParams{
|
||||||
|
UDPConn: conn,
|
||||||
|
Net: s.transportNet,
|
||||||
|
FilterFn: s.filterFn,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return func(bufs [][]byte, sizes []int, eps []wgConn.Endpoint) (n int, err error) {
|
||||||
|
msgs := ipv4MsgsPool.Get().(*[]ipv4.Message)
|
||||||
|
defer ipv4MsgsPool.Put(msgs)
|
||||||
|
for i := range bufs {
|
||||||
|
(*msgs)[i].Buffers[0] = bufs[i]
|
||||||
|
}
|
||||||
|
var numMsgs int
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
numMsgs, err = pc.ReadBatch(*msgs, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg := &(*msgs)[0]
|
||||||
|
msg.N, msg.NN, _, msg.Addr, err = conn.ReadMsgUDP(msg.Buffers[0], msg.OOB)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
numMsgs = 1
|
||||||
|
}
|
||||||
|
for i := 0; i < numMsgs; i++ {
|
||||||
|
msg := &(*msgs)[i]
|
||||||
|
|
||||||
|
// todo: handle err
|
||||||
|
ok, _ := s.filterOutStunMessages(msg.Buffers, msg.N, msg.Addr)
|
||||||
|
if ok {
|
||||||
|
sizes[i] = 0
|
||||||
|
} else {
|
||||||
|
sizes[i] = msg.N
|
||||||
|
}
|
||||||
|
|
||||||
|
addrPort := msg.Addr.(*net.UDPAddr).AddrPort()
|
||||||
|
ep := &wgConn.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
||||||
|
wgConn.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
||||||
|
eps[i] = ep
|
||||||
|
}
|
||||||
|
return numMsgs, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ICEBind) filterOutStunMessages(buffers [][]byte, n int, addr net.Addr) (bool, error) {
|
||||||
|
for i := range buffers {
|
||||||
|
if !stun.IsMessage(buffers[i]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := s.parseSTUNMessage(buffers[i][:n])
|
||||||
|
if err != nil {
|
||||||
|
buffers[i] = []byte{}
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
|
muxErr := s.udpMux.HandleSTUNMessage(msg, addr)
|
||||||
|
if muxErr != nil {
|
||||||
|
log.Warnf("failed to handle STUN packet")
|
||||||
|
}
|
||||||
|
|
||||||
|
buffers[i] = []byte{}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ICEBind) parseSTUNMessage(raw []byte) (*stun.Message, error) {
|
||||||
|
msg := &stun.Message{
|
||||||
|
Raw: raw,
|
||||||
|
}
|
||||||
|
if err := msg.Decode(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// receiveRelayed is a receive function that is used to receive packets from the relayed connection and forward to the
|
||||||
|
// WireGuard. Critical part is do not block if the Closed() has been called.
|
||||||
|
func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpoint) (int, error) {
|
||||||
|
c.closedChanMu.RLock()
|
||||||
|
defer c.closedChanMu.RUnlock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-c.closedChan:
|
||||||
|
return 0, net.ErrClosed
|
||||||
|
case msg, ok := <-c.RecvChan:
|
||||||
|
if !ok {
|
||||||
|
return 0, net.ErrClosed
|
||||||
|
}
|
||||||
|
copy(buffs[0], msg.Buffer)
|
||||||
|
sizes[0] = len(msg.Buffer)
|
||||||
|
eps[0] = wgConn.Endpoint(msg.Endpoint)
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fakeAddress returns a fake address that is used to as an identifier for the peer.
|
||||||
|
// The fake address is in the format of 127.1.x.x where x.x is the last two octets of the peer address.
|
||||||
|
func fakeAddress(peerAddress *net.UDPAddr) (*net.UDPAddr, error) {
|
||||||
|
octets := strings.Split(peerAddress.IP.String(), ".")
|
||||||
|
if len(octets) != 4 {
|
||||||
|
return nil, fmt.Errorf("invalid IP format")
|
||||||
|
}
|
||||||
|
|
||||||
|
newAddr := &net.UDPAddr{
|
||||||
|
IP: net.ParseIP(fmt.Sprintf("127.1.%s.%s", octets[2], octets[3])),
|
||||||
|
Port: peerAddress.Port,
|
||||||
|
}
|
||||||
|
return newAddr, nil
|
||||||
|
}
|
@ -5,7 +5,6 @@ package device
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
@ -31,13 +30,13 @@ type WGTunDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunDevice(address WGAddress, port int, key string, mtu int, transportNet transport.Net, tunAdapter TunAdapter, filterFn bind.FilterFn) *WGTunDevice {
|
func NewTunDevice(address WGAddress, port int, key string, mtu int, iceBind *bind.ICEBind, tunAdapter TunAdapter) *WGTunDevice {
|
||||||
return &WGTunDevice{
|
return &WGTunDevice{
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
key: key,
|
key: key,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn),
|
iceBind: iceBind,
|
||||||
tunAdapter: tunAdapter,
|
tunAdapter: tunAdapter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
@ -29,14 +28,14 @@ type TunDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunDevice(name string, address WGAddress, port int, key string, mtu int, transportNet transport.Net, filterFn bind.FilterFn) *TunDevice {
|
func NewTunDevice(name string, address WGAddress, port int, key string, mtu int, iceBind *bind.ICEBind) *TunDevice {
|
||||||
return &TunDevice{
|
return &TunDevice{
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
key: key,
|
key: key,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn),
|
iceBind: iceBind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ package device
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
@ -30,13 +29,13 @@ type TunDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunDevice(name string, address WGAddress, port int, key string, transportNet transport.Net, tunFd int, filterFn bind.FilterFn) *TunDevice {
|
func NewTunDevice(name string, address WGAddress, port int, key string, iceBind *bind.ICEBind, tunFd int) *TunDevice {
|
||||||
return &TunDevice{
|
return &TunDevice{
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
key: key,
|
key: key,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn),
|
iceBind: iceBind,
|
||||||
tunFd: tunFd,
|
tunFd: tunFd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ package device
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ type TunNetstackDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNetstackDevice(name string, address WGAddress, wgPort int, key string, mtu int, transportNet transport.Net, listenAddress string, filterFn bind.FilterFn) *TunNetstackDevice {
|
func NewNetstackDevice(name string, address WGAddress, wgPort int, key string, mtu int, iceBind *bind.ICEBind, listenAddress string) *TunNetstackDevice {
|
||||||
return &TunNetstackDevice{
|
return &TunNetstackDevice{
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
@ -39,7 +38,7 @@ func NewNetstackDevice(name string, address WGAddress, wgPort int, key string, m
|
|||||||
key: key,
|
key: key,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
listenAddress: listenAddress,
|
listenAddress: listenAddress,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn),
|
iceBind: iceBind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
@ -30,7 +29,7 @@ type USPDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUSPDevice(name string, address WGAddress, port int, key string, mtu int, transportNet transport.Net, filterFn bind.FilterFn) *USPDevice {
|
func NewUSPDevice(name string, address WGAddress, port int, key string, mtu int, iceBind *bind.ICEBind) *USPDevice {
|
||||||
log.Infof("using userspace bind mode")
|
log.Infof("using userspace bind mode")
|
||||||
|
|
||||||
checkUser()
|
checkUser()
|
||||||
@ -41,7 +40,8 @@ func NewUSPDevice(name string, address WGAddress, port int, key string, mtu int,
|
|||||||
port: port,
|
port: port,
|
||||||
key: key,
|
key: key,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn)}
|
iceBind: iceBind,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *USPDevice) Create() (WGConfigurer, error) {
|
func (t *USPDevice) Create() (WGConfigurer, error) {
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
@ -32,14 +31,14 @@ type TunDevice struct {
|
|||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunDevice(name string, address WGAddress, port int, key string, mtu int, transportNet transport.Net, filterFn bind.FilterFn) *TunDevice {
|
func NewTunDevice(name string, address WGAddress, port int, key string, mtu int, iceBind *bind.ICEBind) *TunDevice {
|
||||||
return &TunDevice{
|
return &TunDevice{
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
port: port,
|
port: port,
|
||||||
key: key,
|
key: key,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
iceBind: bind.NewICEBind(transportNet, filterFn),
|
iceBind: iceBind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,16 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/pion/transport/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/errors"
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -22,6 +26,22 @@ const (
|
|||||||
|
|
||||||
type WGAddress = device.WGAddress
|
type WGAddress = device.WGAddress
|
||||||
|
|
||||||
|
type wgProxyFactory interface {
|
||||||
|
GetProxy() wgproxy.Proxy
|
||||||
|
Free() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type WGIFaceOpts struct {
|
||||||
|
IFaceName string
|
||||||
|
Address string
|
||||||
|
WGPort int
|
||||||
|
WGPrivKey string
|
||||||
|
MTU int
|
||||||
|
MobileArgs *device.MobileIFaceArguments
|
||||||
|
TransportNet transport.Net
|
||||||
|
FilterFn bind.FilterFn
|
||||||
|
}
|
||||||
|
|
||||||
// WGIface represents an interface instance
|
// WGIface represents an interface instance
|
||||||
type WGIface struct {
|
type WGIface struct {
|
||||||
tun WGTunDevice
|
tun WGTunDevice
|
||||||
@ -30,6 +50,11 @@ type WGIface struct {
|
|||||||
|
|
||||||
configurer device.WGConfigurer
|
configurer device.WGConfigurer
|
||||||
filter device.PacketFilter
|
filter device.PacketFilter
|
||||||
|
wgProxyFactory wgProxyFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WGIface) GetProxy() wgproxy.Proxy {
|
||||||
|
return w.wgProxyFactory.GetProxy()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserspaceBind indicates whether this interfaces is userspace with bind.ICEBind
|
// IsUserspaceBind indicates whether this interfaces is userspace with bind.ICEBind
|
||||||
@ -124,22 +149,26 @@ func (w *WGIface) Close() error {
|
|||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
err := w.tun.Close()
|
var result *multierror.Error
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to close wireguard interface %s: %w", w.Name(), err)
|
if err := w.wgProxyFactory.Free(); err != nil {
|
||||||
|
result = multierror.Append(result, fmt.Errorf("failed to free WireGuard proxy: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.waitUntilRemoved()
|
if err := w.tun.Close(); err != nil {
|
||||||
if err != nil {
|
result = multierror.Append(result, fmt.Errorf("failed to close wireguard interface %s: %w", w.Name(), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.waitUntilRemoved(); err != nil {
|
||||||
log.Warnf("failed to remove WireGuard interface %s: %v", w.Name(), err)
|
log.Warnf("failed to remove WireGuard interface %s: %v", w.Name(), err)
|
||||||
err = w.Destroy()
|
if err := w.Destroy(); err != nil {
|
||||||
if err != nil {
|
result = multierror.Append(result, fmt.Errorf("failed to remove WireGuard interface %s: %w", w.Name(), err))
|
||||||
return fmt.Errorf("failed to remove WireGuard interface %s: %w", w.Name(), err)
|
return errors.FormatErrorOrNil(result)
|
||||||
}
|
}
|
||||||
log.Infof("interface %s successfully removed", w.Name())
|
log.Infof("interface %s successfully removed", w.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return errors.FormatErrorOrNil(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFilter sets packet filters for the userspace implementation
|
// SetFilter sets packet filters for the userspace implementation
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package iface
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewWGIFace Creates a new WireGuard interface instance
|
|
||||||
func NewWGIFace(iFaceName string, address string, wgPort int, wgPrivKey string, mtu int, transportNet transport.Net, args *device.MobileIFaceArguments, filterFn bind.FilterFn) (*WGIface, error) {
|
|
||||||
wgAddress, err := device.ParseWGAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace := &WGIface{
|
|
||||||
tun: device.NewTunDevice(wgAddress, wgPort, wgPrivKey, mtu, transportNet, args.TunAdapter, filterFn),
|
|
||||||
userspaceBind: true,
|
|
||||||
}
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOnAndroid creates a new Wireguard interface, sets a given IP and brings it up.
|
|
||||||
// Will reuse an existing one.
|
|
||||||
func (w *WGIface) CreateOnAndroid(routes []string, dns string, searchDomains []string) error {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
|
|
||||||
cfgr, err := w.tun.Create(routes, dns, searchDomains)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.configurer = cfgr
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create this function make sense on mobile only
|
|
||||||
func (w *WGIface) Create() error {
|
|
||||||
return fmt.Errorf("this function has not implemented on this platform")
|
|
||||||
}
|
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
package iface
|
package iface
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
// Create creates a new Wireguard interface, sets a given IP and brings it up.
|
// Create creates a new Wireguard interface, sets a given IP and brings it up.
|
||||||
// Will reuse an existing one.
|
// Will reuse an existing one.
|
||||||
// this function is different on Android
|
// this function is different on Android
|
||||||
@ -17,3 +19,8 @@ func (w *WGIface) Create() error {
|
|||||||
w.configurer = cfgr
|
w.configurer = cfgr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateOnAndroid this function make sense on mobile only
|
||||||
|
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
||||||
|
return fmt.Errorf("this function has not implemented on non mobile")
|
||||||
|
}
|
||||||
|
24
client/iface/iface_create_android.go
Normal file
24
client/iface/iface_create_android.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOnAndroid creates a new Wireguard interface, sets a given IP and brings it up.
|
||||||
|
// Will reuse an existing one.
|
||||||
|
func (w *WGIface) CreateOnAndroid(routes []string, dns string, searchDomains []string) error {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
cfgr, err := w.tun.Create(routes, dns, searchDomains)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.configurer = cfgr
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create this function make sense on mobile only
|
||||||
|
func (w *WGIface) Create() error {
|
||||||
|
return fmt.Errorf("this function has not implemented on this platform")
|
||||||
|
}
|
@ -7,39 +7,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v4"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWGIFace Creates a new WireGuard interface instance
|
|
||||||
func NewWGIFace(iFaceName string, address string, wgPort int, wgPrivKey string, mtu int, transportNet transport.Net, _ *device.MobileIFaceArguments, filterFn bind.FilterFn) (*WGIface, error) {
|
|
||||||
wgAddress, err := device.ParseWGAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace := &WGIface{
|
|
||||||
userspaceBind: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if netstack.IsEnabled() {
|
|
||||||
wgIFace.tun = device.NewNetstackDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, netstack.ListenAddr(), filterFn)
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace.tun = device.NewTunDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, filterFn)
|
|
||||||
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOnAndroid this function make sense on mobile only
|
|
||||||
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
|
||||||
return fmt.Errorf("this function has not implemented on this platform")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates a new Wireguard interface, sets a given IP and brings it up.
|
// Create creates a new Wireguard interface, sets a given IP and brings it up.
|
||||||
// Will reuse an existing one.
|
// Will reuse an existing one.
|
||||||
// this function is different on Android
|
// this function is different on Android
|
||||||
@ -65,3 +34,8 @@ func (w *WGIface) Create() error {
|
|||||||
|
|
||||||
return backoff.Retry(operation, backOff)
|
return backoff.Retry(operation, backOff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateOnAndroid this function make sense on mobile only
|
||||||
|
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
||||||
|
return fmt.Errorf("this function has not implemented on this platform")
|
||||||
|
}
|
10
client/iface/iface_guid_windows.go
Normal file
10
client/iface/iface_guid_windows.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetInterfaceGUIDString returns an interface GUID. This is useful on Windows only
|
||||||
|
func (w *WGIface) GetInterfaceGUIDString() (string, error) {
|
||||||
|
return w.tun.(*device.TunDevice).GetInterfaceGUIDString()
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
//go:build ios
|
|
||||||
|
|
||||||
package iface
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewWGIFace Creates a new WireGuard interface instance
|
|
||||||
func NewWGIFace(iFaceName string, address string, wgPort int, wgPrivKey string, mtu int, transportNet transport.Net, args *device.MobileIFaceArguments, filterFn bind.FilterFn) (*WGIface, error) {
|
|
||||||
wgAddress, err := device.ParseWGAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
wgIFace := &WGIface{
|
|
||||||
tun: device.NewTunDevice(iFaceName, wgAddress, wgPort, wgPrivKey, transportNet, args.TunFd, filterFn),
|
|
||||||
userspaceBind: true,
|
|
||||||
}
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOnAndroid creates a new Wireguard interface, sets a given IP and brings it up.
|
|
||||||
// Will reuse an existing one.
|
|
||||||
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
|
||||||
return fmt.Errorf("this function has not implemented on this platform")
|
|
||||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockWGIface struct {
|
type MockWGIface struct {
|
||||||
@ -30,6 +31,7 @@ type MockWGIface struct {
|
|||||||
GetDeviceFunc func() *device.FilteredDevice
|
GetDeviceFunc func() *device.FilteredDevice
|
||||||
GetStatsFunc func(peerKey string) (configurer.WGStats, error)
|
GetStatsFunc func(peerKey string) (configurer.WGStats, error)
|
||||||
GetInterfaceGUIDStringFunc func() (string, error)
|
GetInterfaceGUIDStringFunc func() (string, error)
|
||||||
|
GetProxyFunc func() wgproxy.Proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockWGIface) GetInterfaceGUIDString() (string, error) {
|
func (m *MockWGIface) GetInterfaceGUIDString() (string, error) {
|
||||||
@ -103,3 +105,8 @@ func (m *MockWGIface) GetDevice() *device.FilteredDevice {
|
|||||||
func (m *MockWGIface) GetStats(peerKey string) (configurer.WGStats, error) {
|
func (m *MockWGIface) GetStats(peerKey string) (configurer.WGStats, error) {
|
||||||
return m.GetStatsFunc(peerKey)
|
return m.GetStatsFunc(peerKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockWGIface) GetProxy() wgproxy.Proxy {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
24
client/iface/iface_new_android.go
Normal file
24
client/iface/iface_new_android.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
|
func NewWGIFace(opts WGIFaceOpts) (*WGIface, error) {
|
||||||
|
wgAddress, err := device.ParseWGAddress(opts.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
|
||||||
|
wgIFace := &WGIface{
|
||||||
|
userspaceBind: true,
|
||||||
|
tun: device.NewTunDevice(wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind, opts.MobileArgs.TunAdapter),
|
||||||
|
wgProxyFactory: wgproxy.NewUSPFactory(iceBind),
|
||||||
|
}
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
34
client/iface/iface_new_darwin.go
Normal file
34
client/iface/iface_new_darwin.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//go:build !ios
|
||||||
|
|
||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
|
func NewWGIFace(opts WGIFaceOpts) (*WGIface, error) {
|
||||||
|
wgAddress, err := device.ParseWGAddress(opts.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
|
||||||
|
var tun WGTunDevice
|
||||||
|
if netstack.IsEnabled() {
|
||||||
|
tun = device.NewNetstackDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind, netstack.ListenAddr())
|
||||||
|
} else {
|
||||||
|
tun = device.NewTunDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind)
|
||||||
|
}
|
||||||
|
|
||||||
|
wgIFace := &WGIface{
|
||||||
|
userspaceBind: true,
|
||||||
|
tun: tun,
|
||||||
|
wgProxyFactory: wgproxy.NewUSPFactory(iceBind),
|
||||||
|
}
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
26
client/iface/iface_new_ios.go
Normal file
26
client/iface/iface_new_ios.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//go:build ios
|
||||||
|
|
||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
|
func NewWGIFace(opts WGIFaceOpts) (*WGIface, error) {
|
||||||
|
wgAddress, err := device.ParseWGAddress(opts.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
|
||||||
|
wgIFace := &WGIface{
|
||||||
|
tun: device.NewTunDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, iceBind, opts.MobileArgs.TunFd),
|
||||||
|
userspaceBind: true,
|
||||||
|
wgProxyFactory: wgproxy.NewUSPFactory(iceBind),
|
||||||
|
}
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
45
client/iface/iface_new_unix.go
Normal file
45
client/iface/iface_new_unix.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//go:build (linux && !android) || freebsd
|
||||||
|
|
||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
|
func NewWGIFace(opts WGIFaceOpts) (*WGIface, error) {
|
||||||
|
wgAddress, err := device.ParseWGAddress(opts.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wgIFace := &WGIface{}
|
||||||
|
|
||||||
|
if netstack.IsEnabled() {
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
wgIFace.tun = device.NewNetstackDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind, netstack.ListenAddr())
|
||||||
|
wgIFace.userspaceBind = true
|
||||||
|
wgIFace.wgProxyFactory = wgproxy.NewUSPFactory(iceBind)
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.WireGuardModuleIsLoaded() {
|
||||||
|
wgIFace.tun = device.NewKernelDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, opts.TransportNet)
|
||||||
|
wgIFace.wgProxyFactory = wgproxy.NewKernelFactory(opts.WGPort)
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
||||||
|
if device.ModuleTunIsLoaded() {
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
wgIFace.tun = device.NewUSPDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind)
|
||||||
|
wgIFace.userspaceBind = true
|
||||||
|
wgIFace.wgProxyFactory = wgproxy.NewUSPFactory(iceBind)
|
||||||
|
return wgIFace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("couldn't check or load tun module")
|
||||||
|
}
|
32
client/iface/iface_new_windows.go
Normal file
32
client/iface/iface_new_windows.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package iface
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
|
func NewWGIFace(opts WGIFaceOpts) (*WGIface, error) {
|
||||||
|
wgAddress, err := device.ParseWGAddress(opts.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
iceBind := bind.NewICEBind(opts.TransportNet, opts.FilterFn)
|
||||||
|
|
||||||
|
var tun WGTunDevice
|
||||||
|
if netstack.IsEnabled() {
|
||||||
|
tun = device.NewNetstackDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind, netstack.ListenAddr())
|
||||||
|
} else {
|
||||||
|
tun = device.NewTunDevice(opts.IFaceName, wgAddress, opts.WGPort, opts.WGPrivKey, opts.MTU, iceBind)
|
||||||
|
}
|
||||||
|
|
||||||
|
wgIFace := &WGIface{
|
||||||
|
userspaceBind: true,
|
||||||
|
tun: tun,
|
||||||
|
wgProxyFactory: wgproxy.NewUSPFactory(iceBind),
|
||||||
|
}
|
||||||
|
return wgIFace, nil
|
||||||
|
|
||||||
|
}
|
@ -45,7 +45,16 @@ func TestWGIface_UpdateAddr(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := NewWGIFace(ifaceName, addr, wgPort, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: addr,
|
||||||
|
WGPort: wgPort,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -118,7 +127,16 @@ func Test_CreateInterface(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, 33100, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -153,7 +171,16 @@ func Test_Close(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, wgPort, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: wgPort,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -189,7 +216,16 @@ func TestRecreation(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, wgPort, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: wgPort,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -252,7 +288,15 @@ func Test_ConfigureInterface(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, wgPort, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: wgPort,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -300,7 +344,16 @@ func Test_UpdatePeer(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, 33100, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -361,7 +414,16 @@ func Test_RemovePeer(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := NewWGIFace(ifaceName, wgIP, 33100, key, DefaultMTU, newNet, nil, nil)
|
opts := WGIFaceOpts{
|
||||||
|
IFaceName: ifaceName,
|
||||||
|
Address: wgIP,
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: key,
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -418,7 +480,15 @@ func Test_ConnectPeers(t *testing.T) {
|
|||||||
guid := fmt.Sprintf("{%s}", uuid.New().String())
|
guid := fmt.Sprintf("{%s}", uuid.New().String())
|
||||||
device.CustomWindowsGUIDString = strings.ToLower(guid)
|
device.CustomWindowsGUIDString = strings.ToLower(guid)
|
||||||
|
|
||||||
iface1, err := NewWGIFace(peer1ifaceName, peer1wgIP, peer1wgPort, peer1Key.String(), DefaultMTU, newNet, nil, nil)
|
optsPeer1 := WGIFaceOpts{
|
||||||
|
IFaceName: peer1ifaceName,
|
||||||
|
Address: peer1wgIP,
|
||||||
|
WGPort: peer1wgPort,
|
||||||
|
WGPrivKey: peer1Key.String(),
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
iface1, err := NewWGIFace(optsPeer1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -432,7 +502,12 @@ func Test_ConnectPeers(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peer1endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("127.0.0.1:%d", peer1wgPort))
|
localIP, err := getLocalIP()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peer1endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", localIP, peer1wgPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -444,7 +519,17 @@ func Test_ConnectPeers(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
iface2, err := NewWGIFace(peer2ifaceName, peer2wgIP, peer2wgPort, peer2Key.String(), DefaultMTU, newNet, nil, nil)
|
|
||||||
|
optsPeer2 := WGIFaceOpts{
|
||||||
|
IFaceName: peer2ifaceName,
|
||||||
|
Address: peer2wgIP,
|
||||||
|
WGPort: peer2wgPort,
|
||||||
|
WGPrivKey: peer2Key.String(),
|
||||||
|
MTU: DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
iface2, err := NewWGIFace(optsPeer2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -458,7 +543,7 @@ func Test_ConnectPeers(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peer2endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("127.0.0.1:%d", peer2wgPort))
|
peer2endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", localIP, peer2wgPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -527,3 +612,28 @@ func getPeer(ifaceName, peerPubKey string) (wgtypes.Peer, error) {
|
|||||||
}
|
}
|
||||||
return wgtypes.Peer{}, fmt.Errorf("peer not found")
|
return wgtypes.Peer{}, fmt.Errorf("peer not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLocalIP() (string, error) {
|
||||||
|
// Get all interfaces
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
ipNet, ok := addr.(*net.IPNet)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ipNet.IP.IsLoopback() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipNet.IP.To4() == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return ipNet.IP.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("no local IP found")
|
||||||
|
}
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
//go:build (linux && !android) || freebsd
|
|
||||||
|
|
||||||
package iface
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewWGIFace Creates a new WireGuard interface instance
|
|
||||||
func NewWGIFace(iFaceName string, address string, wgPort int, wgPrivKey string, mtu int, transportNet transport.Net, args *device.MobileIFaceArguments, filterFn bind.FilterFn) (*WGIface, error) {
|
|
||||||
wgAddress, err := device.ParseWGAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace := &WGIface{}
|
|
||||||
|
|
||||||
// move the kernel/usp/netstack preference evaluation to upper layer
|
|
||||||
if netstack.IsEnabled() {
|
|
||||||
wgIFace.tun = device.NewNetstackDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, netstack.ListenAddr(), filterFn)
|
|
||||||
wgIFace.userspaceBind = true
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if device.WireGuardModuleIsLoaded() {
|
|
||||||
wgIFace.tun = device.NewKernelDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet)
|
|
||||||
wgIFace.userspaceBind = false
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !device.ModuleTunIsLoaded() {
|
|
||||||
return nil, fmt.Errorf("couldn't check or load tun module")
|
|
||||||
}
|
|
||||||
wgIFace.tun = device.NewUSPDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, nil)
|
|
||||||
wgIFace.userspaceBind = true
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOnAndroid this function make sense on mobile only
|
|
||||||
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
|
||||||
return fmt.Errorf("CreateOnAndroid function has not implemented on %s platform", runtime.GOOS)
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package iface
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/pion/transport/v3"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewWGIFace Creates a new WireGuard interface instance
|
|
||||||
func NewWGIFace(iFaceName string, address string, wgPort int, wgPrivKey string, mtu int, transportNet transport.Net, args *device.MobileIFaceArguments, filterFn bind.FilterFn) (*WGIface, error) {
|
|
||||||
wgAddress, err := device.ParseWGAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace := &WGIface{
|
|
||||||
userspaceBind: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if netstack.IsEnabled() {
|
|
||||||
wgIFace.tun = device.NewNetstackDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, netstack.ListenAddr(), filterFn)
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
wgIFace.tun = device.NewTunDevice(iFaceName, wgAddress, wgPort, wgPrivKey, mtu, transportNet, filterFn)
|
|
||||||
return wgIFace, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOnAndroid this function make sense on mobile only
|
|
||||||
func (w *WGIface) CreateOnAndroid([]string, string, []string) error {
|
|
||||||
return fmt.Errorf("this function has not implemented on non mobile")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInterfaceGUIDString returns an interface GUID. This is useful on Windows only
|
|
||||||
func (w *WGIface) GetInterfaceGUIDString() (string, error) {
|
|
||||||
return w.tun.(*device.TunDevice).GetInterfaceGUIDString()
|
|
||||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IWGIface interface {
|
type IWGIface interface {
|
||||||
@ -22,6 +23,7 @@ type IWGIface interface {
|
|||||||
ToInterface() *net.Interface
|
ToInterface() *net.Interface
|
||||||
Up() (*bind.UniversalUDPMuxDefault, error)
|
Up() (*bind.UniversalUDPMuxDefault, error)
|
||||||
UpdateAddr(newAddr string) error
|
UpdateAddr(newAddr string) error
|
||||||
|
GetProxy() wgproxy.Proxy
|
||||||
UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error
|
UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error
|
||||||
RemovePeer(peerKey string) error
|
RemovePeer(peerKey string) error
|
||||||
AddAllowedIP(peerKey string, allowedIP string) error
|
AddAllowedIP(peerKey string, allowedIP string) error
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IWGIface interface {
|
type IWGIface interface {
|
||||||
@ -20,6 +21,7 @@ type IWGIface interface {
|
|||||||
ToInterface() *net.Interface
|
ToInterface() *net.Interface
|
||||||
Up() (*bind.UniversalUDPMuxDefault, error)
|
Up() (*bind.UniversalUDPMuxDefault, error)
|
||||||
UpdateAddr(newAddr string) error
|
UpdateAddr(newAddr string) error
|
||||||
|
GetProxy() wgproxy.Proxy
|
||||||
UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error
|
UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error
|
||||||
RemovePeer(peerKey string) error
|
RemovePeer(peerKey string) error
|
||||||
AddAllowedIP(peerKey string, allowedIP string) error
|
AddAllowedIP(peerKey string, allowedIP string) error
|
||||||
|
137
client/iface/wgproxy/bind/proxy.go
Normal file
137
client/iface/wgproxy/bind/proxy.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProxyBind struct {
|
||||||
|
Bind *bind.ICEBind
|
||||||
|
|
||||||
|
wgAddr *net.UDPAddr
|
||||||
|
wgEndpoint *bind.Endpoint
|
||||||
|
remoteConn net.Conn
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
closeMu sync.Mutex
|
||||||
|
closed bool
|
||||||
|
|
||||||
|
pausedMu sync.Mutex
|
||||||
|
paused bool
|
||||||
|
isStarted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTurnConn adds a new connection to the bind.
|
||||||
|
// endpoint is the NetBird address of the remote peer. The SetEndpoint return with the address what will be used in the
|
||||||
|
// WireGuard configuration.
|
||||||
|
func (p *ProxyBind) AddTurnConn(ctx context.Context, nbAddr *net.UDPAddr, remoteConn net.Conn) error {
|
||||||
|
addr, err := p.Bind.SetEndpoint(nbAddr, remoteConn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.wgAddr = addr
|
||||||
|
p.wgEndpoint = addrToEndpoint(addr)
|
||||||
|
p.remoteConn = remoteConn
|
||||||
|
p.ctx, p.cancel = context.WithCancel(ctx)
|
||||||
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
func (p *ProxyBind) EndpointAddr() *net.UDPAddr {
|
||||||
|
return p.wgAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyBind) Work() {
|
||||||
|
if p.remoteConn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pausedMu.Lock()
|
||||||
|
p.paused = false
|
||||||
|
p.pausedMu.Unlock()
|
||||||
|
|
||||||
|
// Start the proxy only once
|
||||||
|
if !p.isStarted {
|
||||||
|
p.isStarted = true
|
||||||
|
go p.proxyToLocal(p.ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyBind) Pause() {
|
||||||
|
if p.remoteConn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pausedMu.Lock()
|
||||||
|
p.paused = true
|
||||||
|
p.pausedMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyBind) CloseConn() error {
|
||||||
|
if p.cancel == nil {
|
||||||
|
return fmt.Errorf("proxy not started")
|
||||||
|
}
|
||||||
|
return p.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyBind) close() error {
|
||||||
|
p.closeMu.Lock()
|
||||||
|
defer p.closeMu.Unlock()
|
||||||
|
|
||||||
|
if p.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.closed = true
|
||||||
|
|
||||||
|
p.cancel()
|
||||||
|
|
||||||
|
p.Bind.RemoveEndpoint(p.wgAddr)
|
||||||
|
|
||||||
|
return p.remoteConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyBind) proxyToLocal(ctx context.Context) {
|
||||||
|
defer func() {
|
||||||
|
if err := p.close(); err != nil {
|
||||||
|
log.Warnf("failed to close remote conn: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
buf := make([]byte, 1500)
|
||||||
|
for {
|
||||||
|
n, err := p.remoteConn.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Errorf("failed to read from remote conn: %s, %s", p.remoteConn.RemoteAddr(), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pausedMu.Lock()
|
||||||
|
if p.paused {
|
||||||
|
p.pausedMu.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := bind.RecvMessage{
|
||||||
|
Endpoint: p.wgEndpoint,
|
||||||
|
Buffer: buf[:n],
|
||||||
|
}
|
||||||
|
p.Bind.RecvChan <- msg
|
||||||
|
p.pausedMu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addrToEndpoint(addr *net.UDPAddr) *bind.Endpoint {
|
||||||
|
ip, _ := netip.AddrFromSlice(addr.IP.To4())
|
||||||
|
addrPort := netip.AddrPortFrom(ip, uint16(addr.Port))
|
||||||
|
return &bind.Endpoint{AddrPort: addrPort}
|
||||||
|
}
|
@ -119,7 +119,7 @@ func (p *WGEBPFProxy) Free() error {
|
|||||||
p.ctxCancel()
|
p.ctxCancel()
|
||||||
|
|
||||||
var result *multierror.Error
|
var result *multierror.Error
|
||||||
if p.conn != nil { // p.conn will be nil if we have failed to listen
|
if p.conn != nil {
|
||||||
if err := p.conn.Close(); err != nil {
|
if err := p.conn.Close(); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
@ -28,7 +28,7 @@ type ProxyWrapper struct {
|
|||||||
isStarted bool
|
isStarted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyWrapper) AddTurnConn(ctx context.Context, remoteConn net.Conn) error {
|
func (p *ProxyWrapper) AddTurnConn(ctx context.Context, endpoint *net.UDPAddr, remoteConn net.Conn) error {
|
||||||
addr, err := p.WgeBPFProxy.AddTurnConn(remoteConn)
|
addr, err := p.WgeBPFProxy.AddTurnConn(remoteConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add turn conn: %w", err)
|
return fmt.Errorf("add turn conn: %w", err)
|
47
client/iface/wgproxy/factory_kernel.go
Normal file
47
client/iface/wgproxy/factory_kernel.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//go:build linux && !android
|
||||||
|
|
||||||
|
package wgproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy/ebpf"
|
||||||
|
udpProxy "github.com/netbirdio/netbird/client/iface/wgproxy/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KernelFactory struct {
|
||||||
|
wgPort int
|
||||||
|
|
||||||
|
ebpfProxy *ebpf.WGEBPFProxy
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKernelFactory(wgPort int) *KernelFactory {
|
||||||
|
f := &KernelFactory{
|
||||||
|
wgPort: wgPort,
|
||||||
|
}
|
||||||
|
|
||||||
|
ebpfProxy := ebpf.NewWGEBPFProxy(wgPort)
|
||||||
|
if err := ebpfProxy.Listen(); err != nil {
|
||||||
|
log.Warnf("failed to initialize ebpf proxy, fallback to user space proxy: %s", err)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
f.ebpfProxy = ebpfProxy
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *KernelFactory) GetProxy() Proxy {
|
||||||
|
if w.ebpfProxy == nil {
|
||||||
|
return udpProxy.NewWGUDPProxy(w.wgPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ebpf.ProxyWrapper{
|
||||||
|
WgeBPFProxy: w.ebpfProxy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *KernelFactory) Free() error {
|
||||||
|
if w.ebpfProxy == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return w.ebpfProxy.Free()
|
||||||
|
}
|
26
client/iface/wgproxy/factory_kernel_freebsd.go
Normal file
26
client/iface/wgproxy/factory_kernel_freebsd.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package wgproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
udpProxy "github.com/netbirdio/netbird/client/iface/wgproxy/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KernelFactory todo: check eBPF support on FreeBSD
|
||||||
|
type KernelFactory struct {
|
||||||
|
wgPort int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKernelFactory(wgPort int) *KernelFactory {
|
||||||
|
f := &KernelFactory{
|
||||||
|
wgPort: wgPort,
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *KernelFactory) GetProxy() Proxy {
|
||||||
|
return udpProxy.NewWGUDPProxy(w.wgPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *KernelFactory) Free() error {
|
||||||
|
return nil
|
||||||
|
}
|
27
client/iface/wgproxy/factory_usp.go
Normal file
27
client/iface/wgproxy/factory_usp.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package wgproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
proxyBind "github.com/netbirdio/netbird/client/iface/wgproxy/bind"
|
||||||
|
)
|
||||||
|
|
||||||
|
type USPFactory struct {
|
||||||
|
bind *bind.ICEBind
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUSPFactory(iceBind *bind.ICEBind) *USPFactory {
|
||||||
|
f := &USPFactory{
|
||||||
|
bind: iceBind,
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *USPFactory) GetProxy() Proxy {
|
||||||
|
return &proxyBind.ProxyBind{
|
||||||
|
Bind: w.bind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *USPFactory) Free() error {
|
||||||
|
return nil
|
||||||
|
}
|
15
client/iface/wgproxy/proxy.go
Normal file
15
client/iface/wgproxy/proxy.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package wgproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Proxy is a transfer layer between the relayed connection and the WireGuard
|
||||||
|
type Proxy interface {
|
||||||
|
AddTurnConn(ctx context.Context, endpoint *net.UDPAddr, remoteConn net.Conn) error
|
||||||
|
EndpointAddr() *net.UDPAddr // EndpointAddr returns the address of the WireGuard peer endpoint
|
||||||
|
Work() // Work start or resume the proxy
|
||||||
|
Pause() // Pause to forward the packages from remote connection to WireGuard. The opposite way still works.
|
||||||
|
CloseConn() error
|
||||||
|
}
|
56
client/iface/wgproxy/proxy_linux_test.go
Normal file
56
client/iface/wgproxy/proxy_linux_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//go:build linux && !android
|
||||||
|
|
||||||
|
package wgproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy/ebpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProxyCloseByRemoteConnEBPF(t *testing.T) {
|
||||||
|
if os.Getenv("GITHUB_ACTIONS") != "true" {
|
||||||
|
t.Skip("Skipping test as it requires root privileges")
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
ebpfProxy := ebpf.NewWGEBPFProxy(51831)
|
||||||
|
if err := ebpfProxy.Listen(); err != nil {
|
||||||
|
t.Fatalf("failed to initialize ebpf proxy: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := ebpfProxy.Free(); err != nil {
|
||||||
|
t.Errorf("failed to free ebpf proxy: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
proxy Proxy
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "ebpf proxy",
|
||||||
|
proxy: &ebpf.ProxyWrapper{
|
||||||
|
WgeBPFProxy: ebpfProxy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
relayedConn := newMockConn()
|
||||||
|
err := tt.proxy.AddTurnConn(ctx, nil, relayedConn)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = relayedConn.Close()
|
||||||
|
if err := tt.proxy.CloseConn(); err != nil {
|
||||||
|
t.Errorf("error: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy/ebpf"
|
"github.com/netbirdio/netbird/client/iface/wgproxy/ebpf"
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy/usp"
|
udpProxy "github.com/netbirdio/netbird/client/iface/wgproxy/udp"
|
||||||
"github.com/netbirdio/netbird/util"
|
"github.com/netbirdio/netbird/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ func TestProxyCloseByRemoteConn(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "userspace proxy",
|
name: "userspace proxy",
|
||||||
proxy: usp.NewWGUserSpaceProxy(51830),
|
proxy: udpProxy.NewWGUDPProxy(51830),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ func TestProxyCloseByRemoteConn(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
relayedConn := newMockConn()
|
relayedConn := newMockConn()
|
||||||
err := tt.proxy.AddTurnConn(ctx, relayedConn)
|
err := tt.proxy.AddTurnConn(ctx, nil, relayedConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error: %v", err)
|
t.Errorf("error: %v", err)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package usp
|
package udp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/errors"
|
"github.com/netbirdio/netbird/client/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WGUserSpaceProxy proxies
|
// WGUDPProxy proxies
|
||||||
type WGUserSpaceProxy struct {
|
type WGUDPProxy struct {
|
||||||
localWGListenPort int
|
localWGListenPort int
|
||||||
|
|
||||||
remoteConn net.Conn
|
remoteConn net.Conn
|
||||||
@ -28,10 +28,10 @@ type WGUserSpaceProxy struct {
|
|||||||
isStarted bool
|
isStarted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWGUserSpaceProxy instantiate a user space WireGuard proxy. This is not a thread safe implementation
|
// NewWGUDPProxy instantiate a UDP based WireGuard proxy. This is not a thread safe implementation
|
||||||
func NewWGUserSpaceProxy(wgPort int) *WGUserSpaceProxy {
|
func NewWGUDPProxy(wgPort int) *WGUDPProxy {
|
||||||
log.Debugf("Initializing new user space proxy with port %d", wgPort)
|
log.Debugf("Initializing new user space proxy with port %d", wgPort)
|
||||||
p := &WGUserSpaceProxy{
|
p := &WGUDPProxy{
|
||||||
localWGListenPort: wgPort,
|
localWGListenPort: wgPort,
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
@ -42,7 +42,7 @@ func NewWGUserSpaceProxy(wgPort int) *WGUserSpaceProxy {
|
|||||||
// the connection is complete, an error is returned. Once successfully
|
// the connection is complete, an error is returned. Once successfully
|
||||||
// connected, any expiration of the context will not affect the
|
// connected, any expiration of the context will not affect the
|
||||||
// connection.
|
// connection.
|
||||||
func (p *WGUserSpaceProxy) AddTurnConn(ctx context.Context, remoteConn net.Conn) error {
|
func (p *WGUDPProxy) AddTurnConn(ctx context.Context, endpoint *net.UDPAddr, remoteConn net.Conn) error {
|
||||||
dialer := net.Dialer{}
|
dialer := net.Dialer{}
|
||||||
localConn, err := dialer.DialContext(ctx, "udp", fmt.Sprintf(":%d", p.localWGListenPort))
|
localConn, err := dialer.DialContext(ctx, "udp", fmt.Sprintf(":%d", p.localWGListenPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +57,7 @@ func (p *WGUserSpaceProxy) AddTurnConn(ctx context.Context, remoteConn net.Conn)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *WGUserSpaceProxy) EndpointAddr() *net.UDPAddr {
|
func (p *WGUDPProxy) EndpointAddr() *net.UDPAddr {
|
||||||
if p.localConn == nil {
|
if p.localConn == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ func (p *WGUserSpaceProxy) EndpointAddr() *net.UDPAddr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Work starts the proxy or resumes it if it was paused
|
// Work starts the proxy or resumes it if it was paused
|
||||||
func (p *WGUserSpaceProxy) Work() {
|
func (p *WGUDPProxy) Work() {
|
||||||
if p.remoteConn == nil {
|
if p.remoteConn == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ func (p *WGUserSpaceProxy) Work() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pause pauses the proxy from receiving data from the remote peer
|
// Pause pauses the proxy from receiving data from the remote peer
|
||||||
func (p *WGUserSpaceProxy) Pause() {
|
func (p *WGUDPProxy) Pause() {
|
||||||
if p.remoteConn == nil {
|
if p.remoteConn == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -94,14 +94,14 @@ func (p *WGUserSpaceProxy) Pause() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CloseConn close the localConn
|
// CloseConn close the localConn
|
||||||
func (p *WGUserSpaceProxy) CloseConn() error {
|
func (p *WGUDPProxy) CloseConn() error {
|
||||||
if p.cancel == nil {
|
if p.cancel == nil {
|
||||||
return fmt.Errorf("proxy not started")
|
return fmt.Errorf("proxy not started")
|
||||||
}
|
}
|
||||||
return p.close()
|
return p.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *WGUserSpaceProxy) close() error {
|
func (p *WGUDPProxy) close() error {
|
||||||
p.closeMu.Lock()
|
p.closeMu.Lock()
|
||||||
defer p.closeMu.Unlock()
|
defer p.closeMu.Unlock()
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ func (p *WGUserSpaceProxy) close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// proxyToRemote proxies from Wireguard to the RemoteKey
|
// proxyToRemote proxies from Wireguard to the RemoteKey
|
||||||
func (p *WGUserSpaceProxy) proxyToRemote(ctx context.Context) {
|
func (p *WGUDPProxy) proxyToRemote(ctx context.Context) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := p.close(); err != nil {
|
if err := p.close(); err != nil {
|
||||||
log.Warnf("error in proxy to remote loop: %s", err)
|
log.Warnf("error in proxy to remote loop: %s", err)
|
||||||
@ -157,7 +157,7 @@ func (p *WGUserSpaceProxy) proxyToRemote(ctx context.Context) {
|
|||||||
|
|
||||||
// proxyToLocal proxies from the Remote peer to local WireGuard
|
// proxyToLocal proxies from the Remote peer to local WireGuard
|
||||||
// if the proxy is paused it will drain the remote conn and drop the packets
|
// if the proxy is paused it will drain the remote conn and drop the packets
|
||||||
func (p *WGUserSpaceProxy) proxyToLocal(ctx context.Context) {
|
func (p *WGUDPProxy) proxyToLocal(ctx context.Context) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := p.close(); err != nil {
|
if err := p.close(); err != nil {
|
||||||
log.Warnf("error in proxy to local loop: %s", err)
|
log.Warnf("error in proxy to local loop: %s", err)
|
@ -267,7 +267,17 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wgIface, err := iface.NewWGIFace(fmt.Sprintf("utun230%d", n), fmt.Sprintf("100.66.100.%d/32", n+1), 33100, privKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
|
||||||
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: fmt.Sprintf("utun230%d", n),
|
||||||
|
Address: fmt.Sprintf("100.66.100.%d/32", n+1),
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: privKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
wgIface, err := iface.NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -345,7 +355,15 @@ func TestDNSFakeResolverHandleUpdates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
privKey, _ := wgtypes.GeneratePrivateKey()
|
privKey, _ := wgtypes.GeneratePrivateKey()
|
||||||
wgIface, err := iface.NewWGIFace("utun2301", "100.66.100.1/32", 33100, privKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: "utun2301",
|
||||||
|
Address: "100.66.100.1/32",
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: privKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
wgIface, err := iface.NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("build interface wireguard: %v", err)
|
t.Errorf("build interface wireguard: %v", err)
|
||||||
return
|
return
|
||||||
@ -803,7 +821,17 @@ func createWgInterfaceWithBind(t *testing.T) (*iface.WGIface, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
privKey, _ := wgtypes.GeneratePrivateKey()
|
privKey, _ := wgtypes.GeneratePrivateKey()
|
||||||
wgIface, err := iface.NewWGIFace("utun2301", "100.66.100.2/24", 33100, privKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
|
||||||
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: "utun2301",
|
||||||
|
Address: "100.66.100.2/24",
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: privKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
wgIface, err := iface.NewWGIFace(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("build interface wireguard: %v", err)
|
t.Fatalf("build interface wireguard: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/internal/rosenpass"
|
"github.com/netbirdio/netbird/client/internal/rosenpass"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager"
|
"github.com/netbirdio/netbird/client/internal/routemanager"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy"
|
|
||||||
nbssh "github.com/netbirdio/netbird/client/ssh"
|
nbssh "github.com/netbirdio/netbird/client/ssh"
|
||||||
"github.com/netbirdio/netbird/client/system"
|
"github.com/netbirdio/netbird/client/system"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
@ -142,7 +141,6 @@ type Engine struct {
|
|||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
wgInterface iface.IWGIface
|
wgInterface iface.IWGIface
|
||||||
wgProxyFactory *wgproxy.Factory
|
|
||||||
|
|
||||||
udpMux *bind.UniversalUDPMuxDefault
|
udpMux *bind.UniversalUDPMuxDefault
|
||||||
|
|
||||||
@ -299,9 +297,6 @@ func (e *Engine) Start() error {
|
|||||||
}
|
}
|
||||||
e.wgInterface = wgIface
|
e.wgInterface = wgIface
|
||||||
|
|
||||||
userspace := e.wgInterface.IsUserspaceBind()
|
|
||||||
e.wgProxyFactory = wgproxy.NewFactory(userspace, e.config.WgPort)
|
|
||||||
|
|
||||||
if e.config.RosenpassEnabled {
|
if e.config.RosenpassEnabled {
|
||||||
log.Infof("rosenpass is enabled")
|
log.Infof("rosenpass is enabled")
|
||||||
if e.config.RosenpassPermissive {
|
if e.config.RosenpassPermissive {
|
||||||
@ -966,7 +961,7 @@ func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, e
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
peerConn, err := peer.NewConn(e.ctx, config, e.statusRecorder, e.wgProxyFactory, e.signaler, e.mobileDep.IFaceDiscover, e.relayManager)
|
peerConn, err := peer.NewConn(e.ctx, config, e.statusRecorder, e.signaler, e.mobileDep.IFaceDiscover, e.relayManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1117,12 +1112,6 @@ func (e *Engine) parseNATExternalIPMappings() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) close() {
|
func (e *Engine) close() {
|
||||||
if e.wgProxyFactory != nil {
|
|
||||||
if err := e.wgProxyFactory.Free(); err != nil {
|
|
||||||
log.Errorf("failed closing ebpf proxy: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("removing Netbird interface %s", e.config.WgIfaceName)
|
log.Debugf("removing Netbird interface %s", e.config.WgIfaceName)
|
||||||
if e.wgInterface != nil {
|
if e.wgInterface != nil {
|
||||||
if err := e.wgInterface.Close(); err != nil {
|
if err := e.wgInterface.Close(); err != nil {
|
||||||
@ -1167,21 +1156,29 @@ func (e *Engine) newWgIface() (*iface.WGIface, error) {
|
|||||||
log.Errorf("failed to create pion's stdnet: %s", err)
|
log.Errorf("failed to create pion's stdnet: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mArgs *device.MobileIFaceArguments
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: e.config.WgIfaceName,
|
||||||
|
Address: e.config.WgAddr,
|
||||||
|
WGPort: e.config.WgPort,
|
||||||
|
WGPrivKey: e.config.WgPrivateKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: transportNet,
|
||||||
|
FilterFn: e.addrViaRoutes,
|
||||||
|
}
|
||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "android":
|
case "android":
|
||||||
mArgs = &device.MobileIFaceArguments{
|
opts.MobileArgs = &device.MobileIFaceArguments{
|
||||||
TunAdapter: e.mobileDep.TunAdapter,
|
TunAdapter: e.mobileDep.TunAdapter,
|
||||||
TunFd: int(e.mobileDep.FileDescriptor),
|
TunFd: int(e.mobileDep.FileDescriptor),
|
||||||
}
|
}
|
||||||
case "ios":
|
case "ios":
|
||||||
mArgs = &device.MobileIFaceArguments{
|
opts.MobileArgs = &device.MobileIFaceArguments{
|
||||||
TunFd: int(e.mobileDep.FileDescriptor),
|
TunFd: int(e.mobileDep.FileDescriptor),
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return iface.NewWGIFace(e.config.WgIfaceName, e.config.WgAddr, e.config.WgPort, e.config.WgPrivateKey.String(), iface.DefaultMTU, transportNet, mArgs, e.addrViaRoutes)
|
return iface.NewWGIFace(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) wgInterfaceCreate() (err error) {
|
func (e *Engine) wgInterfaceCreate() (err error) {
|
||||||
|
@ -602,7 +602,16 @@ func TestEngine_UpdateNetworkMapWithRoutes(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
engine.wgInterface, err = iface.NewWGIFace(wgIfaceName, wgAddr, engine.config.WgPort, key.String(), iface.DefaultMTU, newNet, nil, nil)
|
|
||||||
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: wgIfaceName,
|
||||||
|
Address: wgAddr,
|
||||||
|
WGPort: engine.config.WgPort,
|
||||||
|
WGPrivKey: key.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
engine.wgInterface, err = iface.NewWGIFace(opts)
|
||||||
assert.NoError(t, err, "shouldn't return error")
|
assert.NoError(t, err, "shouldn't return error")
|
||||||
input := struct {
|
input := struct {
|
||||||
inputSerial uint64
|
inputSerial uint64
|
||||||
@ -774,7 +783,15 @@ func TestEngine_UpdateNetworkMapWithDNSUpdate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
engine.wgInterface, err = iface.NewWGIFace(wgIfaceName, wgAddr, 33100, key.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: wgIfaceName,
|
||||||
|
Address: wgAddr,
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: key.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
engine.wgInterface, err = iface.NewWGIFace(opts)
|
||||||
assert.NoError(t, err, "shouldn't return error")
|
assert.NoError(t, err, "shouldn't return error")
|
||||||
|
|
||||||
mockRouteManager := &routemanager.MockManager{
|
mockRouteManager := &routemanager.MockManager{
|
||||||
|
@ -17,8 +17,8 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||||
"github.com/netbirdio/netbird/client/internal/stdnet"
|
"github.com/netbirdio/netbird/client/internal/stdnet"
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy"
|
|
||||||
relayClient "github.com/netbirdio/netbird/relay/client"
|
relayClient "github.com/netbirdio/netbird/relay/client"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
nbnet "github.com/netbirdio/netbird/util/net"
|
nbnet "github.com/netbirdio/netbird/util/net"
|
||||||
@ -81,11 +81,10 @@ type Conn struct {
|
|||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
config ConnConfig
|
config ConnConfig
|
||||||
statusRecorder *Status
|
statusRecorder *Status
|
||||||
wgProxyFactory *wgproxy.Factory
|
|
||||||
signaler *Signaler
|
signaler *Signaler
|
||||||
iFaceDiscover stdnet.ExternalIFaceDiscover
|
|
||||||
relayManager *relayClient.Manager
|
relayManager *relayClient.Manager
|
||||||
allowedIPsIP string
|
allowedIP net.IP
|
||||||
|
allowedNet string
|
||||||
handshaker *Handshaker
|
handshaker *Handshaker
|
||||||
|
|
||||||
onConnected func(remoteWireGuardKey string, remoteRosenpassPubKey []byte, wireGuardIP string, remoteRosenpassAddr string)
|
onConnected func(remoteWireGuardKey string, remoteRosenpassPubKey []byte, wireGuardIP string, remoteRosenpassAddr string)
|
||||||
@ -116,8 +115,8 @@ type Conn struct {
|
|||||||
|
|
||||||
// NewConn creates a new not opened Conn to the remote peer.
|
// NewConn creates a new not opened Conn to the remote peer.
|
||||||
// To establish a connection run Conn.Open
|
// To establish a connection run Conn.Open
|
||||||
func NewConn(engineCtx context.Context, config ConnConfig, statusRecorder *Status, wgProxyFactory *wgproxy.Factory, signaler *Signaler, iFaceDiscover stdnet.ExternalIFaceDiscover, relayManager *relayClient.Manager) (*Conn, error) {
|
func NewConn(engineCtx context.Context, config ConnConfig, statusRecorder *Status, signaler *Signaler, iFaceDiscover stdnet.ExternalIFaceDiscover, relayManager *relayClient.Manager) (*Conn, error) {
|
||||||
_, allowedIPsIP, err := net.ParseCIDR(config.WgConfig.AllowedIps)
|
allowedIP, allowedNet, err := net.ParseCIDR(config.WgConfig.AllowedIps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to parse allowedIPS: %v", err)
|
log.Errorf("failed to parse allowedIPS: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -132,14 +131,12 @@ func NewConn(engineCtx context.Context, config ConnConfig, statusRecorder *Statu
|
|||||||
ctxCancel: ctxCancel,
|
ctxCancel: ctxCancel,
|
||||||
config: config,
|
config: config,
|
||||||
statusRecorder: statusRecorder,
|
statusRecorder: statusRecorder,
|
||||||
wgProxyFactory: wgProxyFactory,
|
|
||||||
signaler: signaler,
|
signaler: signaler,
|
||||||
iFaceDiscover: iFaceDiscover,
|
|
||||||
relayManager: relayManager,
|
relayManager: relayManager,
|
||||||
allowedIPsIP: allowedIPsIP.String(),
|
allowedIP: allowedIP,
|
||||||
|
allowedNet: allowedNet.String(),
|
||||||
statusRelay: NewAtomicConnStatus(),
|
statusRelay: NewAtomicConnStatus(),
|
||||||
statusICE: NewAtomicConnStatus(),
|
statusICE: NewAtomicConnStatus(),
|
||||||
|
|
||||||
iCEDisconnected: make(chan bool, 1),
|
iCEDisconnected: make(chan bool, 1),
|
||||||
relayDisconnected: make(chan bool, 1),
|
relayDisconnected: make(chan bool, 1),
|
||||||
}
|
}
|
||||||
@ -692,7 +689,7 @@ func (conn *Conn) doOnConnected(remoteRosenpassPubKey []byte, remoteRosenpassAdd
|
|||||||
}
|
}
|
||||||
|
|
||||||
if conn.onConnected != nil {
|
if conn.onConnected != nil {
|
||||||
conn.onConnected(conn.config.Key, remoteRosenpassPubKey, conn.allowedIPsIP, remoteRosenpassAddr)
|
conn.onConnected(conn.config.Key, remoteRosenpassPubKey, conn.allowedNet, remoteRosenpassAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,8 +780,13 @@ func (conn *Conn) freeUpConnID() {
|
|||||||
|
|
||||||
func (conn *Conn) newProxy(remoteConn net.Conn) (wgproxy.Proxy, error) {
|
func (conn *Conn) newProxy(remoteConn net.Conn) (wgproxy.Proxy, error) {
|
||||||
conn.log.Debugf("setup proxied WireGuard connection")
|
conn.log.Debugf("setup proxied WireGuard connection")
|
||||||
wgProxy := conn.wgProxyFactory.GetProxy()
|
udpAddr := &net.UDPAddr{
|
||||||
if err := wgProxy.AddTurnConn(conn.ctx, remoteConn); err != nil {
|
IP: conn.allowedIP,
|
||||||
|
Port: conn.config.WgConfig.WgListenPort,
|
||||||
|
}
|
||||||
|
|
||||||
|
wgProxy := conn.config.WgConfig.WgInterface.GetProxy()
|
||||||
|
if err := wgProxy.AddTurnConn(conn.ctx, udpAddr, remoteConn); err != nil {
|
||||||
conn.log.Errorf("failed to add turn net.Conn to local proxy: %v", err)
|
conn.log.Errorf("failed to add turn net.Conn to local proxy: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/internal/stdnet"
|
"github.com/netbirdio/netbird/client/internal/stdnet"
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy"
|
|
||||||
"github.com/netbirdio/netbird/util"
|
"github.com/netbirdio/netbird/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,11 +43,7 @@ func TestNewConn_interfaceFilter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConn_GetKey(t *testing.T) {
|
func TestConn_GetKey(t *testing.T) {
|
||||||
wgProxyFactory := wgproxy.NewFactory(false, connConf.LocalWgPort)
|
conn, err := NewConn(context.Background(), connConf, nil, nil, nil, nil)
|
||||||
defer func() {
|
|
||||||
_ = wgProxyFactory.Free()
|
|
||||||
}()
|
|
||||||
conn, err := NewConn(context.Background(), connConf, nil, wgProxyFactory, nil, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -59,11 +54,7 @@ func TestConn_GetKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConn_OnRemoteOffer(t *testing.T) {
|
func TestConn_OnRemoteOffer(t *testing.T) {
|
||||||
wgProxyFactory := wgproxy.NewFactory(false, connConf.LocalWgPort)
|
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), nil, nil, nil)
|
||||||
defer func() {
|
|
||||||
_ = wgProxyFactory.Free()
|
|
||||||
}()
|
|
||||||
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), wgProxyFactory, nil, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -96,11 +87,7 @@ func TestConn_OnRemoteOffer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConn_OnRemoteAnswer(t *testing.T) {
|
func TestConn_OnRemoteAnswer(t *testing.T) {
|
||||||
wgProxyFactory := wgproxy.NewFactory(false, connConf.LocalWgPort)
|
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), nil, nil, nil)
|
||||||
defer func() {
|
|
||||||
_ = wgProxyFactory.Free()
|
|
||||||
}()
|
|
||||||
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), wgProxyFactory, nil, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -132,11 +119,7 @@ func TestConn_OnRemoteAnswer(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
func TestConn_Status(t *testing.T) {
|
func TestConn_Status(t *testing.T) {
|
||||||
wgProxyFactory := wgproxy.NewFactory(false, connConf.LocalWgPort)
|
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), nil, nil, nil)
|
||||||
defer func() {
|
|
||||||
_ = wgProxyFactory.Free()
|
|
||||||
}()
|
|
||||||
conn, err := NewConn(context.Background(), connConf, NewRecorder("https://mgm"), wgProxyFactory, nil, nil, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,15 @@ func TestManagerUpdateRoutes(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wgInterface, err := iface.NewWGIFace(fmt.Sprintf("utun43%d", n), "100.65.65.2/24", 33100, peerPrivateKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: fmt.Sprintf("utun43%d", n),
|
||||||
|
Address: "100.65.65.2/24",
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: peerPrivateKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
wgInterface, err := iface.NewWGIFace(opts)
|
||||||
require.NoError(t, err, "should create testing WGIface interface")
|
require.NoError(t, err, "should create testing WGIface interface")
|
||||||
defer wgInterface.Close()
|
defer wgInterface.Close()
|
||||||
|
|
||||||
|
@ -61,7 +61,14 @@ func TestAddRemoveRoutes(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wgInterface, err := iface.NewWGIFace(fmt.Sprintf("utun53%d", n), "100.65.75.2/24", 33100, peerPrivateKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: fmt.Sprintf("utun53%d", n),
|
||||||
|
Address: "100.65.75.2/24",
|
||||||
|
WGPrivKey: peerPrivateKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
wgInterface, err := iface.NewWGIFace(opts)
|
||||||
require.NoError(t, err, "should create testing WGIface interface")
|
require.NoError(t, err, "should create testing WGIface interface")
|
||||||
defer wgInterface.Close()
|
defer wgInterface.Close()
|
||||||
|
|
||||||
@ -213,7 +220,15 @@ func TestAddExistAndRemoveRoute(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wgInterface, err := iface.NewWGIFace(fmt.Sprintf("utun53%d", n), "100.65.75.2/24", 33100, peerPrivateKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: fmt.Sprintf("utun53%d", n),
|
||||||
|
Address: "100.65.75.2/24",
|
||||||
|
WGPort: 33100,
|
||||||
|
WGPrivKey: peerPrivateKey.String(),
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
wgInterface, err := iface.NewWGIFace(opts)
|
||||||
require.NoError(t, err, "should create testing WGIface interface")
|
require.NoError(t, err, "should create testing WGIface interface")
|
||||||
defer wgInterface.Close()
|
defer wgInterface.Close()
|
||||||
|
|
||||||
@ -345,7 +360,15 @@ func createWGInterface(t *testing.T, interfaceName, ipAddressCIDR string, listen
|
|||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
wgInterface, err := iface.NewWGIFace(interfaceName, ipAddressCIDR, listenPort, peerPrivateKey.String(), iface.DefaultMTU, newNet, nil, nil)
|
opts := iface.WGIFaceOpts{
|
||||||
|
IFaceName: interfaceName,
|
||||||
|
Address: ipAddressCIDR,
|
||||||
|
WGPrivKey: peerPrivateKey.String(),
|
||||||
|
WGPort: listenPort,
|
||||||
|
MTU: iface.DefaultMTU,
|
||||||
|
TransportNet: newNet,
|
||||||
|
}
|
||||||
|
wgInterface, err := iface.NewWGIFace(opts)
|
||||||
require.NoError(t, err, "should create testing WireGuard interface")
|
require.NoError(t, err, "should create testing WireGuard interface")
|
||||||
|
|
||||||
err = wgInterface.Create()
|
err = wgInterface.Create()
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
//go:build !android
|
|
||||||
|
|
||||||
package wgproxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy/ebpf"
|
|
||||||
"github.com/netbirdio/netbird/client/internal/wgproxy/usp"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Factory struct {
|
|
||||||
wgPort int
|
|
||||||
ebpfProxy *ebpf.WGEBPFProxy
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFactory(userspace bool, wgPort int) *Factory {
|
|
||||||
f := &Factory{wgPort: wgPort}
|
|
||||||
|
|
||||||
if userspace {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
ebpfProxy := ebpf.NewWGEBPFProxy(wgPort)
|
|
||||||
err := ebpfProxy.Listen()
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("failed to initialize ebpf proxy, fallback to user space proxy: %s", err)
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
f.ebpfProxy = ebpfProxy
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Factory) GetProxy() Proxy {
|
|
||||||
if w.ebpfProxy != nil {
|
|
||||||
p := &ebpf.ProxyWrapper{
|
|
||||||
WgeBPFProxy: w.ebpfProxy,
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
return usp.NewWGUserSpaceProxy(w.wgPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Factory) Free() error {
|
|
||||||
if w.ebpfProxy == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return w.ebpfProxy.Free()
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
//go:build !linux || android
|
|
||||||
|
|
||||||
package wgproxy
|
|
||||||
|
|
||||||
import "github.com/netbirdio/netbird/client/internal/wgproxy/usp"
|
|
||||||
|
|
||||||
type Factory struct {
|
|
||||||
wgPort int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFactory(_ bool, wgPort int) *Factory {
|
|
||||||
return &Factory{wgPort: wgPort}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Factory) GetProxy() Proxy {
|
|
||||||
return usp.NewWGUserSpaceProxy(w.wgPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Factory) Free() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package wgproxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Proxy is a transfer layer between the relayed connection and the WireGuard
|
|
||||||
type Proxy interface {
|
|
||||||
AddTurnConn(ctx context.Context, turnConn net.Conn) error
|
|
||||||
EndpointAddr() *net.UDPAddr
|
|
||||||
Work()
|
|
||||||
Pause()
|
|
||||||
CloseConn() error
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user