mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
d0d4faad65aeb6b5f5d037cef14a0b7059a14e95
2926 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d0d4faad65 |
build(deps): bump zbus from 5.11.0 to 5.12.0 in /rust (#10959)
Bumps [zbus](https://github.com/z-galaxy/zbus) from 5.11.0 to 5.12.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/z-galaxy/zbus/releases">zbus's releases</a>.</em></p> <blockquote> <h2>🔖 zbus 5.12.0</h2> <ul> <li>🚚 Update name of Github space from <code>dbus2</code> to <code>z-galaxy</code>.</li> <li>✨ Add <code>Error::description</code> method. This gives a simple description about the error.</li> <li>🥅 Provide description for zbus::Error in DBusError. <a href="https://redirect.github.com/z-galaxy/zbus/issues/1523">#1523</a></li> <li>🐛 Remove minimum amount of required address options. Set the minimum amount of address options to 0, as per the spec. <a href="https://redirect.github.com/z-galaxy/zbus/issues/1513">#1513</a></li> <li>➖ remove <code>rand</code> and replace with <code>uuid</code>. This makes <code>uuid</code> mandatory for <code>zbus</code>, and changes the <code>p2p</code> feature to enable <code>v4</code> of <code>uuid</code>.</li> <li>📝 book: Update version of zbus in the sample Cargo.toml.</li> <li>🧵 Launch a multi-threaded tokio runtime for blocking. Otherwise, any blocking calls in the application code can block our internal tasks. This is breaking our "we won't launch threads behind your back" promise a little but its only limited to blocking API and therefore worth the benefit of not unexpectedly stopping to work. <a href="https://redirect.github.com/z-galaxy/zbus/issues/1512">#1512</a></li> <li>🐛 Fix tracing span names showing as {}.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
e5a46590e0 |
build(deps): bump clap from 4.5.47 to 4.5.50 in /rust (#10960)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.47 to 4.5.50. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/clap-rs/clap/releases">clap's releases</a>.</em></p> <blockquote> <h2>v4.5.50</h2> <h2>[4.5.50] - 2025-10-20</h2> <h3>Features</h3> <ul> <li>Accept <code>Cow</code> where <code>String</code> and <code>&str</code> are accepted</li> </ul> <h2>v4.5.48</h2> <h2>[4.5.48] - 2025-09-19</h2> <h3>Documentation</h3> <ul> <li>Add a new CLI Concepts document as another way of framing clap</li> <li>Expand the <code>typed_derive</code> cookbook entry</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's changelog</a>.</em></p> <blockquote> <h2>[4.5.50] - 2025-10-20</h2> <h3>Features</h3> <ul> <li>Accept <code>Cow</code> where <code>String</code> and <code>&str</code> are accepted</li> </ul> <h2>[4.5.49] - 2025-10-13</h2> <h3>Fixes</h3> <ul> <li><em>(help)</em> Correctly wrap when ANSI escape codes are present</li> </ul> <h2>[4.5.48] - 2025-09-19</h2> <h3>Documentation</h3> <ul> <li>Add a new CLI Concepts document as another way of framing clap</li> <li>Expand the <code>typed_derive</code> cookbook entry</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
6d01fa6c70 |
ci: run more Rust tests on all platforms (#10927)
Running only the unit-tests of select crates on some platforms is problematic. We are unlikely to update this list of crates as we introduce new ones. It is a better default to run the tests of all crates on all platforms and selectively exclude the ones that can't run because they are unsupported. |
||
|
|
d70d6168e2 |
fix(connlib): use correct host for OpenDNS DoH URL (#10934)
Fixes a small typo in the hard-coded host of the OpenDNS DoH URL. |
||
|
|
7c2c78f68c | chore(connlib): improve formatting of wire::dns TRACE logs (#10935) | ||
|
|
8539f2ff2c |
refactor(gateway): update flow-logs fields in subject (#10939)
Resolves: #10928 |
||
|
|
0c5ca66f57 |
fix(connlib): override query ID of DoH response (#10931)
As per the RFC, queries to DoH servers should always set their query ID to 0. This is more cache-friendly because two queries for the same domain end up being byte-for-byte equivalent in the HTTP request. When transported over HTTP, the query ID is obsolete because the response can be unambiguously mapped back to the request already. Connlib's DoH feature zeros out the query ID in the IO layer. To correctly test this functionality, we therefore extend the test-suite to do the same and restore the original query ID before sending back the response on the original transport. This fixes a bug where all DNS queries that were forwarded to a DoH server incorrectly had their query ID set to 0. |
||
|
|
aab779e68b |
fix(connlib): signal all local candidates on upsert (#10920)
Firezone's UDP connections are designed to be idempotent. If a Client discards its "half" of the connection but the Gateway still keeps the state around, a subsequent connection setup by the Client will reuse connection state on the Gateway. To fully support this, `snownet` re-sends all its local candidates to the remote peer whenever a connection gets upserted. The current `seed_agent_with_local_candidates` function attempts to do this job but its design overlooked a crucial detail: Re-adding a candidate that the `IceAgent` already knows about is considered to be redundant. As such, the candidate is not re-signalled to the remote! The real-world consequences for this are subtle. `str0m`'s support for peer-reflexive candidate means that incoming STUN binding requests are still answered, even if they come from an address that the agent doesn't know anything about, i.e. it has never been told about that candidate. Thus, what happens right now is that when a Client re-creates a connection that is still present on the Gateway, it will start receiving STUN binding requests for candidates it doesn't know about and create peer-reflexive candidates for them. Where this does show up is in our test-suite which has fairly strict timing constraints. When we simulate the re-deploy of relays, we expect connections to be migrated to a new relay immediately. To support this, the current relay candidates are invalidated on both sides. This however only works if the current candidate is correctly recognised by the local ICE agent. Peer-reflexive candidates are created on-demand and typically only serve a placeholder-like role until we learn about the real candidate that is being used. Due to the above described behaviour of `seed_agent_with_local_candidates`, this however may not happen at all. As a result, attempting to invalidate a relay candidate fails because we don't recognise the relay candidate as we only have a peer-reflexive one. Putting all of this together, whilst not re-sending all candidates doesn't cause immediate issues for a connection, it may cause problems at a later point when we are trying to invalidate a currently active candidate to achieve a speedy failover to a new one. |
||
|
|
62a39a81d0 |
fix(connlib): index tunnelled DNS queries by source socket (#10914)
It appears that several systems (at least MacOS) may send DNS queries to the same server with the same query ID but from different source sockets. Within connlib, we operate multiple DNS servers (one for each upstream) and use the tuple of server address and query ID to remember the necessary state we need to map the response back once we have the response from the upstream server. Given the discovery that this tuple is not necessarily unique, we now need to also track the source socket that _we_ are using to send our queries in order to correctly remember, which socket we need to send the response back to. For that, we extend the layer 3 UDP and TCP clients to return us the socket they are using for each query that we queue. In very specific circumstances, this can still fail. In particular, when connlib receives an SRV or TXT query for a resource, it resolves that query in the context of the resource's site by sending it to port 53535 of the Gateway's TUN device. The Gateway listens to DNS queries on this port and resolves them using its configured system resolvers. It however only listens on a single address, meaning we may be forwarding queries from several of connlib's "servers" to a single query which again may break the uniqueness constraint if two queries with the same ID are received at the same time because we would reuse the TCP connection to the resolver running in the Gateway and thus send them from the same source port. We consider this case to be sufficiently rare and handle it by just failing the 2nd DNS query. There may be ways of resolving it but it requires a bigger refactoring of how we establish TCP connections to upstream resolvers. |
||
|
|
32df4b399a |
chore: modularize .tool-versions (#10919)
Not all tools are needed for all parts of the codebase. In order to avoid installing all tools, we create nested `.tool-versions` files that list the specific dev-tools needed for a certain part of the product. |
||
|
|
ffce55376f |
chore(connlib): add time-related tests to l3-udp-dns-client (#10913)
This module didn't have any tests yet so I generated some with Claude and trimmed them down to a meaningful set. |
||
|
|
aa4a08889b |
test(connlib): set TCP connections as connected after roaming (#10910)
TCP connections have a keep-alive mechanism and therefore will automatically trigger a new connection to a resource after roaming. We need to model this in our tests by setting the resource as connected whenever we reset the network state. |
||
|
|
ea5e734254 |
test(connlib): fix off-by-1 second error in NAT table test (#10912)
A CI failure uncovered that we have an off-by-1 second error in our NAT table test. The mapping only expires after the last packet seen + the protocol TTL, not after the first sent one + protocol TTL. --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
01e16e87d6 |
feat(connlib): support DoH (#10876)
Building on top of a series of refactors and smaller features, this PR enables connlib to send DNS queries over HTTPS to one or more configured DoH providers. A DoH server itself is addressed via a domain which first needs to be resolved before it can be contacted. The RFC recommends to perform this bootstrapping using the system DNS resolvers. For connlib, this is a bit tricky because the system resolvers may already be set to connlib's sentinel servers by the time we need to bootstrap the DoH clients. Therefore, we maintain a dedicated UDP DNS client inside connlib's `Io` component which is always configured with the latest system DNS resolvers known to connlib. The actual bootstrapping of a DoH client happens in the following cases: 1. Our TUN device configuration changes and the configured DNS servers mapping contains DoH upstreams. 2. We need to make a DNS query to a DoH server but don't have a client yet. The first case ensures we bootstrap the DoH clients as early as possible. The latter case ensures we have a self-healing behaviour in case the TCP connection to the DoH server breaks (in which case the DoH client will be de-allocated). Once the DoH client is initialized, making queries with it is a trivial act of sending an HTTP request and parsing the HTTP response. Within connlib, this now requires almost no special handling apart from a new `dns::Upstream` type that differentiates between Do53 servers (addressed by a `SocketAddr`) and DoH servers (addressed by a `Url`). Related: #10764 Related: #10788 Related: #10850 Related: #10851 Related: #10856 Related: #10857 Related: #10871 Related: #10872 Related: #10875 Related: #10881 Resolves: #10790 |
||
|
|
9b0ae92b29 |
feat(gateway): extend ICE timeout (#10887)
Currently, a `snownet` Client and Server always have the same ICE timeout configuration. This doesn't necessarily have to be the case. A Gateway cannot establish connections to a Client anyway and thus, we can have much laxer requirements on when we detect that a Client has disappeared (without saying "goodbye"). Extending the idle and default ICE timeout values should hopefully reduce the number of false-positive disconnects that users may experience where a Gateway cuts a connection because it believes the Client is gone when in reality, perhaps a few STUN packets just got lost or backed up. Changing the ICE timeout exposes a few corner-cases in how we track and use time within `snownet`. In particular, it is now obviously possible for a Gateway to still retain the connection state of a Client whilst the Client has long disconnected but now reconnects using the same ICE credentials and private key. Our proptests uncovered some state misalignment in that scenario due to some remaining time impurity within `boringtun` (see https://github.com/firezone/boringtun/pull/126 for details). In addition, our idle state transitions needed to be updated to also take into account candidate changes on both sides in order to achieve a deterministic outcome. |
||
|
|
ccee476daa |
fix(snownet): allow direct connections on port 3478 (#10907)
When a NAT between the Client and Gateway remaps the source port to 3478, it is tricky to de-multiplex that p2p traffic from the packets we receive from a relay. Currently, we handle this edge-case by dropping these packets which effectively forces a fallback to a relayed connection. Remapping onto exactly this port is likely to be quite rare in practice which is why this behaviour was implemented in the first place. We can however do better than that by remembering, which relays we have previously been connected to. That is because the problem with traffic on port 3478 isn't so much the correct handling in case it _is_ p2p traffic: We can simply check whether the IP is one of the relays we are connected to. The problem is the mis-classification as p2p traffic in case they are packets from a relay that we have disconnected from, causing a log-spam of "unknown packet". To gracefully handle this, we now remember up to 64 relay IPs that we have been connected to in the past. This ensures we can correctly classify traffic from previous relays as such and drop the packet whilst at the same time continuing processing of packets from unknown origins which likely then is p2p traffic. The effect of this is that we can now establish direct connections to peers, even if a NAT inbetween remaps their source port to 3478. To make this fix easier, we precede it with a refactoring of introducing an `Allocations` container for the map of `Allocations`. This allows us to easily track, when we remove a value from the map and then remember the relay's IPs. This came up as part of test failures in #10887. --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
35b28692de |
feat(gateway): improve state tracking of DNS resource NAT (#10868)
Right now, the state tracking within the DNS resource NAT table is pretty simple: - We map from inside to outside and back - When we see a TCP RST, we remove it immediately To improve our logs a bit and make the NAT table more robust, we extend it by: - Tracking last inbound and outbound packet - Tracking FIN and RST flags This allows us to fully observe e.g. a TCP shutdown where both parties send TCP FIN. It also allows us to remove entries that have never been confirmed after a shorter amount of time. Resolves: #10795 --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
28f0dac50a |
build(deps): bump the react group in /rust/gui-client with 5 updates (#10833)
Bumps the react group in /rust/gui-client with 5 updates: | Package | From | To | | --- | --- | --- | | [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.1.1` | `19.2.0` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.1.15` | `19.2.2` | | [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.1.1` | `19.2.0` | | [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.1.9` | `19.2.1` | | [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) | `7.9.3` | `7.9.4` | Updates `react` from 19.1.1 to 19.2.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/facebook/react/releases">react's releases</a>.</em></p> <blockquote> <h2>19.2.0 (Oct 1, 2025)</h2> <p>Below is a list of all new features, APIs, and bug fixes.</p> <p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React 19.2 release post</a> for more information.</p> <h2>New React Features</h2> <ul> <li><a href="https://react.dev/reference/react/Activity"><code><Activity></code></a>: A new API to hide and restore the UI and internal state of its children.</li> <li><a href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a> is a React Hook that lets you extract non-reactive logic into an <a href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect Event</a>.</li> <li><a href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a> (for RSCs) lets your know when the <code>cache()</code> lifetime is over.</li> <li><a href="https://react.dev/reference/developer-tooling/react-performance-tracks">React Performance tracks</a> appear on the Performance panel’s timeline in your browser developer tools</li> </ul> <h2>New React DOM Features</h2> <ul> <li>Added resume APIs for partial pre-rendering with Web Streams: <ul> <li><a href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>: to resume a prerender to a stream.</li> <li><a href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>: to resume a prerender to HTML.</li> </ul> </li> <li>Added resume APIs for partial pre-rendering with Node Streams: <ul> <li><a href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>: to resume a prerender to a stream.</li> <li><a href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>: to resume a prerender to HTML.</li> </ul> </li> <li>Updated <a href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a> APIs to return a <code>postponed</code> state that can be passed to the <code>resume</code> APIs.</li> </ul> <h2>Notable changes</h2> <ul> <li>React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <code><ViewTransition></code> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.</li> <li>Add Node Web Streams (<code>prerender</code>, <code>renderToReadableStream</code>) to server-side-rendering APIs for Node.js</li> <li>Use underscore instead of <code>:</code> IDs generated by useId</li> </ul> <h2>All Changes</h2> <h3>React</h3> <ul> <li><code><Activity /></code> was developed over many years, starting before <code>ClassComponent.setState</code> (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> and many others)</li> <li>Stringify context as "SomeContext" instead of "SomeContext.Provider" (<a href="https://github.com/kassens"><code>@kassens</code></a> <a href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li> <li>Include stack of cause of React instrumentation errors with <code>%o</code> placeholder (<a href="https://github.com/eps1lon"><code>@eps1lon</code></a> <a href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li> <li>Fix infinite <code>useDeferredValue</code> loop in popstate event (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li> <li>Fix a bug when an initial value was passed to <code>useDeferredValue</code> (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li> <li>Fix a crash when submitting forms with Client Actions (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li> <li>Hide/unhide the content of dehydrated suspense boundaries if they resuspend (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li> <li>Avoid stack overflow on wide trees during Hot Reload (<a href="https://github.com/sophiebits"><code>@sophiebits</code></a> <a href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li> <li>Improve Owner and Component stacks in various places (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a>, <a href="https://github.com/eps1lon"><code>@eps1lon</code></a>: <a href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>, <a href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>, <a href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>, <a href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li> <li>Add <code>cacheSignal</code> (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li> </ul> <h3>React DOM</h3> <ul> <li>Block on Suspensey Fonts during reveal of server-side-rendered content (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li> <li>Use underscore instead of <code>:</code> for IDs generated by <code>useId</code> (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a>, <a href="https://github.com/eps1lon"><code>@eps1lon</code></a>: <a href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>, <a href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>, <a href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li> <li>Stop warning when ARIA 1.3 attributes are used (<a href="https://github.com/Abdul-Omira"><code>@Abdul-Omira</code></a> <a href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li> <li>Allow <code>nonce</code> to be used on hoistable styles (<a href="https://github.com/Andarist"><code>@Andarist</code></a> <a href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li> <li>Warn for using a React owned node as a Container if it also has text content (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/32774">#32774</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/facebook/react/blob/main/CHANGELOG.md">react's changelog</a>.</em></p> <blockquote> <h2>19.2.0 (October 1st, 2025)</h2> <p>Below is a list of all new features, APIs, and bug fixes.</p> <p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React 19.2 release post</a> for more information.</p> <h3>New React Features</h3> <ul> <li><a href="https://react.dev/reference/react/Activity"><code><Activity></code></a>: A new API to hide and restore the UI and internal state of its children.</li> <li><a href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a> is a React Hook that lets you extract non-reactive logic into an <a href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect Event</a>.</li> <li><a href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a> (for RSCs) lets your know when the <code>cache()</code> lifetime is over.</li> <li><a href="https://react.dev/reference/dev-tools/react-performance-tracks">React Performance tracks</a> appear on the Performance panel’s timeline in your browser developer tools</li> </ul> <h3>New React DOM Features</h3> <ul> <li>Added resume APIs for partial pre-rendering with Web Streams: <ul> <li><a href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>: to resume a prerender to a stream.</li> <li><a href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>: to resume a prerender to HTML.</li> </ul> </li> <li>Added resume APIs for partial pre-rendering with Node Streams: <ul> <li><a href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>: to resume a prerender to a stream.</li> <li><a href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>: to resume a prerender to HTML.</li> </ul> </li> <li>Updated <a href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a> APIs to return a <code>postponed</code> state that can be passed to the <code>resume</code> APIs.</li> </ul> <h3>Notable changes</h3> <ul> <li>React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming <code><ViewTransition></code> Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.</li> <li>Add Node Web Streams (<code>prerender</code>, <code>renderToReadableStream</code>) to server-side-rendering APIs for Node.js</li> <li>Use underscore instead of <code>:</code> IDs generated by useId</li> </ul> <h3>All Changes</h3> <h4>React</h4> <ul> <li><code><Activity /></code> was developed over many years, starting before <code>ClassComponent.setState</code> (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> and many others)</li> <li>Stringify context as "SomeContext" instead of "SomeContext.Provider" (<a href="https://github.com/kassens"><code>@kassens</code></a> <a href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li> <li>Include stack of cause of React instrumentation errors with <code>%o</code> placeholder (<a href="https://github.com/eps1lon"><code>@eps1lon</code></a> <a href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li> <li>Fix infinite <code>useDeferredValue</code> loop in popstate event (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li> <li>Fix a bug when an initial value was passed to <code>useDeferredValue</code> (<a href="https://github.com/acdlite"><code>@acdlite</code></a> <a href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li> <li>Fix a crash when submitting forms with Client Actions (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li> <li>Hide/unhide the content of dehydrated suspense boundaries if they resuspend (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li> <li>Avoid stack overflow on wide trees during Hot Reload (<a href="https://github.com/sophiebits"><code>@sophiebits</code></a> <a href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li> <li>Improve Owner and Component stacks in various places (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a>, <a href="https://github.com/eps1lon"><code>@eps1lon</code></a>: <a href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>, <a href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>, <a href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>, <a href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li> <li>Add <code>cacheSignal</code> (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li> </ul> <h4>React DOM</h4> <ul> <li>Block on Suspensey Fonts during reveal of server-side-rendered content (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a> <a href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li> <li>Use underscore instead of <code>:</code> for IDs generated by <code>useId</code> (<a href="https://github.com/sebmarkbage"><code>@sebmarkbage</code></a>, <a href="https://github.com/eps1lon"><code>@eps1lon</code></a>: <a href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>, <a href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>, <a href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li> <li>Stop warning when ARIA 1.3 attributes are used (<a href="https://github.com/Abdul-Omira"><code>@Abdul-Omira</code></a> <a href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li> <li>Allow <code>nonce</code> to be used on hoistable styles (<a href="https://github.com/Andarist"><code>@Andarist</code></a> <a href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
f25195f6cf |
build(deps): bump roxmltree from 0.20.0 to 0.21.1 in /rust (#10827)
Bumps [roxmltree](https://github.com/RazrFalcon/roxmltree) from 0.20.0 to 0.21.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/RazrFalcon/roxmltree/blob/master/CHANGELOG.md">roxmltree's changelog</a>.</em></p> <blockquote> <h2>[0.21.1] - 2025-10-09</h2> <h3>Fixed</h3> <ul> <li>Remove implict <code>'static</code> lifetime bound on <code>EntityResolver</code> dyn trait type alias.</li> <li>Upgrade <code>EntityResolver</code> dyn trait type alias from <code>FnMut</code> to <code>Fn</code> to resolve lifetime issues.</li> </ul> <h2>[0.21.0] - 2025-10-04</h2> <h3>Added</h3> <ul> <li><code>ParsingOptions::entity_resolver</code> can be used to resolve external entities referenced via public ID and URI.</li> </ul> <h3>Changed</h3> <ul> <li><code>Node::has_attribute</code>, <code>Node::attribute</code> and <code>Node::attribute_node</code> match local names similar to how <code>Node::has_tag_name</code> works.</li> <li>Various internal performance improvements, e.g. devirtualization of token dispatch and usage of <code>memchr</code> for finding delimiters.</li> </ul> <h3>Fixed</h3> <ul> <li>Possible panic when entity resolution yields unbalanced tags.</li> <li>Quadratic runtime when merging consecutive text nodes.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
934477d1f5 |
build(deps): bump the sentry group in /rust with 2 updates (#10825)
Bumps the sentry group in /rust with 2 updates: [sentry](https://github.com/getsentry/sentry-rust) and [sentry-tracing](https://github.com/getsentry/sentry-rust). Updates `sentry` from 0.43.0 to 0.45.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/getsentry/sentry-rust/releases">sentry's releases</a>.</em></p> <blockquote> <h2>0.45.0</h2> <h3>Breaking changes</h3> <ul> <li>Add custom variant to <code>AttachmentType</code> that holds an arbitrary String. (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/916">#916</a>)</li> </ul> <h2>0.44.0</h2> <h3>Breaking changes</h3> <ul> <li>feat(log): support combined LogFilters and RecordMappings (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/914">#914</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>Breaking change: <code>sentry::integrations::log::LogFilter</code> has been changed to a <code>bitflags</code> struct.</li> <li>It's now possible to map a <code>log</code> record to multiple items in Sentry by combining multiple log filters in the filter, e.g. <code>log::Level::ERROR => LogFilter::Event | LogFilter::Log</code>.</li> <li>If using a custom <code>mapper</code> instead, it's possible to return a <code>Vec<sentry::integrations::log::RecordMapping></code> to map a <code>log</code> record to multiple items in Sentry.</li> </ul> </li> </ul> <h3>Behavioral changes</h3> <ul> <li>ref(log): send logs by default when logs feature flag is enabled (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/915">#915</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>If the <code>logs</code> feature flag is enabled, the default Sentry <code>log</code> logger now sends logs for all events at or above INFO.</li> </ul> </li> <li>ref(logs): enable logs by default if logs feature flag is used (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/910">#910</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>This changes the default value of <code>sentry::ClientOptions::enable_logs</code> to <code>true</code>.</li> <li>This simplifies the setup of Sentry structured logs by requiring users to just add the <code>log</code> feature flag to the <code>sentry</code> dependency to opt-in to sending logs.</li> <li>When the <code>log</code> feature flag is enabled, the <code>tracing</code> and <code>log</code> integrations will send structured logs to Sentry for all logs/events at or above INFO level by default.</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/getsentry/sentry-rust/blob/master/CHANGELOG.md">sentry's changelog</a>.</em></p> <blockquote> <h2>0.45.0</h2> <h3>Breaking changes</h3> <ul> <li>Add custom variant to <code>AttachmentType</code> that holds an arbitrary String. (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/916">#916</a>)</li> </ul> <h2>0.44.0</h2> <h3>Breaking changes</h3> <ul> <li>feat(log): support combined LogFilters and RecordMappings (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/914">#914</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>Breaking change: <code>sentry::integrations::log::LogFilter</code> has been changed to a <code>bitflags</code> struct.</li> <li>It's now possible to map a <code>log</code> record to multiple items in Sentry by combining multiple log filters in the filter, e.g. <code>log::Level::ERROR => LogFilter::Event | LogFilter::Log</code>.</li> <li>If using a custom <code>mapper</code> instead, it's possible to return a <code>Vec<sentry::integrations::log::RecordMapping></code> to map a <code>log</code> record to multiple items in Sentry.</li> </ul> </li> </ul> <h3>Behavioral changes</h3> <ul> <li>ref(log): send logs by default when logs feature flag is enabled (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/915">#915</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>If the <code>logs</code> feature flag is enabled, the default Sentry <code>log</code> logger now sends logs for all events at or above INFO.</li> </ul> </li> <li>ref(logs): enable logs by default if logs feature flag is used (<a href="https://redirect.github.com/getsentry/sentry-rust/pull/910">#910</a>) by <a href="https://github.com/lcian"><code>@lcian</code></a> <ul> <li>This changes the default value of <code>sentry::ClientOptions::enable_logs</code> to <code>true</code>.</li> <li>This simplifies the setup of Sentry structured logs by requiring users to just add the <code>log</code> feature flag to the <code>sentry</code> dependency to opt-in to sending logs.</li> <li>When the <code>log</code> feature flag is enabled, the <code>tracing</code> and <code>log</code> integrations will send structured logs to Sentry for all logs/events at or above INFO level by default.</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
d850185309 |
build(deps): bump the tailwind group in /rust/gui-client with 3 updates (#10832)
Bumps the tailwind group in /rust/gui-client with 3 updates: [@tailwindcss/cli](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-cli), [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) and [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss). Updates `@tailwindcss/cli` from 4.1.13 to 4.1.14 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tailwindlabs/tailwindcss/releases"><code>@tailwindcss/cli</code>'s releases</a>.</em></p> <blockquote> <h2>v4.1.14</h2> <h3>Fixed</h3> <ul> <li>Handle <code>'</code> syntax in ClojureScript when extracting classes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18888">#18888</a>)</li> <li>Handle <code>@variant</code> inside <code>@custom-variant</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18885">#18885</a>)</li> <li>Merge suggestions when using <code>@utility</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18900">#18900</a>)</li> <li>Ensure that file system watchers created when using the CLI are always cleaned up (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18905">#18905</a>)</li> <li>Do not generate <code>grid-column</code> utilities when configuring <code>grid-column-start</code> or <code>grid-column-end</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18907">#18907</a>)</li> <li>Do not generate <code>grid-row</code> utilities when configuring <code>grid-row-start</code> or <code>grid-row-end</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18907">#18907</a>)</li> <li>Prevent duplicate CSS when overwriting a static utility with a theme key (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18056">#18056</a>)</li> <li>Show Lightning CSS warnings (if any) when optimizing/minifying (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18918">#18918</a>)</li> <li>Use <code>default</code> export condition for <code>@tailwindcss/vite</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18948">#18948</a>)</li> <li>Re-throw errors from PostCSS nodes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18373">#18373</a>)</li> <li>Detect classes in markdown inline directives (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18967">#18967</a>)</li> <li>Ensure files with only <code>@theme</code> produce no output when built (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18979">#18979</a>)</li> <li>Support Maud templates when extracting classes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18988">#18988</a>)</li> <li>Upgrade: Do not migrate <code>variant = 'outline'</code> during upgrades (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18922">#18922</a>)</li> <li>Upgrade: Show version mismatch (if any) when running upgrade tool (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19028">#19028</a>)</li> <li>Upgrade: Ensure first class inside <code>className</code> is migrated (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19031">#19031</a>)</li> <li>Upgrade: Migrate classes inside <code>*ClassName</code> and <code>*Class</code> attributes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19031">#19031</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md"><code>@tailwindcss/cli</code>'s changelog</a>.</em></p> <blockquote> <h2>[4.1.14] - 2025-10-01</h2> <h3>Fixed</h3> <ul> <li>Handle <code>'</code> syntax in ClojureScript when extracting classes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18888">#18888</a>)</li> <li>Handle <code>@variant</code> inside <code>@custom-variant</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18885">#18885</a>)</li> <li>Merge suggestions when using <code>@utility</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18900">#18900</a>)</li> <li>Ensure that file system watchers created when using the CLI are always cleaned up (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18905">#18905</a>)</li> <li>Do not generate <code>grid-column</code> utilities when configuring <code>grid-column-start</code> or <code>grid-column-end</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18907">#18907</a>)</li> <li>Do not generate <code>grid-row</code> utilities when configuring <code>grid-row-start</code> or <code>grid-row-end</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18907">#18907</a>)</li> <li>Prevent duplicate CSS when overwriting a static utility with a theme key (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18056">#18056</a>)</li> <li>Show Lightning CSS warnings (if any) when optimizing/minifying (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18918">#18918</a>)</li> <li>Use <code>default</code> export condition for <code>@tailwindcss/vite</code> (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18948">#18948</a>)</li> <li>Re-throw errors from PostCSS nodes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18373">#18373</a>)</li> <li>Detect classes in markdown inline directives (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18967">#18967</a>)</li> <li>Ensure files with only <code>@theme</code> produce no output when built (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18979">#18979</a>)</li> <li>Support Maud templates when extracting classes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18988">#18988</a>)</li> <li>Upgrade: Do not migrate <code>variant = 'outline'</code> during upgrades (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/18922">#18922</a>)</li> <li>Upgrade: Show version mismatch (if any) when running upgrade tool (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19028">#19028</a>)</li> <li>Upgrade: Ensure first class inside <code>className</code> is migrated (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19031">#19031</a>)</li> <li>Upgrade: Migrate classes inside <code>*ClassName</code> and <code>*Class</code> attributes (<a href="https://redirect.github.com/tailwindlabs/tailwindcss/pull/19031">#19031</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
f90debb9fd |
build(deps): bump socket2 from 0.6.0 to 0.6.1 in /rust (#10826)
Bumps [socket2](https://github.com/rust-lang/socket2) from 0.6.0 to 0.6.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md">socket2's changelog</a>.</em></p> <blockquote> <h1>0.6.1</h1> <h2>Added</h2> <ul> <li>Added support for Windows Registered I/O (RIO) (<a href="https://redirect.github.com/rust-lang/socket2/pull/604">rust-lang/socket2#604</a>).</li> <li>Added support for <code>TCP_NOTSENT_LOWAT</code> on Linux via <code>Socket::(set_)tcp_notsent_lowat</code> (<a href="https://redirect.github.com/rust-lang/socket2/pull/611">rust-lang/socket2#611</a>).</li> <li>Added support for <code>SO_BUSY_POLL</code> on Linux via <code>Socket::set_busy_poll</code> (<a href="https://redirect.github.com/rust-lang/socket2/pull/607">rust-lang/socket2#607</a>).</li> <li><code>SockFilter::new</code> is now a const function (<a href="https://redirect.github.com/rust-lang/socket2/pull/609">rust-lang/socket2#609</a>).</li> </ul> <h2>Changed</h2> <ul> <li>Updated the windows-sys dependency to version 0.60 (<a href="https://redirect.github.com/rust-lang/socket2/pull/605">rust-lang/socket2#605</a>).</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
6e2be658b0 |
chore(gateway): log unroutable packets only on DEBUG (#10897)
Currently, the Gateway logs all kinds of errors during packet processing on WARN. Whilst it is generally good to be aware of warnings / errors, some of these scenarios are particularly noisy. For various reasons, we may not be able to route a packet arriving from the TUN device. In such cases, we now return an `UnroutablePacket` error to the event-loop which is special-cased to only log on DEBUG. It also includes the 5 tuple as variables, which should make log analysis a bit easier if we want to filter on specific parts of the 5 tuple. |
||
|
|
663f23e9fb |
fix(connlib): classify WireGuard first (#10890)
WireGuard packets can have all kinds of byte-patterns at the very front of the packet. Thus, we need to first check if a payload is a WireGuard packet before attempting to classify it as anything else. This function is currently only used for logging purposes. `snownet` has its own logic for de-multiplexing and classifying packets. |
||
|
|
7e5994b3c6 |
chore: bump to upstream proptest (#10888)
The changes from our fork have been upstreamed successfully. We can therefore switch our dependency back to that. |
||
|
|
ed6e2a4e7d |
feat(connlib): introduce DoHUrl abstraction (#10881)
When connlib processes DoH queries, we need to pass the server's URL around a lot. In order to bootstrap the HTTP client, we need to extract the host part of this URL and resolve it for IP addresses using the system resolver. A regular URL doesn't necessarily have a host: It could be relative. This creates an error path within our code that _should_ never get hit for DoH URLs as those are always absolute. To avoid this error path, we follow the "parse, don't validate" approach typical among strongly typed languages. We create our own type that can only be constructed from absolute URLs. If we receive a URL from the portal that is not absolute, we already fail at the deserialization step. Using data privacy of the encapsulated url, we can then guarantee that the host-part of the URL is always there and can access it in an infallible way. Given that we are now already parsing the URL to begin with, I've also opted to directly implement an optimisation where we create a fast-path for the 4 known DoH providers that we have which allows us to pass them around and copy them without incurring extra allocations. Finally, this custom type also comes with its own Display/Debug implementation, making the log output a bit easier to read. |
||
|
|
c523add895 |
build(deps): bump zip from 5.1.1 to 6.0.0 in /rust (#10829)
Bumps [zip](https://github.com/zip-rs/zip2) from 5.1.1 to 6.0.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/zip-rs/zip2/releases">zip's releases</a>.</em></p> <blockquote> <h2>v6.0.0</h2> <h3><!-- raw HTML omitted -->🐛 Bug Fixes</h3> <ul> <li>panic when reading empty extended-timestamp field (<a href="https://redirect.github.com/zip-rs/zip2/pull/404">#404</a>) (<a href="https://redirect.github.com/zip-rs/zip2/pull/422">#422</a>)</li> <li>Restore original file timestamp when unzipping with <code>chrono</code> (<a href="https://redirect.github.com/zip-rs/zip2/pull/46">#46</a>)</li> </ul> <h3><!-- raw HTML omitted -->⚙️ Miscellaneous Tasks</h3> <ul> <li>Configure Amazon Q rules (<a href="https://redirect.github.com/zip-rs/zip2/pull/421">#421</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md">zip's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/zip-rs/zip2/compare/v5.1.1...v6.0.0">6.0.0</a> - 2025-10-09</h2> <h3><!-- raw HTML omitted -->🚀 Features</h3> <ul> <li>Add by_index_with_options(), which can be used to ignore encryption in a file's metadata (<a href="https://redirect.github.com/zip-rs/zip2/pull/439">#439</a>) and may be used for other file-specific overrides in the future.</li> </ul> <h3><!-- raw HTML omitted -->⚙️ Miscellaneous Tasks</h3> <ul> <li>[<strong>breaking</strong>] <code>FileOptions::add_extra_data</code> is now generic and accepts any <code>AsRef<[u8]></code>. (<a href="https://redirect.github.com/zip-rs/zip2/issues/435">#435</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
95fdb7f62a |
fix(connlib): sanitize resolvers before re-resolving portal URL (#10880)
In #10817, connlib gained the ability to re-resolve the portal's hostname on WebSocket connection hiccups. The list of upstream servers used for that may contain sentinel DNS server IPs on certain systems if connlib's DNS control is currently active. Connlib filters these servers internally before computing the effective list of upstream servers. The DNS client used by the event-loop contacts all servers in the list but waits for at most 2s before merging all received records together. If there are upstream DNS servers defined in the portal and those are also resources which we are currently not connected to, querying these servers would trigger a message to the portal, forming a circular dependency. This circular dependency is only broken by the 2s timeout. Whilst not fatal for connlib's functionality, it means that in such a situation, reconnecting to the portal always has to wait for this timeout. To fix this, we first apply the system DNS resolvers to connlib and only pass the now returned sanitized list on to the DNS client. Related: #10854 --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: thomaseizinger <5486389+thomaseizinger@users.noreply.github.com> |
||
|
|
33bd31c1eb |
chore(connlib): pass through DoH servers to DNS config (#10872)
This is a follow-up to #10851. In order to be able to use and reason about the DoH servers, we need to deserialize the list and pass the servers into connlib's `DnsConfig`. Right now, they just sit there and we don't do anything with them. Thus, this PR is save to go into `main`, even if we were to make a release before our DoH support is fully finished. To ensure this is the case, we also update the proptests in this PR to randomly sample and apply DoH servers. --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> |
||
|
|
d282b641c5 |
refactor(connlib): use anyhow::Error for recursive DNS (#10871)
With the introduction of DoH, we will need a more advanced error type for recursive DNS responses. In particular, a DoH query might fail because the underlying TCP connection got closed. With #10856, the HTTP client no longer supports retries but instead needs to be recreated. In order to accurately detect this failure case, we need `anyhow`'s downcasting abilities. This PR prepares the already existing code for that by switching from `io::Error` to `anyhow::Error`. |
||
|
|
1a5c40bd75 |
refactor(connlib): extract l4-udp-dns-client (#10854)
In order to bootstrap DoH servers, we need a way of reliably resolving the domain of the DoH server to an IP address. Initially, I thought that this would be tricky to do if we have to integrate this into the Client's state machine. Whilst implementing DoH however, I realised that we can instead put this responsibility onto the IO layer of connlib. Similar to other cases, we can reuse external triggers as our retry mechanism in case of failure. In particular, we can simply issue UDP DNS queries for the DoH domain to all system-defined DNS resolvers every time we are told to send a DNS query over DoH but the corresponding client isn't initialized yet. In other words, instead of building a retry mechanism ourselves, we attempt to repair any kind of broken state once per DNS query that we receive. Performing this DNS resolution does require a bit of code. We already started to do something similar in #10817. In order to reuse that code, we extract it into a `l4-udp-dns-client` crate and slightly refactor its semantics. In particular, we now wait for the response of all upstream servers (but at most 2s) and combine the result. The resulting `UdpDnsClient` can now be used inside the Client's event-loop to re-resolve the portal URL and will also be used as part of our DoH implementation to bootstrap the connection to the DoH server. Related: #4668 |
||
|
|
ff3ff93e1a |
fix(dns-types): use base64url encoding without padding (#10875)
According to the DoH spec, the base64url encoded query must not include any padding characters. |
||
|
|
81023dbf52 |
feat(connlib): make parallel requests with HttpClient (#10856)
Our `socket-factory`-aware HttpClient is currently only able to handle a single request at a time. That is a result of the requirement that we wanted to support connections to different domains but also be able to "self-heal" those connections by establishing a new one if the current one failed. As I am learning more about how connlib's DoH support is going to work, it became apparent that we will only ever need to connect to a single domain per instance of the `HttpClient`. In addition, it is quite important to allow for concurrent requests: We don't want to process DoH queries in sequence but instead make full use of the underlying HTTP2 protocol and send multiple requests in parallel. This PR refactors the `HttpClient` (which isn't in use anywhere yet) to only support a single connection per instance. That connection is established when the instance is created. This is also conceptually easier to understand as we only manage a single connection without mutable state. Related: #4668 |
||
|
|
53113c645f |
fix(connlib): don't panic in fallible function (#10874)
Panicking - even though it is unlikely to happen here - is unnecessary because we can simply return an error instead. |
||
|
|
cd650de1f8 |
refactor: prepare client init for upstream DoH servers (#10851)
In order to support multiple different protocols of upstream DNS resolvers, we deprecate the `upstream_dns` field in the client's `init` message and introduce two new fields: - `upstream_do53` - `upstream_doh` For now, only `upstream_do53` is populated and `upstream_doh` is always empty. On the client-side, we for now only introduce the `upstream_do53` field but fall-back to `upstream_dns` if that one is empty. This makes this PR backwards-compatible with the portal version that is currently deployed in production. Thus, this PR can be merged even prior to deploying the portal. Internally, we prepare connlib's abstractions to deal with different kinds of upstreams by renaming all existing "upstream DNS" references to `upstream_do53`: DNS over port 53. That includes UDP as well as TCP DNS resolution. Resolves: #10791 --------- Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com> |
||
|
|
4bd768aed5 |
build(deps): bump @types/node from 24.5.2 to 24.7.2 in /rust/gui-client (#10834)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.5.2 to 24.7.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> |
||
|
|
8af8978ad5 |
chore(connlib): include "packet kind" in decapsulation errors (#10867)
When looking at error logs from Gateways or Clients, it can be useful to know, what kind of packet we failed to process. |
||
|
|
ee38ccc120 |
chore(connlib): log index of failed connections (#10866)
Logging the peer index of a failed connection makes it easier to correlate it with logs when we receive packets for an unknown connection. |
||
|
|
32e1c088e7 |
chore(gateway): include domain in "not allowed" log (#10863)
The resource could be a wildcard DNS resource. It is useful to know, which particular domain the client tried to access. |
||
|
|
5f61eaf8f2 |
feat(connlib): encode and decode DoH messages (#10857)
In order to support DoH, we need to be able to encode and decode DNS queries and responses from and to HTTP requests and responses. We therefore extend your `dns-types` crate with the required functionality. The [RFC8484](https://datatracker.ietf.org/doc/html/rfc8484) provides us with two test vectors that we can test against. Related: #4668 --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: thomaseizinger <5486389+thomaseizinger@users.noreply.github.com> |
||
|
|
cf14a8694c |
fix(connlib): use system DNS resolvers to re-resolve portal URL (#10853)
In #10817, we landed a fix that allows Clients to re-resolve the portal URL every time the WebSocket connection fails. Currently, we use the active upstream resolvers for this. This can lead to a kind of deadlock in case the upstream resolver is a CIDR resource that we are not yet connected to. In that case, we'd need a connection to the portal to establish a connection to the Gateway. By always using the system resolvers for this, we avoid this circular dependency. |
||
|
|
3e849ae852 |
fix(gui-client): use Wayland rendering backend on Linux (#10849)
Previously, we opted into the X11 GTK backend when rendering the GUI Client's window. This is causing issues on newer Linux distributions such as Fedora 43 where Wayland is now the only available compositor. Removing the X11 GTK requires us to draw our own CSDs such as titlebars and a close button. This PR does exactly that by adding a minimalistic title bar. To make better use of the space, we move the section headers into there. |Before|After| |---|---| |<img width="1900" height="1174" alt="Screenshot From 2025-11-11 11-14-11" src="https://github.com/user-attachments/assets/9439a69b-65ba-41d6-b1f8-4448e0f80728" />|<img width="1800" height="1000" alt="Screenshot From 2025-11-11 11-40-55" src="https://github.com/user-attachments/assets/7884b2cc-3d9c-4b47-9a1e-c6462aef36ab" />| |<img width="1900" height="1174" alt="Screenshot From 2025-11-11 11-14-16" src="https://github.com/user-attachments/assets/2cfea825-5c08-45a5-873c-5afcbc1dbf16" />|<img width="1800" height="1000" alt="Screenshot From 2025-11-11 11-40-58" src="https://github.com/user-attachments/assets/43ddd7c9-ce65-42f7-b972-28c6b172b70d" />| |<img width="1900" height="1174" alt="Screenshot From 2025-11-11 11-14-19" src="https://github.com/user-attachments/assets/446873a7-9023-4266-9377-ea7b8b4353ee" />|<img width="1800" height="1000" alt="Screenshot From 2025-11-11 11-41-01" src="https://github.com/user-attachments/assets/64439383-f33f-461d-9b4a-6b4138bd675b" />| |<img width="1900" height="1174" alt="Screenshot From 2025-11-11 11-14-22" src="https://github.com/user-attachments/assets/6c39e06c-1d77-471f-91f1-32a78b90a21c" />|<img width="1800" height="1000" alt="Screenshot From 2025-11-11 11-41-04" src="https://github.com/user-attachments/assets/b56912cb-9c85-4b5a-9295-dae6139b25c6" />| |<img width="1900" height="1174" alt="Screenshot From 2025-11-11 11-14-26" src="https://github.com/user-attachments/assets/5a5d638c-15bf-4523-8466-2e0977a03e22" />|<img width="1800" height="1000" alt="Screenshot From 2025-11-11 11-41-06" src="https://github.com/user-attachments/assets/ed169b52-ef86-4dc4-8f25-852da622eaa1" />| |
||
|
|
0008539b65 |
refactor(connlib): use dedicated UDP DNS client (#10850)
By default, DNS queries are sent over UDP by most systems. UDP is an easy to understand protocol because each packet stands by itself and at least as far as UDP is concerned, the payload is contained within a single packet. In Firezone, we receive all DNS traffic on the TUN device as IP packets. Processing the UDP packets is trivial as each query is contained within a single IP packet. For TCP, we first need to assemble the TCP stream before we can read the entire query. In case a DNS query is not for a Firezone DNS resource, we want to forward it to the specified upstream resolver, either directly from the system or - in case the specified upstream resolver is an IP resource - through the tunnel as an IP packet. Specifically, the forwarding of UDP DNS packets through the tunnel currently happens like this: IP packet -> read UDP payload -> parse DNS query -> mangle original destination IP to new upstream -> send through tunnel For TCP DNS queries, it is not quite as easy as we have to decode the incoming TCP stream first before we can parse the DNS query. Thus, when we want to then forward the query, we need to open our own TCP stream to the upstream resolver and encode the DNS query onto that stream, sending each IP packet from the TCP client through the tunnel. The difference in these designs makes several code paths in connlib hard to follow. Therefore - and despite the simplicity of DNS over UDP - we already created our own "Layer 3 UDP DNS"-client. This PR now integrates this client into the tunnel. Using this new client, we can simplify the processing of UDP DNS queries because we never have to "go back" to the original IP packet. Instead, when a DNS query needs to be forwarded to an usptream resolver through the tunnel, we simply tell the Layer 3 UDP DNS client to make a new DNS query. The processing of the resulting IP packet then happens in a different place, right next to where we also process the IP packets of the TCP DNS client. That simplifications unlocks further refactorings where we now only process DNS queries in a single place and the transport we received it over is a simple function parameter with the control flow for both of them being identical. Related: #4668 |
||
|
|
de7d3bff89 |
fix(connlib): re-resolve portal host on WS hiccup (#10817)
Currently, the DNS records for the portal's hostname are only resolved during startup. When the WebSocket connection fails, we try to reconnect but only with the IPs that we have previously resolved. If the local IP stack changed since then or the hostname now points to different IPs, we will run into the reconnect-timeout configured in `phoenix-channel`. To fix this, we re-resolve the portal's hostname every time the WebSocket connection fails. For the Gateway, this is easy as we can simply reuse the already existing `TokioResolver` provided by hickory. For the Client, we need to write our own DNS client on top of our socket factory abstraction to ensure we don't create a routing loop with the resulting DNS queries. To simplify things, we only send DNS queries over UDP. Those are not guaranteed to succeed but given that we do this on every "hiccup", we already have a retry mechanism. We use the currently configured upstream DNS servers for this. Resolves: #10238 |
||
|
|
a9058c7f55 |
build(deps): bump known-folders from 1.3.1 to 1.4.0 in /rust (#10831)
Bumps [known-folders](https://github.com/artichoke/known-folders-rs) from 1.3.1 to 1.4.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/artichoke/known-folders-rs/releases">known-folders's releases</a>.</em></p> <blockquote> <h2>v1.4.0</h2> <h2>What's Changed</h2> <ul> <li>Bump thor from 1.3.2 to 1.4.0 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/85">artichoke/known-folders-rs#85</a></li> <li>Bump rubocop from 1.77.0 to 1.79.1 in the bundler-deps group by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/86">artichoke/known-folders-rs#86</a></li> <li>Bump the gha-deps group with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/87">artichoke/known-folders-rs#87</a></li> <li>Use zizmor audit action by <a href="https://github.com/lopopolo"><code>@lopopolo</code></a> in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/88">artichoke/known-folders-rs#88</a></li> <li>Bump rubocop from 1.79.1 to 1.81.1 in the bundler-deps group by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/89">artichoke/known-folders-rs#89</a></li> <li>Bump the gha-deps group with 5 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/91">artichoke/known-folders-rs#91</a></li> <li>Relax windows-sys version requirement, prepare for v1.4.0 release by <a href="https://github.com/lopopolo"><code>@lopopolo</code></a> in <a href="https://redirect.github.com/artichoke/known-folders-rs/pull/92">artichoke/known-folders-rs#92</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/artichoke/known-folders-rs/compare/v1.3.1...v1.4.0">https://github.com/artichoke/known-folders-rs/compare/v1.3.1...v1.4.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
e9fcb20564 |
build(deps): bump nu-ansi-term from 0.50.1 to 0.50.3 in /rust (#10830)
Bumps [nu-ansi-term](https://github.com/nushell/nu-ansi-term) from 0.50.1 to 0.50.3. <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/nushell/nu-ansi-term/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> |
||
|
|
6e85638360 |
chore(connlib): silence hickory_resolver (#10848)
Logs from the `hickory_resolver` module are a bit noisy, so filter those out from our logs. |
||
|
|
5ae2707719 | chore: publish gateway 1.4.18 (#10823) | ||
|
|
3022c019e1 |
chore(connlib): set user.account_slug for Sentry logs (#10815)
By default, the Sentry SDK doesn't include custom user attributes when it sends logs. To make viewing logs easier, we add the `account_slug` attribute to all logs that are posted to Sentry. |
||
|
|
166b0d1573 |
feat(linux): compute device ID from /etc/machine-id (#10805)
All of our Linux applications have a soft-dependency on systemd. That is, in the default configuration, we expect systemd to be present on the machine. The only exception here are the docker containers for Headless Client and Gateway. For the GUI client in particular, systemd is a hard-dependency in order to control DNS on the system which we do via `systemd-resolved`. To secure the communication between the GUI client and its tunnel process, we automatically create a group called `firezone-client` to which the user gets added. All members of the group are allowed to access the unix socket which is used for IPC between the two processes. Membership in this group is also a prerequisite for accessing any of the configuration files. On the first launch of the GUI client on a Linux system, this presents a problem. For group membership changes to take the effect, the user needs to reboot. We say that in the documentation but it is unclear whether all users will read that thoroughly enough. To help the user, the GUI client checks for membership of the current user in the group and alerts the user via a dialog box if that isn't the case. This would all be fine if it would actually work. Unfortunately, that check ends up being too late in the process. If we aren't a member of the group, we cannot read the device ID and bail early, thus never reaching the check and terminating the process without any dialog box or user-visible error. We could attempt to fix this by shuffling around some of the startup init code. That is a sub-optimal solution however because it a) may get broken again in the future and b) it means we have to delay initialisation of telemetry until a much later point. Given that this is only a problem on Linux, a better solution is to simply not rely on the disk-based device ID at all. Instead, we can integrate with systemd and deterministically derive a device ID from the unique machine ID and a randomly chosen "app ID". For backwards-compatibility reasons, the disk-based device ID is still prioritised. For all new installs however, we will use the one based on `/etc/machine-id`. |