Commit Graph

345 Commits

Author SHA1 Message Date
Thomas Eizinger
424e5ac5b0 chore(connlib): update dependency after merged PR (#4066)
The linked PR got merged, so we can now depend on the upstream
repository.
2024-03-11 04:27:39 +00:00
Thomas Eizinger
51bff720ea fix(connlib): ignore certain multicast addresses (#4062)
Resolves: #3015.
Resolves: #4024.
2024-03-11 04:13:25 +00:00
Thomas Eizinger
e64189c2de feat(snownet): log duration since intent after WG handshake completes (#3991)
Preceded by some refactoring, this PR adds a log line with a very
important metric: Time since connection intent after WG handshake. This
is the equivalent of time-to-first-byte, i.e. how long the user needs to
wait to actually send their first application data after they've tried
for the firs time (and generated an intent).
2024-03-09 09:42:27 +00:00
Thomas Eizinger
fdb33674cd refactor(connlib): introduce LoginUrl component (#4048)
Currently, we are passing a lot of data into `Session::connect`. Half of
this data is only needed to construct the URL we will use to connect to
the portal. We can simplify this by extracting a dedicated `LoginUrl`
component that captures and validates this data early.

Not only does this reduce the number of parameters we pass to
`Session::connect`, it also reduces the number of failure cases we have
to deal with in `Session::connect`. Any time the session fails, we have
to call `onDisconnected` to inform the client. Thus, we should perform
as much validation as we can early on. In other words, once
`Session::connect` returns, the client should be able to expect that the
tunnel is starting.
2024-03-09 09:35:15 +00:00
Thomas Eizinger
a2f289f0b1 feat(connlib): decrease connection setup latency (#4022)
`snownet` is built in a SANS-IO way, which means it doesn't have
internal timers or IO. It is up to the upper layer to correctly check
`poll_timeout` and call `handle_timeout` as soon as that expires. _When_
we want to be called again (i.e. the result of `poll_timeout`) may
change every time `snownet`s internal state changes. This is especially
critical during the initial setup of a connection.

As we learn about our own candidates and candidates from the other
party, we form new pairs. To actually detect whether the pair is a
viable network path, we need to send a STUN request. When to send STUN
requests is controlled by time. A newly formed pair should send a STUN
request as soon as possible to minimize latency.

Previously, we did not update the timer upon which we "wake" `snownet`
using `handle_timeout`. As such, we waited unnecessarily long before
sending STUN requests to newly formed pairs. With this patch, we check
`poll_timeout` at end of the `Tunnel`'s `poll` function and immediately
call `handle_timeout` in case we need to.

Currently, `str0m` throttles updates to `handle_timeout` in 50ms blocks
which still creates some delay. With that commented out, I observed
improvements of ~0.7s for establishing new connections. Most of the
time, the 2nd ping already goes through!
2024-03-09 09:29:14 +00:00
Thomas Eizinger
ea53ae7a55 feat(snownet): timeout connections if we don't receive a candidate within 10s (#3790)
Previously, we had a dedicated timer for this within the tunnel
implementation. Now that we have control over the internals of our
connection via `snownet`, we can timeout the connection if we don't
receive a candidate from the remote within 10s.
2024-03-09 08:03:57 +00:00
Gabi
21fe85048c refactor(connlib): No longer replacing Device in the Tunnel and android fixes to Tun struct (#4012)
This PR does the following:

* Remove `Closeable` struct for andorid's tun file descriptor
* Make `add_route` and `remove_route` mutate tun device so android can
mutate file descriptor and no longer have upper layers replacing
`Device`
* Fix a bug where android closed still used file descriptor if
`add_route` and `remove_route` returned the same
2024-03-08 19:09:36 +00:00
Reactor Scram
7211e88338 feat(linux-client): generate firezone-id (device ID) automatically if it's not provided at launch (#3920)
Closes #3815 

Changes that are breaking (but these aren't in production so it should
be okay)

- Windows, renaming `device_id.json` to `firezone-id.json` to match the
rest of the code
- Linux GUI, storing the firezone-id under `/var/lib` instead of under
`$HOME`
- Linux GUI, bails out if not run with `sudo --preserve-env` by
detecting `$HOME == root` or `$USER != root`

---------

Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
2024-03-08 16:13:59 +00:00
Thomas Eizinger
998bf17891 refactor(connlib): only call onDisconnect for unrecoverable errors (#4014)
Previously, we called `onDisconnect` in two kinds of situations:

- With an error when we wanted the clients to clear the token
- Without an error when the token was still valid (i.e. after a call to
`disconnect` from the clients)

This is unnecessarily redundant. Firezone is designed to **not** have a
state of "signed in but disconnected". Thus, every time connlib calls
`disconnect`, we should clear the token and sign the user out.

At present, we only do this for errors with the control plane. Errors in
the actual tunnel are only logged and we continue trying to use the
tunnel. There are errors in the tunnel where we should also give up
(i.e. TUN device gone, fatal IO error, etc). At present, those are not
yet bubbled up but we will at some point. Once we have
https://github.com/firezone/firezone/pull/3682, it will be much easier
to create a type-safe contract that ensures we only disconnect on fatal
errors.

---------

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
Co-authored-by: ReactorScram <ReactorScram@users.noreply.github.com>
2024-03-08 02:22:48 +00:00
Jamil
c948693655 chore(deps): Fix deprecation error with chrono (#4032)
Fixes the issue in #4008
2024-03-07 18:44:54 +00:00
Thomas Eizinger
46d60da136 chore(snownet): improve logs in Allocation (#3986)
This adds a few logs that I noticed could be helpful after looking at
some logs shared by a customer. Most importantly, we now log everything
in `handle_timeout` in the scope of the relay's IP, meaning we can
differentiate them from each other.
2024-03-06 19:54:05 +00:00
Thomas Eizinger
0ed2480ac0 refactor(connlib): merge control_protocol::gateway into gateway module (#3984)
This separation doesn't really hold anymore as we already have an `impl
Tunnel` and `impl GatewayState` within `gateway.rs`. It is easier to
maintain if more gateway-specific things are in `gateway.rs`. Plus, once
we integrate the portal connection into the tunnel, we can collapse a
lot of these APIs.
2024-03-06 19:37:09 +00:00
Thomas Eizinger
2f74edd581 feat(snownet): always force a handshake when we change the socket (#3985)
Some local testing identified that we might lose the first packet if we
switch the sockets too quickly, i.e. upgrade from a relayed one to a
direct one initially. To mitigate having to wait for the wireguard
timeout here, let's force a handshake every time we switch to a new
socket.
2024-03-06 19:36:24 +00:00
Thomas Eizinger
ae6c32643f refactor(connlib): fail tunnel in case the device gets closed (#3981)
Currently, we have some duplication between client and gateway in how we
handle a closed TUN device (i.e. reading a 0-length packet). Previously,
we would just deactivate the tunnel as we can't do anything when the
device is gone. I don't think that is actually helpful. Instead, we
should fail the tunnel if the device gets closed, similar to any other
IO error on the device.\

This reduces duplication between the two eventloops.
2024-03-06 19:35:29 +00:00
Thomas Eizinger
784a34faa1 chore(connlib): move wire trace logs to Socket (#3983)
This further improves consistency in when we emit these logs.
Previously, the `wire` trace would also log packets that we failed to
send (so never actually hit the wire) and would omit packets that we
handled internally within `snownet`.

To implement this consistently, I ended up merging the two iterators for
IPv4 and IPv6 packets which is a nice addition because it means we
always empty both sockets and don't prioritize IPv4 over IPv6.
2024-03-06 19:35:09 +00:00
dependabot[bot]
26c10fb361 build(deps): Bump base64 from 0.21.7 to 0.22.0 in /rust (#3935)
Bumps [base64](https://github.com/marshallpierce/rust-base64) from
0.21.7 to 0.22.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md">base64's
changelog</a>.</em></p>
<blockquote>
<h1>0.22.0</h1>
<ul>
<li><code>DecodeSliceError::OutputSliceTooSmall</code> is now
conservative rather than precise. That is, the error will only occur if
the decoded output <em>cannot</em> fit, meaning that
<code>Engine::decode_slice</code> can now be used with exactly-sized
output slices. As part of this, <code>Engine::internal_decode</code> now
returns <code>DecodeSliceError</code> instead of
<code>DecodeError</code>, but that is not expected to affect any
external callers.</li>
<li><code>DecodeError::InvalidLength</code> now refers specifically to
the <em>number of valid symbols</em> being invalid (i.e. <code>len % 4
== 1</code>), rather than just the number of input bytes. This avoids
confusing scenarios when based on interpretation you could make a case
for either <code>InvalidLength</code> or <code>InvalidByte</code> being
appropriate.</li>
<li>Decoding is somewhat faster (5-10%)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5d70ba7576"><code>5d70ba7</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/269">#269</a>
from marshallpierce/mp/decode-precisely</li>
<li><a
href="efb6c006c7"><code>efb6c00</code></a>
Release notes</li>
<li><a
href="2b91084a31"><code>2b91084</code></a>
Add some tests to boost coverage</li>
<li><a
href="9e9c7abe65"><code>9e9c7ab</code></a>
Engine::internal_decode now returns DecodeSliceError</li>
<li><a
href="a8a60f43c5"><code>a8a60f4</code></a>
Decode main loop improvements</li>
<li><a
href="a25be0667c"><code>a25be06</code></a>
Simplify leftover output writes</li>
<li><a
href="9979cc33bb"><code>9979cc3</code></a>
Keep morsels as separate bytes</li>
<li><a
href="37670c5ec2"><code>37670c5</code></a>
Bump dev toolchain version (<a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/268">#268</a>)</li>
<li>See full diff in <a
href="https://github.com/marshallpierce/rust-base64/compare/v0.21.7...v0.22.0">compare
view</a></li>
</ul>
</details>
<br />


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

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
2024-03-06 02:29:22 +00:00
Reactor Scram
379f577291 chore(windows client): update windows and windows-implement deps (#3919)
Closes #3879 and #3902 

I re-created Cargo.lock, so it incidentally updated a bunch of other
stuff. I can revert that file if it's a problem.

Had to search a bit for the breaking changes. Found here that they
renamed `ComInterface`:
https://github.com/microsoft/windows-rs/issues/2875#issuecomment-1962332067

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 15:38:19 +00:00
Thomas Eizinger
fd78e711f0 chore(connlib): make some logs more meaningful (#3835)
Extracted out of: #3682.
2024-03-05 02:35:30 +00:00
Jamil
268e792f48 chore(ci): Use GH actions cache for Tauri builds (#3906)
Builds off #3905 and uses the GH actions cache for tauri builds in order
to get around the `crate-type` problem sccache has with Tauri apps.

Fixes #3456
2024-03-05 01:07:31 +00:00
Reactor Scram
c6c4624b66 fix: use atomicwrites to back up /etc/resolv.conf more robustly (#3828)
Part of a small yak shave for #3817

The `atomicwrites` lib uses the atomic rename trick and does correct
fsyncs for us, so if we lose power while rewriting or reverting
`/etc/resolv.conf`, it should always be in a recoverable state. (Unless
the hard drive lies about fsync, but then it's beyond our control.)

---------

Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
2024-03-04 16:16:31 +00:00
Jamil
8c59ff7aa1 refactor: Reduce log levels for production releases to avoid filling customer's… (#3899)
Tuning the logging down a bit on our production releases. Prevents
gathering data we don't need to be gathering and prevents filling up
drive space with debug logs.

refs #3618
2024-03-03 17:42:09 -08:00
dependabot[bot]
5665253ee3 build(deps): Bump tempfile from 3.10.0 to 3.10.1 in /rust (#3878)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.10.0 to
3.10.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md">tempfile's
changelog</a>.</em></p>
<blockquote>
<h2>3.10.1</h2>
<ul>
<li>Handle potential integer overflows in 32-bit systems when
seeking/truncating &quot;spooled&quot; temporary files past 4GiB
(2³²).</li>
<li>Handle a theoretical 32-bit overflow when generating a temporary
file name larger than 4GiB. Now it'll panic (on allocation failure)
rather than silently succeeding due to wraparound.</li>
</ul>
<p>Thanks to <a
href="https://github.com/stoeckmann"><code>@​stoeckmann</code></a> for
finding and fixing both of these issues.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="094c115110"><code>094c115</code></a>
chore: release 3.10.1</li>
<li><a
href="56c593477f"><code>56c5934</code></a>
Fix integer overflows and truncation (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/278">#278</a>)</li>
<li><a
href="5a949d6e75"><code>5a949d6</code></a>
chore: 2021 edition (<a
href="https://redirect.github.com/Stebalien/tempfile/issues/276">#276</a>)</li>
<li>See full diff in <a
href="https://github.com/Stebalien/tempfile/compare/v3.10.0...v3.10.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tempfile&package-manager=cargo&previous-version=3.10.0&new-version=3.10.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>
2024-03-02 14:25:28 +00:00
dependabot[bot]
74ca194b10 build(deps): Bump walkdir from 2.4.0 to 2.5.0 in /rust (#3882)
Bumps [walkdir](https://github.com/BurntSushi/walkdir) from 2.4.0 to
2.5.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4f26be4d45"><code>4f26be4</code></a>
2.5.0</li>
<li><a
href="3be5734033"><code>3be5734</code></a>
api: implement <code>FusedIterator</code></li>
<li><a
href="b0d16b759a"><code>b0d16b7</code></a>
ci: fix it</li>
<li>See full diff in <a
href="https://github.com/BurntSushi/walkdir/compare/2.4.0...2.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=walkdir&package-manager=cargo&previous-version=2.4.0&new-version=2.5.0)](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>
2024-03-01 21:03:02 +00:00
Thomas Eizinger
e9ef15dc43 feat(snownet): set wireguard keep-alive (#3829)
In my local testing, I noticed that not using the tunnel for a bit ends
up expiring the WG session which causes a new handshake if you then run
a ping or something else.

Having the keep-alive should help with not paying that extra RT that is
required for a new session,
2024-03-01 20:23:09 +00:00
Reactor Scram
789d2160de refactor(linux): make a place for reverting /etc/resolv.conf (#3822)
Makes progress towards #3817

---------

Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
2024-03-01 19:09:01 +00:00
Reactor Scram
2df2ef13ba build(connlib): suppress clippy::unnecessary_cast lint on aarch64 Linux (#3824)
This took me 5 entire minutes at least to figure out:

`c_char` is...
- i8 on aarch64 Darwin:
https://docs.rs/libc/latest/aarch64-apple-darwin/libc/type.c_char.html
- i8 on aarch64 Windows:
https://docs.rs/libc/latest/aarch64-pc-windows-msvc/libc/type.c_char.html
- i8 on x86_64 Linux: https://docs.rs/libc/latest/libc/type.c_char.html
- i8 on x86_64 Windows:
https://docs.rs/libc/latest/x86_64-pc-windows-msvc/libc/type.c_char.html
- **u8** on aarch64 Linux. Both GNU and musl:
https://docs.rs/libc/latest/aarch64-unknown-linux-gnu/libc/type.c_char.html

It is also u8 on Android aarch64, but we don't run CI on that so I guess
Clippy never hit it there.
2024-03-01 17:38:01 +00:00
Thomas Eizinger
e2cdde94b6 feat(snownet): print some basic stats for STUN overhead (#3806) 2024-02-29 22:39:10 +00:00
Andrew Dryga
bfe1fb0ff4 refactor(portal): unify format of error payloads in websocket connection (#3697)
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
2024-02-28 23:06:52 +00:00
Reactor Scram
bb4a170ca5 fix: Slow DNS lookups on (at least) Windows by updating to main of Hickory (#3799)
```[tasklist]
- [x] Maybe pick a rev for Hickory so even if Cargo.lock is rebuilt we don't advance unless we want to
- [ ] Maybe ask them politely to cut a release with this patch since it helps us
```

Tested on my Windows laptop and it reduces `nslookup` times for
resources and non-resources (can't remember which way was which) from
something like 10 and 2 seconds to 0.25 and 0.33 seconds, which is
great.

Hickory's patch got merged into main around Jan 5th but they haven't cut
a release since then, so this PR changes us to use Hickory's main branch
instead of crates.io:
https://github.com/hickory-dns/hickory-dns/issues/2081
2024-02-28 19:35:07 +00:00
Gabi
2f72e225f8 fix(connlib): update resource list on resource removal (#3796)
oops
2024-02-28 17:34:39 +00:00
Thomas Eizinger
8809c0872e feat(snownet): only keep the best possible candidate pair alive (#3792)
This took me a while to figure out but I think the solution is quite
neat. We are using ICE trickle which means there could be new candidates
at any point in time. Thus, there really is never a good time to say
"ICE is finished" and clean-up all other candidates (that is what
non-trickle ICE would want you to do:
https://datatracker.ietf.org/doc/html/rfc8445#section-8.3). But what we
can do is, upon each nomination, look at our local candidates and
invalidate all that are of the same priority or less.

For example, if we start with a connection via a relay, discard all
other relay candidates but keep the host and server-reflexive ones. If
the ICE agent then figures out a better path, it will give us a new
nomination and we can discard even more candidates.

On the other hand, if hole-punching fails, str0m will eventually give up
on certain candidate pairs because it is not receiving replies and
consider them failed.

Thus, the behaviour that we are getting with this PR is: Try all
possible candidate pairs but settle on the best possible one.

What is kind of neat is that, because we are still in ICE trickle mode,
receiving a new candidate could still upgrade existing relayed
connections to direct ones if the new candidate allows it.

The other side of this coin is that we won't have a fallback any more to
other pairs if the current one fails. In that case, we will consider the
entire connection failed, remove it and create a new one on the next
connection intent.

Resolves: #3789.
2024-02-28 16:37:16 +00:00
Thomas Eizinger
001fc806b5 refactor(connlib): replace intent timer with explicit throttling (#3778)
The reference that is specified as part of the connection intent
fulfills one particular purpose: To avoid accepting connection details
for a "stale" intent, i.e. a previous one that we sent for the same
resource.

With the move to `phoenix-channel` in #3682, we can no longer specify
the reference explicitly. Instead, sending a message to the portal gives
us an `OutboundRequestId`.

To make the transition in #3682 easier, we emulate this behaviour here
temporarily in the `ControlPlane` of the clients.
2024-02-28 01:51:51 +00:00
Thomas Eizinger
ca0839d072 feat(snownet): reduce connection setup latency (#3772)
Previously, we pretty much always lost the wireguard handshake packet,
causing us to wait for the rekey-timeout before we try again.

We can fix this by first checking that we actually have a socket that we
can send the encapsulated packet on. Additionally, we can directly force
a wireguard handshake as soon as we discover the first socket to the
remote.

This reduces the setup latency to ~3 seconds in my testing.

Resolves: #3779.
2024-02-28 00:15:17 +00:00
dependabot[bot]
beb5c3834d build(deps): Bump anyhow from 1.0.79 to 1.0.80 in /rust (#3765)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.80.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/anyhow/releases">anyhow's
releases</a>.</em></p>
<blockquote>
<h2>1.0.80</h2>
<ul>
<li>Fix unused_imports warnings when compiled by rustc 1.78</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="54437197ee"><code>5443719</code></a>
Release 1.0.80</li>
<li><a
href="dfc7bc07d4"><code>dfc7bc0</code></a>
Work around prelude redundant import warnings</li>
<li><a
href="6e4f86b48b"><code>6e4f86b</code></a>
Import from alloc not std, where possible</li>
<li><a
href="f885a133ed"><code>f885a13</code></a>
Ignore incompatible_msrv clippy false positives in test</li>
<li><a
href="fefbcbcb0b"><code>fefbcbc</code></a>
Ignore incompatible_msrv clippy lint</li>
<li><a
href="78f2d81cc7"><code>78f2d81</code></a>
Update ui test suite to nightly-2024-02-08</li>
<li><a
href="edd88d3a43"><code>edd88d3</code></a>
Update ui test suite to nightly-2024-01-31</li>
<li>See full diff in <a
href="https://github.com/dtolnay/anyhow/compare/1.0.79...1.0.80">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.79&new-version=1.0.80)](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>
2024-02-27 23:57:18 +00:00
Thomas Eizinger
e015d51c70 chore(snownet): reduce log levels (#3777)
Both of these happen quite often and aren't really of concern for
day-to-day operation. Binding a new channel is still a state change but
after using the clients for a bit, it seems that it is not an important
enough state change to actually tell the user about (which I assume will
likely log on `INFO`).

Similarly, dropping a packet because we don't have a channel happens
more often now because we've optimised, which addresses we bind channels
to.
2024-02-27 20:42:50 +00:00
Gabi
77b00b3be9 feat(connlib): support resource updates from the portal (#3754)
This PR doesn't yet provide support for the update of upstream DNS but
it does provide support for all the other resources update messages.

Should comply with the description of issue #2022 but it doesn't respond
to DNS upstream updates which is imply it should on the issue title

---------

Signed-off-by: Gabi <gabrielalejandro7@gmail.com>
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
2024-02-27 03:24:14 +00:00
Thomas Eizinger
67aeb009e9 chore: move markdown files into docs/ directory (#3773)
Apart from the LICENSE, GitHub supports detecting all of these files
also within a `docs/` directory. This includes the README!
2024-02-27 01:12:57 +00:00
Thomas Eizinger
2891481662 refactor(connlib): unify handling of IP packets (#3762)
Instead of converting back and forth between buffers,
`device_channel::Packet` and `IpPacket`, we now use the same `IpPacket`
type everywhere.
2024-02-27 01:08:35 +00:00
Gabi
5edd195320 refactor(connlib): unify peer storage (#3738)
Now that we have `&mut` access everywhere in the tunnel, the remaining
shared-memory and locks are in how we store peers. To resolve this, we
introduce a new `PeerStore` that allows us to look up peers by IP and by
ID.
2024-02-26 16:07:38 +00:00
Thomas Eizinger
220c9ee1e1 fix(connlib): correctly handle GRO (#3732)
With the use of `quinn-udp`, we are actually already using GRO for
reading packets from the UDP socket. Especially during a test like
iperf, it is thus very likely to read multiple packets from the same
peer in a single syscall. In that case, `stride` tells us how they are
split.

Without handling `stride` correctly, we would be feeding multiple
packets at once to boringtun which would (obviously) choke on it because
its checksum verification fails.

It turns out we can actually handle this quite nicely by returning an
`Iterator<Item = Received>` and decapsulating them one-by-one.
2024-02-26 03:40:09 +00:00
Thomas Eizinger
0ded6ad79d refactor(snownet): be more explicit about dispatching messages (#3741)
As part of handling an incoming packet, `snownet` has to go through
several steps:

1. The packet might be a control message from a STUN server, we handle
that first.
2. The packet might from a TURN server, which could either be a control
message or a channel-data message.
The former should be handled directly where as the latter needs to
unpacked and passed along further.
3. Once potentially unpacked, the packet could be a STUN message for an
ICE agent of one of our connections.
4. Lastly, the packet might be a wireguard payload from one of our
connections.

Previously, we handled all of that in one big function which resulted in
us sometimes "falling through" to the next branch when we didn't want
that. For example, if a message is from a TURN server's address, it MUST
be a control or channel data message but it can never be a wireguard
packet. In certain circumstances, we don't detect that though. For
example, if a channel is not yet bound, we refuse to decapsulate the
message which results in us incorrectly passing on the message to later
stages.

We refactor the handling into individual functions and explicitly signal
to the upper layer using `ControlFlow`, whether we should continue or
abort.

As an added benefit, this allows us to remove the "memory" of timed-out
control messages in `StunBinding` and `Allocation`.
2024-02-23 21:26:11 +00:00
Gabi
d16fb616d3 connlib: remove tun mutex (#3743)
extracted from #3738
2024-02-23 15:48:27 +00:00
Reactor Scram
835cd548ef chore: make rtnetlink versions explicit (#3736)
If I do `rm Cargo.lock && cargo check --all` then I get errors about
rtnetlink.


![image](https://github.com/firezone/firezone/assets/13400041/c1eeff84-d65c-403d-9b33-24e00168ba36)

Dependabot tried to update these a couple weeks ago in #3558 and it had
some conflicts, so I'm just making the old versions explicit so that
redoing the lockfile won't break anything.

This is because I got into a weird state with the new `dirs` dependency
for Linux where I removed it from Cargo.toml, but it was still in the
lockfile or something, so the program built even though it should not
have. And then when I tried to rebuild Cargo.lock I got these errors
about rtnetlink.
2024-02-22 22:32:34 +00:00
Thomas Eizinger
2264eeebc3 chore(snownet): reuse RingBuffer (#3725)
Previously, we eagerly created a channel bind message and then buffered
it if we didn't have an allocation. That resulted in some duplicated
checks once we did end up sending the message.

To avoid this, we remove the dedicated `BufferedChannelBindings` struct
and instead use the newly added `RingBuffer`. Whilst we are at it, we
also increase the number of buffered messages to avoid dropping them too
early.
2024-02-22 21:26:41 +00:00
Thomas Eizinger
c85348a25f fix(snownet): don't log addresses twice (#3711)
The `from` address is already logged as part of the `decapsulate` span
in the `Node`. The `local` address isn't that interesting thus noise
most of the time.
2024-02-22 01:10:27 +00:00
Gabi
6256d94799 fix(gateway): expire resources (#3722)
I forgot to actually call the expire resources function after the
refactor 🤦

This will be much cleaned up in a PR that I'm working on to eliminate
the `peers_by_id`/`peers_by_ip` maps.

In the mean time let's merge this asap since the gateway not expiring
resources is a security hole.
2024-02-22 00:28:17 +00:00
Thomas Eizinger
09b1d5cf2e feat(snownet): optimise which channels we bind (#3709)
Currently, we bind a lot of TURN channels on our relays because we bind
a channel to each candidate on each relay. With every node having
usually 4 relays, that results in 16 channels per connection just for
the relay candidates.

We can bring this down optimistically by first checking if the remote's
candidate is a relay candidate and happens to be on a relay that we are
also using. In that case, we only bind the channel on that one.

That should also improve latency when data needs to be relayed because
we reduce the number of hops by 1 and don't send traffic between two
relays.

Additionally, there is no reason to bind channels for host candidates.
2024-02-21 22:38:04 +00:00
Reactor Scram
808cbf4ce7 refactor: move BUNDLE_ID since it won't be Windows-specific (#3706)
It is still client-specific, but this was the closest place I could find
in connlib to put it.
A hypothetical GUI / .deb / systemd-involved gateway would need to be
"dev.firezone.gateway"
2024-02-21 19:50:07 +00:00
Gabi
0cdb8a91fe fix(connlib): set the real packet length before putting it into the device (#3718)
This was fixed at some point in the feature branch but was lost to time.

This is preventing macos from working(and might be causing some issues
in other platforms)
2024-02-21 19:43:24 +00:00
Thomas Eizinger
355edc72b0 fix(snownet): make TURN channel bindings more reliable (#3708)
Previously, we would only bind channels for _established_ connections.
This caused a problem if we'd get the other parties candidates before
the offer response. Additionally, we'd often send multiple channel
bindings for the same peer which caused additional warnings in the logs.
2024-02-21 02:44:44 +00:00