Go가 localhost에서 프록시를 우회하는 이유
Go에 내장된 루프백 우회 규칙과 NO_PROXY 설정을 구분하고 환경 기반 경로 선택을 명시적인 ProxyURL과 비교합니다.
Go의 환경 기반 프록시 선택기에는 localhost와 루프백 IP 목적지에 대한 예외가 내장되어 있습니다. NO_PROXY를 비워도 이 예외는 사라지지 않습니다. 따라서 공용 호스트 이름으로 보내는 요청은 예상대로 프록시를 사용하면서 로컬 테스트는 직접 연결될 수 있습니다.
이 규칙은 요청의 목적지에 관한 것입니다. 프록시 리스너 자체의 주소가 127.0.0.1인 프록시를 사용하는 데에는 제약이 없습니다.
요청을 보내지 않고 선택기 확인하기
package main
import (
"fmt"
"net/http"
"net/url"
)
func main() {
fixed, _ := url.Parse("http://203.0.113.10:8080")
for _, target := range []string{
"http://localhost:8000/",
"http://127.0.0.1:8000/",
"http://example.com/",
} {
request, _ := http.NewRequest("GET", target, nil)
discovered, err := http.ProxyFromEnvironment(request)
explicit, _ := http.ProxyURL(fixed)(request)
fmt.Println(target, discovered, explicit, err)
}
}
환경 설정에 따른 비교를 보려면 프로세스에 프록시 변수를 설정한 뒤 실행하세요. 이 프로그램은 선택기만 평가하며 문서 예제의 프록시나 어떤 목적지에도 연결하지 않습니다.
환경 검색과 명시적인 선택기는 서로 다른 정책
ProxyFromEnvironment는 목적지 스킴, 환경 설정, 루프백의 특별 처리를 포함한 우회 규칙을 고려합니다. ProxyURL은 해당 선택기로 전달된 모든 요청에 대해 지정된 프록시 URL을 반환합니다.
따라서 명시적인 ProxyURL을 사용하는 전용 트랜스포트는 로컬 목적지로 가는 요청도 프록시를 거치게 할 수 있습니다. 이는 프록시가 요청된 목적지에 정당하게 접근할 수 있을 때만 유용합니다. 원격 프록시의 localhost는 내 노트북의 localhost가 아니므로 경로를 강제한다고 해서 곧바로 유용한 연결 테스트가 되는 것은 아닙니다.
프로세스가 환경을 캐시하기 전에 확인하기
표준 net/http의 환경 프록시 설정은 처음 사용된 후 캐시됩니다. 같은 프로그램이 실행 중일 때 나중에 환경 변수를 바꾸는 것은 새 설정 테스트를 다시 수행하는 신뢰할 만한 방법이 아닙니다. 원하는 값을 설정하여 새 프로세스를 시작하거나 동작을 직접 제어할 수 있는 명시적인 선택기를 제공하세요.
이 루프백 동작은 Go 1.27.3의 표준 프록시 선택기에 적용됩니다. 다른 언어와 HTTP 클라이언트는 서로 다른 localhost 경로 선택 규칙을 사용할 수 있습니다.