mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	Working /bootstrap-dns DERP helper
This commit is contained in:
		
							parent
							
								
									54c3e00a1f
								
							
						
					
					
						commit
						70910c4595
					
				| @ -2,14 +2,12 @@ package headscale | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| @ -26,11 +24,6 @@ import ( | ||||
| // following its HTTP request.
 | ||||
| const fastStartHeader = "Derp-Fast-Start" | ||||
| 
 | ||||
| var ( | ||||
| 	dnsCache     atomic.Value // of []byte
 | ||||
| 	bootstrapDNS = "derp.tailscale.com" | ||||
| ) | ||||
| 
 | ||||
| type DERPServer struct { | ||||
| 	tailscaleDERP *derp.Server | ||||
| 	region        tailcfg.DERPRegion | ||||
| @ -137,14 +130,29 @@ func (h *Headscale) DERPProbeHandler(ctx *gin.Context) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // DERPBootstrapDNSHandler implements the /bootsrap-dns endpoint
 | ||||
| // Described in https://github.com/tailscale/tailscale/issues/1405,
 | ||||
| // this endpoint provides a way to help a client when it fails to start up
 | ||||
| // because its DNS are broken.
 | ||||
| // 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.
 | ||||
| func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { | ||||
| 	ctx.Header("Content-Type", "application/json") | ||||
| 	j, _ := dnsCache.Load().([]byte) | ||||
| 	// Bootstrap DNS requests occur cross-regions,
 | ||||
| 	// and are randomized per request,
 | ||||
| 	// so keeping a connection open is pointlessly expensive.
 | ||||
| 	ctx.Header("Connection", "close") | ||||
| 	ctx.Writer.Write(j) | ||||
| 	dnsEntries := make(map[string][]net.IP) | ||||
| 
 | ||||
| 	resolvCtx, cancel := context.WithTimeout(context.Background(), time.Minute) | ||||
| 	defer cancel() | ||||
| 	var r net.Resolver | ||||
| 	for _, region := range h.DERPMap.Regions { | ||||
| 		for _, node := range region.Nodes { // we don't care if we override some nodes
 | ||||
| 			addrs, err := r.LookupIP(resolvCtx, "ip", node.HostName) | ||||
| 			if err != nil { | ||||
| 				log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup failed %q", node.HostName) | ||||
| 				continue | ||||
| 			} | ||||
| 			dnsEntries[node.HostName] = addrs | ||||
| 		} | ||||
| 	} | ||||
| 	ctx.JSON(http.StatusOK, dnsEntries) | ||||
| } | ||||
| 
 | ||||
| // ServeSTUN starts a STUN server on udp/3478
 | ||||
| @ -188,40 +196,3 @@ func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { | ||||
| 		pc.WriteTo(res, ua) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Shamelessly taken from
 | ||||
| // https://github.com/tailscale/tailscale/blob/main/cmd/derper/bootstrap_dns.go
 | ||||
| func refreshBootstrapDNSLoop() { | ||||
| 	if bootstrapDNS == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	for { | ||||
| 		refreshBootstrapDNS() | ||||
| 		time.Sleep(10 * time.Minute) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func refreshBootstrapDNS() { | ||||
| 	if bootstrapDNS == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	dnsEntries := make(map[string][]net.IP) | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute) | ||||
| 	defer cancel() | ||||
| 	names := strings.Split(bootstrapDNS, ",") | ||||
| 	var r net.Resolver | ||||
| 	for _, name := range names { | ||||
| 		addrs, err := r.LookupIP(ctx, "ip", name) | ||||
| 		if err != nil { | ||||
| 			log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup %q", name) | ||||
| 			continue | ||||
| 		} | ||||
| 		dnsEntries[name] = addrs | ||||
| 	} | ||||
| 	j, err := json.MarshalIndent(dnsEntries, "", "\t") | ||||
| 	if err != nil { | ||||
| 		// leave the old values in place
 | ||||
| 		return | ||||
| 	} | ||||
| 	dnsCache.Store(j) | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user