简体   繁体   中英

Golang cross-compiled OSX binary hangs while VPN'ed in net/http.Get()

I created a simple go program which performs a HTTP GET request and prints the elapsed time taken to perform the request:

package main

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

func main() {
    start := time.Now()
    http.Get("https://google.com")
    log.Printf("Elapsed: %v", time.Since(start))
}

When building this natively on OSX (Sierra 10.12.1), the elapsed time to perform the request is reasonable (<500ms).

$ for i in `seq 1 10`; do ./httpgettest ; done
2017/08/15 14:20:44 Elapsed: 525.989928ms
2017/08/15 14:20:45 Elapsed: 479.785494ms
2017/08/15 14:20:45 Elapsed: 477.800294ms
2017/08/15 14:20:46 Elapsed: 494.060461ms
2017/08/15 14:20:46 Elapsed: 477.368627ms
2017/08/15 14:20:47 Elapsed: 454.152783ms
2017/08/15 14:20:47 Elapsed: 463.760254ms
2017/08/15 14:20:48 Elapsed: 470.52473ms
2017/08/15 14:20:48 Elapsed: 461.632058ms
2017/08/15 14:20:49 Elapsed: 465.769262ms

I then cross-compile the same program from the golang Linux docker container:

GOOS=darwin GOARCH=amd64 go build -v -o httpgettest-xcompiled

However when executing the resulting binary while VPNed, the elapsed time is always 10+ seconds:

$ for i in `seq 1 10`; do ./httpgettest-xcompiled ; done
2017/08/15 14:19:43 Elapsed: 10.532037349s
2017/08/15 14:19:54 Elapsed: 10.525551121s
2017/08/15 14:20:04 Elapsed: 10.572715005s
2017/08/15 14:20:15 Elapsed: 10.532407157s
2017/08/15 14:20:25 Elapsed: 10.54083169s
2017/08/15 14:20:36 Elapsed: 10.625399239s
2017/08/15 14:20:46 Elapsed: 10.539333467s
2017/08/15 14:20:57 Elapsed: 10.533211943s
2017/08/15 14:21:07 Elapsed: 10.539430574s
2017/08/15 14:21:18 Elapsed: 10.527510134s

As soon as I disconnect from the VPN, the numbers drop down.

Can someone explain how the cross compiled binary is slow while VPNed but the mac native compiled version is always performant? This is reproducible using the golang 1.7.6, 1.8.3 and 1.9 docker containers.

I use Tunnelblick to connect to a OpenVPN server.

It looks like Go is using system's native DNS resolution code (via a C library) when compiling locally, but Go's own resolver written in Go when cross-compiled. As confirmation, sounds like it's slow when CGO_ENABLED=0 . Although it isn't specifically about what you're experiencing here, https://github.com/golang/go/issues/16345 came up in a quick search and refers to how CGO_ENABLED determines which resolver runs.

I'm not sure, though, how you either compile a binary you want to use the cgo native resolver cross-platform (probably need to at least install C cross-compilers) or get the resolver in Go to work well under your Darwin VPN setup.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM