[relay] Store the StunTurn address in thread safe store (#2470)

Store the StunTurn address in atomic store
This commit is contained in:
Zoltan Papp 2024-09-04 11:14:58 +02:00 committed by GitHub
parent 13e923b7c6
commit 1ff7a953a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 58 additions and 57 deletions

View File

@ -13,6 +13,7 @@ import (
"slices" "slices"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/pion/ice/v3" "github.com/pion/ice/v3"
@ -122,7 +123,8 @@ type Engine struct {
// STUNs is a list of STUN servers used by ICE // STUNs is a list of STUN servers used by ICE
STUNs []*stun.URI STUNs []*stun.URI
// TURNs is a list of STUN servers used by ICE // TURNs is a list of STUN servers used by ICE
TURNs []*stun.URI TURNs []*stun.URI
stunTurn atomic.Value
// clientRoutes is the most recent list of clientRoutes received from the Management Service // clientRoutes is the most recent list of clientRoutes received from the Management Service
clientRoutes route.HAMap clientRoutes route.HAMap
@ -535,6 +537,11 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
return err return err
} }
var stunTurn []*stun.URI
stunTurn = append(stunTurn, e.STUNs...)
stunTurn = append(stunTurn, e.TURNs...)
e.stunTurn.Store(stunTurn)
// todo update signal // todo update signal
} }
@ -961,11 +968,6 @@ func (e *Engine) connWorker(conn *peer.Conn, peerKey string) {
continue continue
} }
// we might have received new STUN and TURN servers meanwhile, so update them
e.syncMsgMux.Lock()
conn.UpdateStunTurn(append(e.STUNs, e.TURNs...))
e.syncMsgMux.Unlock()
err := conn.Open(e.ctx) err := conn.Open(e.ctx)
if err != nil { if err != nil {
log.Debugf("connection to peer %s failed: %v", peerKey, err) log.Debugf("connection to peer %s failed: %v", peerKey, err)
@ -989,9 +991,6 @@ func (e *Engine) peerExists(peerKey string) bool {
func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, error) { func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, error) {
log.Debugf("creating peer connection %s", pubKey) log.Debugf("creating peer connection %s", pubKey)
var stunTurn []*stun.URI
stunTurn = append(stunTurn, e.STUNs...)
stunTurn = append(stunTurn, e.TURNs...)
wgConfig := peer.WgConfig{ wgConfig := peer.WgConfig{
RemoteKey: pubKey, RemoteKey: pubKey,
@ -1024,19 +1023,21 @@ func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, e
// randomize connection timeout // randomize connection timeout
timeout := time.Duration(rand.Intn(PeerConnectionTimeoutMax-PeerConnectionTimeoutMin)+PeerConnectionTimeoutMin) * time.Millisecond timeout := time.Duration(rand.Intn(PeerConnectionTimeoutMax-PeerConnectionTimeoutMin)+PeerConnectionTimeoutMin) * time.Millisecond
config := peer.ConnConfig{ config := peer.ConnConfig{
Key: pubKey, Key: pubKey,
LocalKey: e.config.WgPrivateKey.PublicKey().String(), LocalKey: e.config.WgPrivateKey.PublicKey().String(),
StunTurn: stunTurn, Timeout: timeout,
InterfaceBlackList: e.config.IFaceBlackList, WgConfig: wgConfig,
DisableIPv6Discovery: e.config.DisableIPv6Discovery, LocalWgPort: e.config.WgPort,
Timeout: timeout, RosenpassPubKey: e.getRosenpassPubKey(),
UDPMux: e.udpMux.UDPMuxDefault, RosenpassAddr: e.getRosenpassAddr(),
UDPMuxSrflx: e.udpMux, ICEConfig: peer.ICEConfig{
WgConfig: wgConfig, StunTurn: &e.stunTurn,
LocalWgPort: e.config.WgPort, InterfaceBlackList: e.config.IFaceBlackList,
NATExternalIPs: e.parseNATExternalIPMappings(), DisableIPv6Discovery: e.config.DisableIPv6Discovery,
RosenpassPubKey: e.getRosenpassPubKey(), UDPMux: e.udpMux.UDPMuxDefault,
RosenpassAddr: e.getRosenpassAddr(), UDPMuxSrflx: e.udpMux,
NATExternalIPs: e.parseNATExternalIPMappings(),
},
} }
peerConn, err := peer.NewConn(config, e.statusRecorder, e.wgProxyFactory, e.mobileDep.TunAdapter, e.mobileDep.IFaceDiscover) peerConn, err := peer.NewConn(config, e.statusRecorder, e.wgProxyFactory, e.mobileDep.TunAdapter, e.mobileDep.IFaceDiscover)

View File

@ -7,6 +7,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/pion/ice/v3" "github.com/pion/ice/v3"
@ -41,37 +42,41 @@ type WgConfig struct {
PreSharedKey *wgtypes.Key PreSharedKey *wgtypes.Key
} }
// ConnConfig is a peer Connection configuration type ICEConfig struct {
type ConnConfig struct {
// Key is a public key of a remote peer
Key string
// LocalKey is a public key of a local peer
LocalKey string
// StunTurn is a list of STUN and TURN URLs // StunTurn is a list of STUN and TURN URLs
StunTurn []*stun.URI StunTurn *atomic.Value // []*stun.URI
// InterfaceBlackList is a list of machine interfaces that should be filtered out by ICE Candidate gathering // InterfaceBlackList is a list of machine interfaces that should be filtered out by ICE Candidate gathering
// (e.g. if eth0 is in the list, host candidate of this interface won't be used) // (e.g. if eth0 is in the list, host candidate of this interface won't be used)
InterfaceBlackList []string InterfaceBlackList []string
DisableIPv6Discovery bool DisableIPv6Discovery bool
UDPMux ice.UDPMux
UDPMuxSrflx ice.UniversalUDPMux
NATExternalIPs []string
}
// ConnConfig is a peer Connection configuration
type ConnConfig struct {
// Key is a public key of a remote peer
Key string
// LocalKey is a public key of a local peer
LocalKey string
Timeout time.Duration Timeout time.Duration
WgConfig WgConfig WgConfig WgConfig
UDPMux ice.UDPMux
UDPMuxSrflx ice.UniversalUDPMux
LocalWgPort int LocalWgPort int
NATExternalIPs []string
// RosenpassPubKey is this peer's Rosenpass public key // RosenpassPubKey is this peer's Rosenpass public key
RosenpassPubKey []byte RosenpassPubKey []byte
// RosenpassPubKey is this peer's RosenpassAddr server address (IP:port) // RosenpassPubKey is this peer's RosenpassAddr server address (IP:port)
RosenpassAddr string RosenpassAddr string
// ICEConfig ICE protocol configuration
ICEConfig ICEConfig
} }
// OfferAnswer represents a session establishment offer or answer // OfferAnswer represents a session establishment offer or answer
@ -146,11 +151,6 @@ func (conn *Conn) WgConfig() WgConfig {
return conn.config.WgConfig return conn.config.WgConfig
} }
// UpdateStunTurn update the turn and stun addresses
func (conn *Conn) UpdateStunTurn(turnStun []*stun.URI) {
conn.config.StunTurn = turnStun
}
// 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(config ConnConfig, statusRecorder *Status, wgProxyFactory *wgproxy.Factory, adapter iface.TunAdapter, iFaceDiscover stdnet.ExternalIFaceDiscover) (*Conn, error) { func NewConn(config ConnConfig, statusRecorder *Status, wgProxyFactory *wgproxy.Factory, adapter iface.TunAdapter, iFaceDiscover stdnet.ExternalIFaceDiscover) (*Conn, error) {
@ -187,20 +187,20 @@ func (conn *Conn) reCreateAgent() error {
agentConfig := &ice.AgentConfig{ agentConfig := &ice.AgentConfig{
MulticastDNSMode: ice.MulticastDNSModeDisabled, MulticastDNSMode: ice.MulticastDNSModeDisabled,
NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6}, NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6},
Urls: conn.config.StunTurn, Urls: conn.config.ICEConfig.StunTurn.Load().([]*stun.URI),
CandidateTypes: conn.candidateTypes(), CandidateTypes: conn.candidateTypes(),
FailedTimeout: &failedTimeout, FailedTimeout: &failedTimeout,
InterfaceFilter: stdnet.InterfaceFilter(conn.config.InterfaceBlackList), InterfaceFilter: stdnet.InterfaceFilter(conn.config.ICEConfig.InterfaceBlackList),
UDPMux: conn.config.UDPMux, UDPMux: conn.config.ICEConfig.UDPMux,
UDPMuxSrflx: conn.config.UDPMuxSrflx, UDPMuxSrflx: conn.config.ICEConfig.UDPMuxSrflx,
NAT1To1IPs: conn.config.NATExternalIPs, NAT1To1IPs: conn.config.ICEConfig.NATExternalIPs,
Net: transportNet, Net: transportNet,
DisconnectedTimeout: &iceDisconnectedTimeout, DisconnectedTimeout: &iceDisconnectedTimeout,
KeepaliveInterval: &iceKeepAlive, KeepaliveInterval: &iceKeepAlive,
RelayAcceptanceMinWait: &iceRelayAcceptanceMinWait, RelayAcceptanceMinWait: &iceRelayAcceptanceMinWait,
} }
if conn.config.DisableIPv6Discovery { if conn.config.ICEConfig.DisableIPv6Discovery {
agentConfig.NetworkTypes = []ice.NetworkType{ice.NetworkTypeUDP4} agentConfig.NetworkTypes = []ice.NetworkType{ice.NetworkTypeUDP4}
} }
@ -480,7 +480,7 @@ func (conn *Conn) punchRemoteWGPort(pair *ice.CandidatePair, remoteWgPort int) {
return return
} }
mux, ok := conn.config.UDPMuxSrflx.(*bind.UniversalUDPMuxDefault) mux, ok := conn.config.ICEConfig.UDPMuxSrflx.(*bind.UniversalUDPMuxDefault)
if !ok { if !ok {
log.Warn("invalid udp mux conversion") log.Warn("invalid udp mux conversion")
return return

View File

@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/magiconair/properties/assert" "github.com/magiconair/properties/assert"
"github.com/pion/stun/v2"
"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/client/internal/wgproxy"
@ -15,12 +14,13 @@ import (
) )
var connConf = ConnConfig{ var connConf = ConnConfig{
Key: "LLHf3Ma6z6mdLbriAJbqhX7+nM/B71lgw2+91q3LfhU=", Key: "LLHf3Ma6z6mdLbriAJbqhX7+nM/B71lgw2+91q3LfhU=",
LocalKey: "RRHf3Ma6z6mdLbriAJbqhX7+nM/B71lgw2+91q3LfhU=", LocalKey: "RRHf3Ma6z6mdLbriAJbqhX7+nM/B71lgw2+91q3LfhU=",
StunTurn: []*stun.URI{}, Timeout: time.Second,
InterfaceBlackList: nil, LocalWgPort: 51820,
Timeout: time.Second, ICEConfig: ICEConfig{
LocalWgPort: 51820, InterfaceBlackList: nil,
},
} }
func TestNewConn_interfaceFilter(t *testing.T) { func TestNewConn_interfaceFilter(t *testing.T) {

View File

@ -7,5 +7,5 @@ import (
) )
func (conn *Conn) newStdNet() (*stdnet.Net, error) { func (conn *Conn) newStdNet() (*stdnet.Net, error) {
return stdnet.NewNet(conn.config.InterfaceBlackList) return stdnet.NewNet(conn.config.ICEConfig.InterfaceBlackList)
} }

View File

@ -3,5 +3,5 @@ package peer
import "github.com/netbirdio/netbird/client/internal/stdnet" import "github.com/netbirdio/netbird/client/internal/stdnet"
func (conn *Conn) newStdNet() (*stdnet.Net, error) { func (conn *Conn) newStdNet() (*stdnet.Net, error) {
return stdnet.NewNetWithDiscover(conn.iFaceDiscover, conn.config.InterfaceBlackList) return stdnet.NewNetWithDiscover(conn.iFaceDiscover, conn.config.ICEConfig.InterfaceBlackList)
} }