Fixes the flaky time condition unit test by always using midnight as the
end time range so that the `flow.expires_at` is never calculated across
a day boundary into the future.
Supersedes #6244
If a new resource is created that will use format not supported by
previous client versions we temporarily show a warning:
<img width="683" alt="Screenshot 2024-08-07 at 2 28 57 PM"
src="https://github.com/user-attachments/assets/bbfdfc96-0c4b-4226-93c5-bc2b5fdb9d30">
It will also be excluded from `resources` list for older clients (below
1.2).
---------
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
I recently discovered that the metrics reporting to Google Cloud Metrics
for the relays is actually working. Unfortunately, they are all bucketed
together because we don't set the metadata correctly.
This PR aims to fix that be setting some useful default metadata for
traces and metrics and additionally, discoveres instance ID and name
from GCE metadata.
Related: #2033.
Setting up a logger is something that pretty much every entrypoint needs
to do, be it a test, a shared library embedded in another app or a
standalone application. Thus, it makes sense to introduce a dedicated
crate that allows us to bundle all the things together, how we want to
do logging.
This allows us to introduce convenience functions like
`firezone_logging::test` which allow you to construct a logger for a
test as a one-liner.
Crucially though, introducing `firezone-logging` gives us a place to
store a default log directive that silences very noisy crates. When
looking into a problem, it is common to start by simply setting the
log-filter to `debug`. Without further action, this floods the output
with logs from crates like `netlink_proto` on Linux. It is very unlikely
that those are the logs that you want to see. Without a preset filter,
the only alternative here is to explicitly turn off the log filter for
`netlink_proto` by typing something like
`RUST_LOG=netlink_proto=off,debug`. Especially when debugging issues
with customers, this is annoying.
Log filters can be overridden, i.e. a 2nd filter that matches the exact
same scope overrides a previous one. Thus, with this design it is still
possible to activate certain logs at runtime, even if they have silenced
by default.
I'd expect `firezone-logging` to attract more functionality in the
future. For example, we want to support re-loading of log-filters on
other platforms. Additionally, where logs get stored could also be
defined in this crate.
---------
Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Work for #6074 equivalent to #6166 for MacOS
MacOs view:
<img width="547" alt="image"
src="https://github.com/user-attachments/assets/f465183e-247b-49b5-a916-3ecc5f0a02f4">
iOS(ipad) view:

Other than implementing the resource disabling, this PR also refactor
the IPC between the network extension and the app so that it's some form
of structured IPC instead of relying on it being deserializable to
string to match the message.
One big difference with Android is that we don't introduce the concept
of a `ResourceView` for swift, the main reason for this is that on iOS
the resources are bound to the view instead of just being a parameter
for creating the view. So if we modify the `disabled` property it'd
update the UI unnecessarily, also it'd update the `Store` value for the
resource and then we need to copy that over again to the view. Making it
easier to go out of sync.
This will always be elevated in CI, so just check that it doesn't crash.
This came up during debugging while I was offline, and I just want to
make CI check for regressions, since there's a lot of `unsafe` code in
the Windows impl
The `firezone-bin-shared` crate is meant to house non-tunnel related
things. That allows it to compile in parallel to everything else. It
currently only depends on `connlib-shared` to access the `DEFAULT_MTU`
constant. We can remove that by requiring the MTU as a ctor parameter of
`TunDeviceManager`.
A longer write-up of the intended dependency structure is in #4470.
When forwarding DNS queries, we need to remember the original source
socket in order to send the response back. Previously, this mapping was
indexed by the DNS query ID. As it turns out, at least Windows doesn't
have a global DNS query ID counter and may reuse them across different
DNS servers. If that happens and two of these queries overlap, then we
match the wrong responses together.
In the best case, this produces bad DNS results on the client. In the
worst case, those queries were for DNS servers with different IP
versions in which case we triggered a panic in connlib further down the
stack where we created the IP packet for the response.
To fix this, we first and foremost remove the explicit `panic!` from the
`make::` functions in `ip-packet`. Originally, these functions were only
used in tests but we started to use them in production code too and
unfortunately forgot about this panic. By introducing a `Result`, all
call-sites are made aware that this can fail.
Second, we fix the actual indexing into the data structure for forwarded
DNS queries to also include the DNS server's socket. This ensures we
don't treat the DNS query IDs as globally unique.
Third, we replace the panicking path in
`try_handle_forwarded_dns_response` with a log statement, meaning if the
above assumption turns out wrong for some reason, we still don't panic
and simply don't handle the packet.
I noticed we sometimes have a flaky integration test with an ICE timeout
in its logs. For example:
https://github.com/firezone/firezone/actions/runs/10278933741/job/28443578376
Analyzing this one more closely turned out to be caused by a race
condition between client and gateway, when they exchange their ICE
candidates.
We send ICE candidates in batches but because they are serialized to
strings early, their ordering actually depends on the so-called
"foundation" of the ICE candidates. that one is simply a hash of several
components. As a result, the ordering of these candidates can vary
between test runs.
We should try ICE candidates in order of their reverse-priority (i.e.
best first). By introducing a helper-collection, we can enforce this
ordering before sending ICE candidates across.
LLMNR is a deprecated [0] protocol and we shouldn't advertise it on our
TUN interface. With LLMNR, name resolutions for hosts (i.e. single-label
domains) that are not found via search domains on other interfaces (like
a WiFI or Ethernet adapter) end up failing with "refused" instead of the
appropriate NXDOMAIN.
For example, my WiFi card has the `fritz.box` search domain assigned via
DHCP. This allows me to lookup hosts on my local network. Searching for
a host `foo` that doesn't exist currently fails with "refused":
```
❯ host foo
Host foo not found: 5(REFUSED)
```
By disabling LLMNR, we get the expected "nxdomain":
```
❯ host foo
Host foo not found: 3(NXDOMAIN)
```
To make configuring things via `resolvectl` more ergonomic, I extracted
out a helper function.
Related: #6218.
[0]:
https://techcommunity.microsoft.com/t5/networking-blog/aligning-on-mdns-ramping-down-netbios-name-resolution-and-llmnr/ba-p/3290816
Why:
* The Swagger UI is currently served from the API application. This
means that the Web application does not have access to the external URL
in the API configuration during/after compilation. Without the API
external URL, we cannot generate a proper link in the portal to the
Swagger UI. This commit refactors how the API external URL is set from
the environment variables and allows the Web app to have access to the
value of the API URL.
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
- Adds `http_test_server_image` to inputs so that it gets set properly
for CI (`debug`) and CD (`perf`)
- Updates `dev` -> `debug` in docker-compose.yml to fix pulls
- Fixes issue with seeds and relevant docs from #6205
`foo@bar` was a valid domain, while it's technically possible that
somebody owns a TLD with MX records Stripe will not accept that, so we
have to adopt this validation and make sure sign ups don't results in
HTTP 500s.
We were generating fake tokens when identity was not found but those had
empty ids so the code crashed. Now we fake the entire token and make
sure it's length is stable.
Currently, `connlib` depends on `hickory-resolver` to perform DNS
queries for non-resources. This is unnecessary. Instead of buffering the
original UDP DNS query, consulting hickory to resolve the name and
mapping the response back, we can simply take the UDP payload and send
it via our protected socket directly to the original upstream DNS
server.
This ensures `connlib` is as transparent as possible for DNS queries for
non-resources. Additionally, it removes a lot of error handling and
other cruft that we currently have to perform because we are using
hickory. For example, hickory will automatically retry a DNS query after
a certain timeout. However, the OS / client talking to `connlib` will
also retry after a certain timeout because it is making DNS queries over
an unreliable transport (UDP). It is thus unnecessary for us to do that
internally.
To correctly test this change, our test-suite needed some refactoring.
Specifically, DNS servers are now modelled as dedicated `Host`s that can
receive (UDP) traffic.
Lastly, we can remove our dependency on `hickory-proto` and
`hickory-resolver` everywhere and only use `domain` for parsing DNS
messages.
Resolves: #6141.
Related: #6033.
Related: #4800. (Impossible to happen with this design)
Instead of having one giant, composed strategy, we introduce a dedicated
`stub_portal` strategy. That one samples what is defined in the portal
in production: sites, gateways and resources.
Based on a sampled portal, we can then sample gateways, a client and DNS
records for our resources.
The `DnsServer` struct is quite nested. All it really contains
(currently) is a `SocketAddr`. To make logs containing this structure
easier to use, only print the inner address on debug.
Without masquerading, packets sent by the gateway through the TUN
interface use the wrong source address (the TUN device's address)
instead of the gateway's actual network interface.
We set this env variable in all our uses of the gateway, thus we might
as well remove it and always perform unconditionally.
---------
Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Closes#5878
It won't work properly as admin (deep links will all fail), and this
improves UX by making it obvious that admin powers are no longer needed
for the GUI.
```[tasklist]
- [x] Write up `SAFETY` comments
```
It's missing a couple pieces, see the tasklist

Refs #5123
```[tasklist]
- [x] Add `Add to Favorites` and `Remove from Favorites` buttons
- [x] Update Changelog
- [x] Load and save Favorites from `SharedPreferences`
- [x] Wire up `onClick` events
- [x] Hide and show Resources in the menu based on whether they're favorited
- [x] Hide tabs if nothing is favorited
- [x] Tab icons
- [ ] Make the "Reset Settings" button also reset Favorites
- [ ] Change the "Add to Favorites" and "Remove from Favorites" to a checkbox or star or something cool
```
Closes#5063, supersedes #5850
Other refactors and changes made as part of this:
- Adds the ability to disable DNS control on Windows
- Removes the spooky-action-at-a-distance `from_env` functions that used
to be buried in `tunnel`
- `FIREZONE_DNS_CONTROL` is now a regular `clap` argument again
---------
Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Mitigates #5880.
This should fix the issue for all practical purposes, but we don't need
a channel there, so it does not close the ticket. A more permanent fix
would involve factoring out the callbacks or cheating and using a Mutex
inside the callbacks to do a swap-and-notify thing.
This affects both the Headless Client and the GUI Client's IPC service,
on both Linux and Windows.
This temporarily reverts commit
d1703d2849.
The long term fix will be to have the API URL be set by environment
variables, but in the interest of time it will be hardcoded for now.
---------
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
In my testing, Docker-defined resources are not reachable unless you
explicitly declare a network and add both services to it. Additionally,
`systemd-resolved` refuses to resolve single-label domain names, meaning
a "two-label" domain needs to be used to access this as a DNS resource.
---------
Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.14.12 to 22.0.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>