Skip to content

Commit

Permalink
improve the proxy section
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Sep 19, 2024
1 parent d2d4797 commit 8dcf78d
Showing 1 changed file with 19 additions and 10 deletions.
29 changes: 19 additions & 10 deletions content/docs/masque/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ To create a MASQUE proxy server, the following steps are necessary:

1. Set up an HTTP/3 server that defines an `http.Handler` for the URI template.
2. Decode the client's request and create a socket to the target.
3. Use the `masque.Proxy` to handle proxying of the UDP packet flow.
3. Use the `masque.Proxy` to handle proxying UDP of the UDP packet flow.

## URI Templates

HTTP clients are configured to use a UDP proxy with a URI Template ([RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570)).
HTTP clients are configured to use a CONNECT-UDP proxy with a URI Template ([RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570)).
This URI template encodes the target host and port number.

For example, for a proxy running on `https://proxy.example.com`, these are possible URI templates:
Expand Down Expand Up @@ -44,7 +44,9 @@ http.Handle("/masque", func(w http.ResponseWriter, r *http.Request) {
return
}

// Optional: Whitelisting / blacklisting logic.
// optional: whitelisting / blacklisting logic

// start proxying UDP datagrams back and forth
err = proxy.Proxy(w, mreq)
// ... error handling
}
Expand All @@ -54,24 +56,23 @@ s := http3.Server{Addr: ":4443"}
s.ListenAndServeTLS(<certfile>, <keyfile>)
```

The error returned from `masque ParseRequest` is a `masque.RequestParseError`, which contains a field 'HTTPStatus'. This allows the proxy to reject
invalid requests with the correct HTTP status code.
`masque.ParseRequest` parses the Extended CONNECT request, and extracts the target host and port from the URI template. If parsing of the request fails, it returns a `masque.RequestParseError`. This struct contains a field 'HTTPStatus', allowing the application to reject invalid requests with the correct HTTP status code.

The `masque Request.Target` contains the requested target as `{target_host}:{target_port}`. Proxies can implement custom logic to decide which proxying requests are permissible.
The `masque Request.Target` contains the requested target encoded as `{target_host}:{target_port}`. Applications can implement custom logic to decide which proxying requests are permissible.

{{< callout type="warning" >}}
Applications may add custom header fields to the response header, but must not call `WriteHeader` on the `http.ResponseWriter`
The header is sent when `Proxy.Proxy` is called.
{{< / callout >}}
{{< /callout >}}

For more details on how to set up and configure an HTTP/3 server, see [Serving HTTP/3]({{< relref "../http3/server.md" >}}).


## Controlling the Socket
## Managing UDP Sockets

`proxy.Proxy` creates a new connected UDP socket on `:0` to send UDP datagrams to the target.
The `proxy.Proxy` function used above creates a new connected UDP socket on `:0` to send UDP datagrams to the target.

An application that wishes a more fine-grained control over the socket can use `Proxy.ProxyConnectedSocket` instead of `Proxy.Proxy`:
An application that wishes a more fine-grained control over the socket can instead use `Proxy.ProxyConnectedSocket`:
```go
http.Handle("/masque", func(w http.ResponseWriter, r *http.Request) {
// parse the UDP proxying request
Expand All @@ -89,6 +90,14 @@ http.Handle("/masque", func(w http.ResponseWriter, r *http.Request) {
}
```

The `net.UDPConn` passed to `ProxyConnectedSocket` is closed by the proxy after proxying is done.

{{< callout type="warning" >}}
Note that it is currently not possible to use unconnected UDP sockets (issue [#3]((https://github.com/quic-go/masque-go/issues/3))).
It is invalid to pass an unconnected socket to `ProxyConnectedSocket`.
{{< /callout >}}



## 📝 Future Work

Expand Down

0 comments on commit 8dcf78d

Please sign in to comment.