Closed felschr closed 3 years ago
Is this still the case for 2021.2? Then I'll have a look at it.
Seems like NixOS's firewall is interfering with our netfilter rules. And even if I force the firewall to use a netfilter comptabile iptables
, it's still broken (but OpenVPN connects, but no traffic flows). We changed the way tunnel traffic is routed to rely on some netfilter rules to allow for split tunelling. The long and short of it is, I'll try and see if there's anything we can do daemon side to circumvent this issue, possibly adding iptables
if iptables
exist. Otherwise, you'll have to change the mullvad-vpn
service to add permissive firewall rules to NixOS's firewall, and maybe even apply the nftables compatible iptable
package.
I'm having a similar issue with 2021.2 2021-02-18
, my full config is available here: https://github.com/shazow/nixfiles/blob/1fa955ea1fcb8510561c85feda2993b6647e1056/common/desktop.nix#L98
Some networking-related configs live here: https://github.com/shazow/nixfiles/blob/1fa955ea1fcb8510561c85feda2993b6647e1056/shazowic-corvus.nix
I thought it was related to having tailscale enabled (both being wireguard) but removing tailscale didn't seem to help. I also tried switching from networking.firewall
to networking.nftables
but that didn't seem to help.
@pinkisemils thanks for having a look! Which firewall rules would you need? Or shall we wait for you to try and fix it on your end first?
I've merged a fix for this already in our code. The issue was reverse path filtering. It seems that the default firewall does have a module to do that, so we added a chain to mark traffic from the relay so that it passes the RPF. Users who have enabled strict reverse path filtering in kernel should also configure net.*.conf.*.src_valid_mark=1
appropriately, otherwise the kernel won't take the firewall mark into account when evaluating the reverse route, thus filtering our traffic.
The issues were stemming from the fact that we use policy based routing now, which is inherently at odds with reverse path filters unless our rules accommodate them. And now they do. We are still discussing if we should set the src_valid_mark
sysctl at runtime. On one hand, it's just a very bad thing to do. On the other, we don't know under what circumstances would a user want to have strict reverse path filtering in the kernel and not want a way to have policy based routing to work.
I've now tried the beta. It times out when connecting via wireguard. When it switches to OpenVPN, it shows connected
, but all connections time out. When disabling the firewall, it works perfectly again.
Here's some info:
❯ sudo sysctl -a | grep src_valid
sysctl: Schlüssel »kernel.spl.hostid« wird gelesen
net.ipv4.conf.all.src_valid_mark = 1
net.ipv4.conf.default.src_valid_mark = 1
net.ipv4.conf.docker0.src_valid_mark = 1
net.ipv4.conf.enp0s31f6.src_valid_mark = 1
net.ipv4.conf.enp59s0u1u3.src_valid_mark = 1
net.ipv4.conf.lo.src_valid_mark = 1
net.ipv4.conf.vboxnet0.src_valid_mark = 1
net.ipv4.conf.wlp2s0.src_valid_mark = 1
logs while trying to connect
❯ sudo ./result/bin/mullvad-daemon
[2021-04-13 14:39:47.606][mullvad_daemon::version][INFO] Starting mullvad-daemon - 2021.3-beta1 2021-04-13
[2021-04-13 14:39:47.606][mullvad_daemon][INFO] Logging to /var/log/mullvad-vpn
[2021-04-13 14:39:47.607][mullvad_daemon][INFO] Management interface listening on /var/run/mullvad-vpn
[2021-04-13 14:39:47.674][mullvad_daemon::relays][INFO] Initialized with 754 cached relays from 2021-04-13 14:25:09.868
[2021-04-13 14:39:47.674][mullvad_daemon::settings][INFO] Loading settings from /etc/mullvad-vpn/settings.json
[2021-04-13 14:39:47.674][mullvad_daemon::account_history][INFO] Opening account history file in /etc/mullvad-vpn/account-history.json
[2021-04-13 14:39:47.685][talpid_core::firewall][INFO] Resetting firewall policy
[2021-04-13 14:39:47.686][mullvad_daemon][INFO] Account already has WireGuard key
[2021-04-13 14:39:51.372][mullvad_daemon::relays][INFO] Selected relay de11-wireguard at 185.209.196.70
[2021-04-13 14:39:51.376][talpid_core::firewall][INFO] Applying firewall policy: Connecting to 185.209.196.70:46490 over UDP with gateways 10.64.0.1,fc00:bbbb:bbbb:bb01::1, Blocking LAN
[2021-04-13 14:40:06.446][talpid_core::tunnel::wireguard][WARN] Timeout while checking tunnel connection
[2021-04-13 14:40:06.512][talpid_core::tunnel_state_machine::connecting_state][INFO] Tunnel closed. Reconnecting, attempt 1.
[2021-04-13 14:40:06.513][mullvad_daemon::relays][INFO] Selected relay de21-wireguard at 185.254.75.4
[2021-04-13 14:40:06.513][talpid_core::firewall][INFO] Applying firewall policy: Connecting to 185.254.75.4:53 over UDP with gateways 10.64.0.1,fc00:bbbb:bbbb:bb01::1, Blocking LAN
[2021-04-13 14:40:21.563][talpid_core::tunnel::wireguard][WARN] Timeout while checking tunnel connection
[2021-04-13 14:40:21.625][talpid_core::tunnel_state_machine::connecting_state][INFO] Tunnel closed. Reconnecting, attempt 2.
[2021-04-13 14:40:21.626][mullvad_daemon::relays][INFO] Selected relay de-fra-002 at 185.213.155.132
[2021-04-13 14:40:21.626][talpid_core::firewall][INFO] Applying firewall policy: Connecting to 185.213.155.132:1302 over UDP with gateways , Blocking LAN
[2021-04-13 14:40:24.004][talpid_core::firewall][INFO] Applying firewall policy: Connected to 185.213.155.132:1302 over UDP over "tun0" (ip: 10.16.0.14, v4 gw: 10.16.0.1, v6 gw: None), Blocking LAN
[2021-04-13 14:40:24.006][talpid_core::dns][INFO] Setting DNS servers to 10.16.0.1
[2021-04-13 14:40:34.127][mullvad_daemon][WARN] Unable to fetch GeoIP location: Error: Request timed out
Caused by: deadline has elapsed
[2021-04-13 14:40:43.407][talpid_core::dns][INFO] Resetting DNS
[2021-04-13 14:40:44.325][talpid_core::firewall][INFO] Resetting firewall policy
^C[2021-04-13 14:40:47.052][mullvad_daemon::relays][ERROR] Relay list updater shutting down
[2021-04-13 14:40:47.052][mullvad_daemon][INFO] Tunnel state machine shut down
[2021-04-13 14:40:47.053][mullvad_daemon][INFO] Mullvad daemon is quitting
[2021-04-13 14:40:47.053][mullvad_daemon::management_interface][INFO] Management interface shut down
I peeked at mullvad's code and it seems like it uses nftables which I assume causes issues in some way with iptables. Replacing iptables with just nftables as a workaround seems to have fixed wireguard with the newest beta for me.
For reference here is the config I wrote to test with nftables (Still lacks most of the config needed for being a drop-in replacement for iptables):
{
networking.firewall.enable = false;
networking.nftables = {
enable = true;
ruleset = ''
table inet firewall {
chain inbound {
type filter hook input priority 0;
policy drop;
iifname lo accept;
tcp dport { ${builtins.concatStringsSep ", " ((map (port: toString port) config.networking.firewall.allowedTCPPorts) ++ (map (range: "${toString range.from}-${toString range.to}") config.networking.firewall.allowedTCPPortRanges)) } } accept
udp dport { ${builtins.concatStringsSep ", " ((map (port: toString port) config.networking.firewall.allowedUDPPorts) ++ (map (range: "${toString range.from}-${toString range.to}") config.networking.firewall.allowedUDPPortRanges)) } } accept
ct state {established, related} accept;
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain outbound {
type filter hook output priority 0; policy accept;
}
}
'';
};
}
No idea what the best way to fix this is, or if it even is possible without disabling iptables and moving to nftables which is a bit out of scope for this issue.
So, I've found a fix. Setting networking.firewall.checkReversePath = "loose"
will allow connection.
@thefloweringash As you were the last one to edit the firewall module, I'm pinging you: Is there a security implication if this module sets reverse path filtering to loose
?
So, I've found a fix. Setting
networking.firewall.checkReversePath = "loose"
will allow connection. @thefloweringash As you were the last one to edit the firewall module, I'm pinging you: Is there a security implication if this module sets reverse path filtering toloose
?
There's precedent for disabling this when it breaks vpn modules, see wg-quick. I don't want to make strong claims about security here. The reverse path filter is a security feature so disabling it necessarily affects security. If what wg-quick does is ok, then it should be ok here too.
Thanks for the feedback. I've opened a PR which acknowledges the potential security issue.
Have you tried our latest release? Regardless, I don't believe RPF done via iptables is any better than RPF done via the kernel, but I must assume that iptables allows for a more flexible configuration. Ideally, iptables RP filter would consider the packet mark during evaluation.
+1 to workarounds in this issue.
To summarize for anyone else wanting to setup mullvad VPN on NixOS (as of 2021-08-04)...
1) Add the following to /etc/nixos/configuration.nix
:
networking.firewall.checkReversePath = "loose";
networking.wireguard.enable = true;
services.mullvad-vpn.enable = true;
2) nixos-rebuild switch
and reboot
.
3) nix-shell -i mullvad-vpn
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
https://discourse.nixos.org/t/mullvad-module-installed-but-missing-files-or-components/15953/2
I had a lot of headache making a WireGuard setup work with systemd-networkd, where all traffic is sent through wg tunnel. After a long amount of fiddling, I could make it work only with networking.firewall.checkReversePath = "loose";
. Here is the config that worked for me, so that future me (and others) may suffer less:
let
address = "1.2.3.4,dead::beef";
dns = [ "1.1.1.1" ];
peerPk = "...";
allowedIPs = "0.0.0.0/0,::0/0";
endpoint = "my-vpn-provider.net:5300";
firewallMark = 13;
routeTable = 1000;
# utils
inherit (config.networking) hostName;
skAttr = "wg-private-key-${hostName}";
split = lib.strings.splitString ",";
in {
age.secrets.${skAttr} = {
file = ../secrets/${skAttr};
owner = "systemd-network";
};
systemd.network =
{
netdevs."90-wg" = {
netdevConfig.Kind = "wireguard";
netdevConfig.Name = "wg-extern";
wireguardConfig.PrivateKeyFile = config.age.secrets.${skAttr}.path;
wireguardConfig.FirewallMark = firewallMark;
wireguardConfig.RouteTable = routeTable;
wireguardPeers = [
{
wireguardPeerConfig.AllowedIPs = split allowedIPs;
wireguardPeerConfig.Endpoint = endpoint;
wireguardPeerConfig.PublicKey = peerPk;
}
];
};
networks."90-wg" = {
inherit dns;
address = split address;
linkConfig.ActivationPolicy = "manual";
matchConfig.Name = "wg-extern";
networkConfig.LinkLocalAddressing = "no";
networkConfig.DNSDefaultRoute = true;
networkConfig.Domains = "~";
routingPolicyRules = [
{
routingPolicyRuleConfig = {
FirewallMark = firewallMark;
InvertRule = true;
Table = routeTable;
Priority = 10;
};
}
];
};
};
# otherwise the firwallmark stuff doesn't work
networking.firewall.checkReversePath = "loose";
}
Describe the bug After upgrading mullvad to 2021.1 it can't connect to the servers properly.
To Reproduce Configure mullvad service:
Run
mullvad-vpn
GUI and try to connect to a WireGuard or OpenVPN server. For WireGuard it'll get stuck in the connecting state. For OpenVPN it will show that it's connected in the GUI, but there's no actual internet connection.Expected behavior The connection should be established successfully.
Notify maintainers @Br1ght0ne @ymarkus @xfix
Metadata
Maintainer information: