Firewall Rules
Ports
You do not need to make any changes to the firewall rules of hosts that connect outbound to a central Crux VPN hub or server.
However, for central Crux VPN hubs or other servers that accept inbound connections from Crux VPN clients, you will need to open two ports:
- A UDP port for WireGuard access;
51820
by default. - A TCP port for Arqit SKA-Platform™ (SKA-P) peering;
8887
by default.
On the host itself, WireGuard for Windows will automatically open up access to the WireGuard port; but you still will have to manually open up access to the SKA-P port. For this, we recommend a Windows Defender Firewall rule like the following:
PS> New-NetFirewallRule `
-Name cruxska `
-DisplayName "Crux VPN SKA" `
-Group "Custom" `
-Enabled True `
-Program "C:\Program Files\Sirius Computer\Crux VPN Agent\cruxvpn-agent-service.exe" `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalPort 8887
On other platforms, if a host-based firewall is enabled, you will have to open up access to both ports.
Forwarding
For a central hub or other server that forwards connections on to other servers, you will need to enable forwarding on the host.
On Windows, run the following command as Administrator for each network interface that needs to forward packets (for example, the crux0
interface):
PS> Set-NetIPInterface -InterfaceAlias crux0 -Forwarding Enabled
On Linux this can be accomplished by running the following commands as root:
# sysctl -w net.ipv4.conf.all.forwarding=1
# sysctl -w net.ipv6.conf.all.forwarding=1
But on Linux, you may also need to alter your firewall rules to allow connections to be forwarded. For example, on a host using iptables to manage its firewall rules, the following commands would allow unrestricted forwarding through the crux0
network interface:
# iptables -I FORWARD -i crux0 -j ACCEPT
# iptables -I FORWARD -o crux0 -j ACCEPT
# ip6tables -I FORWARD -i crux0 -j ACCEPT
# ip6tables -I FORWARD -o crux0 -j ACCEPT
You can enable forwarding with course-grained access control in the Crux VPN web UI through the advanced settings of an interface, via the "Forwarding" setting. These are roughly the iptables rules that each option corresponds to:
- Internal within WireGuard network:
iptables -A FORWARD -i crux0 -o crux0 -j ACCEPT
- Inbound from WireGuard network:
iptables -A FORWARD -i crux0 -j ACCEPT
- Outbound to WireGuard network:
iptables -A FORWARD -o crux0 -j ACCEPT
- All to and from WireGuard network: (both inbound and outbound rules)
See the Windows Script Settings section at the bottom of the page for settings on the host that you will need to make in order to use the web UI's "Forwarding" setting on Windows.
MSS
If you need to forward connections through a series of servers, you may want to apply MSS (Maximum Segment Size) clamping to those connections on the forwarding servers (which helps prevent packet fragmentation).
On Windows, run the following command as Administrator on each network interface to clamp (for example, the crux0
interface):
PS> Set-NetIPInterface -InterfaceAlias crux0 -ClampMss Enabled
On Linux this can be accomplished by running the following commands as root:
# iptables -t mangle -A FORWARD -o crux0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# ip6tables -t mangle -A FORWARD -o crux0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Alternately, you can turn this on through the advanced settings for an interface in the Crux VPN web UI, via the "MSS Clamping" checkbox.
See the Windows Script Settings section at the bottom of the page for settings on the host that you will need to make in order to use the web UI's "MSS Clamping" setting on Windows.
NAT
If you want to apply NAT (Network Address Translation) to forwarded connections, you may do so manually.
On Windows, you can create SNAT (Source Network Address Translation) rules via the New-NetNat
PowerShell command. For example, if you used 10.0.0.0/24
as your private Crux VPN address space, you might create a SNAT rule like the following to masquerade connections forwarded from the Crux VPN network to the host's LAN:
PS> New-NetNat -Name CruxNAT -InternalIPInterfaceAddressPrefix 10.0.0.0/24
("Masquerading" translates a connection's source address to the address of the network interface out of which the connection is forwarded, making the connection appear to originate from the host itself.)
On Linux, the equivalent iptables rule would be the following:
# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
Alternatively, you can enable basic SNAT through the advanced settings for an interface in the Crux VPN web UI, via the "Masquerading" setting. These are roughly the iptables rules that each option corresponds to:
- Inbound from WireGuard network:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- Outbound to WireGuard network:
iptables -t nat -A POSTROUTING -o crux0 -j MASQUERADE
- All to and from WireGuard network: (both inbound and outbound rules)
See the Windows Script Settings section at the bottom of the page for settings on the host that you will need to make in order to use the web UI's "Masquerading" setting on Windows.
Zones
On hosts with a zonal firewall, such as firewalld, you can use the Crux VPN web UI's advanced settings for an interface to customize which zone the interface will be added to. For example, to add the interface to the internal
zone on a host, select the "Internal" option of the "Firewall Zone" setting.
On Windows, if the host has been joined to an Active Directory domain, its Crux VPN interfaces will always be added to the Domain
firewall profile. Otherwise, you can use this setting to determine whether an interface should be added to the host's Public
firewall profile, or to the Private
firewall profile.
See the Windows Script Settings section at the bottom of the page for settings on the host that you will need to make in order to use the web UI's "Firewall Zone" setting on Windows.
Hub and Spoke
You can use the following rulesets as starting points for building a complete firewall ruleset on a Crux VPN hub. (If you do so, make sure to remove any firewall-related settings from the interface's advanced settings in the Crux VPN web UI, to avoid conflicts.)
Iptables Hub Ruleset
The following IPv4 iptables ruleset will allow inbound ICMP (eg for ping etc), SSH, SKA-P peering, and WireGuard traffic to the hub, as well as unrestricted forwarding of traffic between spokes on the Crux VPN network:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state INVALID -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# allow SSH to hub
-A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# allow SKA-P peering to hub
-A INPUT -i eth0 -p tcp --dport 8887 -j ACCEPT
# allow WireGuard to hub
-A INPUT -i eth0 -p udp --dport 51820 -j ACCEPT
-A FORWARD -m state --state INVALID -j DROP
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# forward all traffic sent from one Crux VPN spoke to another
-A FORWARD -i crux0 -o crux0 -j ACCEPT
COMMIT
Once you have Crux VPN up and running on the host, you may want to change its SSH rule to allow access only through a Crux VPN connection, instead of through its public network interface:
# allow SSH to hub through Crux VPN
-A INPUT -i crux0 -p tcp --dport 22 -j ACCEPT
Nftables Hub Ruleset
Similar to the above iptables rulset, the following nftables ruleset will allow inbound ICMP, SSH, SKA-P peering, and WireGuard traffic to the hub, as well as unrestricted forwarding of traffic between spokes on the Crux VPN network. In addition, it also applies to IPv6, and allows for DHCPv6 traffic:
#!/usr/sbin/nft -f
flush ruleset
define pub_iface = "eth0"
define crux_iface = "crux0"
define crux_port = 51820
define ska_port = 8887
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# accept all loopback packets
iif "lo" accept
# accept all icmp/icmpv6 packets
meta l4proto { icmp, ipv6-icmp } accept
# accept all packets that are part of an already-established connection
ct state vmap { invalid : drop, established : accept, related : accept }
# accept all DHCPv6 packets received at a link-local address
ip6 daddr fe80::/64 udp dport dhcpv6-client accept
# accept all SSH packets received on a public interface
iifname $pub_iface tcp dport ssh accept
# accept all SKA-P peering packets received on a public interface
iifname $pub_iface tcp dport $ska_port accept
# accept all WireGuard packets received on a public interface
iifname $pub_iface udp dport $crux_port accept
# reject with polite "port unreachable" icmp response
reject
}
chain forward {
type filter hook forward priority 0; policy drop;
# forward all packets transiting the Crux VPN network
iifname $crux_iface oifname $crux_iface accept
# reject with polite "host unreachable" icmp response
reject with icmpx type host-unreachable
}
}
Once you have Crux VPN up and running on the host, you may want to change its SSH rule to allow access only through a Crux VPN connection, instead of through its public network interface:
# accept all SSH packets received from the Crux VPN network
iifname $crux_iface tcp dport ssh accept
Point to Site
You can use the following rulesets as starting points for building a complete firewall ruleset on a Crux VPN server that is meant to forward connections to its local site. (If you do so, make sure to remove any firewall-related settings from the interface's advanced settings in the Crux VPN web UI, to avoid conflicts.)
Iptables Gateway Ruleset
The following IPv4 iptables ruleset will allow inbound ICMP, SSH, SKA-P peering, and WireGuard traffic to the server, as well as unrestricted forwarding of traffic from the Crux VPN network to the site:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state INVALID -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# allow SSH to gateway
-A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# allow SKA-P peering to gateway
-A INPUT -i eth0 -p tcp --dport 8887 -j ACCEPT
# allow WireGuard to gateway
-A INPUT -i eth0 -p udp --dport 51820 -j ACCEPT
-A FORWARD -m state --state INVALID -j DROP
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# forward all traffic sent from Crux VPN endpoints to the site
-A FORWARD -i crux0 -o eth0 -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# masquerade traffic forwarded to site
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
Once you have Crux VPN up and running on the host, you may want to change its SSH rule to allow access only through a Crux VPN connection, instead of through its public network interface:
# allow SSH to gateway through Crux VPN
-A INPUT -i crux0 -p tcp --dport 22 -j ACCEPT
Or you may want to change its SSH rule to allow access only from the local site (if the local network address space at the site was 192.168.1.0/24
):
# allow SSH to gateway from site
-A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
Additionally, you may want to remove the NAT rule that masquerades traffic to the site, and instead adjust the site's LAN router to route traffic from the Crux VPN network back to the Crux VPN gateway.
For example, if the Crux VPN network address space was 10.0.0.0/24
, the Crux VPN gateway's LAN address was 192.168.1.123
, and the LAN router's LAN interface was eth1
, you might use add a routing rule like the following to enable LAN hosts to route traffic back to the Crux VPN network without masquerading:
ip route add 10.0.0.0/24 via 192.168.1.123 dev eth1
The disadvantage of masquerading is that it hides the original Crux VPN network addresses from the other servers at the site; whereas enabling the site to route Crux VPN addresses directly enables you to expose their original addresses. Since each Crux VPN address is statically bound to a device, rather than assigned dynamically, the original address will reveal exactly which device is behind each connection.
For example, if Alice's laptop has a Crux VPN address of 10.0.0.11
, and Bob's workstation has a Crux VPN address of 10.0.0.22
, and you see 10.0.0.11
in the logs of one of the servers at the site, you'll know that it was Alice and not Bob who accessed the server. Furthermore, you could configure the server to allow access to Alice and deny access to Bob based on their Crux VPN addresses (eg allow from 10.0.0.11
, deny from 10.0.0.22
).
Nftables Gateway Ruleset
Similar to the above iptables rulset, the following nftables ruleset will allow inbound ICMP, SSH, SKA-P peering, and WireGuard traffic to the server, as well as unrestricted forwarding of traffic from the Crux VPN network to the site. In addition, it also applies to IPv6, and allows for DHCPv6 traffic:
#!/usr/sbin/nft -f
flush ruleset
define pub_iface = "eth0"
define crux_iface = "crux0"
define crux_port = 51820
define ska_port = 8887
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# accept all loopback packets
iif "lo" accept
# accept all icmp/icmpv6 packets
meta l4proto { icmp, ipv6-icmp } accept
# accept all packets that are part of an already-established connection
ct state vmap { invalid : drop, established : accept, related : accept }
# accept all DHCPv6 packets received at a link-local address
ip6 daddr fe80::/64 udp dport dhcpv6-client accept
# accept all SSH packets received on a public interface
iifname $pub_iface tcp dport ssh accept
# accept all SKA-P peering packets received on a public interface
iifname $pub_iface tcp dport $ska_port accept
# accept all WireGuard packets received on a public interface
iifname $pub_iface udp dport $crux_port accept
# reject with polite "port unreachable" icmp response
reject
}
chain forward {
type filter hook forward priority 0; policy drop;
# forward all packets that are part of an already-established connection
ct state vmap { invalid : drop, established : accept, related : accept }
# forward all packets from the Crux VPN network to the site network
iifname $crux_iface oifname $pub_iface accept
# reject with polite "host unreachable" icmp response
reject with icmpx type host-unreachable
}
}
table inet nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# masquerade all packets from the Crux VPN network to the site network
iifname $crux_iface oifname $pub_iface masquerade
}
}
Once you have Crux VPN up and running on the host, you may want to change its SSH rule to allow access only through a Crux VPN connection, instead of through its public network interface:
# accept all SSH packets received from the Crux VPN network
iifname $crux_iface tcp dport ssh accept
Or you may want to change its SSH rule to allow access only from the local site (if the local network address space at the site was 192.168.1.0/24
):
# accept all SSH packets received from local site addresses
ip saddr 192.168.1.0/24 tcp dport ssh accept
Additionally, you may want to remove the NAT table (containing the rule that masquerades traffic to the site), and instead adjust the site's LAN router to route traffic from the Crux VPN network back to the Crux VPN gateway (as described for the iptables ruleset above).
Windows Script Settings
On Windows, the Crux VPN agent applies firewall changes via PowerShell scripts, run by the WireGuard when it starts up a tunnel. To enable WireGuard to execute these "PostUp" scripts, set the following registry key on the host:
> reg add HKEY_LOCAL_MACHINE\SOFTWARE\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f
Then allow unrestricted execution of PowerShell scripts:
PS> Set-ExecutionPolicy -ExecutionPolicy Unrestricted