Make STUN server configurable
This commit is contained in:
parent
dc909ba6d7
commit
eb500155e8
4 changed files with 33 additions and 5 deletions
6
app.go
6
app.go
|
@ -121,6 +121,8 @@ type OIDCConfig struct {
|
||||||
|
|
||||||
type DERPConfig struct {
|
type DERPConfig struct {
|
||||||
ServerEnabled bool
|
ServerEnabled bool
|
||||||
|
STUNEnabled bool
|
||||||
|
STUNAddr string
|
||||||
URLs []url.URL
|
URLs []url.URL
|
||||||
Paths []string
|
Paths []string
|
||||||
AutoUpdate bool
|
AutoUpdate bool
|
||||||
|
@ -497,8 +499,10 @@ func (h *Headscale) Serve() error {
|
||||||
h.DERPMap = GetDERPMap(h.cfg.DERP)
|
h.DERPMap = GetDERPMap(h.cfg.DERP)
|
||||||
|
|
||||||
if h.cfg.DERP.ServerEnabled {
|
if h.cfg.DERP.ServerEnabled {
|
||||||
go h.ServeSTUN()
|
|
||||||
h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region
|
h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region
|
||||||
|
if h.cfg.DERP.STUNEnabled {
|
||||||
|
go h.ServeSTUN()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.cfg.DERP.AutoUpdate {
|
if h.cfg.DERP.AutoUpdate {
|
||||||
|
|
|
@ -118,6 +118,8 @@ func LoadConfig(path string) error {
|
||||||
|
|
||||||
func GetDERPConfig() headscale.DERPConfig {
|
func GetDERPConfig() headscale.DERPConfig {
|
||||||
enabled := viper.GetBool("derp.server.enabled")
|
enabled := viper.GetBool("derp.server.enabled")
|
||||||
|
stunEnabled := viper.GetBool("derp.server.stun.enabled")
|
||||||
|
stunAddr := viper.GetString("derp.server.stun.listen_addr")
|
||||||
|
|
||||||
urlStrs := viper.GetStringSlice("derp.urls")
|
urlStrs := viper.GetStringSlice("derp.urls")
|
||||||
|
|
||||||
|
@ -141,6 +143,8 @@ func GetDERPConfig() headscale.DERPConfig {
|
||||||
|
|
||||||
return headscale.DERPConfig{
|
return headscale.DERPConfig{
|
||||||
ServerEnabled: enabled,
|
ServerEnabled: enabled,
|
||||||
|
STUNEnabled: stunEnabled,
|
||||||
|
STUNAddr: stunAddr,
|
||||||
URLs: urls,
|
URLs: urls,
|
||||||
Paths: paths,
|
Paths: paths,
|
||||||
AutoUpdate: autoUpdate,
|
AutoUpdate: autoUpdate,
|
||||||
|
|
|
@ -60,6 +60,12 @@ derp:
|
||||||
# The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place
|
# The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
# If enabled, also listens in the configured address for STUN connections to help on NAT traversal
|
||||||
|
# For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/
|
||||||
|
stun:
|
||||||
|
enabled: false
|
||||||
|
listen_addr: "0.0.0.0:3478"
|
||||||
|
|
||||||
# List of externally available DERP maps encoded in JSON
|
# List of externally available DERP maps encoded in JSON
|
||||||
urls:
|
urls:
|
||||||
- https://controlplane.tailscale.com/derpmap/default
|
- https://controlplane.tailscale.com/derpmap/default
|
||||||
|
|
|
@ -75,6 +75,19 @@ func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.cfg.DERP.STUNEnabled {
|
||||||
|
_, portStr, err := net.SplitHostPort(h.cfg.DERP.STUNAddr)
|
||||||
|
if err != nil {
|
||||||
|
return tailcfg.DERPRegion{}, err
|
||||||
|
}
|
||||||
|
port, err := strconv.Atoi(portStr)
|
||||||
|
if err != nil {
|
||||||
|
return tailcfg.DERPRegion{}, err
|
||||||
|
}
|
||||||
|
localDERPregion.Nodes[0].STUNPort = port
|
||||||
|
}
|
||||||
|
|
||||||
return localDERPregion, nil
|
return localDERPregion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +149,7 @@ func (h *Headscale) DERPProbeHandler(ctx *gin.Context) {
|
||||||
// because its DNS are broken.
|
// because its DNS are broken.
|
||||||
// The initial implementation is here https://github.com/tailscale/tailscale/pull/1406
|
// The initial implementation is here https://github.com/tailscale/tailscale/pull/1406
|
||||||
// They have a cache, but not clear if that is really necessary at Headscale, uh, scale.
|
// They have a cache, but not clear if that is really necessary at Headscale, uh, scale.
|
||||||
|
// An example implementation is found here https://derp.tailscale.com/bootstrap-dns
|
||||||
func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) {
|
func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) {
|
||||||
dnsEntries := make(map[string][]net.IP)
|
dnsEntries := make(map[string][]net.IP)
|
||||||
|
|
||||||
|
@ -155,14 +169,14 @@ func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) {
|
||||||
ctx.JSON(http.StatusOK, dnsEntries)
|
ctx.JSON(http.StatusOK, dnsEntries)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeSTUN starts a STUN server on udp/3478
|
// ServeSTUN starts a STUN server on the configured addr
|
||||||
func (h *Headscale) ServeSTUN() {
|
func (h *Headscale) ServeSTUN() {
|
||||||
pc, err := net.ListenPacket("udp", "0.0.0.0:3478")
|
packetConn, err := net.ListenPacket("udp", h.cfg.DERP.STUNAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Msgf("failed to open STUN listener: %v", err)
|
log.Fatal().Msgf("failed to open STUN listener: %v", err)
|
||||||
}
|
}
|
||||||
log.Trace().Msgf("STUN server started at %s", pc.LocalAddr())
|
log.Info().Msgf("STUN server started at %s", packetConn.LocalAddr())
|
||||||
serverSTUNListener(context.Background(), pc.(*net.UDPConn))
|
serverSTUNListener(context.Background(), packetConn.(*net.UDPConn))
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverSTUNListener(ctx context.Context, pc *net.UDPConn) {
|
func serverSTUNListener(ctx context.Context, pc *net.UDPConn) {
|
||||||
|
|
Loading…
Reference in a new issue