使用 iptables 实现 OpenVPN “终止开关”

使用 iptables 实现 OpenVPN “终止开关”

我正在尝试为 OpenVPN 实现一组 iptables 规则:

  1. 一切(无一例外)都通过 OpenVPN
  2. 如果 OpenVPN 瘫痪或无法访问,则所有内容(无一例外)都无法访问互联网
  3. 无论 OpenVPN 的状态如何,始终可以进行本地访问

到目前为止,我见过的最好的(六个例子中)是这个,但是当 VPN 通过 ipv6 关闭时,它仍然允许访问互联网:

# Clean down existing rules
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -t nat -F
ip6tables -t mangle -F
ip6tables -F
ip6tables -X

# Allow loopback device (internal communication)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic.
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT

# Allow VPN establishment
iptables -A OUTPUT -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -p udp --sport 1194 -j ACCEPT

# Accept all TUN connections (tun = VPN tunnel)
iptables -A OUTPUT -o tun+ -j ACCEPT
iptables -A INPUT -i tun+ -j ACCEPT

# Set default policies to drop all communication unless specifically allowed
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

如果我尝试全面阻止所有 IPv6 流量(许多示例都表明如此),那么我将无法连接任何东西:

# Set default policies to drop all communication unless specifically allowed
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP

如果我尝试镜像 ipv4 部分中的内容,则会出现以下情况:

# Allow loopback device (internal communication)
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic.
# (Skipped as I don't know how to do this)

# Allow VPN establishment
ip6tables -A OUTPUT -p udp --dport 1194 -j ACCEPT
ip6tables -A INPUT -p udp --sport 1194 -j ACCEPT

# Accept all TUN connections (tun = VPN tunnel)
ip6tables -A OUTPUT -o tun+ -j ACCEPT
ip6tables -A INPUT -i tun+ -j ACCEPT

现在我无法连接到任何地方,curl https://ipinfo.io/ip只是挂起了。

我怎样才能解决这个问题?

答案1

未来的读者请注意这里提出的规则“将允许去匿名化因为它允许通过端口 1194 的任何连接,而不仅仅是来自 OpenVPN 的流量”。这个答案提出了一组更简单的规则,不需要对任何 IP 或端口进行硬编码。

答案2

事实证明,我没有将 VPN 服务的 DNS 服务器列入白名单。一旦我这样做了,我就可以毫无问题地将 ipv6 列入黑名单。

请注意:根据 Rock Storm 的评论,这可能不是最好的方法,因为它允许通过端口 1194 进行任何连接。请参阅这个答案更好的方法是不需要对任何 IP 或端口进行硬编码 - 但是它需要进一步修改以允许本地流量(在我的情况下,允许输入和输出192.168.0.0/16

为了完整起见,以下是我最终完成的工作。需要记住三件事:

  1. 您应该将[Primary DNS IP here]和替换[Secondary DNS IP here]为您计划使用的 DNS 服务器的 IP 地址
  2. 不要忘记编辑/etc/resolvconf.conf以将#1 中的 IP 地址添加为名称服务器,并将您自己的 IP 地址列入黑名单,以避免 DNS 泄漏。
  3. 假设您的本地流量有一个以 开头的 IP 范围192.168。如果不是,您需要更改它。

代码如下:

# Remove any existing rules
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -F
sudo iptables -X
sudo ip6tables -P INPUT ACCEPT
sudo ip6tables -P FORWARD ACCEPT
sudo ip6tables -P OUTPUT ACCEPT
sudo ip6tables -t nat -F
sudo ip6tables -t mangle -F
sudo ip6tables -F
sudo ip6tables -X

# Allow loopback device (internal communication)
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
    
# Allow all local traffic
sudo iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT

# Allow DNS (could be VPN provider or someone like Cloudflare's 1.1.1.1)
sudo iptables -A OUTPUT -d [Primary DNS IP here] -j ACCEPT
sudo iptables -A OUTPUT -d [Secondary DNS IP here] -j ACCEPT

# Allow related and established connections
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Allow VPN establishment
sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 53 -j ACCEPT
sudo iptables -A OUTPUT -p udp --dport 1198 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 1198 -j ACCEPT

# Accept all tun0 (VPN tunnel) connections
sudo iptables -A OUTPUT -o tun0 -j ACCEPT
sudo iptables -A INPUT -i tun0 -j ACCEPT

# Allow for nslookup to not throw an error
sudo ip6tables -I OUTPUT 1 -p udp -s 0000:0000:0000:0000:0000:0000:0000:0001 -d 0000:0000:0000:0000:0000:0000:0000:0001 -j ACCEPT

# Drop everything else (ipv4)
sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT DROP
sudo iptables -P FORWARD DROP

# Drop everything (ipv6)
sudo ip6tables -P INPUT DROP
sudo ip6tables -P OUTPUT DROP
sudo ip6tables -P FORWARD DROP

答案3

简短的解决方案

  1. 添加空组tunnel
  2. 在此组内运行 OpenVPN(使用sg tunnelGroup=tunnel用于 systemd 单元)
  3. 使用以下规则
# Local traffic is allowed
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Real interfaces are allowed only for tunnel group
iptables -I OUTPUT -o wlan+ -m owner \! --gid-owner tunnel -j REJECT
iptables -I OUTPUT -o eth+  -m owner \! --gid-owner tunnel -j REJECT
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

答案4

我刚刚遇到了这个话题,并有一些评论和一些补充信息。

我的目标是通过网络网关建立 VPN 连接和 killswitch(在 tun0 上运行)以在本地局域网上共享 VPN 服务..在服务器 IP 上(用作各种 PC 和电视上的网关等)

但我还想通过 WAN IP 上的 SSH 访问服务器!

我还想在 tun1 上运行第二个私人 VPN,这样我就可以从任何地方访问我的本地 LAN。

所以。我运行一个带有终止开关和网关的 VPN 客户端以及一个 VPN 服务器。并且我在全球 WAN IP 上拥有完整的 VPN 和 SSH 访问权限

这使得事情有点复杂。

还有这条线

#Allow related and established connections
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

将禁用 killswitch 服务器端!!!网关正常,但如果主 vpn 出现故障,程序链接 torrent 客户端等仍可访问网络。

这是我的解决方案

它运行得很好。

任何 iptables 专家能否发现设置中的任何漏洞等,请发表评论。

我已将其作为脚本来激活设置。它使调试和设置为无防火墙时更加容易。它不是真正持久的,因此要么正确提交它,要么在启动时使用 systemd 运行。

#!/bin/sh
#A link to this script runs as a systemd runscript
#Here:
#nano /usr/local/bin/fwmark.sh
echo running NEW set_iptabels

# Clean down existing rules
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -F
iptables -X
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -t nat -F
ip6tables -t nat -X
ip6tables -t mangle -F
ip6tables -F
ip6tables -X

#Start Killswitch configuration
# Allow loopback device (internal communication)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow all local traffic
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT

# Allow DNS 
iptables -A OUTPUT -d 4.2.2.2 -j ACCEPT
iptables -A OUTPUT -d 4.2.2.3 -j ACCEPT

# Allow related and established connections
# DO NOT RUN THIS---LOTS OF GUIDES SAY TO..IT DISABLES THE KILLSWITCH SERVER SIDE. GATEWAY IS OK SEVER NOT!!!!!!!!
#### DONT RUN >>iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Allow VPN establishment
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 1912 -j ACCEPT
iptables -A INPUT -p udp --sport 1912 -j ACCEPT

# Accept all tun0 (VPN tunnel) connections
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A INPUT -i tun0 -j ACCEPT

# Allow for nslookup to not throw an error
ip6tables -I OUTPUT 1 -p udp -s 0000:0000:0000:0000:0000:0000:0000:0001 -d 0000:0000:0000:0000:0000:0000:0000:0001 -j ACCEPT

# Drop everything else (ipv4)
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# Drop everything (ipv6)
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP
#End Killswitch

#Gatewate forward
#ssh port  80 etc are set to route to enp6s0 via mark 65 rule created here:
ip rule add fwmark 65 table novpn > /dev/null 2>&1;
ip route add default via 192.168.1.1 dev enp6s0 table novpn > /dev/null 2>&1;
ip route flush cache > /dev/null 2>&1;

#VPN Gateway
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o enp6s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp6s0 -o tun0 -j ACCEPT

#Set connection port for Access from WAN
#ssh force private global IP IN AND OUT
iptables -A INPUT -p tcp --sport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -o enp6s0 -p tcp -m tcp --sport 22 -m comment --comment "ssh-22" -j ACCEPT
iptables -A OUTPUT -o enp6s0 -p tcp -m tcp --dport 22 -m comment --comment "ssh-22" -j ACCEPT
iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 65
iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 65
iptables -A INPUT -i tun0 -p tcp -m tcp --sport 22 -j DROP
iptables -A INPUT -i tun0 -p tcp -m tcp --dport 22 -j DROP
iptables -A OUTPUT -o tun0 -p tcp -m tcp --sport 22 -j DROP
iptables -A OUTPUT -o tun0 -p tcp -m tcp --dport 22 -j DROP
#Private VPN ON tun1 IN AND OUT - use TCP! UDP will give endless TLS errors, that are currently unresolved.
iptables -A INPUT -p tcp --sport 1194 -j ACCEPT
iptables -A INPUT -p tcp --dport 1194 -j ACCEPT
iptables -A OUTPUT -o enp6s0 -p tcp -m tcp --sport 1194 -m comment --comment "vpn-1194" -j ACCEPT
iptables -A OUTPUT -o enp6s0 -p tcp -m tcp --dport 1194 -m comment --comment "vpn-1194" -j ACCEPT
iptables -t mangle -A OUTPUT -p tcp --sport 1194 -j MARK --set-mark 65
iptables -t mangle -A OUTPUT -p tcp --dport 1194 -j MARK --set-mark 65
iptables -A INPUT -i tun0 -p tcp -m tcp --sport 1194 -j DROP
iptables -A INPUT -i tun0 -p tcp -m tcp --dport 1194 -j DROP
iptables -A OUTPUT -o tun0 -p tcp -m tcp --sport 1194 -j DROP
iptables -A OUTPUT -o tun0 -p tcp -m tcp --dport 1194 -j DROP
#http force private global IP OUT ONLY
iptables -A INPUT -p tcp --sport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -t mangle -A OUTPUT -p tcp --sport 80 -j MARK --set-mark 65
iptables -t mangle -A OUTPUT -p tcp --sport 80 -j MARK --set-mark 65
iptables -A INPUT -i tun0 -p tcp -m tcp --sport 80 -j DROP
iptables -A INPUT -i tun0 -p tcp -m tcp --dport 80 -j DROP
#End WAN access

#Specific private VPN server setup on tun1 service Activate with>> openvpn@server start/stop/status
#Private VPN Server
 iptables -t nat -A POSTROUTING -o tun1 -j MASQUERADE
 iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp6s0 -j MASQUERADE
 iptables -A FORWARD -i tun1 -o enp6s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
 iptables -A FORWARD -i enp6s0 -o tun1 -j ACCEPT
#VPN server forward
 iptables -A FORWARD -i tun1 -o enp6s0 -s 10.8.0.0/24 -j ACCEPT
 iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
#Local LAN access
 iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp6s0 -j SNAT --to-source 192.168.1.100
# VPN Server enable tun1
 iptables -A INPUT -i tun1 -j ACCEPT
 iptables -A FORWARD -i tun1 -j ACCEPT
 iptables -A OUTPUT -o tun1 -j ACCEPT
#End Private VPN Server

#save and make persistant - remove all putput from logfile
iptables-save >/etc/iptables/rules.v4 > /dev/null 2>&1;
ip6tables-save >/etc/iptables/rules.v6 > /dev/null 2>&1;
netfilter-persistent save > /dev/null 2>&1;

相关内容