mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-20 11:36:06 +00:00
fix(nodes): honor TLS verify mode skip/pin for remote node operations (#5264)
The node probe honored the per-node TlsVerifyMode (skip/pin) but runtime.Remote used a shared client with no TLSClientConfig, so traffic sync and every other remote op fell back to system-CA verification and failed against self-signed nodes even after the operator set skip/pin. Move the TLS client builder into the runtime layer (HTTPClientForNode / DecodeCertPin) as the single source of truth, have Remote build and cache its per-node client through it, and delegate the service probe to the same builder so the two paths can no longer diverge.
This commit is contained in:
@@ -23,15 +23,6 @@ import (
|
||||
|
||||
const remoteHTTPTimeout = 10 * time.Second
|
||||
|
||||
var remoteHTTPClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
MaxIdleConns: 64,
|
||||
MaxIdleConnsPerHost: 4,
|
||||
IdleConnTimeout: 60 * time.Second,
|
||||
DialContext: netsafe.SSRFGuardedDialContext,
|
||||
},
|
||||
}
|
||||
|
||||
type envelope struct {
|
||||
Success bool `json:"success"`
|
||||
Msg string `json:"msg"`
|
||||
@@ -43,6 +34,12 @@ type Remote struct {
|
||||
|
||||
mu sync.RWMutex
|
||||
remoteIDByTag map[string]int
|
||||
|
||||
// Per-node client honoring the TLS verify mode, built once and reused; a
|
||||
// node config change drops the cached Remote so the next one rebuilds it.
|
||||
clientOnce sync.Once
|
||||
client *http.Client
|
||||
clientErr error
|
||||
}
|
||||
|
||||
type RemoteInboundOption struct {
|
||||
@@ -61,6 +58,15 @@ func NewRemote(n *model.Node) *Remote {
|
||||
|
||||
func (r *Remote) Name() string { return "node:" + r.node.Name }
|
||||
|
||||
// httpClient lazily builds and caches the per-node client honoring the TLS
|
||||
// verify mode, so Remote ops don't fall back to system CA on skip/pin (#5264).
|
||||
func (r *Remote) httpClient() (*http.Client, error) {
|
||||
r.clientOnce.Do(func() {
|
||||
r.client, r.clientErr = HTTPClientForNode(r.node)
|
||||
})
|
||||
return r.client, r.clientErr
|
||||
}
|
||||
|
||||
func (r *Remote) baseURL() (string, error) {
|
||||
addr, err := netsafe.NormalizeHost(r.node.Address)
|
||||
if err != nil {
|
||||
@@ -129,7 +135,11 @@ func (r *Remote) do(ctx context.Context, method, path string, body any) (*envelo
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
}
|
||||
|
||||
resp, err := remoteHTTPClient.Do(req)
|
||||
client, err := r.httpClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s %s: %w", method, path, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user