fix(node): keep master requests on the node they were sent to

The master's node clients followed redirects to any host, presenting the
same panel-wide credentials (the mTLS client certificate) and replaying
the request there, so one node could have the master push to another.
Node clients and the certificate-pin probe now stop at a redirect off
the original host:port and report the 3xx as the node's answer. The
probe change is wiring; TestNodeClientsDoNotFollowARedirectToAnotherHost
covers the guard.
This commit is contained in:
MHSanaei
2026-10-31 09:14:57 +00:00
parent f1e1b0fb0c
commit 08482154c2
3 changed files with 44 additions and 1 deletions
+11 -1
View File
@@ -152,7 +152,16 @@ func newNodeTransport(tlsCfg *tls.Config) *http.Transport {
// defaultNodeHTTPClient reaches nodes trusting the system CA store ("verify"
// mode or plain http); shared so connections pool across nodes.
var defaultNodeHTTPClient = &http.Client{Transport: newNodeTransport(nil)}
var defaultNodeHTTPClient = &http.Client{Transport: newNodeTransport(nil), CheckRedirect: NoCrossHostRedirect}
// NoCrossHostRedirect keeps a request on the host:port it was sent to: the master presents
// the same credentials to every node, so a node's Location must not carry them elsewhere.
func NoCrossHostRedirect(req *http.Request, via []*http.Request) error {
if len(via) >= 10 || !strings.EqualFold(req.URL.Host, via[0].URL.Host) {
return http.ErrUseLastResponse
}
return nil
}
// nodeClients caches one client per node: heartbeat and traffic sync reach it
// every few seconds, and a rebuilt client would open its own empty pool.
@@ -214,6 +223,7 @@ func HTTPClientForNode(n *model.Node, proxyURL string) (*http.Client, error) {
if err != nil {
return nil, err
}
client.CheckRedirect = NoCrossHostRedirect
nodeClientsMu.Lock()
if entry, ok := nodeClientsCache[key]; ok {