Commit Graph

7759 Commits

Author SHA1 Message Date
Jamil
e98aa82e8e fix(portal): respect gateway_group_id filter in REST API (#9840)
Fixes #9815
2025-07-11 19:12:05 +00:00
Jamil
12351e5985 ci: publish apple 1.5.4 clients (#9842) 2025-07-11 16:35:25 +00:00
Thomas Eizinger
55eaa7cdc7 test(connlib): establish real TCP connections in proptests (#9814)
With this patch, we sample a list of DNS resources on each test run and
create a "TCP service" for each of their addresses. Using this list of
resources, we then change the `SendTcpPayload` transition to
`ConnectTcp` and establish TCP connections using `smoltcp` to these
services.

For now, we don't send any data on these connections but we do set the
keep-alive interval to 5s, meaning `smoltcp` itself will keep these
connections alive. We also set the timeout to 30s and after each
transition in a test-run, we assert that all TCP sockets are still in
their expected state:

- `ESTABLISHED` for most of them.
- `CLOSED` for all sockets where we ended up sampling an IPv4 address
but the DNS resource only supports IPv6 addresses (or vice-versa). In
these cases, we use the ICMP error to sent by the Gateway to assert that
the socket is `CLOSED`. Unfortunately, `smoltcp` currently does not
handle ICMP messages for its sockets, so we have to call `abort`
ourselves.

Overall, this should assert that regardless of whether we roam networks,
switch relays or do other kind of stuff with the underlying connection,
the tunneled TCP connection stays alive.

In order to make this work, I had to tweak the timeouts when we are
on-demand refreshing allocations. This only happens in one particular
case: When we are being given new relays by the portal, we refresh all
_other_ relays to make sure they are still present. In other words, all
relays that we didn't remove and didn't just add but still had in-memory
are refreshed. This is important for cases where we are
network-partitioned from the portal whilst relays are deployed or reset
their state otherwise. Instead of the previous 8s max elapsed time of
the exponential backoff like we have it for other requests, we now only
use a single message with a 1s timeout there. With the increased ICE
timeout of 15s, a TCP connection with a 30s timeout would otherwise not
survive such an event. This is because it takes the above mentioned 8s
for us to remove a non-functioning relay, all whilst trying to establish
a new connection (which also incurs its own ICE timeout then).

With the reduced timeout on the on-demand refresh of 1s, we detect the
disappeared relay much quicker and can immediately establish a new
connection via one of the new ones. As always with reduced timeouts,
this can create false-positives if the relay doesn't reply within 1s for
some reason.

Resolves: #9531
2025-07-11 15:10:22 +00:00
Jamil
26cfab3b88 fix(portal): reply to all wal keepalives with ack (#9828)
The Postgres logical decoding protocol is lacking documentation and
unclear about keepalive behavior when `wal_sender_timeout` is set to 0
(disabled). We have it disabled so that Postgres doesn't terminate our
connection for falling too far behind.

What we failed to take into account is that on some installations,
Postgres _never_ requests an immediate reply (keepalive with the reply
now bit set) if wal_sender_timeout is disabled. This means we would
always reply with the empty message, failing to advance the position of
the LSN.

In this PR, we fix that to always respond to every keepalive message
with a standby status update to advance the LSN position.

Relevant documentation:
https://www.postgresql.org/docs/current/protocol-replication.html#PROTOCOL-REPLICATION-STANDBY-STATUS-UPDATE
2025-07-11 14:32:56 +00:00
Thomas Eizinger
520dd0aa31 feat(gateway): respond with ICMP error for filtered packets (#9816)
When defining a resource, a Firezone admin can define traffic filters to
only allow traffic on certain TCP and/or UDP ports and/or restrict
traffic on the ICMP protocol.

Presently, when a packet is filtered out on the Gateway, we simply drop
it. Dropping packets means the sending application can only react to
timeouts and has no other means on error handling. ICMP was conceived to
deal with these kind of situations. In particular, the "destination
unreachable" type has a dedicated code for filtered packets:
"Communication administratively prohibited".

Instead of just dropping the not-allowed packet, we now send back an
ICMP error with this particular code set, thus informing the sending
application that the packet did not get lost but was in fact not routed
for policy reasons.

When setting a traffic filter that does not allow TCP traffic,
attempting to `curl` such a resource now results in the following:

```
❯ sudo docker compose exec --env RUST_LOG=info -it client /bin/sh -c 'curl -v example.com'
* Host example.com:80 was resolved.
* IPv6: fd00:2021:1111:8000::, fd00:2021:1111:8000::1, fd00:2021:1111:8000::2, fd00:2021:1111:8000::3
* IPv4: 100.96.0.1, 100.96.0.2, 100.96.0.3, 100.96.0.4
*   Trying [fd00:2021:1111:8000::]:80...
* connect to fd00:2021:1111:8000:: port 80 from fd00:2021:1111::1e:7658 port 34560 failed: Permission denied
*   Trying [fd00:2021:1111:8000::1]:80...
* connect to fd00:2021:1111:8000::1 port 80 from fd00:2021:1111::1e:7658 port 34828 failed: Permission denied
*   Trying [fd00:2021:1111:8000::2]:80...
* connect to fd00:2021:1111:8000::2 port 80 from fd00:2021:1111::1e:7658 port 44314 failed: Permission denied
*   Trying [fd00:2021:1111:8000::3]:80...
* connect to fd00:2021:1111:8000::3 port 80 from fd00:2021:1111::1e:7658 port 37628 failed: Permission denied
*   Trying 100.96.0.1:80...
* connect to 100.96.0.1 port 80 from 100.66.110.26 port 53780 failed: Host is unreachable
*   Trying 100.96.0.2:80...
* connect to 100.96.0.2 port 80 from 100.66.110.26 port 60748 failed: Host is unreachable
*   Trying 100.96.0.3:80...
* connect to 100.96.0.3 port 80 from 100.66.110.26 port 38378 failed: Host is unreachable
*   Trying 100.96.0.4:80...
* connect to 100.96.0.4 port 80 from 100.66.110.26 port 49866 failed: Host is unreachable
* Failed to connect to example.com port 80 after 9 ms: Could not connect to server
* closing connection #0
curl: (7) Failed to connect to example.com port 80 after 9 ms: Could not connect to server
```
2025-07-11 13:54:41 +00:00
Thomas Eizinger
fb7d780b6f refactor(gui-client): don't hardcode IDs (#9831)
A linter I am trying out locally suggested to not hardcode HTML IDs. TIL
about React's `useId`.
2025-07-11 13:47:15 +00:00
Thomas Eizinger
06f703a0b5 feat(telemetry): log use of map-enobufs-to-wouldblock (#9829)
In order to better track, how well our `ENOBUFS` mitigation is working,
we should log the use of our feature flag to PostHog. This will give us
some stats how often this is happening. That combined with the lack of
error reports should give us good confidence in permanently enabling
this behaviour.
2025-07-11 13:32:11 +00:00
Thomas Eizinger
9c4e71a68f chore(connlib): improve error message for filtered packets (#9833)
When a packet gets filtered because we are unable to evaluate the source
protocol (i.e. TCP/UDP/ICMP), then the current error message currently
misleadingly says that the packet got filtered because the protocol is
not supported.

The truth however is that we were never able to apply the filter in the
first place. This is a subtle difference that is quite important when
debugging filtered packets. To improve this, we add an error message to
the stack here.
2025-07-11 13:24:55 +00:00
Thomas Eizinger
8e5ce66810 feat(gateway): don't apply traffic filters to ICMP errors (#9834)
Firezone uses ICMP errors to signal to client applications that e.g. a
certain IP is not reachable. This happens for example if a DNS resource
only resolves to IPv4 addresses yet the client application attempted to
use an IPv6 proxy address to connect to it.

In the presence of traffic filters for such a resource that does _not_
allow ICMP, we currently filter out these ICMP errors because - well -
ICMP traffic is not allowed! However, even in the presence of ICMP
traffic being allowed, we would fail to evaluate this filter because the
ICMP error packet is not an ICMP echo reply and therefore doesn't have
an ICMP identifier. We require this in the DNS resource NAT to identify
"connections" and NAT them correctly. The same L4 component is used to
evaluate the traffic filters.

ICMP errors are critical to many usage scenarios and algorithms like
happy-eyeballs. Dropping them usually results in weird behaviour as
client applications can then only react to timeouts.
2025-07-11 13:20:37 +00:00
Thomas Eizinger
a363f9e2fb chore: migrate service ID to hex-representation (#9836)
We aren't sending the OTEL metrics anywhere yet but it still makes sense
to also use the "newer" hex-representation of the Firezone ID here as
the service ID.
2025-07-11 12:03:50 +00:00
Jamil
cfcd5b3b8f chore(portal): track more WAL monitoring info (#9826)
When debugging WAL processing, it's helpful to know what the last
replied LSN was and when the last keepalive message was received from
postgres.
2025-07-10 18:30:34 -07:00
Jamil
080818c466 fix(portal): fix reply for remaining wal message (#9824)
Missed one reply fix from #9821
2025-07-10 21:46:05 +00:00
Jamil
fb0dd36dbc chore(portal): ignore expected libcluster issue (#9822)
Adds another expected error message to the ignore list. We have a
different (less noisy) log that will alert us if the cluster is below
threshold.
2025-07-10 21:35:18 +00:00
Thomas Eizinger
04499da11e feat(telemetry): grab env and distinct_id from Sentry session (#9801)
At present, our primary indicator as to whether telemetry is active is
whether we have a Sentry session. For our analytics events however, we
currently require passing in the Firezone ID and API url again. This
makes it difficult to send analytics events from areas of the code that
don't have this information available.

To still allow for that, we integrate the `analytics` module more
tightly with the Sentry session. This allows us to drop two parameters
from the `$identify` event and also means we now respect the
`NO_TELEMETRY` setting for these events except for `new_session`. This
event is sent regardless because it allows us to track, how many on-prem
installations of Firezone are out there.
2025-07-10 20:05:08 +00:00
Jamil
704ff9fd7a fix(portal): send empty reply for incoming wal messages (#9821)
In #9733, we changed the replies of the handle_data messages which seems
to have caused Postgres to not respect our acknowledgements sent in the
keepalive.

To fix this, we revert to sending an empty message in response to write
messages.
2025-07-10 19:50:00 +00:00
Thomas Eizinger
13c8c70750 fix(connlib): treat ENOBUFS as EWOULDBLOCK (#9798)
Socket APIs across operating systems vary in how they handle
back-pressure. In most cases, a non-blocking socket should return
`EWOULDBLOCK` when it cannot send a given datagram and would have to
block to wait for resources to free up.

It appears that macOS doesn't always behave like that. In particular, we
are seeing error logs from a few users where sending a datagram fails
with

> No buffer space available (os error 55)

Digging through `libc`, I've found that this error is known as `ENOBUFS`
[0].

There are reports on the Apple developer forum [1] that recommend
retrying when this error happens. It is however unclear as to whether it
is entirely safe to map this error to `EWOULDBLOCK`. Other non-blocking
event-loop implementations [2] appear to do that but we don't know
whether it is fully correct.

At present, Firezone's behaviour here is to drop the packet. This means
the host networking stack has to fall-back to running into a timeout and
re-send the packet. This very likely negatively impacts the UX for the
users hitting this.

In order to validate this assumption, we implement a feature-flag. This
allows us to ship this code but switch back to the old behaviour, should
it negatively impact how Firezone behaves. In particular, if the
assumption that mapping `ENOBUFS` to `EWOULDBLOCK` is safe turns out
wrong and `kqueue` does in fact not signal readiness when more buffers
are available, then we may have missing wake-ups which would lead a
further delay in datagrams being sent.

[0]:
8e6f36c6ba/src/unix/bsd/apple/mod.rs (L2998)
[1]: https://developer.apple.com/forums/thread/42334
[2]:
aac866f399/src/unix/stream.c (L820)
2025-07-10 17:51:16 +00:00
dependabot[bot]
eb6830daa2 build(deps): bump flowbite-react from 0.11.7 to 0.11.8 in /rust/gui-client in the flowbite group (#9754)
Bumps the flowbite group in /rust/gui-client with 1 update:
[flowbite-react](https://github.com/themesberg/flowbite-react/tree/HEAD/packages/ui).

Updates `flowbite-react` from 0.11.7 to 0.11.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/themesberg/flowbite-react/releases">flowbite-react's
releases</a>.</em></p>
<blockquote>
<h2>flowbite-react@0.11.8</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/themesberg/flowbite-react/pull/1579">#1579</a>
<a
href="d44648d0ab"><code>d44648d</code></a>
Thanks <a
href="https://github.com/SutuSebastian"><code>@​SutuSebastian</code></a>!
- fix(Datepicker): switch hardcoded color <code>cyan</code> -&gt;
<code>primary</code></li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Improve table pagination by <a
href="https://github.com/jfacoustic"><code>@​jfacoustic</code></a> in <a
href="https://redirect.github.com/themesberg/flowbite-react/pull/1567">themesberg/flowbite-react#1567</a></li>
<li>fix(Datepicker): switch hardcoded color <code>cyan</code> -&gt;
<code>primary</code> by <a
href="https://github.com/SutuSebastian"><code>@​SutuSebastian</code></a>
in <a
href="https://redirect.github.com/themesberg/flowbite-react/pull/1579">themesberg/flowbite-react#1579</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/jfacoustic"><code>@​jfacoustic</code></a> made
their first contribution in <a
href="https://redirect.github.com/themesberg/flowbite-react/pull/1567">themesberg/flowbite-react#1567</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/themesberg/flowbite-react/compare/flowbite-react@0.11.7...flowbite-react@0.11.8">https://github.com/themesberg/flowbite-react/compare/flowbite-react@0.11.7...flowbite-react@0.11.8</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/themesberg/flowbite-react/blob/main/packages/ui/CHANGELOG.md">flowbite-react's
changelog</a>.</em></p>
<blockquote>
<h2>0.11.8</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/themesberg/flowbite-react/pull/1579">#1579</a>
<a
href="d44648d0ab"><code>d44648d</code></a>
Thanks <a
href="https://github.com/SutuSebastian"><code>@​SutuSebastian</code></a>!
- fix(Datepicker): switch hardcoded color <code>cyan</code> -&gt;
<code>primary</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="557d2336b6"><code>557d233</code></a>
Version Packages (<a
href="https://github.com/themesberg/flowbite-react/tree/HEAD/packages/ui/issues/1580">#1580</a>)</li>
<li><a
href="d44648d0ab"><code>d44648d</code></a>
fix(Datepicker): switch hardcoded color <code>cyan</code> -&gt;
<code>primary</code> (<a
href="https://github.com/themesberg/flowbite-react/tree/HEAD/packages/ui/issues/1579">#1579</a>)</li>
<li><a
href="c6f235cc97"><code>c6f235c</code></a>
Improve table pagination (<a
href="https://github.com/themesberg/flowbite-react/tree/HEAD/packages/ui/issues/1567">#1567</a>)</li>
<li>See full diff in <a
href="https://github.com/themesberg/flowbite-react/commits/flowbite-react@0.11.8/packages/ui">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flowbite-react&package-manager=npm_and_yarn&previous-version=0.11.7&new-version=0.11.8)](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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 16:57:12 +00:00
Thomas Eizinger
7689402c50 chore(snownet): print packets of unknown format (#9818)
When receiving UDP packets that we cannot decode we log an error. In
order to identify, whether we might have bugs in our decoding logic, we
now also print the hex-encoding of the packet for further analysis on
DEBUG.
2025-07-10 15:11:54 +00:00
Thomas Eizinger
b4b50b5615 fix(gui-client): move tslink metadata (#9817)
A recent release of `tslink` now supports configuration via the
`package.metadata` table which resolved a warning about "unknown key"
that we have seeing for a while.
2025-07-10 14:54:50 +00:00
Thomas Eizinger
0c151a2a96 chore(gateway): include ID of unknown peer in error message (#9819)
This will help with diagnosing issues in Sentry.
2025-07-10 14:32:05 +00:00
Thomas Eizinger
f98fcca542 refactor(connlib): directly implement async fn (#9806)
At present, and as a result of how `connlib` evolved, we still implement
a `Poll`-based function for receiving data on our UDP socket. Ever since
we moved to dedicated threads for the UDP socket, we can directly block
on "block" on receiving datagrams and don't have to poll the socket.

This simplifies the implementation a fair bit. Additionally, it made me
reailise that we currently don't expose any errors on the UDP socket.
Likely, those will be ephemeral but it is still better than completely
silencing them.
2025-07-10 13:54:44 +00:00
Thomas Eizinger
f659ee2c00 refactor(windows): move valueName to text in .admx (#9796)
With a real AD (and not Intune), it seems the `valueName` attribute is
required for text elements.

Supersedes: #9419
Co-authored-by: Antoine Labarussias <antoinelabarussias@gmail.com>
2025-07-10 13:52:07 +00:00
Thomas Eizinger
d4ba045eec chore(gui-client): move log about existing session (#9813)
This log is misplaced within the current `try_connect` function because
that will also be called when we didn't have Internet while we tried to
first connect and then witnessed a network change (in which case the
token is cached in the `WaitingForNetwork` session state).

Thus, we move the log to the `Connect` msg handler where we shouldn't
have any existing session.
2025-07-10 13:41:23 +00:00
dependabot[bot]
32151b6b0d build(deps): bump tslink from 0.3.0 to 0.4.2 in /rust (#9485)
Bumps [tslink](https://github.com/icsmw/tslink) from 0.3.0 to 0.4.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/icsmw/tslink/blob/master/changelog.md">tslink's
changelog</a>.</em></p>
<blockquote>
<h1>0.4.2 (08.06.2025)</h1>
<h2>Changes</h2>
<ul>
<li>Migrate settings to <code>package.metadata.tslink</code></li>
</ul>
<h1>0.4.1 (08.06.2025)</h1>
<h2>Changes</h2>
<ul>
<li>Add support arrays in the context of <code>const</code></li>
</ul>
<h1>0.4.0 (08.06.2025)</h1>
<h2>Features</h2>
<ul>
<li>Add support of <code>const</code> for primitive types</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/icsmw/tslink/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tslink&package-manager=cargo&previous-version=0.3.0&new-version=0.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR 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>

> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 09:57:07 +00:00
Thomas Eizinger
55aef6ae11 chore: publish gui-client 1.5.5 (#9811) 2025-07-09 12:44:38 +00:00
Thomas Eizinger
df57e6c3da docs(website): add changelog entries (#9794)
We've not added changelog entries for several of the PRs that went in
recently. This adds some for the more user-facing changes and fixes that
we are shipping.
2025-07-08 22:36:04 +02:00
Thomas Eizinger
a87485a4e0 chore(connlib): silence EHOSTDOWN errors (#9797)
Certain UNIX systems such as macOS also use the EHOSTDOWN error to
signal that a packet cannot be sent to a certain IP. There is nothing we
can do about this error so we downgrade it from a WARN to a DEBUG like
we do for other kinds of "unreachable" errors.
2025-07-07 22:52:39 +00:00
Thomas Eizinger
237bd62b20 fix(snownet): don't generate candidates of mixed IP version (#9804)
When we shipped the feature of optimistc server-reflexive candidates, we
failed to add a check to only combine address and base such that they
are the same IP version. This is not harmful but unnecessary noise.
2025-07-07 22:47:40 +00:00
Thomas Eizinger
e5fb6adbb4 fix(connlib): always signal server-reflexive candidates (#9802)
When we create a new connection, we seed the local ICE agent with all
known local candidates, i.e. host addresses and allocations on relays.
Server-reflexive candidates are never added to the local agent because
you cannot send directly from a server-reflexive addresses. Instead, an
agent sends from the _base_ of a server-reflexive candidate which in
turn is known as a host candidate.

The server-reflexive candidate is however signaled to the remote so it
can try and send packets to it. Those will then be mapped by the NAT to
our host candidate.

In case we have just performed a network reset, our own server-reflexive
candidate may not be known yet and therefore the seeding doesn't add an
candidates. With no candidates being seeded, we also can't signal them
to the remote.

For candidates discovered later in this process, the signalling happens
as part of adding them to the local agent. Because server-reflexive
candidates are not added to the local agent, we currently miss out on
signaling those to the remote IF they weren't already present when the
ICE agent got created.

This scenario can happen right after a network reset. In practice, it
shouldn't be much of an issue though. As soon as we start sending from
our host candidate, the remote will create a peer-reflexive candidate
for it. It is however cleaner to directly send the server-reflexive
candidate once we discover it.
2025-07-07 22:46:46 +00:00
dependabot[bot]
5a5843bfa7 build(deps): bump reqwest from 0.12.20 to 0.12.22 in /rust (#9799)
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.12.20 to
0.12.22.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/seanmonstar/reqwest/releases">reqwest's
releases</a>.</em></p>
<blockquote>
<h2>v0.12.22</h2>
<h2>tl;dr</h2>
<ul>
<li>Fix socks proxies when resolving IPv6 destinations.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>fix(socks): bracket IPv6 addresses when formatting destination host
by <a href="https://github.com/0x676e67"><code>@​0x676e67</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2753">seanmonstar/reqwest#2753</a></li>
<li>Prepare v0.12.22 by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2754">seanmonstar/reqwest#2754</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seanmonstar/reqwest/compare/v0.12.21...v0.12.22">https://github.com/seanmonstar/reqwest/compare/v0.12.21...v0.12.22</a></p>
<h2>v0.12.21</h2>
<h2>tl;dr</h2>
<ul>
<li>Fix socks proxy to use <code>socks4a://</code> instead of
<code>socks4h://</code>.</li>
<li>Fix <code>Error::is_timeout()</code> to check for hyper and IO
timeouts too.</li>
<li>Fix request <code>Error</code> to again include URLs when
possible.</li>
<li>Fix socks connect error to include more context.</li>
<li>(wasm) implement <code>Default</code> for <code>Body</code>.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>chore: remove unused slab dep by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2729">seanmonstar/reqwest#2729</a></li>
<li>docs: mention requiring Tokio by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2731">seanmonstar/reqwest#2731</a></li>
<li>Fix Typos in Comments for Multipart and Redirect Tests by <a
href="https://github.com/leopardracer"><code>@​leopardracer</code></a>
in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2738">seanmonstar/reqwest#2738</a></li>
<li>fix: request errors should include url by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2741">seanmonstar/reqwest#2741</a></li>
<li>fix: consider timeout from hyper::Error by <a
href="https://github.com/flisky"><code>@​flisky</code></a> in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2742">seanmonstar/reqwest#2742</a></li>
<li>feat: add Default impl for wasm::Body by <a
href="https://github.com/jpopesculian"><code>@​jpopesculian</code></a>
in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2746">seanmonstar/reqwest#2746</a></li>
<li>fix: Fix SOCKS4a proxy protocol matching by <a
href="https://github.com/0x676e67"><code>@​0x676e67</code></a> in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2732">seanmonstar/reqwest#2732</a></li>
<li>fix: add more context and description to SOCKS errors by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2750">seanmonstar/reqwest#2750</a></li>
<li>Prepare v0.12.21 by <a
href="https://github.com/seanmonstar"><code>@​seanmonstar</code></a> in
<a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2751">seanmonstar/reqwest#2751</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/leopardracer"><code>@​leopardracer</code></a>
made their first contribution in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2738">seanmonstar/reqwest#2738</a></li>
<li><a
href="https://github.com/jpopesculian"><code>@​jpopesculian</code></a>
made their first contribution in <a
href="https://redirect.github.com/seanmonstar/reqwest/pull/2746">seanmonstar/reqwest#2746</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/seanmonstar/reqwest/compare/v0.12.20...v0.12.21">https://github.com/seanmonstar/reqwest/compare/v0.12.20...v0.12.21</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md">reqwest's
changelog</a>.</em></p>
<blockquote>
<h2>v0.12.22</h2>
<ul>
<li>Fix socks proxies when resolving IPv6 destinations.</li>
</ul>
<h2>v0.12.21</h2>
<ul>
<li>Fix socks proxy to use <code>socks4a://</code> instead of
<code>socks4h://</code>.</li>
<li>Fix <code>Error::is_timeout()</code> to check for hyper and IO
timeouts too.</li>
<li>Fix request <code>Error</code> to again include URLs when
possible.</li>
<li>Fix socks connect error to include more context.</li>
<li>(wasm) implement <code>Default</code> for <code>Body</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e6e2d8a25d"><code>e6e2d8a</code></a>
v0.12.22</li>
<li><a
href="a9ab0fae3f"><code>a9ab0fa</code></a>
fix(socks): bracket IPv6 addresses when formatting destination host (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2753">#2753</a>)</li>
<li><a
href="b739726c4a"><code>b739726</code></a>
v0.12.21</li>
<li><a
href="d9ecdc19b3"><code>d9ecdc1</code></a>
fix: add more context and description to SOCKS errors (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2750">#2750</a>)</li>
<li><a
href="d4c9eec3c2"><code>d4c9eec</code></a>
fix: look for socks4a instead of socks4h (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2732">#2732</a>)</li>
<li><a
href="d793ed2623"><code>d793ed2</code></a>
(wasm) feat: add Default impl for wasm::Body (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2746">#2746</a>)</li>
<li><a
href="4cb2866cd4"><code>4cb2866</code></a>
fix: Error::is_timeout() checks for hyper::Error::is_timeout() (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2742">#2742</a>)</li>
<li><a
href="1794d99737"><code>1794d99</code></a>
fix: request errors should include url (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2741">#2741</a>)</li>
<li><a
href="9edbd2e00b"><code>9edbd2e</code></a>
tests: fix typos in multipart and redirect tests (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2738">#2738</a>)</li>
<li><a
href="e03d6f4ec4"><code>e03d6f4</code></a>
docs: mention requiring Tokio (<a
href="https://redirect.github.com/seanmonstar/reqwest/issues/2731">#2731</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/seanmonstar/reqwest/compare/v0.12.20...v0.12.22">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=reqwest&package-manager=cargo&previous-version=0.12.20&new-version=0.12.22)](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>
2025-07-07 12:16:11 +00:00
dependabot[bot]
b3372370e8 build(deps): bump tokio from 1.45.1 to 1.46.1 in /rust (#9800)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.45.1 to 1.46.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/tokio/releases">tokio's
releases</a>.</em></p>
<blockquote>
<h2>Tokio v1.46.1</h2>
<h1>1.46.1 (July 4th, 2025)</h1>
<p>This release fixes incorrect spawn locations in runtime task hooks
for tasks spawned using <code>tokio::spawn</code> rather than
<code>Runtime::spawn</code>. This issue only effected the spawn location
in <code>TaskMeta::spawned_at</code>, and did not effect task locations
in Tracing events.</p>
<h2>Unstable</h2>
<ul>
<li>runtime: add <code>TaskMeta::spawn_location</code> tracking where a
task was spawned (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7440">#7440</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/tokio/issues/7440">#7440</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7440">tokio-rs/tokio#7440</a></p>
<h2>Tokio v1.46.0</h2>
<h1>1.46.0 (July 2nd, 2025)</h1>
<h3>Fixed</h3>
<ul>
<li>net: fixed <code>TcpStream::shutdown</code> incorrectly returning an
error on macOS (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7290">#7290</a>)</li>
</ul>
<h2>Added</h2>
<ul>
<li>sync: <code>mpsc::OwnedPermit::{same_channel,
same_channel_as_sender}</code> methods (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7389">#7389</a>)</li>
<li>macros: <code>biased</code> option for <code>join!</code> and
<code>try_join!</code>, similar to <code>select!</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7307">#7307</a>)</li>
<li>net: support for cygwin (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7393">#7393</a>)</li>
<li>net: support <code>pope::OpenOptions::read_write</code> on Android
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7426">#7426</a>)</li>
<li>net: add <code>Clone</code> implementation for
<code>net::unix::SocketAddr</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7422">#7422</a>)</li>
</ul>
<h2>Changed</h2>
<ul>
<li>runtime: eliminate unnecessary lfence while operating on
<code>queue::Local&lt;T&gt;</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7340">#7340</a>)</li>
<li>task: disallow blocking in <code>LocalSet::{poll,drop}</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7372">#7372</a>)</li>
</ul>
<h2>Unstable</h2>
<ul>
<li>runtime: add <code>TaskMeta::spawn_location</code> tracking where a
task was spawned (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7417">#7417</a>)</li>
<li>runtime: removed borrow from <code>LocalOptions</code> parameter to
<code>runtime::Builder::build_local</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7346">#7346</a>)</li>
</ul>
<h2>Documented</h2>
<ul>
<li>io: clarify behavior of seeking when <code>start_seek</code> is not
used (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7366">#7366</a>)</li>
<li>io: document cancellation safety of
<code>AsyncWriteExt::flush</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7364">#7364</a>)</li>
<li>net: fix docs for <code>recv_buffer_size</code> method (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7336">#7336</a>)</li>
<li>net: fix broken link of <code>RawFd</code> in <code>TcpSocket</code>
docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7416">#7416</a>)</li>
<li>net: update <code>AsRawFd</code> doc link to current Rust stdlib
location (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7429">#7429</a>)</li>
<li>readme: fix double period in reactor description (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7363">#7363</a>)</li>
<li>runtime: add doc note that <code>on_*_task_poll</code> is unstable
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7311">#7311</a>)</li>
<li>sync: update broadcast docs on allocation failure (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7352">#7352</a>)</li>
<li>time: add a missing panic scenario of <code>time::advance</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7394">#7394</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/tokio/issues/7290">#7290</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7290">tokio-rs/tokio#7290</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7307">#7307</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7307">tokio-rs/tokio#7307</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ab3ff69cf2"><code>ab3ff69</code></a>
chore: prepare to release v1.46.1 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7444">#7444</a>)</li>
<li><a
href="a0d5b8ab30"><code>a0d5b8a</code></a>
runtime(unstable): fix task hook spawn locations for
<code>tokio::spawn</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7440">#7440</a>)</li>
<li><a
href="a1ee3ef218"><code>a1ee3ef</code></a>
chore: fix some minor typos in the comments (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7442">#7442</a>)</li>
<li><a
href="171cd148a3"><code>171cd14</code></a>
changelog: fix typo in <code>pipe::OpenOptions</code> for 1.46.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7439">#7439</a>)</li>
<li><a
href="3f1f268583"><code>3f1f268</code></a>
chore: prepare Tokio v1.46.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7437">#7437</a>)</li>
<li><a
href="3e890cc017"><code>3e890cc</code></a>
rt(unstable): add spawn <code>Location</code> to <code>TaskMeta</code>
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7417">#7417</a>)</li>
<li><a
href="69290a6432"><code>69290a6</code></a>
net: derive <code>Clone</code> for <code>net::unix::SocketAddr</code>
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7422">#7422</a>)</li>
<li><a
href="e2b175848b"><code>e2b1758</code></a>
fuzz: cfg fuzz tests under cfg(test) (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7428">#7428</a>)</li>
<li><a
href="b7a75b5be3"><code>b7a75b5</code></a>
net: update <code>AsRawFd</code> doc link to current Rust stdlib
location (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7429">#7429</a>)</li>
<li><a
href="6b705b3053"><code>6b705b3</code></a>
net: allow <code>pipe::OpenOptions::read_write</code> on Android (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7426">#7426</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-1.45.1...tokio-1.46.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio&package-manager=cargo&previous-version=1.45.1&new-version=1.46.1)](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>
2025-07-07 12:15:23 +00:00
Thomas Eizinger
ced0579f93 fix(ci): use outcome instead of conclusion (#9792)
According to the documentation [0]:

> When a `continue-on-error step` fails, the `outcome` is `failure`, but
the final `conclusion` is `success`.

We update the action accordingly to make our retry mechanism work.

[0]:
https://docs.github.com/es/actions/reference/contexts-reference#steps-context

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
2025-07-06 08:44:31 +00:00
Jamil
b20c141759 feat(portal): add batch-insert to change logs (#9733)
Inserting a change log incurs some minor overhead for sending query over
the network and reacting to its response. In many cases, this makes up
the bulk of the actual time it takes to run the change log insert.

To reduce this overhead and avoid any kind of processing delay in the
WAL consumers, we introduce batch insert functionality with size `500`
and timeout `30` seconds. If either of those two are hit, we flush the
batch using `insert_all`.

`insert_all` does not use `Ecto.Changeset`, so we need to be a bit more
careful about the data we insert, and check the inserted LSNs to
determine what to update the acknowledged LSN pointer to.

The functionality to determine when to call the new `on_flush/1`
callback lives in the replication_connection module, but the actual
behavior of `on_flush/1` is left to the child modules to implement. The
`Events.ReplicationConnection` module does not use flush behavior, and
so does not override the defaults, which is not to use a flush
mechanism.

Related: #949
2025-07-05 19:03:28 +00:00
Thomas Eizinger
c48ed2a1a0 feat(connlib): introduce 2s grace-period upon ICE disconnect (#9793)
When Firezone detects that the user is switching networks, we perform an
internal reset where we clear all connections and also all local
candidates. As part of the reset, we then send STUN requests to our
relays to re-discover our host and server-reflexive candidates. In this
scenario, the Gateway is still connected to its network and is therefore
able to send its candidates as soon as it receives the connection intent
from the portal.

This opens us up to the following race condition which leads to a
false-positive "ICE timeout":

1. Client roams network and clears all local state.
2. Client sends STUN binding requests to relays.
3. Client initiates a new connection.
4. Gateway acknowledges connection.
5. Client creates new ICE agent and attempts to seed it with local
candidates. We don't have a response from the relays yet and therefore
don't have any local candidates.
6. Client receives remote candidates and adds them to the agent.
7. ICE agent is unable to form pairs and therefore concludes that it is
disconnected.
8. We treat the disconnected event as a connection failure and clear the
connection.
9. Relays respond to STUN binding requests but we cannot add the new
candidates to the connection because it is already cleared.

The ICE spec states that after an agent transitions into the
"disconnected" state, it may transition back to "connected" if e.g. new
candidates are added as those allow the forming of new pairs. In
general, it is recommended to not treat "disconnected" as a permanent
state. To honor this recommendation, we introduce a 2s grace-period in
which we can recover from such a "disconnected" state.
2025-07-05 18:52:59 +00:00
Jamil
4a02e89b43 ci: publish headless 1.5.1 (#9791) 2025-07-05 08:18:14 +00:00
Jamil
c869bcfe13 chore(portal): tag Relay WAL todos (#9767)
These aren't a priority to clean up right now, but I wanted to tag them
so I don't forget to do it later on.
2025-07-04 22:30:06 +00:00
Jamil
2a38c532af chore(portal): remove gateway masquerade option (#9790)
AFAIK these are ignored by connlib. Instead, we configure masquerading
on the host.
2025-07-04 21:08:11 +00:00
Thomas Eizinger
f04c23c8d9 ci: retry authentication with GCP (#9786)
At present, it appears that `actions/toolkit` has a bug where it isn't
always able to correctly fetch an ID token. See
https://github.com/actions/toolkit/issues/2098 for the upstream issue.
As a result, our CI often fails relatively often. A simple restart
usually fixes the issue. This however is annoying because it means PRs
get de-queued from the merge-queue or don't queue in the first place and
therefore require baby-sitting.

To fix this, we attempt to build a retry-mechanism from within the
action. Using `continue-on-error`, we tell the "auth" step to continue,
even if it fails. Following that, we try to authenticate again but only
if the previous one failed. We do this up to 3 times before actually
giving up.

---------

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2025-07-04 18:29:17 +00:00
Thomas Eizinger
a6796fe8b2 fix(telemetry): always use hex-encoded ID as user ID (#9781)
We are currently in the process of transitioning the Firezone Clients
away from always hashing the ID before sending it to the portal. This
will make lookups and correlation of data between our systems much
easier.

The way we are performing this migration is that new installations of
Firezone will directly generate a 64 char hex-string as the Firezone ID.
If the ID looks like a UUID (which is the old format), we still hash it
and send it to the portal, otherwise we send it as-is.

Presently, the telemetry integration with Sentry and PostHog do the
opposite. They always sets the Firezone ID as-is and includes an
`external_id` that is the hashed form if it detects that it is a UUID
(or in the case of PostHog, create an alias). It is much better to flip
this around and always set the hex-string as the user id. That way, we
can simply always filter by the `user.id` attribute in Sentry and always
refer to the ID that we are seeing in the portal.
2025-07-04 16:55:44 +00:00
Thomas Eizinger
8b001b3e8b refactor(telemetry): use atomics for feature-flags (#9783)
Feature flags may be accessed _very_ often such as on every log
statement with #9780. To make sure this is as performant as possible, we
move from an `RwLock` to atomic booleans with relaxed ordering.
2025-07-04 14:55:45 +00:00
Thomas Eizinger
ec2599d545 chore(rust): simplify stream logs feature (#9780)
Instead of conditionally enabling the `logs` feature in the Sentry
client, we always enable it and control via the `tracing` integration,
which events should get forwarded to Sentry. The feature-flag check
accesses only shared-memory and is therefore really fast.

We already re-evaluate feature flags on a timer which means this boolean
will flip over automatically and logs will be streamed to Sentry.
2025-07-04 14:51:53 +00:00
Thomas Eizinger
0617c96b69 chore(nix): follow system release channel (#9784)
In order to avoid glibc mismatches, the dev-shell started by the nix
flake should follow the system channel instead of pinning a version by
itself.
2025-07-04 14:27:53 +00:00
Thomas Eizinger
abfdda18d8 fix(gui-client): allow disabling telemetry (#9785)
Resolves: #9778
2025-07-04 14:27:28 +00:00
Thomas Eizinger
a556b39136 chore: remove duplicate labels from actionlint configuration (#9789) 2025-07-04 14:25:47 +00:00
Thomas Eizinger
cb9b087bf3 refactor(ci): reuse gcp-docker-login action (#9787)
It appears the code for authenticating with GCP is duplicated in some of
our workflows.
2025-07-04 14:06:21 +00:00
Thomas Eizinger
01e3fea0ac fix(gui-client): don't panic on existing session (#9779)
Customer hit what seems to be a rare race condition where we try to
connect whilst we already have a session. I don't know which state it is
in so I am replacing it with a WARN log to learn more about this in
Sentry in case it gets hit again.
2025-07-04 07:44:53 +00:00
Thomas Eizinger
4be8e5458a chore(telemetry): don't fmt fields from the log crate (#9774)
Those are internal to `tracing` and don't need to be formatted into the
message we send to Sentry.
2025-07-04 00:03:18 +00:00
Thomas Eizinger
e0c607dd57 chore(gui-client): remove unnecessary identify call (#9775)
It is unnecessary to call this in the GUI client because the tunnel
service will already do this _and_ supply the `account_slug` with it as
well.
2025-07-03 23:17:28 +00:00
dependabot[bot]
fc256d7e37 build(deps): bump phoenix_ecto from 4.6.4 to 4.6.5 in /elixir (#9755)
Bumps [phoenix_ecto](https://github.com/phoenixframework/phoenix_ecto)
from 4.6.4 to 4.6.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/phoenixframework/phoenix_ecto/blob/main/CHANGELOG.md">phoenix_ecto's
changelog</a>.</em></p>
<blockquote>
<h2>v4.6.5</h2>
<ul>
<li>Bug fixes
<ul>
<li>Unallow existing allowances when attempting to allow a Plug to
access a connection</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/phoenixframework/phoenix_ecto/commits/v4.6.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=phoenix_ecto&package-manager=hex&previous-version=4.6.4&new-version=4.6.5)](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>
2025-07-03 23:05:48 +00:00
Thomas Eizinger
17a1d36eae fix(gui-client): set IO error type for missing non-tunnel routes (#9777)
On Windows - in order to prevent routing loops - we resolve the best
"non-tunnel" route to a particular host for each IP address. The
resulting source IP is then used as source for packets leaving our
interface. In case the system doesn't have IPv6 connectivity or are
simply no routes available, we fail this "source IP resolver" with an IO
error.

Presently, this uses the "other" IO error type which causes this to be
logged on a WARN level in the event-loop. The IO error types
`HostUnreachable` and `NetworkUnreachable` are expected during normal
operation of Firezone and are therefore only logged on DEBUG.

By changing this IO error type, we fix the WARN log spam on Windows for
machines without IPv6 connectivity.
2025-07-03 21:45:06 +00:00