pingcap / pingcap/tiup

tiup HTTP clients ignore NO_PROXY

Open
#2,710 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

contribution first-time-contributor type/bug
Dominant language
Go
Stars
466
Forks
338
Avg merge
3d 7h
Merged PRs (30d)
8

Description

Bug Report

Please answer these questions before submitting your issue. Thanks!

  1. What did you do?

On a control machine behind an HTTP proxy (needed to reach the component mirror), with the cluster on an internal network excluded via NO_PROXY:

export HTTP_PROXY=http://internal-proxy:3128
export HTTPS_PROXY=http://internal-proxy:3128
export NO_PROXY=10.0.0.0/8,.internal.example.com,localhost,127.0.0.1
tiup cluster reload <cluster> -R tikv
  1. What did you expect to see?

NO_PROXY honored: internal hosts (PD, TiKV) reached directly; only the external component mirror goes through the proxy — the standard HTTP_PROXY/NO_PROXY contract.

  1. What did you see instead?

Every request is forced through HTTP_PROXY regardless of NO_PROXY, so the internal API calls fail. It surfaces in two stages of reload:

  • PD APIerror requesting http://pd-1.internal.example.com:2379/pd/api/v1/config, ... code 403 (the proxy rejects the internal request).
  • After fixing that, TiKV status scrapeError: failed to get leader count ...: metric tikv_raftstore_region_count{type="leader"} not found. tiup scrapes http://tikv-1.internal.example.com:20180/metrics to count leaders before restart; that request also goes through the proxy and returns the proxy's error page, so the metric can't be parsed.

(Conversely, without a proxy, InitConfig fails to fetch /timestamp.json from the mirror — there is no single configuration that works.)

  1. What version of TiUP are you using (tiup --version)?

v1.16.5 (also reproduced on master).


Root cause

Two HTTP clients set tr.Proxy to a fixed http.ProxyURL (applied to every destination, ignoring NO_PROXY) instead of http.ProxyFromEnvironment:

  • pkg/utils/http_client.goNewHTTPClient — used by the PD API client (pkg/cluster/api/pdapi.go).
  • pkg/cluster/spec/tikv.gomakeTransport — used by genLeaderCounter to scrape the TiKV status port.
httpProxy := os.Getenv("TIUP_INNER_HTTP_PROXY")
if len(httpProxy) == 0 {
    httpProxy = os.Getenv("HTTP_PROXY")
}
if len(httpProxy) > 0 {
    if proxyURL, err := url.Parse(httpProxy); err == nil {
        tr.Proxy = http.ProxyURL(proxyURL) // ignores NO_PROXY
    }
}
Proposed fix (backward compatible)

Resolve the proxy with golang.org/x/net/http/httpproxy so NO_PROXY is honored, keeping the TIUP_INNER_HTTP_PROXY override, in both clients:

import "golang.org/x/net/http/httpproxy"

proxyCfg := httpproxy.FromEnvironment() // HTTP(S)_PROXY + NO_PROXY
if inner := os.Getenv("TIUP_INNER_HTTP_PROXY"); len(inner) > 0 {
    proxyCfg.HTTPProxy, proxyCfg.HTTPSProxy = inner, inner
}
proxyFunc := proxyCfg.ProxyFunc()
tr.Proxy = func(req *http.Request) (*url.URL, error) {
    return proxyFunc(req.URL)
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read pkg/utils/http_client.go and pkg/cluster/spec/tikv.go, then trace NewHTTPClient, makeTransport, and their PD API and TiKV metric callers. Verify that internal requests honor NO_PROXY while the component mirror remains reachable through the proxy, and that TIUP_INNER_HTTP_PROXY continues to override the environment proxy.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.