@@ -103,14 +103,7 @@ func NewServerTailnet(
103
103
transport :tailnetTransport .Clone (),
104
104
}
105
105
tn .transport .DialContext = tn .dialContext
106
-
107
- // Bugfix: for some reason all calls to tn.dialContext come from
108
- // "localhost", causing connections to be cached and requests to go to the
109
- // wrong workspaces. This disables keepalives for now until the root cause
110
- // can be found.
111
- tn .transport .MaxIdleConnsPerHost = - 1
112
- tn .transport .DisableKeepAlives = true
113
-
106
+ tn .transport .MaxIdleConnsPerHost = 10
114
107
tn .transport .MaxIdleConns = 0
115
108
// We intentionally don't verify the certificate chain here.
116
109
// The connection to the workspace is already established and most
@@ -312,7 +305,15 @@ type ServerTailnet struct {
312
305
}
313
306
314
307
func (s * ServerTailnet )ReverseProxy (targetURL ,dashboardURL * url.URL ,agentID uuid.UUID ) (_ * httputil.ReverseProxy ,release func (),_ error ) {
315
- proxy := httputil .NewSingleHostReverseProxy (targetURL )
308
+ // Rewrite the targetURL's Host to point to the agent's IP. This is
309
+ // necessary because due to TCP connection caching, each agent needs to be
310
+ // addressed invidivually. Otherwise, all connections get dialed as
311
+ // "localhost:port", causing connections to be shared across agents.
312
+ tgt := * targetURL
313
+ _ ,port ,_ := net .SplitHostPort (tgt .Host )
314
+ tgt .Host = net .JoinHostPort (tailnet .IPFromUUID (agentID ).String (),port )
315
+
316
+ proxy := httputil .NewSingleHostReverseProxy (& tgt )
316
317
proxy .ErrorHandler = func (w http.ResponseWriter ,r * http.Request ,err error ) {
317
318
site .RenderStaticErrorPage (w ,r , site.ErrorPageData {
318
319
Status :http .StatusBadGateway ,