Skip to content

Commit

Permalink
use the configured timeout as hard deadline for the raw connection wh…
Browse files Browse the repository at this point in the history
…ile doing the proxy connect and only there;
  • Loading branch information
bogdanfinn committed Apr 10, 2024
1 parent cae67ec commit 1a7b483
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 9 deletions.
1 change: 1 addition & 0 deletions cffi_dist/.tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
nodejs 20.10.0
golang 1.20
2 changes: 1 addition & 1 deletion cffi_dist/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.20

require (
github.com/bogdanfinn/fhttp v0.5.27
github.com/bogdanfinn/tls-client v1.7.2
github.com/bogdanfinn/tls-client v1.7.3-proxy-connect
github.com/google/uuid v1.3.0
)

Expand Down
4 changes: 2 additions & 2 deletions cffi_dist/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bogdanfinn/fhttp v0.5.27 h1:+glR3k8v5nxfUSk7+J3M246zEQ2yadhS0vLq1utK71A=
github.com/bogdanfinn/fhttp v0.5.27/go.mod h1:oJiYPG3jQTKzk/VFmogH8jxjH5yiv2rrOH48Xso2lrE=
github.com/bogdanfinn/tls-client v1.7.2 h1:vpL5qBYUfT9ueygEf1yLfymrXyUEZQatL25amfqGV8M=
github.com/bogdanfinn/tls-client v1.7.2/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
github.com/bogdanfinn/tls-client v1.7.3-proxy-connect h1:+9Yy9Q3DEsy0D6ZeerATNfV0S+36B4tl1AtkKPaWntQ=
github.com/bogdanfinn/tls-client v1.7.3-proxy-connect/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
github.com/bogdanfinn/utls v1.6.1 h1:dKDYAcXEyFFJ3GaWaN89DEyjyRraD1qb4osdEK89ass=
github.com/bogdanfinn/utls v1.6.1/go.mod h1:VXIbRZaiY/wHZc6Hu+DZ4O2CgTzjhjCg/Ou3V4r/39Y=
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
Expand Down
8 changes: 4 additions & 4 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func NewHttpClient(logger Logger, options ...HttpClientOption) (HttpClient, erro
return nil, err
}

client, clientProfile, err := buildFromConfig(config)
client, clientProfile, err := buildFromConfig(logger, config)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -112,12 +112,12 @@ func validateConfig(_ *httpClientConfig) error {
return nil
}

func buildFromConfig(config *httpClientConfig) (*http.Client, profiles.ClientProfile, error) {
func buildFromConfig(logger Logger, config *httpClientConfig) (*http.Client, profiles.ClientProfile, error) {
var dialer proxy.ContextDialer
dialer = newDirectDialer(config.timeout, config.localAddr, config.dialer)

if config.proxyUrl != "" {
proxyDialer, err := newConnectDialer(config.proxyUrl, config.timeout, config.localAddr, config.dialer)
proxyDialer, err := newConnectDialer(config.proxyUrl, config.timeout, config.localAddr, config.dialer, logger)
if err != nil {
return nil, profiles.ClientProfile{}, err
}
Expand Down Expand Up @@ -221,7 +221,7 @@ func (c *httpClient) applyProxy() error {

if c.config.proxyUrl != "" {
c.logger.Debug("proxy url %s supplied - using proxy connect dialer", c.config.proxyUrl)
proxyDialer, err := newConnectDialer(c.config.proxyUrl, c.config.timeout, c.config.localAddr, c.config.dialer)
proxyDialer, err := newConnectDialer(c.config.proxyUrl, c.config.timeout, c.config.localAddr, c.config.dialer, c.logger)
if err != nil {
c.logger.Error("failed to create proxy connect dialer: %s", err.Error())
return err
Expand Down
29 changes: 27 additions & 2 deletions connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"io"
"net"
"net/url"
"os"
"sync"
"time"

Expand Down Expand Up @@ -74,6 +75,7 @@ func (s *socksContextDialer) DialContext(ctx context.Context, network, address s

// connectDialer allows to configure one-time use HTTP CONNECT client
type connectDialer struct {
logger Logger
ProxyUrl url.URL
DefaultHeader http.Header

Expand All @@ -92,7 +94,7 @@ type connectDialer struct {
// newConnectDialer creates a dialer to issue CONNECT requests and tunnel traffic via HTTP/S proxy.
// proxyUrlStr must provide Scheme and Host, may provide credentials and port.
// Example: https://username:[email protected]:443
func newConnectDialer(proxyUrlStr string, timeout time.Duration, localAddr *net.TCPAddr, configDialer net.Dialer) (proxy.ContextDialer, error) {
func newConnectDialer(proxyUrlStr string, timeout time.Duration, localAddr *net.TCPAddr, configDialer net.Dialer, logger Logger) (proxy.ContextDialer, error) {
proxyUrl, err := url.Parse(proxyUrlStr)
if err != nil {
return nil, err
Expand Down Expand Up @@ -126,6 +128,7 @@ func newConnectDialer(proxyUrlStr string, timeout time.Duration, localAddr *net.
}

dialer := &connectDialer{
logger: logger,
ProxyUrl: *proxyUrl,
Dialer: _dialer,
Timeout: timeout,
Expand Down Expand Up @@ -219,6 +222,7 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
_ = rawConn.Close()
return nil, errors.New("Proxy responded with non 200 code: " + resp.Status)
}

return newHttp2Conn(rawConn, pw, resp.Body), nil
}

Expand All @@ -227,14 +231,29 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
req.ProtoMajor = 1
req.ProtoMinor = 1

err := req.Write(rawConn)
deadline := time.Now().Add(c.Timeout)
err := rawConn.SetDeadline(deadline)
if err != nil {
_ = rawConn.Close()
return nil, err
}

err = req.Write(rawConn)
if err != nil {
if errors.Is(err, os.ErrDeadlineExceeded) {
c.logger.Error("deadline exceeded while trying to write proxy connection")
}

_ = rawConn.Close()
return nil, err
}

resp, err := http.ReadResponse(bufio.NewReader(rawConn), req)
if err != nil {
if errors.Is(err, os.ErrDeadlineExceeded) {
c.logger.Error("deadline exceeded while trying to read proxy connection")
}

_ = rawConn.Close()
return nil, err
}
Expand All @@ -243,6 +262,9 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
_ = rawConn.Close()
return nil, errors.New("Proxy responded with non 200 code: " + resp.Status)
}

rawConn.SetDeadline(time.Time{})

return rawConn, nil
}

Expand All @@ -255,6 +277,7 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
cc := c.cachedH2ClientConn
c.cacheH2Mu.Unlock()
unlocked = true

proxyConn, err := connectHttp2(rc, cc)
if err == nil {
return proxyConn, err
Expand All @@ -273,6 +296,7 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
switch c.ProxyUrl.Scheme {
case "http":
rawConn, err = c.Dialer.DialContext(ctx, network, c.ProxyUrl.Host)

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -320,6 +344,7 @@ func (c *connectDialer) DialContext(ctx context.Context, network, address string
_ = rawConn.Close()
return nil, err
}

if c.EnableH2ConnReuse {
c.cacheH2Mu.Lock()
c.cachedH2ClientConn = h2clientConn
Expand Down

0 comments on commit 1a7b483

Please sign in to comment.