diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index fff696ae7..289dda00c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,7 @@ * FEATURE: vmagent: add support for `follow_redirects` option to `scrape_configs` section in the same way as [Prometheus 2.26 does](https://github.com/prometheus/prometheus/pull/8546). * FEATURE: vmagent: add support for `authorization` section in `-promscrape.config` in the same way as [Prometheus 2.26 does](https://github.com/prometheus/prometheus/pull/8512). * FEATURE: vmagent: add support for socks5 proxy in `proxy_url` config option. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1177). +* FEATURE: vmagent: add support for `socks5 over tls` proxy in `proxy_url` config option. It can be set up with the following config: `proxy_url: tls+socks5://proxy-addr:port`. * FEATURE: vmagent: reduce memory usage when `-remoteWrite.queues` is set to a big value. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1167). * FEATURE: vmagent: add AWS IAM roles for tasks support for EC2 service discovery according to [these docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html). * FEATURE: vmagent: add support for `proxy_tls_config`, `proxy_authorization`, `proxy_basic_auth`, `proxy_bearer_token` and `proxy_bearer_token_file` options to `consul_sd_config`, `dockerswarm_sd_config` and `eureka_sd_config` sections. diff --git a/lib/proxy/proxy.go b/lib/proxy/proxy.go index 087d35fb0..ebf476b60 100644 --- a/lib/proxy/proxy.go +++ b/lib/proxy/proxy.go @@ -105,18 +105,13 @@ func (u *URL) NewDialFunc(ac *promauth.Config) (fasthttp.DialFunc, error) { return defaultDialFunc, nil } pu := u.url - if pu.Scheme != "http" && pu.Scheme != "https" && pu.Scheme != "socks5" { - return nil, fmt.Errorf("unknown scheme=%q for proxy_url=%q, must be http, https or socks5", pu.Scheme, pu.Redacted()) + switch pu.Scheme { + case "http", "https", "socks5", "tls+socks5": + default: + return nil, fmt.Errorf("unknown scheme=%q for proxy_url=%q, must be http, https, socks5 or tls+socks5", pu.Scheme, pu.Redacted()) } - isTLS := pu.Scheme == "https" + isTLS := (pu.Scheme == "https" || pu.Scheme == "tls+socks5") proxyAddr := addMissingPort(pu.Host, isTLS) - if pu.Scheme == "socks5" { - return socks5DialFunc(proxyAddr, pu) - } - authHeader := u.GetAuthHeader(ac) - if authHeader != "" { - authHeader = "Proxy-Authorization: " + authHeader + "\r\n" - } var tlsCfg *tls.Config if isTLS { tlsCfg = ac.NewTLSConfig() @@ -124,6 +119,13 @@ func (u *URL) NewDialFunc(ac *promauth.Config) (fasthttp.DialFunc, error) { tlsCfg.ServerName = tlsServerName(proxyAddr) } } + if pu.Scheme == "socks5" || pu.Scheme == "tls+socks5" { + return socks5DialFunc(proxyAddr, pu, tlsCfg) + } + authHeader := u.GetAuthHeader(ac) + if authHeader != "" { + authHeader = "Proxy-Authorization: " + authHeader + "\r\n" + } dialFunc := func(addr string) (net.Conn, error) { proxyConn, err := defaultDialFunc(proxyAddr) if err != nil { @@ -142,7 +144,7 @@ func (u *URL) NewDialFunc(ac *promauth.Config) (fasthttp.DialFunc, error) { return dialFunc, nil } -func socks5DialFunc(proxyAddr string, pu *url.URL) (fasthttp.DialFunc, error) { +func socks5DialFunc(proxyAddr string, pu *url.URL, tlsCfg *tls.Config) (fasthttp.DialFunc, error) { var sac *proxy.Auth if pu.User != nil { username := pu.User.Username() @@ -153,7 +155,14 @@ func socks5DialFunc(proxyAddr string, pu *url.URL) (fasthttp.DialFunc, error) { } } network := netutil.GetTCPNetwork() - d, err := proxy.SOCKS5(network, proxyAddr, sac, proxy.Direct) + var dialer proxy.Dialer = proxy.Direct + if tlsCfg != nil { + dialer = &tls.Dialer{ + NetDialer: proxy.Direct, + Config: tls.Config, + } + } + d, err := proxy.SOCKS5(network, proxyAddr, sac, dialer) if err != nil { return nil, fmt.Errorf("cannot create socks5 proxy for url: %s, err: %w", pu.Redacted(), err) }