Running a Client
Setting up a Proxied Connection
A client needs to be configured with the same URI template as the proxy. For more information on URI templates, see URI Templates.
template := uritemplate.MustNew("https://example.org:4443/masque?h={target_host}&p={target_port}")Create a CONNECT-UDP request for the target, then use a masque.Transport to dial it.
The target is passed as host:port; when the host is a name, DNS resolution is handled by the proxy:
req, err := masque.NewRequest(ctx, template, "quic-go.net:443")
// ... handle error ...
tr := masque.Transport{}
conn, rsp, err := tr.Dial(req)For IP addresses, pass the address in the same host:port format:
req, err := masque.NewRequest(ctx, template, "203.0.113.1:443")
// ... handle error ...
conn, rsp, err := tr.Dial(req)It is possible to add HTTP headers to the CONNECT-UDP request before dialing:
req, err := masque.NewRequest(ctx, template, "quic-go.net:443")
// ... handle error ...
req.Header().Set("Authorization", "Bearer token")
conn, rsp, err := tr.Dial(req)The *masque.Conn returned from Dial is only non-nil if the proxy accepted the proxying request.
For a non-2xx response, Dial returns an error and the HTTP response:
conn, rsp, err := tr.Dial(req)
if err != nil {
if rsp != nil {
// proxying request rejected
// The response status code and body might contain more information.
}
return
}
// use conn to send and receive UDP datagrams to the targetMultiple UDP flows can be proxied over the same QUIC connection to the proxy by creating a ClientConn from an established QUIC connection:
qconn, err := quic.DialAddr(ctx, "example.org:4443", tlsConf, &quic.Config{EnableDatagrams: true})
// ... handle error ...
cconn, err := tr.NewClientConn(qconn)
// ... handle error ...
req, err := masque.NewRequest(ctx, template, "quic-go.net:443")
// ... handle error ...
conn, rsp, err := cconn.Dial(req)