如何通过代理进行HTTP / HTTPS GET

问题描述 投票:-2回答:1

我正在尝试通过工作代理发出http / s请求。我在节点JS的遗留项目中有一个工作示例,其中使用本机Node.js httpsrequire('https'))lib可以在与以下选项对象一起使用时发出请求:

{
    host: "<actual target url>"
    hostname: "<proxy ip>"
}

例如,要通过代理example.com1.1.1.1发出https请求,我将使用:

{
    host: "http://example.com"
    hostname: "1.1.1.1"
}

在Golang,我尝试了几个记录的选项。具体来说,我希望:

proxyUrl, _ := url.Parse("<proxy ip>")
myClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
resp, err := myClient.Get("https://<actual target url>/...")

结果是代理拒绝连接,表明请求中存在不正确的内容。 (err存在,而resp是nil


代理本身是根据这个要点配置的NGINX实例:

https://gist.github.com/selfish/6e858eb17aa82971d25b21775e9649cb#file-nginx-conf

任何人都可以帮助理解Node.js和Golang的HTTP处理的区别吗?

http go proxy
1个回答
1
投票

您正在混淆正向和反向代理。

从概念上讲它的工作原理如下:

反向代理

  • 部署在连接的服务器端附近
  • 假装是原点
  • 由网站所有者或代表网站所有者控制
  • 用户代理本身并不知道

转发代理

  • 部署在连接的客户端附近
  • 由用户代理或代表用户代理控制
  • 在用户代理中显式配置

(当然,现实比这更复杂,但这足以突出差异)。

                                     Internet                    ||  Invisible to
                                         +                       ||  User Agent
                                         |                       ||
 +------------+     +---------------+    |    +---------------+  ||  +--------+
 |            |     |               |    |    |               |  ||  |        |
 | User Agent +---->+ Forward Proxy +-------->+ Reverse Proxy +----->+ Origin |
 |            |     |               |    |    |               |  ||  |        |
 +------------+     +---------------+    |    +---------------+  ||  +--------+
                                         |                       ||
                                         +                       ||
                                                                 ||

nginx是一个反向代理,但通过设置Transport.Proxy字段,您可以将其视为转发代理。这是nginx看到的请求:

CONNECT example.com:443 HTTP/1.1
Host: example.com:443
User-Agent: Go-http-client/1.1

这必要意味着,“建立到example.com:443的TCP连接,然后像一个愚蠢的TCP代理。”由于nginx只是一个反向代理,因此在面对CONNECT请求时会被正确地混淆。

要向特定的反向代理发送请求,您只需修改请求URL,并可能修改主机头(这取决于nginx是否需要特定的server_name)。无需特殊客户端配置。

假设nginx在198.51.100.1上运行:

req, _ := http.NewRequest("GET", "http://198.51.100.1", nil)
req.Host = "example.com" // if necessary
res, _ := http.DefaultClient.Do(req)

这会导致以下请求发送到198.51.100.1:80:

GET / HTTP/1.1
Host: example.com
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

请注意,如果请求实际访问example.com,则完全取决于反向代理。客户端不知道或控制代理后发生的事情。

如果您无法更改请求,则可以设置Transport.DialContext函数,以便始终拨打您的代理,而与请求URL和主机标头无关。这会产生与上面相同的请求,并且应该等同于您的JavaScript代码:

c := &http.Client{
    Transport: &http.Transport{
        DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
            return (&net.Dialer{}).DialContext(ctx, "tcp", "198.51.100.1:80")

            // Or 198.51.100.1:443 if nginx has TLS enabled, although that almost
            // certainly causes TLS validation errors because a certificate for 
            // example.com is expected.
        },
    },
}

req, _ := http.NewRequest("GET", "http://example.com", nil)
res, _ := c.Do(req)
© www.soinside.com 2019 - 2024. All rights reserved.