summaryrefslogtreecommitdiffhomepage
path: root/derp
diff options
context:
space:
mode:
Diffstat (limited to 'derp')
-rw-r--r--derp/derp_server.go17
-rw-r--r--derp/derphttp/derphttp_client.go20
2 files changed, 30 insertions, 7 deletions
diff --git a/derp/derp_server.go b/derp/derp_server.go
index baca898d3..c330572d2 100644
--- a/derp/derp_server.go
+++ b/derp/derp_server.go
@@ -137,6 +137,7 @@ type Server struct {
metaCert []byte // the encoded x509 cert to send after LetsEncrypt cert+intermediate
dupPolicy dupPolicy
debug bool
+ localClient local.Client
// Counters:
packetsSent, bytesSent expvar.Int
@@ -485,6 +486,16 @@ func (s *Server) SetVerifyClientURLFailOpen(v bool) {
s.verifyClientsURLFailOpen = v
}
+// SetTailscaledSocketPath sets the unix socket path to use to talk to
+// tailscaled if client verification is enabled.
+//
+// If unset or set to the empty string, the default path for the operating
+// system is used.
+func (s *Server) SetTailscaledSocketPath(path string) {
+ s.localClient.Socket = path
+ s.localClient.UseSocketOnly = path != ""
+}
+
// SetTCPWriteTimeout sets the timeout for writing to connected clients.
// This timeout does not apply to mesh connections.
// Defaults to 2 seconds.
@@ -1320,8 +1331,6 @@ func (c *sclient) requestMeshUpdate() {
}
}
-var localClient local.Client
-
// isMeshPeer reports whether the client is a trusted mesh peer
// node in the DERP region.
func (s *Server) isMeshPeer(info *clientInfo) bool {
@@ -1340,7 +1349,7 @@ func (s *Server) verifyClient(ctx context.Context, clientKey key.NodePublic, inf
// tailscaled-based verification:
if s.verifyClientsLocalTailscaled {
- _, err := localClient.WhoIsNodeKey(ctx, clientKey)
+ _, err := s.localClient.WhoIsNodeKey(ctx, clientKey)
if err == tailscale.ErrPeerNotFound {
return fmt.Errorf("peer %v not authorized (not found in local tailscaled)", clientKey)
}
@@ -2240,7 +2249,7 @@ func (s *Server) ConsistencyCheck() error {
func (s *Server) checkVerifyClientsLocalTailscaled() error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
- status, err := localClient.StatusWithoutPeers(ctx)
+ status, err := s.localClient.StatusWithoutPeers(ctx)
if err != nil {
return fmt.Errorf("localClient.Status: %w", err)
}
diff --git a/derp/derphttp/derphttp_client.go b/derp/derphttp/derphttp_client.go
index 7387b60b4..319c02429 100644
--- a/derp/derphttp/derphttp_client.go
+++ b/derp/derphttp/derphttp_client.go
@@ -652,7 +652,11 @@ func (c *Client) tlsClient(nc net.Conn, node *tailcfg.DERPNode) *tls.Conn {
tlsConf.VerifyConnection = nil
}
if node.CertName != "" {
- tlsdial.SetConfigExpectedCert(tlsConf, node.CertName)
+ if suf, ok := strings.CutPrefix(node.CertName, "sha256-raw:"); ok {
+ tlsdial.SetConfigExpectedCertHash(tlsConf, suf)
+ } else {
+ tlsdial.SetConfigExpectedCert(tlsConf, node.CertName)
+ }
}
}
return tls.Client(nc, tlsConf)
@@ -666,7 +670,7 @@ func (c *Client) tlsClient(nc net.Conn, node *tailcfg.DERPNode) *tls.Conn {
func (c *Client) DialRegionTLS(ctx context.Context, reg *tailcfg.DERPRegion) (tlsConn *tls.Conn, connClose io.Closer, node *tailcfg.DERPNode, err error) {
tcpConn, node, err := c.dialRegion(ctx, reg)
if err != nil {
- return nil, nil, nil, err
+ return nil, nil, nil, fmt.Errorf("dialRegion(%d): %w", reg.RegionID, err)
}
done := make(chan bool) // unbuffered
defer close(done)
@@ -741,6 +745,17 @@ func (c *Client) dialNode(ctx context.Context, n *tailcfg.DERPNode) (net.Conn, e
nwait := 0
startDial := func(dstPrimary, proto string) {
+ dst := cmp.Or(dstPrimary, n.HostName)
+
+ // If dialing an IP address directly, check its address family
+ // and bail out before incrementing nwait.
+ if ip, err := netip.ParseAddr(dst); err == nil {
+ if proto == "tcp4" && ip.Is6() ||
+ proto == "tcp6" && ip.Is4() {
+ return
+ }
+ }
+
nwait++
go func() {
if proto == "tcp4" && c.preferIPv6() {
@@ -755,7 +770,6 @@ func (c *Client) dialNode(ctx context.Context, n *tailcfg.DERPNode) (net.Conn, e
// Start v4 dial
}
}
- dst := cmp.Or(dstPrimary, n.HostName)
port := "443"
if !c.useHTTPS() {
port = "3340"