Go SDK Transport, Proxy, and DNS
Configure how Go agents reach the rstream engine.
Transport settings control how a Go process reaches the rstream engine. They do not change what a tunnel publishes. A published HTTP tunnel, a private TCP tunnel, and a datagram tunnel can all use the same agent transport policy.
Direct TLS Transport
The default transport opens a TCP connection to the engine and negotiates the rstream TLS session end to end.
client, err := rstream.NewClient(rstream.ClientOptions{
Engine: "project-endpoint.cluster.example.rstream.test:443",
Token: os.Getenv("RSTREAM_AUTHENTICATION_TOKEN"),
})
if err != nil {
log.Fatal(err)
}Bind options can pin the local source address or constrain the address family.
client := &rstream.Client{
EngineURL: "project-endpoint.cluster.example.rstream.test:443",
Token: os.Getenv("RSTREAM_AUTHENTICATION_TOKEN"),
Transport: &rstream.Transport{
LocalAddr: rstream.StringPtr("10.10.0.25"),
ForceIPv4: rstream.BoolPtr(true),
},
}MPTCPEnabled can be enabled for TCP paths when the host and network support Multipath TCP.
QUIC Transport
QUICTransport uses one QUIC connection for SDK-to-engine streams and datagrams. Select it directly in code when the process owns its transport configuration.
client := &rstream.Client{
EngineURL: "project-endpoint.cluster.example.rstream.test:443",
Token: os.Getenv("RSTREAM_AUTHENTICATION_TOKEN"),
Transport: &rstream.QUICTransport{},
}The config bridge can select QUIC for a process with RSTREAM_QUIC_TRANSPORT=1, or from YAML with transport.useQuic: true.
contexts:
- name: lab
engine: project-endpoint.cluster.example.rstream.test:443
transport:
useQuic: trueQUICTransport is stateful. Keep one instance for the lifetime of the client and create a fresh instance after a connection failure.
Proxy Support Matrix
The Go SDK supports proxying the agent-to-engine session for both TCP/TLS and QUIC transports.
| Agent transport | Proxy type | Protocol used between agent and proxy |
|---|---|---|
Transport | proxy.http | HTTP CONNECT for a TCP tunnel to the engine. |
Transport | proxy.socks5 | SOCKS5 CONNECT for a TCP tunnel to the engine. |
QUICTransport | proxy.http | HTTPS MASQUE CONNECT-UDP to the engine UDP endpoint. |
QUICTransport | proxy.socks5 | SOCKS5 UDP ASSOCIATE to the engine UDP endpoint. |
Configure only one proxy type at a time. The SDK rejects configurations that set both proxy.http and proxy.socks5.
proxy.fromEnvironment: true reads the process proxy environment when neither proxy.http nor proxy.socks5 is set. The lookup honors HTTPS_PROXY, HTTP_PROXY, ALL_PROXY, and NO_PROXY in upper- and lower-case forms. HTTP and HTTPS proxy URLs become HTTP proxy transport settings, while socks5:// and socks5h:// become SOCKS5 proxy settings.
contexts:
- name: corp-env
engine: project-endpoint.cluster.example.rstream.test:443
transport:
proxy:
fromEnvironment: trueThe Go SDK does not read desktop proxy preferences directly from macOS System Settings, Windows Internet Options, or similar GUI stores. Agents and services should receive deterministic process environment variables or explicit YAML transport settings.
HTTP CONNECT Proxy for TCP/TLS
Use proxy.http when a network requires outbound TCP through an HTTP proxy.
contexts:
- name: corp
engine: project-endpoint.cluster.example.rstream.test:443
transport:
proxy:
http: http://proxy.corp:3128
username: agent
password: "<proxy-password>"
headers:
X-Company: acmeIn Go code, the equivalent configuration is explicit on rstream.Transport.
transport := &rstream.Transport{
ProxyHTTP: rstream.StringPtr("http://proxy.corp:3128"),
ProxyUsername: rstream.StringPtr("agent"),
ProxyPassword: rstream.StringPtr(os.Getenv("PROXY_PASSWORD")),
ProxyHTTPHeaders: map[string]string{
"X-Company": "acme",
},
}The HTTP proxy sees the CONNECT target authority. The rstream TLS session is negotiated through that TCP tunnel and remains end to end between the SDK and the engine.
MASQUE Proxy for QUIC Transport
QUIC transport cannot use classic HTTP CONNECT because QUIC runs over UDP. When QUICTransport is combined with proxy.http, the SDK uses HTTPS MASQUE CONNECT-UDP.
contexts:
- name: masque
engine: project-endpoint.cluster.example.rstream.test:443
transport:
useQuic: true
proxy:
http: https://masque-proxy.corpThe default MASQUE URI template expands to the standard well-known CONNECT-UDP route.
https://masque-proxy.corp:443/.well-known/masque/udp/{target_host}/{target_port}/Use a custom template when the proxy publishes a different route.
transport:
useQuic: true
proxy:
http: https://masque-proxy.corp/connect-udp/{target_host}/{target_port}proxy.username, proxy.password, and proxy.headers apply to HTTP CONNECT proxy paths. For QUIC over MASQUE, authenticate the proxy endpoint at the MASQUE layer or with the deployment policy provided by that proxy.
SOCKS5 Proxy
Use proxy.socks5 when a SOCKS5 proxy is the approved egress path.
contexts:
- name: socks
engine: project-endpoint.cluster.example.rstream.test:443
transport:
proxy:
socks5: socks5://proxy.corp:1080
username: agent
password: "<proxy-password>"The same proxy.socks5 setting works with transport.useQuic: true. TCP/TLS uses SOCKS5 CONNECT. QUIC uses SOCKS5 UDP ASSOCIATE.
contexts:
- name: socks-quic
engine: project-endpoint.cluster.example.rstream.test:443
transport:
useQuic: true
proxy:
socks5: socks5://proxy.corp:1080HTTP proxy headers do not apply to SOCKS5.
DNS Behavior
With no custom DNS settings, proxied target resolution stays with the proxy whenever the proxy protocol supports it. HTTP CONNECT, MASQUE CONNECT-UDP, and SOCKS5 can receive the engine hostname and resolve it from the proxy side.
When transport.dns is configured, the SDK intentionally resolves the engine name before opening the proxied connection and sends the selected IP address to the proxy. This is the correct mode when the client must use a dedicated resolver, DNS over TLS, DNSSEC validation, or a resolver reachable through a specific local route.
transport:
dns:
override: 1.1.1.1:853
tls: true
serverName: cloudflare-dns.com
dnssec: trueThe same DNS policy is used for direct engine hostname resolution and for ECH discovery through DNS SVCB and HTTPS records. Without explicit DNS settings, the SDK uses the platform resolver configuration. On macOS, scoped per-domain resolvers from the system DNS state are respected.
Bind and address-family settings apply to the local side of the selected path. With a proxy, that means the TCP or UDP socket opened toward the proxy is bound or constrained; with custom DNS, the SDK resolves the engine hostname first and sends the selected IP address through the proxy protocol.
Environment Variables
The config bridge reads the same core environment variables as the CLI.
| Variable | Use |
|---|---|
RSTREAM_CONFIG | Select the configuration file path. |
RSTREAM_CONTEXT | Select a named context from the configuration file. |
RSTREAM_ENGINE | Override the engine endpoint used by runtime clients. |
RSTREAM_AUTHENTICATION_TOKEN | Override the authentication token used by the SDK. |
RSTREAM_MTLS_CERT_FILE | Client certificate file for mTLS agent authentication. |
RSTREAM_MTLS_KEY_FILE | Client private key file for mTLS agent authentication. |
RSTREAM_QUIC_TRANSPORT | Set to 1 to make config.NewClientFromEnv() use QUIC transport while preserving configured bind, DNS, and proxy settings. |
HTTPS_PROXY / HTTP_PROXY / ALL_PROXY / NO_PROXY | Used when transport.proxy.fromEnvironment is true and no explicit proxy URL is configured. |
Token authentication and mTLS agent authentication are mutually exclusive for the control-channel connection. When both mTLS variables are set, the SDK authenticates that connection with the client certificate and does not use a stored context token.