mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
Currently, the eBPF module can translate from channel data messages to UDP packets and vice versa. It can even do that across IP stacks, i.e. translate from an IPv6 UDP packet to an IPv4 channel data messages. What it cannot do is handle packets to itself. This can happen if both - Client and Gateway - pick the same relay to make an allocation. When exchanging candidates, ICE will then form pairs between both relay candidates, essentially requiring the relay to loop packets back to itself. In eBPF, we cannot do that. When sending a packet back out with `XDP_TX`, it will actually go out on the wire without an additional check whether they are for our own IP. Properly handling this in eBPF (by comparing the destination IP to our public IP) adds more cases we need to handle. The current module structure where everything is one file makes this quite hard to understand, which is why I opted to create four sub-modules: - `from_ipv4_channel` - `from_ipv4_udp` - `from_ipv6_channel` - `from_ipv6_udp` For traffic arriving via a data-channel, it is possible that we also need to send it back out via a data-channel if the peer address we are sending to is the relay itself. Therefore, the `from_ipX_channel` modules have four sub-modules: - `to_ipv4_channel` - `to_ipv4_udp` - `to_ipv6_channel` - `to_ipv6_udp` For the traffic arriving on an allocation port (`from_ipX_udp`), we always map to a data-channel and therefore can never get into a routing loop, resulting in only two modules: - `to_ipv4_channel` - `to_ipv6_channel` The actual implementation of the new code paths is rather simple and mostly copied from the existing ones. For half of them, we don't need to make any adjustments to the buffer size (i.e. IPv4 channel to IPv4 channel). For the other half, we need to adjust for the difference in the IP header size. To test these changes, we add a new integration test that makes use of the new docker-compose setup added in #10301 and configures masquerading for both Client and Gateway. To make this more useful, we also remove the `direct-` prefix from all tests as the test script itself no longer makes any decisions as to whether it is operating over a direct or relayed connection. Resolves: #7518
37 lines
1.1 KiB
Bash
Executable File
37 lines
1.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# The integration tests call this to test Linux DNS control, using the `/etc/resolv.conf`
|
|
# method which only works well inside Alpine Docker containers.
|
|
|
|
source "./scripts/tests/lib.sh"
|
|
|
|
HTTPBIN=dns
|
|
HTTPBIN_FQDN="$HTTPBIN.httpbin.search.test"
|
|
|
|
# Re-up the gateway since a local dev setup may run this back-to-back
|
|
docker compose up -d gateway --no-build
|
|
|
|
echo "# check original resolv.conf"
|
|
client sh -c "cat /etc/resolv.conf.before-firezone"
|
|
|
|
echo "# Make sure gateway can reach httpbin by DNS"
|
|
gateway sh -c "curl --fail $HTTPBIN_FQDN/get"
|
|
|
|
echo "# Try to ping httpbin as a DNS resource"
|
|
client_ping_resource "$HTTPBIN"
|
|
|
|
echo "# Access httpbin by DNS"
|
|
client_curl_resource "$HTTPBIN/get"
|
|
|
|
echo "# Make sure it's going through the tunnel"
|
|
client_nslookup "$HTTPBIN" | grep "100\\.96\\.0\\."
|
|
|
|
echo "# Make sure a non-resource doesn't go through the tunnel"
|
|
(client_nslookup "github.com" | grep "100\\.96.\\0\\.") && exit 1
|
|
|
|
echo "# Stop the gateway and make sure the resource is inaccessible"
|
|
docker compose stop gateway
|
|
client_curl_resource "$HTTPBIN/get" && exit 1
|
|
|
|
exit 0
|