Part of a yak shave to profile startup time for reducing it on Windows
#5026
Median of 3 runs:
- Windows 11 aarch64 Parallels VM - 4.8 s
- Windows 11 x86_64 laptop - 3.1 s (I thought it used to be slower)
- Windows Server 2022 VM - 22.2 s
---------
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
## The problem
To find the correct peer for a given resource we keep a map of
`resource_id -> gateway_id` in the client state called
`resources_gateways`.
For CIDR resource connlib when sees a packet it does the following
steps:
1. Find the packet's corresponding resource
2. Find the resource corresponding gateway
3. Find the peer corresponding to the gateway, if none, request
access/connection
The problem was that when roaming, we didn't cleanup the map between
`resource_id -> gateway_id` so if after disconnecting with a gateway we
created a new connection due to a another resource, in step 3, connlib
would find a connected gateway and not request access.
This would cause the client to send unallowed packets to the gateway.
## Steps to reproduce
1. Open the client
2. Ping a CIDR resource on a gateway
3. roam and wait until disconnection
4. Ping a different resource on the same gateway
5. Ping the same CIDR resource as in step 2
This will result in no reply for step 5
## The fix
Cleanup the `resource -> gateway` map after disconnecting with a
gateway.
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
Closes#5042
Smoke test plan:
- Install on a before-Firezone VM
- Confirm logs default to `str0m=warn,info`
- Set log filter to `debug` in GUI
- Restart IPC service
- Confirm logs are `debug`
- Clear settings back to default
- Restart IPC service
- Confirm logs are `str0m=warn,info`
Directions to apply new log level:
1. Put the new log filter in
2. Click "Apply"
3. Quit Firezone Client
4. Right-click on the Start Menu and click "Terminal (Admin)" to open a
Powershell prompt
5. Run `Restart-Service -Name FirezoneClientIpcService` (on Linux, `sudo
systemctl restart firezone-client-ipc.service`)
6. Re-open Firezone Client
```[tasklist]
- [x] Log the log filter maybe
- [x] Use `atomicwrites` to write the file
- [x] (cancelled) ~~Make the GUI write the file on boot if it's not there (saves a step when upgrading from older versions)~~
- [x] Windows smoke test
- [x] Fix permissions on `/var/lib/dev.firezone.client/config`
- [x] Fix Linux IPC service not loading the log filter file
- [x] Linux smoke test
- [ ] Make sure it's okay that users in `firezone-client` can change the device ID
- [ ] Update user guides to include restarting the computer or IPC service after updating the log level?
```
---------
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Closes#4765
It turns out that if I don't join the worker thread explicitly it messes
up wintun a lot. I wonder if I should report that as a bug or what. It's
kind of our fault for keeping a handle to the `Session` alive in the
thread.
```[tasklist]
- [x] Move the debug command from `gui-client` to `headless-client`
- [x] Move the initialization out of `firezone-tunnel`, revert the `pub` changes, use `anyhow::Context`
```
---------
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
Bumps [tokio-tungstenite](https://github.com/snapview/tokio-tungstenite)
from 0.21.0 to 0.23.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/snapview/tokio-tungstenite/blob/master/CHANGELOG.md">tokio-tungstenite's
changelog</a>.</em></p>
<blockquote>
<h1>0.23.0</h1>
<ul>
<li>Update <code>tungstenite</code> to <code>0.23.0</code>.</li>
<li>Disable default features on TLS crates.</li>
</ul>
<h1>0.22.0</h1>
<ul>
<li>Update TLS dependencies.</li>
<li><del>Update <code>tungstenite</code> to match
<code>0.22.0</code>.</del></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/snapview/tokio-tungstenite/commits">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gabi <gabrielalejandro7@gmail.com>
It turns out they were all unused, but I like having a place to keep
them for new features.
---------
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Some of the debug-assertions in the relay are a bit too strict.
Specifically, if an allocation times out because it is not refreshed, we
also clean-up all channel bindings associated with that allocation. Yet,
if an existing channel binding has already been removed earlier, it will
no longer be present in the respective map.
This isn't an issue at all. We can simply change the debug-assertion to
only compare what used to be present in the map. What really matters is
that the item we just removed does in fact point to the data that we are
expecting.
Related: #5355.
When creating the `Transition` strategy, we are currently repeating the
same pattern again and again: We want to conditionally add a strategy if
one or more parts of our state are not empty.
We reduce this duplication with a custom `CompositeStrategy` that offers
a `with_if_not_empty` chainable method to only construct a strategy if
the given input element is not empty.
To make this usable across several usecases, we define an `IsEmpty`
helper trait that is implemented for `Vec`s, `Option`s and tuples.
If we end up sampling filters that don't have any gaps, we cannot create
filters for all the gaps. Thus, we need to shortcut this strategy to
create an empty set of filters in case we don't have any gaps.
Fixes: #5345.
Currently, we use `sample::Index` and `sample::Selector` to
deterministically select parts of our state. Originally, this was done
because I did not yet fully understand, how `proptest-state-machine`
works.
The available transitions are always sampled from the current state,
meaning we can directly use `sample::select` to pick an element like an
IP address from a list. This has several advantages:
- The transitions are more readable when debug-printed because they now
contain the actual data that is being used.
- I _think_ this results in better shrinking because `sample::select`
will perform a binary search for the problematic value.
- We can more easily implement transitions that _remove_ state.
Currently, we cannot remove things from the `ReferenceState` because the
system-under-test would also have to index into the `ReferenceState` as
part of executing its transition. By directly embedding all necessary
information in the transition, this is much simpler.
Previously, we asserted at the end of `TunnelTest::apply`.
`proptest-state-machine` offers a dedicated function for checking
invariants which only gives you a regular reference. That is a good
thing to enforce as we don't want our assertions to change state.
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.14.0 to 20.14.2.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Reading through more of the `proptest` library, I came across the
`Selector` concept. It is more generic than the `sample::Index` and
allows us to directly pick from anything that is an `IntoIterator`.
This greatly simplifies a lot of the code in `tunnel_test`. In order
(pun intended) to make things deterministic, we migrate all maps and
sets to `BTreeMap`s and `BTreeSets` which have a deterministic ordering
of their contents, thus avoiding additional sorting.
Detecting blocked STUN traffic is somewhat tricky. What we can observe
is not receiving any responses from a relay (neither on IPv4 nor IPv6).
Once an `Allocation` gives up retrying requests with a relay (after
60s), we now de-allocate the `Allocation` and print the following
message:
> INFO snownet::node: Disconnecting from relay; no response received. Is
STUN blocked? id=613f68ac-483e-4e9d-bf87-457fd7223bf6
I chose to go with the wording of "disconnecting from relay" as
sysdamins likely don't have any clue of what an "Allocation" is. The
error message is specific to a relay though so it could also be emitted
if a relay is down for > 60s or not responding for whatever reason.
Resolves: #5281.
Bumps [crash-handler](https://github.com/EmbarkStudios/crash-handling)
from 0.6.1 to 0.6.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/EmbarkStudios/crash-handling/releases">crash-handler's
releases</a>.</em></p>
<blockquote>
<h2>crash-handler-0.6.2</h2>
<h3>Added</h3>
<ul>
<li><a
href="https://redirect.github.com/EmbarkStudios/crash-handling/pull/86">PR#86</a>
(carrying on from <a
href="https://redirect.github.com/EmbarkStudios/crash-handling/pull/85">PR#85</a>)
added support for <a
href="https://learn.microsoft.com/en-us/windows/win32/debug/vectored-exception-handling">vectored
exception handlers</a> on Windows, which can catch heap corruption
exceptions that the vanilla exception handler cannot catch. Thanks <a
href="https://github.com/h3r2tic">Tom!</a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="45a469c86e"><code>45a469c</code></a>
chore: Release</li>
<li><a
href="d4d6f25cce"><code>d4d6f25</code></a>
chore: Release</li>
<li><a
href="7818928239"><code>7818928</code></a>
Update CHANGELOGs</li>
<li><a
href="e524a897c2"><code>e524a89</code></a>
Add heap corruption exception handling (<a
href="https://redirect.github.com/EmbarkStudios/crash-handling/issues/86">#86</a>)</li>
<li><a
href="065f3dd9c1"><code>065f3dd</code></a>
chore: Release</li>
<li><a
href="37e56acd3f"><code>37e56ac</code></a>
Update (<a
href="https://redirect.github.com/EmbarkStudios/crash-handling/issues/83">#83</a>)</li>
<li><a
href="3b77c9b00d"><code>3b77c9b</code></a>
chore: Release</li>
<li>See full diff in <a
href="https://github.com/EmbarkStudios/crash-handling/compare/crash-handler-0.6.1...crash-handler-0.6.2">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the npm_and_yarn group in /rust/gui-client with 1 update:
[braces](https://github.com/micromatch/braces).
Updates `braces` from 3.0.2 to 3.0.3
<details>
<summary>Commits</summary>
<ul>
<li><a
href="74b2db2938"><code>74b2db2</code></a>
3.0.3</li>
<li><a
href="88f1429a0f"><code>88f1429</code></a>
update eslint. lint, fix unit tests.</li>
<li><a
href="415d660c30"><code>415d660</code></a>
Snyk js braces 6838727 (<a
href="https://redirect.github.com/micromatch/braces/issues/40">#40</a>)</li>
<li><a
href="190510f79d"><code>190510f</code></a>
fix tests, skip 1 test in test/braces.expand</li>
<li><a
href="716eb9f12d"><code>716eb9f</code></a>
readme bump</li>
<li><a
href="a5851e57f4"><code>a5851e5</code></a>
Merge pull request <a
href="https://redirect.github.com/micromatch/braces/issues/37">#37</a>
from coderaiser/fix/vulnerability</li>
<li><a
href="2092bd1fb1"><code>2092bd1</code></a>
feature: braces: add maxSymbols (<a
href="https://github.com/micromatch/braces/issues/">https://github.com/micromatch/braces/issues/</a>...</li>
<li><a
href="9f5b4cf473"><code>9f5b4cf</code></a>
fix: vulnerability (<a
href="https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727">https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727</a>)</li>
<li><a
href="98414f9f1f"><code>98414f9</code></a>
remove funding file</li>
<li><a
href="665ab5d561"><code>665ab5d</code></a>
update keepEscaping doc (<a
href="https://redirect.github.com/micromatch/braces/issues/27">#27</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/micromatch/braces/compare/3.0.2...3.0.3">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/firezone/firezone/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
The implementation of `tunnel_test` has grown substantially in the last
couple of weeks (> 2500 LoC). To make things easier to manage, we split
it up into multiple modules:
- `assertions`: Houses the actual assertions of the test.
- `reference:` The reference implementation of connlib. Used to as the
"expectation" for the assertions.
- `sut`: A wrapper around connlib itself, acting as the
system-under-test (SUT).
- `transition`: All state transitions that the test might go through.
- `strategies`: Auxiliary strategies used in multiple places.
- `sim_*`: Wrappers for simulating various parts in the code: Clients,
relays, gateways & the portal.
I chose to place strategies into the same modules as where things are
defined. For example, the `sim_node_prototype` strategy is defined in
the `sim_node` module. Similarly, the strategies for the individual
transitions are also defined in the `transition` module.
Currently, there is a bug in `snownet` where we accidentally invalidate
a srflx candidate because we try and look for the nominated candidate
based on the nominated address. The nominated address represents the
socket that the application should send from:
- For host candidates, this is the host candidate's address itself.
- For server-reflexive candidates, it is their base (which is equivalent
to the host candidate)
- For relay candidates, it is the address of the allocation.
Because of the ambiguity between host and server-reflexive candidates,
we invalidate the server-reflexive candidate locally, send that to the
remote and the remote as a result kills the connection because it thinks
it should no longer talk to this address.
To fix this, we don't add server-reflexive candidates to the local agent
anymore. Only the remote peer needs to know about the server-reflexive
address in order to send packets _to_ it. By sending from the host
candidate, we automatically send "from" the server-reflexive address.
Not adding these server-reflexive candidates has an additional impact.
To make the tests pass reliably, I am entirely removing the invalidation
of candidates after the connection setup, as keeping that fails
connections early in the roaming test. This will increase background
traffic a bit but that seems like an okay trade-off to get more
resilient connections (the current bug is only caused by us trying to be
clever in how many candidate pairs we keep alive). We still use the
messages for invalidating candidates on the remote to make roaming work
reasonably smoothly.
Resolves: #5276.
In production, the portal will signal disconnected relays to both the
client and the gateway. We should mimic this in the tests.
In #5283, we remove invalidation of candidates during the connection
setup which breaks this roaming test due to "unhandled messages". We
could ignore those but I'd prefer to setup the test such that we panic
on unhandled messages instead and thus, this seems to be the better fix.
- Removes version numbers from infra components (elixir/relay)
- Removes version bumping from Rust workspace members that don't get
published
- Splits release publishing into `gateway-`, `headless-client-`, and
`gui-client-`
- Removes auto-deploying new infrastructure when a release is published.
Use the Deploy Production workflow instead.
Fixes#4397
Currently, we simply drop a DNS query if we can't fulfill it. Because
DNS is based on UDP which is unreliable, a downstream system will
re-send a DNS query if it doesn't receive an answer within a certain
timeout window.
Instead of dropping queries, we now reply with `SERVFAIL`, indicating to
the client that we can't fulfill that DNS query. The intent is that this
will stop any kind of automated retry-loop and surface an error to the
user.
Related: #4800.
---------
Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Currently, the same proxy IP can only ever point to one DNS record.
Proxy IPs are given out on a per-connection basis. As a result, if two
or more domains resolve to the same IP on the same gateway, previous
entries to this domain are lost and return an empty record as a result.
To fix this issue, we now store the set of resources that resolves to
this proxy IP instead of just a single resource. An invariant we have to
maintain here is that all of these resources must point to the same
gateway. This should always be true because proxy IPs are assigned
sequentially across all connections and thus the same IP can always
point back to the same proxy IP on the same gateway.
Fixes: #5259.
---------
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
Closes#3567 (again)
Closes#5214
Ready for review
```[tasklist]
### Before merging
- [x] The IPC service should report system uptime when it starts. This will tell us whether the computer was rebooted or just the IPC service itself was upgraded / rebooted.
- [x] The IPC service should report the PID of itself and the GUI if possible
- [x] The GUI should report the PID of the IPC service if possible
- [x] Extra logging between `GIT_VERSION = ` and the token loading log line, especially right before and right after the critical Tauri launching step
- [x] If a 2nd GUI or IPC service runs and exits due to single-instance, it must log that
- [x] Remove redundant DNS deactivation when IPC service starts (I think conectado noticed this in another PR)
- [x] Manually test that the GUI logs something on clean shutdown
- [x] Logarithmic heartbeat?
- [x] If possible, log monotonic time somewhere so NTP syncs don't make the logs unreadable (uptime in the heartbeat should be monotonic, mostly)
- [x] Apply the same logging fix to the IPC service
- [x] Ensure log zips include GUI crash dumps
- [x] ~~Fix #5042~~ (that's a separate issue, I don't want to drag this PR out)
- [x] Test IPC service restart (logs as a stop event)
- [x] Test IPC service stop
- [x] Test IPC service logs during system suspend (Not logged, maybe because we aren't subscribed to power events)
- [x] Test IPC service logs during system reboot (Logged as shutdown, we exit gracefully)
- [x] Test IPC service logs during system shut down (Logged as a suspend)
- [x] Test IPC service upgrade (Logged as a stop)
- [x] Log unhandled events from the Windows service controller (Power events like suspend and resume are logged and not handled)
```
---------
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
In case a configured DNS server is also a CIDR resource, DNS queries
will be routed through the tunnel to the gateway. For this to work
correctly, the destination of the request and the source of the response
need to be mangled back to the originally configured DNS server.
Currently, this mangling happens in the connection-specific
`GatewayOnClient` state. More specifically, the state that we need to
track are the IDs of the DNS queries that we actually mangled. This
state isn't connection-specific and can thus be moved out of
`GatewayOnClient` into `ClientState`.
Removing this state is important because we will soon (#5080) implement
roaming the client by simply dropping all connections and establishing
new connections as the packets are flowing in. For this, we must store
as little state as possible associated with each connection.
Resolves: #5079.
In #5207, I already added logs for which assertions we are performing on
ICMP packets. This PR does the same thing for the DNS queries that are
being to connlib. It also adds spans that add some more context to the
messages.
Here is an excerpt of what this looks like:
```
Applying transition 19/19: SendICMPPacketToResource { idx: Index(3210705382108961150), seq: 57053, identifier: 28234, src: TunnelIp6 }
2024-06-05T07:06:30.742455Z INFO assertions: ✅ Performed the expected 2 ICMP handshakes
2024-06-05T07:06:30.742459Z INFO icmp{seq=15543 identifier=63125}: assertions: ✅ dst IP of request matches src IP of response: 3fb8:a7b0:c912:a648:6c9:7910:92dc:8db
2024-06-05T07:06:30.742461Z INFO icmp{seq=15543 identifier=63125}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742464Z INFO icmp{seq=15543 identifier=63125}: assertions: ✅ 3fb8:a7b0:c912:a648:6c9:7910:92dc:8db is the correct resource
2024-06-05T07:06:30.742467Z INFO icmp{seq=57053 identifier=28234}: assertions: ✅ dst IP of request matches src IP of response: 3fb8:a7b0:c912:a648:6c9:7910:92dc:8d8
2024-06-05T07:06:30.742470Z INFO icmp{seq=57053 identifier=28234}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742473Z INFO icmp{seq=57053 identifier=28234}: assertions: ✅ 3fb8:a7b0:c912:a648:6c9:7910:92dc:8d8 is the correct resource
2024-06-05T07:06:30.742477Z INFO dns{query_id=58256}: assertions: ✅ dst IP of request matches src IP of response: fd00:2021:1111:8000:100:100:111:0
2024-06-05T07:06:30.742480Z INFO dns{query_id=58256}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742483Z INFO dns{query_id=58256}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742485Z INFO dns{query_id=58256}: assertions: ✅ src port of request matches dst port of response: 9999
2024-06-05T07:06:30.742488Z INFO dns{query_id=22568}: assertions: ✅ dst IP of request matches src IP of response: 100.100.111.1
2024-06-05T07:06:30.742491Z INFO dns{query_id=22568}: assertions: ✅ src IP of request matches dst IP of response: 100.75.34.66
2024-06-05T07:06:30.742494Z INFO dns{query_id=22568}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742497Z INFO dns{query_id=22568}: assertions: ✅ src port of request matches dst port of response: 9999
2024-06-05T07:06:30.742500Z INFO dns{query_id=58735}: assertions: ✅ dst IP of request matches src IP of response: fd00:2021:1111:8000:100:100:111:2
2024-06-05T07:06:30.742502Z INFO dns{query_id=58735}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742505Z INFO dns{query_id=58735}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742507Z INFO dns{query_id=58735}: assertions: ✅ src port of request matches dst port of response: 9999
2024-06-05T07:06:30.742512Z INFO dns{query_id=59096}: assertions: ✅ dst IP of request matches src IP of response: fd00:2021:1111:8000:100:100:111:1
2024-06-05T07:06:30.742514Z INFO dns{query_id=59096}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742517Z INFO dns{query_id=59096}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742519Z INFO dns{query_id=59096}: assertions: ✅ src port of request matches dst port of response: 9999
2024-06-05T07:06:30.742522Z INFO dns{query_id=41570}: assertions: ✅ dst IP of request matches src IP of response: fd00:2021:1111:8000:100:100:111:1
2024-06-05T07:06:30.742525Z INFO dns{query_id=41570}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742527Z INFO dns{query_id=41570}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742530Z INFO dns{query_id=41570}: assertions: ✅ src port of request matches dst port of response: 9999
2024-06-05T07:06:30.742533Z INFO dns{query_id=15028}: assertions: ✅ dst IP of request matches src IP of response: fd00:2021:1111:8000:100:100:111:1
2024-06-05T07:06:30.742536Z INFO dns{query_id=15028}: assertions: ✅ src IP of request matches dst IP of response: fd00:2021:1111::a:3531
2024-06-05T07:06:30.742538Z INFO dns{query_id=15028}: assertions: ✅ dst port of request matches src port of response: 53
2024-06-05T07:06:30.742541Z INFO dns{query_id=15028}: assertions: ✅ src port of request matches dst port of response: 9999
```
It is a bit repetitive because all assertions always run on all state
transition. Nevertheless I've found it useful to be able to look at the
assertions and visually verify that they make sense.
To make proptests efficient, it is important to generate the set of
possible test cases algorithmically instead of filtering through
randomly generated values.
This PR makes the strategies for upstream DNS servers and IP networks
more efficient by removing the filtering.
With #5049, we will allocate a fixed set of 4 IPs per DNS resource on
the client. In order to ensure that this always works correctly,
increase the number of resolved IPs to at most 6.
This may have been needed when the logger rolled files and uploaded, but
now it compiles fine without it.
I tested it once manually on Windows. I don't think the logging is
covered by automated tests.
In case an upstream DNS server is a resource, we need to not only send
an ICMP packet through the tunnel but also DNS queries. These can be
larger than 200 bytes which currently breaks the test because we only
give it a buffer of 200 bytes.
Closes#5143
The initial half-second backoff should typically be enough, and if the
user is manually re-opening the GUI after a GUI crash, I don't think
they'll notice. If they do, they can open the GUI again and it should
all work.
Most of these were in `known_dirs.rs` because it's platform-specific and
`cargo-mutants` wasn't ignoring other platforms correctly.
Using `cargo mutants -p firezone-gui-client -p firezone-headless-client`
176 / 236 mutants missed before
155 / 206 mutants missed after