go x/net/http/httproxy: 空主机应该绕过代理

xvw2m8pv  于 2个月前  发布在  Go
关注(0)|答案(2)|浏览(28)

你正在使用哪个版本的Go( go version )?

$ go version
go version go1.18.2 linux/amd64

这个问题在最新版本中是否会重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/ubuntu/.cache/go-build"
GOENV="/home/ubuntu/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/ubuntu/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/ubuntu/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/ubuntu/.local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/ubuntu/.local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/ubuntu/hello/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build736401068=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

我们模拟了一个行为,其中CoreDNS健康插件通过http_proxy向 http://:8080/health 发送http请求,该请求由健康插件本身监听。我们发现,如果我们指定 http://127.0.0.1:8080/ ,它将无法连接到代理,但只有在我们指定 http://:8080/health 时,它才会始终连接到代理。
以下示例代码使用了net/http的默认传输方式,模仿了CoreDNS健康插件中的过载函数,在运行之前配置 export http_proxy=http://127.0.0.1:8000 :

package main

import (
	"fmt"
	"net/http"
	"time"
)

func main() {
	timeout := time.Duration(3 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	// url := "http://127.0.0.1:8080/health" // not using proxy
	url := "http://:8080/health" // using proxy

	resp, err := client.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("succeed")
	resp.Body.Close()
}

你期望看到什么?

Get "http://:8080/health": dial tcp 127.0.0.1:8080: connect: connection refused 应该显示,因为它不应该到达代理

你看到了什么?

Get "http://:8080/health": proxyconnect tcp: dial tcp 127.0.0.1:8000: connect: connection refused
请注意, useProxy 函数专门检查 "localhost" 和环回地址,如果没有提供主机名,是否也应该使用代理是有意义的?
另请参阅: #1589#28866 ,请注意,在这种情况下,无法使用no_proxy来豁免代理的使用,因为no_proxy跳过了空字符串。

o4tp2gmn

o4tp2gmn2#

我很惊讶我们愿意在URL中使用空主机名发起请求。这是不幸的。
由于改变这种行为是危险的(这里有一个证明的例子,有人依赖它),don't-proxy-localhost检查也应该查找空字符串。可能0.0.0.0[::]也需要检查,因为net.Dial也把它们当作环回地址处理。

相关问题