feat: tunnel raw TCP database connections through HTTP CONNECT proxy#357
Open
jaymiracola wants to merge 7 commits into
Open
feat: tunnel raw TCP database connections through HTTP CONNECT proxy#357jaymiracola wants to merge 7 commits into
jaymiracola wants to merge 7 commits into
Conversation
b1c4391 to
a7cfc19
Compare
Collaborator
fernandezcuesta
left a comment
There was a problem hiding this comment.
similarly for the rest
When HTTP_PROXY or HTTPS_PROXY is set, PostgreSQL, MySQL, and MSSQL connections are tunnelled through the proxy via HTTP CONNECT. This mirrors how net/http handles proxies automatically for HTTP-based providers, extending the same behaviour to raw TCP database drivers which bypass net/http entirely. Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
Co-authored-by: J. Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
Co-authored-by: J. Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
Co-authored-by: J. Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
Co-authored-by: J. Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
Apply the defer-based error handling pattern consistently across all three proxy files. Named return values allow the deferred closure to capture and wrap close errors alongside the original error rather than discarding them silently. Signed-off-by: Jay Miracola <jaymiracola@gmail.com>
f6dc878 to
08a59bb
Compare
chlunde
reviewed
May 15, 2026
| return nil, err | ||
| } | ||
| var resp *http.Response | ||
| resp, err = http.ReadResponse(bufio.NewReader(conn), req) |
Collaborator
There was a problem hiding this comment.
this will possibly hijack bytes from the database server - as NewReader does a 4 KB read and that could be some of the bytes not just from the proxy but the sql server banner data?
chlunde
reviewed
May 15, 2026
| return conn, nil | ||
| } | ||
|
|
||
| // openDB opens a *sql.DB for the given DSN. When HTTP_PROXY or HTTPS_PROXY is |
Collaborator
There was a problem hiding this comment.
does it respect HTTP_PROXY? you construct a https URL below?
chlunde
reviewed
May 15, 2026
| // set and applicable to the target endpoint, connections are tunnelled through | ||
| // the proxy via HTTP CONNECT. | ||
| func openDB(endpoint, port, dsn string) (*sql.DB, error) { | ||
| req, _ := http.NewRequest(http.MethodConnect, "https://"+endpoint+":"+port, nil) |
Collaborator
There was a problem hiding this comment.
will this panic on invalid URL?
Collaborator
There was a problem hiding this comment.
You construct a &http.Request{ manually in the code the other place - should probably use the same here? this would avoid discarding the error too
Collaborator
|
Also, shall we consolidate this to |
chlunde
reviewed
May 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
HTTP_PROXYorHTTPS_PROXYis set, connections are tunnelled through the proxy via HTTP CONNECT rather than dialling the database endpoint directlynet/http-based providers get automatically, extending it to raw TCP database drivers that bypassnet/httpentirelyBackground
Database drivers (
lib/pq,go-sql-driver/mysql,go-mssqldb) usenet.Dialdirectly and do not respectHTTP_PROXY/HTTPS_PROXYenvironment variables. This means provider-sql could not reach database endpoints that require an HTTP CONNECT proxy, for example when running under Upbound Private Network Agent which injects proxy env vars to route traffic to private VPC endpoints.Implementation
Each driver uses its own dialer injection API:
pq.NewConnector+connector.Dialer(&httpProxyDialer{})+sql.OpenDBgomysql.ParseDSN+cfg.DialFunc+gomysql.NewConnector+sql.OpenDBmssqldb.NewConnector+connector.Dialer+sql.OpenDBProxy detection uses
http.ProxyFromEnvironment, the same function the standard library uses, soNO_PROXYand other proxy env var semantics are respected automatically.When no proxy is configured,
openDBfalls through tosql.Openwith the same driver name and DSN as before. No other code runs. The stdlib itself uses this same pattern in(*Transport).roundTrip: check proxy URL, fall through to direct dial if nil.The dialer injection APIs used here are each driver's documented extension point:
pq.Connector.Dialeris the interface pq exports specifically for custom dialersmysql.Config.DialFuncis the field go-sql-driver provides for dial interceptionmssqldb.Connector.Dialeris the field go-mssqldb exposes for custom dialersConnections that do not match the proxy scope (via
NO_PROXY, scheme filtering, etc.) are handled byhttp.ProxyFromEnvironmentbefore any driver code is touched.Test plan
go test ./pkg/clients/...openDBfalls through tosql.Open, behaviour identical to before (TestOpenDBNoProxy)TestTunnelSuccess)TestTunnelProxyRejected