Skip to content

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:

  1. A UDP port for WireGuard access; 51820 by default.
  2. 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