This PR allows the TURN allocation binding to be optionally configured
by `TURN_LOWEST_PORT` and `TURN_HIGHEST_PORT` environment variables.
This will allow client app developers to test their apps against a
fully-working local development cluster in Docker Desktop for
Linux/macOS/Windows, allowing us to remove the PortalMock, Connlib Mock,
and SwiftMock codepaths entirely.
cc @roop @pratikvelani
This patch series adds support for IPv6 allocations. If not specified
otherwise in the ALLOCATE request, clients will get an IP4 allocation.
They can also request an IPv6 address or an additional IPv6 address in
addition to their IPv4 address.
Either of those is only possible if the relay actually has a listening
socket for the requested address family. The CLI is designed such that
the user can either specify IP4, IP6 or both of them.
The `Server` component handles all of this logic and responds with
either a successful allocation response or an Address Family Not
Supported error (see
https://www.rfc-editor.org/rfc/rfc8656#name-stun-error-response-codes).
Multiple refactorings were necessary to achieve this design, they are
all extracted into separate PRs:
Depends-On: #1831.
Depends-On: #1832.
Depends-On: #1833.
---------
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
The metrics are available at `http://{listen_addr}:8080/metrics`.
Currently, we collect the following:
- Number of active allocations: We can have an alert once the number of
allocations passes through a certain threshold.
- Outcome (success / error) and message kind (allocation / channel_bind
/ ...) of all responses: Summing all of these up would give you the
total number of requests handled. We might want to have a grafana alert
for an increased number of error responses.
- Total number of bytes relayed: Dividing this by time gives us an
average "internal" bandwidth.
This is just a start, we can explore what else is useful as we have it
operate.
Depends-On: https://github.com/firezone/firezone/pull/1743
Previously, the relay would treat the `stamp_secret` internally as bytes and share it with the outside world as hex-string. The portal however treats it as an opaque string and uses the UTF-8 bytes to create username and password.
This patch aligns the relay's functionality with the portal and stores the `stamp_secret` internally as a string.
To complete the authentication scheme for the relay, we need to prompt
the client with a nonce when they send an unauthenticated request. The
semantic meaning of a nonce is opaque to the client. As a starting
point, we implement a count-based scheme. Each nonce is valid for 10
requests. After that, a request will be rejected with a 401 and the
client has to authenticate with a new nonce.
This scheme provides a basic form of replay-protection.
We introduce dedicated types for each message that the `Server` can
handle. This allows us to make the functions public because the
type-system now guarantees that those are either parsed from bytes or
constructed with the correct data.
The latter will be useful to write tests against a richer API.
With this patch, the relay can parse and respond to allocation requests. I
ran some basics tests against https://icetest.info/ and implemented a
regression test as a result of the logged data.
In writing this, I also had to slightly change the design of `Server`
(as expected). Event handlers for incoming data now do not return a
message directly. Instead, the caller is responsible to drain `Command`s
from it.
When creating an allocation, we need to start listening on a new port.
This needs to happen outside the `Server` as I am going for a sans-IO
style. We emit a `Command` that instructs the main event loop to listen
on a new port. Any incoming data on that port will be forwarded to the
`Server`.
At the moment, this incoming data is just dropped. This is actually
standards-compliant because we cannot handle binding requests yet which
would allow this data to be forwarded to the client.
In some areas, the code is still a bit rough but I expect to iron those
things out as we go along.
This is an alternative to https://github.com/firezone/firezone/pull/1602
that implements the server using a library I've found called
`stun_codec`.
It already has support for parsing a variety of attributes.
The following is a nice website to test some of the functionality:
https://icetest.info/
The server is still listening on:
`ec2-3-89-112-240.compute-1.amazonaws.com:3478`.