Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 46 additions & 31 deletions openvpn-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2929,6 +2929,7 @@ verb 3" >>/etc/openvpn/server/server.conf
fi

# Configure firewall rules
# Use source-based rules for VPN traffic (works reliably regardless of which tun interface OpenVPN uses)
log_info "Configuring firewall rules..."

if systemctl is-active --quiet firewalld; then
Expand All @@ -2937,7 +2938,8 @@ verb 3" >>/etc/openvpn/server/server.conf
run_cmd "Adding OpenVPN port to firewalld" firewall-cmd --permanent --add-port="$PORT/$PROTOCOL"
run_cmd "Adding masquerade to firewalld" firewall-cmd --permanent --add-masquerade

# Add rich rules for VPN traffic (source-based rules work reliably with dynamic tun0 interface)
# Add rich rules for VPN traffic (source-based only, as firewalld doesn't reliably
# support interface patterns with direct rules when using nftables backend)
if [[ $CLIENT_IPV4 == 'y' ]]; then
run_cmd "Adding IPv4 VPN subnet rule" firewall-cmd --permanent --add-rich-rule="rule family=\"ipv4\" source address=\"$VPN_SUBNET_IPV4/24\" accept"
fi
Expand All @@ -2952,20 +2954,33 @@ verb 3" >>/etc/openvpn/server/server.conf
log_info "nftables detected, configuring nftables rules..."
run_cmd_fatal "Creating nftables directory" mkdir -p /etc/nftables

# Create nftables rules file - base filter rules
echo "table inet openvpn {
chain input {
type filter hook input priority 0; policy accept;
iifname \"tun0\" accept
iifname \"$NIC\" $PROTOCOL dport $PORT accept
}

chain forward {
type filter hook forward priority 0; policy accept;
iifname \"$NIC\" oifname \"tun0\" accept
iifname \"tun0\" oifname \"$NIC\" accept
}
}" >/etc/nftables/openvpn.nft
# Create nftables rules file
{
echo "table inet openvpn {"
echo " chain input {"
echo " type filter hook input priority 0; policy accept;"
if [[ $CLIENT_IPV4 == 'y' ]]; then
echo " iifname \"tun*\" ip saddr $VPN_SUBNET_IPV4/24 accept"
fi
if [[ $CLIENT_IPV6 == 'y' ]]; then
echo " iifname \"tun*\" ip6 saddr ${VPN_SUBNET_IPV6}/112 accept"
fi
echo " iifname \"$NIC\" $PROTOCOL dport $PORT accept"
echo " }"
echo ""
echo " chain forward {"
echo " type filter hook forward priority 0; policy accept;"
if [[ $CLIENT_IPV4 == 'y' ]]; then
echo " iifname \"tun*\" ip saddr $VPN_SUBNET_IPV4/24 accept"
echo " oifname \"tun*\" ip daddr $VPN_SUBNET_IPV4/24 accept"
fi
if [[ $CLIENT_IPV6 == 'y' ]]; then
echo " iifname \"tun*\" ip6 saddr ${VPN_SUBNET_IPV6}/112 accept"
echo " oifname \"tun*\" ip6 daddr ${VPN_SUBNET_IPV6}/112 accept"
fi
echo " }"
echo "}"
} >/etc/nftables/openvpn.nft

# IPv4 NAT rules (only if clients get IPv4)
if [[ $CLIENT_IPV4 == 'y' ]]; then
Expand Down Expand Up @@ -3006,18 +3021,18 @@ table ip6 openvpn-nat {
# IPv4 rules (only if clients get IPv4)
if [[ $CLIENT_IPV4 == 'y' ]]; then
echo "iptables -t nat -I POSTROUTING 1 -s $VPN_SUBNET_IPV4/24 -o $NIC -j MASQUERADE
iptables -I INPUT 1 -i tun0 -j ACCEPT
iptables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT
iptables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT
iptables -I INPUT 1 -i tun+ -s $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -I FORWARD 1 -i tun+ -s $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -I FORWARD 1 -o tun+ -d $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/add-openvpn-rules.sh
fi

# IPv6 rules (only if clients get IPv6)
if [[ $CLIENT_IPV6 == 'y' ]]; then
echo "ip6tables -t nat -I POSTROUTING 1 -s ${VPN_SUBNET_IPV6}/112 -o $NIC -j MASQUERADE
ip6tables -I INPUT 1 -i tun0 -j ACCEPT
ip6tables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT
ip6tables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT
ip6tables -I INPUT 1 -i tun+ -s ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -I FORWARD 1 -i tun+ -s ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -I FORWARD 1 -o tun+ -d ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/add-openvpn-rules.sh
fi

Expand All @@ -3027,18 +3042,18 @@ ip6tables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptabl
# IPv4 removal rules
if [[ $CLIENT_IPV4 == 'y' ]]; then
echo "iptables -t nat -D POSTROUTING -s $VPN_SUBNET_IPV4/24 -o $NIC -j MASQUERADE
iptables -D INPUT -i tun0 -j ACCEPT
iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT
iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT
iptables -D INPUT -i tun+ -s $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -D FORWARD -i tun+ -s $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -D FORWARD -o tun+ -d $VPN_SUBNET_IPV4/24 -j ACCEPT
iptables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/rm-openvpn-rules.sh
fi

# IPv6 removal rules
if [[ $CLIENT_IPV6 == 'y' ]]; then
echo "ip6tables -t nat -D POSTROUTING -s ${VPN_SUBNET_IPV6}/112 -o $NIC -j MASQUERADE
ip6tables -D INPUT -i tun0 -j ACCEPT
ip6tables -D FORWARD -i $NIC -o tun0 -j ACCEPT
ip6tables -D FORWARD -i tun0 -o $NIC -j ACCEPT
ip6tables -D INPUT -i tun+ -s ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -D FORWARD -i tun+ -s ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -D FORWARD -o tun+ -d ${VPN_SUBNET_IPV6}/112 -j ACCEPT
ip6tables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >>/etc/iptables/rm-openvpn-rules.sh
fi

Expand Down Expand Up @@ -3854,13 +3869,13 @@ function removeOpenVPN() {
# firewalld was used
run_cmd "Removing OpenVPN port from firewalld" firewall-cmd --permanent --remove-port="$PORT/$PROTOCOL_BASE"
run_cmd "Removing masquerade from firewalld" firewall-cmd --permanent --remove-masquerade
# Remove IPv4 rule if it was configured
# Remove IPv4 rich rule if configured
if [[ -n $VPN_SUBNET_IPV4 ]]; then
run_cmd "Removing IPv4 VPN subnet rule" firewall-cmd --permanent --remove-rich-rule="rule family=\"ipv4\" source address=\"$VPN_SUBNET_IPV4/24\" accept" 2>/dev/null || true
firewall-cmd --permanent --remove-rich-rule="rule family=\"ipv4\" source address=\"$VPN_SUBNET_IPV4/24\" accept" 2>/dev/null || true
fi
# Remove IPv6 rule if it was configured
# Remove IPv6 rich rule if configured
if [[ -n $VPN_SUBNET_IPV6 ]]; then
run_cmd "Removing IPv6 VPN subnet rule" firewall-cmd --permanent --remove-rich-rule="rule family=\"ipv6\" source address=\"${VPN_SUBNET_IPV6}/112\" accept" 2>/dev/null || true
firewall-cmd --permanent --remove-rich-rule="rule family=\"ipv6\" source address=\"${VPN_SUBNET_IPV6}/112\" accept" 2>/dev/null || true
fi
run_cmd "Reloading firewalld" firewall-cmd --reload
elif [[ -f /etc/nftables/openvpn.nft ]]; then
Expand Down
2 changes: 1 addition & 1 deletion test/server-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ if systemctl is-active --quiet firewalld; then
firewall-cmd --list-ports
exit 1
fi
# Verify VPN subnet rich rule exists
# Verify VPN subnet rich rule exists (source-based rules work reliably across firewalld backends)
if firewall-cmd --list-rich-rules | grep -q "source address=\"$VPN_SUBNET_IPV4/24\""; then
echo "PASS: VPN subnet rich rule is configured"
else
Expand Down