package exportproxy import ( "context" "errors" "fmt" "io" "net" "time" ) const proxyTimeout = 30 * time.Second func dialTarget(ctx context.Context, address string, dialer *net.Dialer, resolver *net.Resolver) (net.Conn, error) { host, port, err := net.SplitHostPort(address) if err != nil { return nil, err } if ip := net.ParseIP(host); ip != nil { return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port)) } ips, err := resolver.LookupIPAddr(ctx, host) if err != nil { return nil, err } var lastErr error for _, ip := range ips { connection, err := dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.IP.String(), port)) if err == nil { return connection, nil } lastErr = err } if lastErr == nil { lastErr = fmt.Errorf("%w: no addresses for %s", errors.ErrUnsupported, host) } return nil, lastErr } func pipe(left, right net.Conn) { done := make(chan struct{}, 2) go func() { _, _ = copyConnection(right, left); done <- struct{}{} }() go func() { _, _ = copyConnection(left, right); done <- struct{}{} }() <-done } func copyConnection(destination net.Conn, source net.Conn) (int64, error) { written, err := io.CopyBuffer(destination, source, make([]byte, 32*1024)) if err == nil && written > 0 { if connection, ok := destination.(interface{ CloseWrite() error }); ok { _ = connection.CloseWrite() } } return written, err }