mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Glue up all together
This commit is contained in:
@@ -111,7 +111,7 @@ func RunClient(ctx context.Context, config *Config, statusRecorder *peer.Status,
|
|||||||
localPeerState := peer.LocalPeerState{
|
localPeerState := peer.LocalPeerState{
|
||||||
IP: loginResp.GetPeerConfig().GetAddress(),
|
IP: loginResp.GetPeerConfig().GetAddress(),
|
||||||
PubKey: myPrivateKey.PublicKey().String(),
|
PubKey: myPrivateKey.PublicKey().String(),
|
||||||
KernelInterface: iface.WireguardModuleIsLoaded(),
|
KernelInterface: iface.WireGuardModuleIsLoaded(),
|
||||||
FQDN: loginResp.GetPeerConfig().GetFqdn(),
|
FQDN: loginResp.GetPeerConfig().GetFqdn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package internal
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/netbirdio/netbird/iface/bind"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@@ -103,7 +102,8 @@ type Engine struct {
|
|||||||
|
|
||||||
wgInterface *iface.WGIface
|
wgInterface *iface.WGIface
|
||||||
|
|
||||||
udpMux *bind.UniversalUDPMuxDefault
|
udpMux ice.UDPMux
|
||||||
|
udpMuxSrflx ice.UniversalUDPMux
|
||||||
udpMuxConn *net.UDPConn
|
udpMuxConn *net.UDPConn
|
||||||
udpMuxConnSrflx *net.UDPConn
|
udpMuxConnSrflx *net.UDPConn
|
||||||
|
|
||||||
@@ -118,6 +118,9 @@ type Engine struct {
|
|||||||
routeManager routemanager.Manager
|
routeManager routemanager.Manager
|
||||||
|
|
||||||
dnsServer dns.Server
|
dnsServer dns.Server
|
||||||
|
|
||||||
|
// userspaceBind indicates whether a
|
||||||
|
userspaceBind bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer is an instance of the Connection Peer
|
// Peer is an instance of the Connection Peer
|
||||||
@@ -173,7 +176,7 @@ func (e *Engine) Start() error {
|
|||||||
e.syncMsgMux.Lock()
|
e.syncMsgMux.Lock()
|
||||||
defer e.syncMsgMux.Unlock()
|
defer e.syncMsgMux.Unlock()
|
||||||
|
|
||||||
wgIfaceName := e.config.WgIfaceName
|
wgIFaceName := e.config.WgIfaceName
|
||||||
wgAddr := e.config.WgAddr
|
wgAddr := e.config.WgAddr
|
||||||
myPrivateKey := e.config.WgPrivateKey
|
myPrivateKey := e.config.WgPrivateKey
|
||||||
var err error
|
var err error
|
||||||
@@ -181,31 +184,60 @@ func (e *Engine) Start() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to create pion's stdnet: %s", err)
|
log.Warnf("failed to create pion's stdnet: %s", err)
|
||||||
}
|
}
|
||||||
e.wgInterface, err = iface.NewWGIFace(wgIfaceName, wgAddr, iface.DefaultMTU, e.config.TunAdapter, transportNet)
|
e.wgInterface, err = iface.NewWGIFace(wgIFaceName, wgAddr, iface.DefaultMTU, e.config.TunAdapter, transportNet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed creating wireguard interface instance %s: [%s]", wgIfaceName, err.Error())
|
log.Errorf("failed creating wireguard interface instance %s: [%s]", wgIFaceName, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = e.wgInterface.Create()
|
err = e.wgInterface.Create()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed creating tunnel interface %s: [%s]", wgIfaceName, err.Error())
|
log.Errorf("failed creating tunnel interface %s: [%s]", wgIFaceName, err.Error())
|
||||||
e.close()
|
e.close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = e.wgInterface.Configure(myPrivateKey.String(), e.config.WgPort)
|
err = e.wgInterface.Configure(myPrivateKey.String(), e.config.WgPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed configuring Wireguard interface [%s]: %s", wgIfaceName, err.Error())
|
log.Errorf("failed configuring Wireguard interface [%s]: %s", wgIFaceName, err.Error())
|
||||||
e.close()
|
e.close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
iceBind := e.wgInterface.GetBind()
|
if e.wgInterface.IsUserspaceBind() {
|
||||||
e.udpMux, err = iceBind.GetICEMux()
|
iceBind := e.wgInterface.GetBind()
|
||||||
if err != nil {
|
udpMux, err := iceBind.GetICEMux()
|
||||||
e.close()
|
if err != nil {
|
||||||
return err
|
e.close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.udpMux = udpMux.UDPMuxDefault
|
||||||
|
e.udpMuxSrflx = udpMux
|
||||||
|
log.Infof("using userspace bind mode %s", udpMux.LocalAddr().String())
|
||||||
|
} else {
|
||||||
|
networkName := "udp"
|
||||||
|
if e.config.DisableIPv6Discovery {
|
||||||
|
networkName = "udp4"
|
||||||
|
}
|
||||||
|
e.udpMuxConn, err = net.ListenUDP(networkName, &net.UDPAddr{Port: e.config.UDPMuxPort})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed listening on UDP port %d: [%s]", e.config.UDPMuxPort, err.Error())
|
||||||
|
e.close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
udpMuxParams := ice.UDPMuxParams{
|
||||||
|
UDPConn: e.udpMuxConn,
|
||||||
|
Net: transportNet,
|
||||||
|
}
|
||||||
|
e.udpMux = ice.NewUDPMuxDefault(udpMuxParams)
|
||||||
|
|
||||||
|
e.udpMuxConnSrflx, err = net.ListenUDP(networkName, &net.UDPAddr{Port: e.config.UDPMuxSrflxPort})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed listening on UDP port %d: [%s]", e.config.UDPMuxSrflxPort, err.Error())
|
||||||
|
e.close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.udpMuxSrflx = ice.NewUniversalUDPMuxDefault(ice.UniversalUDPMuxParams{UDPConn: e.udpMuxConnSrflx, Net: transportNet})
|
||||||
}
|
}
|
||||||
|
|
||||||
e.routeManager = routemanager.NewManager(e.ctx, e.config.WgPrivateKey.PublicKey().String(), e.wgInterface, e.statusRecorder)
|
e.routeManager = routemanager.NewManager(e.ctx, e.config.WgPrivateKey.PublicKey().String(), e.wgInterface, e.statusRecorder)
|
||||||
@@ -476,7 +508,7 @@ func (e *Engine) updateConfig(conf *mgmProto.PeerConfig) error {
|
|||||||
e.statusRecorder.UpdateLocalPeerState(peer.LocalPeerState{
|
e.statusRecorder.UpdateLocalPeerState(peer.LocalPeerState{
|
||||||
IP: e.config.WgAddr,
|
IP: e.config.WgAddr,
|
||||||
PubKey: e.config.WgPrivateKey.PublicKey().String(),
|
PubKey: e.config.WgPrivateKey.PublicKey().String(),
|
||||||
KernelInterface: iface.WireguardModuleIsLoaded(),
|
KernelInterface: iface.WireGuardModuleIsLoaded(),
|
||||||
FQDN: conf.GetFqdn(),
|
FQDN: conf.GetFqdn(),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -797,11 +829,12 @@ func (e Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, er
|
|||||||
InterfaceBlackList: e.config.IFaceBlackList,
|
InterfaceBlackList: e.config.IFaceBlackList,
|
||||||
DisableIPv6Discovery: e.config.DisableIPv6Discovery,
|
DisableIPv6Discovery: e.config.DisableIPv6Discovery,
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
UDPMux: e.udpMux.UDPMuxDefault,
|
UDPMux: e.udpMux,
|
||||||
UDPMuxSrflx: e.udpMux,
|
UDPMuxSrflx: e.udpMuxSrflx,
|
||||||
ProxyConfig: proxyConfig,
|
ProxyConfig: proxyConfig,
|
||||||
LocalWgPort: e.config.WgPort,
|
LocalWgPort: e.config.WgPort,
|
||||||
NATExternalIPs: e.parseNATExternalIPMappings(),
|
NATExternalIPs: e.parseNATExternalIPMappings(),
|
||||||
|
UserspaceBind: e.wgInterface.IsUserspaceBind(),
|
||||||
}
|
}
|
||||||
|
|
||||||
peerConn, err := peer.NewConn(config, e.statusRecorder, e.config.TunAdapter, e.config.IFaceDiscover)
|
peerConn, err := peer.NewConn(config, e.statusRecorder, e.config.TunAdapter, e.config.IFaceDiscover)
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ type ConnConfig struct {
|
|||||||
LocalWgPort int
|
LocalWgPort int
|
||||||
|
|
||||||
NATExternalIPs []string
|
NATExternalIPs []string
|
||||||
|
|
||||||
|
// UsesBind indicates whether the WireGuard interface is userspace and uses bind.ICEBind
|
||||||
|
UserspaceBind bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// OfferAnswer represents a session establishment offer or answer
|
// OfferAnswer represents a session establishment offer or answer
|
||||||
@@ -291,7 +294,7 @@ func (conn *Conn) Open() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn.proxy.Type() == proxy.TypeNoProxy {
|
if conn.proxy.Type() == proxy.TypeDirectNoProxy {
|
||||||
host, _, _ := net.SplitHostPort(remoteConn.LocalAddr().String())
|
host, _, _ := net.SplitHostPort(remoteConn.LocalAddr().String())
|
||||||
rhost, _, _ := net.SplitHostPort(remoteConn.RemoteAddr().String())
|
rhost, _, _ := net.SplitHostPort(remoteConn.RemoteAddr().String())
|
||||||
// direct Wireguard connection
|
// direct Wireguard connection
|
||||||
@@ -313,14 +316,21 @@ func (conn *Conn) Open() error {
|
|||||||
|
|
||||||
// useProxy determines whether a direct connection (without a go proxy) is possible
|
// useProxy determines whether a direct connection (without a go proxy) is possible
|
||||||
//
|
//
|
||||||
// There are 2 cases:
|
// There are 3 cases:
|
||||||
//
|
//
|
||||||
// * When neither candidate is from hard nat and one of the peers has a public IP
|
// * When neither candidate is from hard nat and one of the peers has a public IP
|
||||||
//
|
//
|
||||||
// * both peers are in the same private network
|
// * both peers are in the same private network
|
||||||
//
|
//
|
||||||
|
// * Local peer uses userspace interface with bind.ICEBind and is not relayed
|
||||||
|
//
|
||||||
// Please note, that this check happens when peers were already able to ping each other using ICE layer.
|
// Please note, that this check happens when peers were already able to ping each other using ICE layer.
|
||||||
func shouldUseProxy(pair *ice.CandidatePair) bool {
|
func shouldUseProxy(pair *ice.CandidatePair, userspaceBind bool) bool {
|
||||||
|
|
||||||
|
if !isRelayCandidate(pair.Local) && userspaceBind {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if !isHardNATCandidate(pair.Local) && isHostCandidateWithPublicIP(pair.Remote) {
|
if !isHardNATCandidate(pair.Local) && isHostCandidateWithPublicIP(pair.Remote) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -336,6 +346,10 @@ func shouldUseProxy(pair *ice.CandidatePair) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRelayCandidate(candidate ice.Candidate) bool {
|
||||||
|
return candidate.Type() == ice.CandidateTypeRelay
|
||||||
|
}
|
||||||
|
|
||||||
func isHardNATCandidate(candidate ice.Candidate) bool {
|
func isHardNATCandidate(candidate ice.Candidate) bool {
|
||||||
return candidate.Type() == ice.CandidateTypeRelay || candidate.Type() == ice.CandidateTypePeerReflexive
|
return candidate.Type() == ice.CandidateTypeRelay || candidate.Type() == ice.CandidateTypePeerReflexive
|
||||||
}
|
}
|
||||||
@@ -384,7 +398,7 @@ func (conn *Conn) startProxy(remoteConn net.Conn, remoteWgPort int) error {
|
|||||||
if pair.Local.Type() == ice.CandidateTypeRelay || pair.Remote.Type() == ice.CandidateTypeRelay {
|
if pair.Local.Type() == ice.CandidateTypeRelay || pair.Remote.Type() == ice.CandidateTypeRelay {
|
||||||
peerState.Relayed = true
|
peerState.Relayed = true
|
||||||
}
|
}
|
||||||
peerState.Direct = p.Type() == proxy.TypeNoProxy
|
peerState.Direct = p.Type() == proxy.TypeDirectNoProxy
|
||||||
|
|
||||||
err = conn.statusRecorder.UpdatePeerState(peerState)
|
err = conn.statusRecorder.UpdatePeerState(peerState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -395,8 +409,7 @@ func (conn *Conn) startProxy(remoteConn net.Conn, remoteWgPort int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) getProxyWithMessageExchange(pair *ice.CandidatePair, remoteWgPort int) proxy.Proxy {
|
func (conn *Conn) getProxyWithMessageExchange(pair *ice.CandidatePair, remoteWgPort int) proxy.Proxy {
|
||||||
return proxy.NewWireGuardProxy(conn.config.ProxyConfig)
|
useProxy := shouldUseProxy(pair, conn.config.UserspaceBind)
|
||||||
useProxy := shouldUseProxy(pair)
|
|
||||||
localDirectMode := !useProxy
|
localDirectMode := !useProxy
|
||||||
remoteDirectMode := localDirectMode
|
remoteDirectMode := localDirectMode
|
||||||
|
|
||||||
@@ -406,9 +419,14 @@ func (conn *Conn) getProxyWithMessageExchange(pair *ice.CandidatePair, remoteWgP
|
|||||||
remoteDirectMode = conn.receiveRemoteDirectMode()
|
remoteDirectMode = conn.receiveRemoteDirectMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conn.config.UserspaceBind {
|
||||||
|
log.Debugf("using WireGuard no proxy userspace bind mode with peer %s", conn.config.Key)
|
||||||
|
return proxy.NewNoProxy(conn.config.ProxyConfig)
|
||||||
|
}
|
||||||
|
|
||||||
if localDirectMode && remoteDirectMode {
|
if localDirectMode && remoteDirectMode {
|
||||||
log.Debugf("using WireGuard direct mode with peer %s", conn.config.Key)
|
log.Debugf("using WireGuard direct mode with peer %s", conn.config.Key)
|
||||||
return proxy.NewNoProxy(conn.config.ProxyConfig, remoteWgPort)
|
return proxy.NewDirectNoProxy(conn.config.ProxyConfig, remoteWgPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("falling back to local proxy mode with peer %s", conn.config.Key)
|
log.Debugf("falling back to local proxy mode with peer %s", conn.config.Key)
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ func TestConn_ShouldUseProxy(t *testing.T) {
|
|||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
result := shouldUseProxy(testCase.candatePair)
|
result := shouldUseProxy(testCase.candatePair, false)
|
||||||
if result != testCase.expected {
|
if result != testCase.expected {
|
||||||
t.Errorf("got a different result. Expected %t Got %t", testCase.expected, result)
|
t.Errorf("got a different result. Expected %t Got %t", testCase.expected, result)
|
||||||
}
|
}
|
||||||
@@ -366,7 +366,7 @@ func TestGetProxyWithMessageExchange(t *testing.T) {
|
|||||||
},
|
},
|
||||||
inputDirectModeSupport: true,
|
inputDirectModeSupport: true,
|
||||||
inputRemoteModeMessage: true,
|
inputRemoteModeMessage: true,
|
||||||
expected: proxy.TypeWireguard,
|
expected: proxy.TypeWireGuard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Should Result In Using Wireguard Proxy When Remote Eval Is Use Proxy",
|
name: "Should Result In Using Wireguard Proxy When Remote Eval Is Use Proxy",
|
||||||
@@ -376,7 +376,7 @@ func TestGetProxyWithMessageExchange(t *testing.T) {
|
|||||||
},
|
},
|
||||||
inputDirectModeSupport: true,
|
inputDirectModeSupport: true,
|
||||||
inputRemoteModeMessage: false,
|
inputRemoteModeMessage: false,
|
||||||
expected: proxy.TypeWireguard,
|
expected: proxy.TypeWireGuard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Should Result In Using Wireguard Proxy When Remote Direct Mode Support Is False And Local Eval Is Use Proxy",
|
name: "Should Result In Using Wireguard Proxy When Remote Direct Mode Support Is False And Local Eval Is Use Proxy",
|
||||||
@@ -386,7 +386,7 @@ func TestGetProxyWithMessageExchange(t *testing.T) {
|
|||||||
},
|
},
|
||||||
inputDirectModeSupport: false,
|
inputDirectModeSupport: false,
|
||||||
inputRemoteModeMessage: false,
|
inputRemoteModeMessage: false,
|
||||||
expected: proxy.TypeWireguard,
|
expected: proxy.TypeWireGuard,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Should Result In Using Direct When Remote Direct Mode Support Is False And Local Eval Is No Use Proxy",
|
name: "Should Result In Using Direct When Remote Direct Mode Support Is False And Local Eval Is No Use Proxy",
|
||||||
@@ -396,7 +396,7 @@ func TestGetProxyWithMessageExchange(t *testing.T) {
|
|||||||
},
|
},
|
||||||
inputDirectModeSupport: false,
|
inputDirectModeSupport: false,
|
||||||
inputRemoteModeMessage: false,
|
inputRemoteModeMessage: false,
|
||||||
expected: proxy.TypeNoProxy,
|
expected: proxy.TypeDirectNoProxy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Should Result In Using Direct When Local And Remote Eval Is No Proxy",
|
name: "Should Result In Using Direct When Local And Remote Eval Is No Proxy",
|
||||||
@@ -406,7 +406,7 @@ func TestGetProxyWithMessageExchange(t *testing.T) {
|
|||||||
},
|
},
|
||||||
inputDirectModeSupport: true,
|
inputDirectModeSupport: true,
|
||||||
inputRemoteModeMessage: true,
|
inputRemoteModeMessage: true,
|
||||||
expected: proxy.TypeNoProxy,
|
expected: proxy.TypeDirectNoProxy,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
|||||||
55
client/internal/proxy/direct.go
Normal file
55
client/internal/proxy/direct.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirectNoProxy is used when there is no need for a proxy between ICE and WireGuard.
|
||||||
|
// This is possible in either of these cases:
|
||||||
|
// - peers are in the same local network
|
||||||
|
// - one of the peers has a public static IP (host)
|
||||||
|
// DirectNoProxy will just update remote peer with a remote host and fixed WireGuard port (r.g. 51820).
|
||||||
|
// In order DirectNoProxy to work, WireGuard port has to be fixed for the time being.
|
||||||
|
type DirectNoProxy struct {
|
||||||
|
config Config
|
||||||
|
// RemoteWgListenPort is a WireGuard port of a remote peer.
|
||||||
|
// It is used instead of the hardcoded 51820 port.
|
||||||
|
RemoteWgListenPort int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDirectNoProxy creates a new DirectNoProxy with a provided config and remote peer's WireGuard listen port
|
||||||
|
func NewDirectNoProxy(config Config, remoteWgPort int) *DirectNoProxy {
|
||||||
|
return &DirectNoProxy{config: config, RemoteWgListenPort: remoteWgPort}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DirectNoProxy) Close() error {
|
||||||
|
err := p.config.WgInterface.RemovePeer(p.config.RemoteKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start just updates WireGuard peer with the remote IP and default WireGuard port
|
||||||
|
func (p *DirectNoProxy) Start(remoteConn net.Conn) error {
|
||||||
|
|
||||||
|
log.Debugf("using DirectNoProxy while connecting to peer %s", p.config.RemoteKey)
|
||||||
|
addr, err := net.ResolveUDPAddr("udp", remoteConn.RemoteAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addr.Port = p.RemoteWgListenPort
|
||||||
|
err = p.config.WgInterface.UpdatePeer(p.config.RemoteKey, p.config.AllowedIps, DefaultWgKeepAlive,
|
||||||
|
addr, p.config.PreSharedKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DirectNoProxy) Type() Type {
|
||||||
|
return TypeDirectNoProxy
|
||||||
|
}
|
||||||
@@ -5,24 +5,18 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NoProxy is used when there is no need for a proxy between ICE and WireGuard.
|
// NoProxy is used just to configure WireGuard without any local proxy in between.
|
||||||
// This is possible in either of these cases:
|
// Used when the WireGuard interface is userspace and uses bind.ICEBind
|
||||||
// - peers are in the same local network
|
|
||||||
// - one of the peers has a public static IP (host)
|
|
||||||
// NoProxy will just update remote peer with a remote host and fixed WireGuard port (r.g. 51820).
|
|
||||||
// In order NoProxy to work, WireGuard port has to be fixed for the time being.
|
|
||||||
type NoProxy struct {
|
type NoProxy struct {
|
||||||
config Config
|
config Config
|
||||||
// RemoteWgListenPort is a WireGuard port of a remote peer.
|
|
||||||
// It is used instead of the hardcoded 51820 port.
|
|
||||||
RemoteWgListenPort int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNoProxy creates a new NoProxy with a provided config and remote peer's WireGuard listen port
|
// NewNoProxy creates a new NoProxy with a provided config
|
||||||
func NewNoProxy(config Config, remoteWgPort int) *NoProxy {
|
func NewNoProxy(config Config) *NoProxy {
|
||||||
return &NoProxy{config: config, RemoteWgListenPort: remoteWgPort}
|
return &NoProxy{config: config}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close removes peer from the WireGuard interface
|
||||||
func (p *NoProxy) Close() error {
|
func (p *NoProxy) Close() error {
|
||||||
err := p.config.WgInterface.RemovePeer(p.config.RemoteKey)
|
err := p.config.WgInterface.RemovePeer(p.config.RemoteKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -31,23 +25,16 @@ func (p *NoProxy) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start just updates WireGuard peer with the remote IP and default WireGuard port
|
// Start just updates WireGuard peer with the remote address
|
||||||
func (p *NoProxy) Start(remoteConn net.Conn) error {
|
func (p *NoProxy) Start(remoteConn net.Conn) error {
|
||||||
|
|
||||||
log.Debugf("using NoProxy while connecting to peer %s", p.config.RemoteKey)
|
log.Debugf("using NoProxy to connect to peer %s at %s", p.config.RemoteKey, remoteConn.RemoteAddr().String())
|
||||||
addr, err := net.ResolveUDPAddr("udp", remoteConn.RemoteAddr().String())
|
addr, err := net.ResolveUDPAddr("udp", remoteConn.RemoteAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
addr.Port = p.RemoteWgListenPort
|
return p.config.WgInterface.UpdatePeer(p.config.RemoteKey, p.config.AllowedIps, DefaultWgKeepAlive,
|
||||||
err = p.config.WgInterface.UpdatePeer(p.config.RemoteKey, p.config.AllowedIps, DefaultWgKeepAlive,
|
|
||||||
addr, p.config.PreSharedKey)
|
addr, p.config.PreSharedKey)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *NoProxy) Type() Type {
|
func (p *NoProxy) Type() Type {
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ const DefaultWgKeepAlive = 25 * time.Second
|
|||||||
type Type string
|
type Type string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeNoProxy Type = "NoProxy"
|
TypeDirectNoProxy Type = "DirectNoProxy"
|
||||||
TypeWireguard Type = "Wireguard"
|
TypeWireGuard Type = "WireGuard"
|
||||||
TypeDummy Type = "Dummy"
|
TypeDummy Type = "Dummy"
|
||||||
|
TypeNoProxy Type = "NoProxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
|||||||
@@ -124,5 +124,5 @@ func (p *WireGuardProxy) proxyToLocal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *WireGuardProxy) Type() Type {
|
func (p *WireGuardProxy) Type() Type {
|
||||||
return TypeWireguard
|
return TypeWireGuard
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,15 @@ const (
|
|||||||
|
|
||||||
// WGIface represents a interface instance
|
// WGIface represents a interface instance
|
||||||
type WGIface struct {
|
type WGIface struct {
|
||||||
tun *tunDevice
|
tun *tunDevice
|
||||||
configurer wGConfigurer
|
configurer wGConfigurer
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
userspaceBind bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserspaceBind indicates whether this interfaces is userspace with bind.ICEBind
|
||||||
|
func (w *WGIface) IsUserspaceBind() bool {
|
||||||
|
return w.userspaceBind
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBind returns a userspace implementation of WireGuard Bind interface
|
// GetBind returns a userspace implementation of WireGuard Bind interface
|
||||||
@@ -32,7 +38,7 @@ func (w *WGIface) GetBind() *bind.ICEBind {
|
|||||||
func (w *WGIface) Create() error {
|
func (w *WGIface) Create() error {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
log.Debugf("create Wireguard interface %s", w.tun.DeviceName())
|
log.Debugf("create WireGuard interface %s", w.tun.DeviceName())
|
||||||
return w.tun.Create()
|
return w.tun.Create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,21 +5,23 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWGIFace Creates a new Wireguard interface instance
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
func NewWGIFace(ifaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) {
|
func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) {
|
||||||
wgIface := &WGIface{
|
wgIFace := &WGIface{
|
||||||
mu: sync.Mutex{},
|
mu: sync.Mutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
wgAddress, err := parseWGAddress(address)
|
wgAddress, err := parseWGAddress(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgIface, err
|
return wgIFace, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tun := newTunDevice(wgAddress, mtu, tunAdapter, transportNet)
|
tun := newTunDevice(wgAddress, mtu, tunAdapter, transportNet)
|
||||||
wgIface.tun = tun
|
wgIFace.tun = tun
|
||||||
|
|
||||||
wgIface.configurer = newWGConfigurer(tun)
|
wgIFace.configurer = newWGConfigurer(tun)
|
||||||
|
|
||||||
return wgIface, nil
|
wgIFace.userspaceBind = !WireGuardModuleIsLoaded()
|
||||||
|
|
||||||
|
return wgIFace, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,20 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWGIFace Creates a new Wireguard interface instance
|
// NewWGIFace Creates a new WireGuard interface instance
|
||||||
func NewWGIFace(ifaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) {
|
func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) {
|
||||||
wgIface := &WGIface{
|
wgIFace := &WGIface{
|
||||||
mu: sync.Mutex{},
|
mu: sync.Mutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
wgAddress, err := parseWGAddress(address)
|
wgAddress, err := parseWGAddress(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgIface, err
|
return wgIFace, err
|
||||||
}
|
}
|
||||||
|
|
||||||
wgIface.tun = newTunDevice(ifaceName, wgAddress, mtu, transportNet)
|
wgIFace.tun = newTunDevice(iFaceName, wgAddress, mtu, transportNet)
|
||||||
|
|
||||||
wgIface.configurer = newWGConfigurer(ifaceName)
|
wgIFace.configurer = newWGConfigurer(iFaceName)
|
||||||
return wgIface, nil
|
wgIFace.userspaceBind = !WireGuardModuleIsLoaded()
|
||||||
|
return wgIFace, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package iface
|
package iface
|
||||||
|
|
||||||
// WireguardModuleIsLoaded check if we can load wireguard mod (linux only)
|
// WireGuardModuleIsLoaded check if we can load WireGuard mod (linux only)
|
||||||
func WireguardModuleIsLoaded() bool {
|
func WireGuardModuleIsLoaded() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,10 @@ func tunModuleIsLoaded() bool {
|
|||||||
return tunLoaded
|
return tunLoaded
|
||||||
}
|
}
|
||||||
|
|
||||||
// WireguardModuleIsLoaded check if we can load wireguard mod (linux only)
|
// WireGuardModuleIsLoaded check if we can load WireGuard mod (linux only)
|
||||||
func WireguardModuleIsLoaded() bool {
|
func WireGuardModuleIsLoaded() bool {
|
||||||
if canCreateFakeWireguardInterface() {
|
return false
|
||||||
|
if canCreateFakeWireGuardInterface() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ func WireguardModuleIsLoaded() bool {
|
|||||||
return loaded
|
return loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
func canCreateFakeWireguardInterface() bool {
|
func canCreateFakeWireGuardInterface() bool {
|
||||||
link := newWGLink("mustnotexist")
|
link := newWGLink("mustnotexist")
|
||||||
|
|
||||||
// We willingly try to create a device with an invalid
|
// We willingly try to create a device with an invalid
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *tunDevice) Create() error {
|
func (c *tunDevice) Create() error {
|
||||||
if WireguardModuleIsLoaded() {
|
if WireGuardModuleIsLoaded() {
|
||||||
log.Info("using kernel WireGuard")
|
log.Info("using kernel WireGuard")
|
||||||
return c.createWithKernel()
|
return c.createWithKernel()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user