turn server poc

This commit is contained in:
Abhishek Kondur 2023-03-22 11:00:03 +04:00
parent e17505979a
commit cafdfa70c1
10 changed files with 151 additions and 1 deletions

View file

@ -28,9 +28,12 @@ services:
MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
MQ_USERNAME: "REPLACE_MQ_USERNAME"
STUN_PORT: "3478"
TURN_SERVER_HOST: "turn.NETMAKER_BASE_DOMAIN"
TURN_PORT: "3479"
DEFAULT_PROXY_MODE: "off"
ports:
- "3478:3478/udp"
- "3479:3479/udp"
netmaker-ui:
container_name: netmaker-ui
image: gravitl/netmaker-ui:REPLACE_UI_IMAGE_TAG

View file

@ -75,6 +75,8 @@ type ServerConfig struct {
StunList string `yaml:"stun_list"`
Proxy string `yaml:"proxy"`
DefaultProxyMode ProxyMode `yaml:"defaultproxymode"`
TurnServer string `yaml:"turn_server"`
TurnPort int `yaml:"turn_port"`
}
// ProxyMode - default proxy mode for server

View file

@ -35,6 +35,12 @@ https://stun.NETMAKER_BASE_DOMAIN {
reverse_proxy netmaker:3478
}
# TURN
https://stun.NETMAKER_BASE_DOMAIN {
reverse_proxy netmaker:3479
}
# MQ
wss://broker.NETMAKER_BASE_DOMAIN {

5
go.mod
View file

@ -44,6 +44,7 @@ require (
github.com/guumaster/tablewriter v0.0.10
github.com/matryer/is v1.4.1
github.com/olekukonko/tablewriter v0.0.5
github.com/pion/turn/v2 v2.1.0
github.com/spf13/cobra v1.6.1
)
@ -52,6 +53,10 @@ require (
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/stun v0.4.0 // indirect
github.com/pion/transport/v2 v2.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)

16
go.sum
View file

@ -101,6 +101,16 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk=
github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw=
github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4=
github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc=
github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI=
github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -139,6 +149,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/txn2/txeh v1.3.0 h1:vnbv63htVMZCaQgLqVBxKvj2+HHHFUzNW7I183zjg3E=
@ -170,6 +181,7 @@ golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
@ -197,17 +209,21 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=

View file

@ -11,6 +11,7 @@ import (
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/turnserver"
"golang.org/x/crypto/bcrypt"
)
@ -97,6 +98,7 @@ func CreateHost(h *models.Host) error {
return err
}
h.HostPass = string(hash)
turnserver.RegisterNewHostWithTurn(h.ID.String(), h.HostPass)
// if another server has already updated proxyenabled, leave it alone
if !h.ProxyEnabledSet {
log.Println("checking default proxy", servercfg.GetServerConfig().DefaultProxyMode)

14
main.go
View file

@ -25,6 +25,7 @@ import (
"github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/serverctl"
stunserver "github.com/gravitl/netmaker/stun-server"
"github.com/gravitl/netmaker/turnserver"
)
var version = "v0.18.4"
@ -112,6 +113,7 @@ func initialize() { // Client Mode Prereq Check
logger.Log(0, "error occurred when notifying nodes of startup", err.Error())
}
}
registerCurrHostsWithTurn()
}
func startControllers(wg *sync.WaitGroup, ctx context.Context) {
@ -146,6 +148,9 @@ func startControllers(wg *sync.WaitGroup, ctx context.Context) {
// starts the stun server
wg.Add(1)
go stunserver.Start(wg, ctx)
// starts the turn server
wg.Add(1)
go turnserver.Start(wg, ctx)
}
// Should we be using a context vice a waitgroup????????????
@ -185,3 +190,12 @@ func setGarbageCollection() {
debug.SetGCPercent(ncutils.DEFAULT_GC_PERCENT)
}
}
func registerCurrHostsWithTurn() {
hosts, err := logic.GetAllHosts()
if err == nil {
for _, hostI := range hosts {
turnserver.RegisterNewHostWithTurn(hostI.ID.String(), hostI.HostPass)
}
}
}

View file

@ -1,6 +1,7 @@
package models
import (
"net"
"strings"
jwt "github.com/golang-jwt/jwt/v4"
@ -232,6 +233,7 @@ type ServerConfig struct {
StunPort int `yaml:"stun_port"`
StunList []StunServer `yaml:"stun_list"`
TrafficKey []byte `yaml:"traffickey"`
TurnServer *net.UDPAddr `yaml:"turn_server"`
}
// User.NameInCharset - returns if name is in charset below or not

View file

@ -2,7 +2,9 @@ package servercfg
import (
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"strconv"
@ -102,7 +104,7 @@ func GetServerInfo() models.ServerConfig {
cfg.Is_EE = Is_EE
cfg.StunPort = GetStunPort()
cfg.StunList = GetStunList()
cfg.TurnServer, _ = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", GetTurnHost(), GetTurnPort()))
return cfg
}
@ -626,6 +628,31 @@ func GetStunPort() int {
return port
}
// GetTurnPort - Get the port to run the turn server on
func GetTurnPort() int {
port := 3479 //default
if os.Getenv("TURN_PORT") != "" {
portInt, err := strconv.Atoi(os.Getenv("TURN_PORT"))
if err == nil {
port = portInt
}
} else if config.Config.Server.TurnPort != 0 {
port = config.Config.Server.TurnPort
}
return port
}
// GetTurnHost - fetches the turn host name
func GetTurnHost() string {
turnServer := ""
if os.Getenv("TURN_SERVER_HOST") != "" {
turnServer = os.Getenv("TURN_SERVER_HOST")
} else if config.Config.Server.TurnServer != "" {
turnServer = config.Config.Server.TurnServer
}
return turnServer
}
// IsProxyEnabled - is proxy on or off
func IsProxyEnabled() bool {
var enabled = false //default

73
turnserver/turnserver.go Normal file
View file

@ -0,0 +1,73 @@
package turnserver
import (
"context"
"log"
"net"
"strconv"
"sync"
"time"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/servercfg"
"github.com/pion/turn/v2"
)
var (
UsersMap = make(map[string][]byte)
)
func RegisterNewHostWithTurn(hostID, hostPass string) {
UsersMap[hostID] = turn.GenerateAuthKey(hostID, servercfg.GetTurnHost(), hostPass)
}
func Start(wg *sync.WaitGroup, ctx context.Context) {
defer wg.Done()
// Create a UDP listener to pass into pion/turn
// pion/turn itself doesn't allocate any UDP sockets, but lets the user pass them in
// this allows us to add logging, storage or modify inbound/outbound traffic
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(servercfg.GetTurnPort()))
if err != nil {
log.Panicf("Failed to create TURN server listener: %s", err)
}
s, err := turn.NewServer(turn.ServerConfig{
Realm: servercfg.GetTurnHost(),
// Set AuthHandler callback
// This is called every time a user tries to authenticate with the TURN server
// Return the key for that user, or false when no user is found
AuthHandler: func(username string, realm string, srcAddr net.Addr) ([]byte, bool) {
if key, ok := UsersMap[username]; ok {
return key, true
}
return nil, false
},
// PacketConnConfigs is a list of UDP Listeners and the configuration around them
PacketConnConfigs: []turn.PacketConnConfig{
{
PacketConn: udpListener,
RelayAddressGenerator: &turn.RelayAddressGeneratorStatic{
RelayAddress: net.ParseIP("64.227.178.89"), // Claim that we are listening on IP passed by user (This should be your Public IP)
Address: "0.0.0.0", // But actually be listening on every interface
},
},
},
})
if err != nil {
log.Panic(err)
}
go func() {
for {
time.Sleep(time.Second * 10)
log.Print(s.AllocationCount())
}
}()
// Block until user sends SIGINT or SIGTERM
<-ctx.Done()
logger.Log(0, "## Stopping Turn Server...")
if err = s.Close(); err != nil {
log.Panic(err)
}
}