iptables 规则允许 VPN 上的设备访问互联网

iptables 规则允许 VPN 上的设备访问互联网

我有一个 Linux 防火墙设置为我的家庭网络网关,它正确地将 IP 地址出租给我网络上的设备,并且这些设备可以访问互联网。

我也在同一台机器上设置了 OpenVPN,它已启动并运行,并分配了 IP 地址,我可以从手机访问 VPN。但是,VPN 上的设备无法访问互联网,我不知道原因。

以下是我正在使用的 iptables 规则:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# enp2s0 is WAN interface, enp1s0 is LAN interface, tun0 is vpn interface
-A POSTROUTING -o enp2s0 -j MASQUERADE
-A POSTROUTING -s 10.8.0.0/8 -o enp2s0 -j MASQUERADE

COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# block invalid packets
-A PREROUTING -m conntrack --ctstate INVALID -j DROP

# block fragmented packets (may be unnecessary)
#-A PREROUTING -f -j DROP

# block new packets that are not SYN
-A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP

# block uncommon MSS values
-A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP

# block packets with bogus TCP flags
-A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
-A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
-A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
-A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
-A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
-A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
-A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
-A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

# block packets from private subnets (spoofing)
-A PREROUTING -s 224.0.0.0/3 -j DROP
-A PREROUTING -s 169.254.0.0/16 -j DROP
-A PREROUTING -s 172.16.0.0/12 -j DROP
-A PREROUTING -s 192.0.2.0/24 -j DROP
#-A PREROUTING -s 192.168.0.0/16 -j DROP
-A PREROUTING -s 10.0.0.0/8 -j DROP
-A PREROUTING -s 0.0.0.0/8 -j DROP
-A PREROUTING -s 240.0.0.0/5 -j DROP
-A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
# Service rules

# Log all input and forward connections
-A INPUT -j LOG
-A FORWARD -j LOG

# basic global accept rules - ICMP, loopback, traceroute, established all accepted
-A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT
#-A OUTPUT -o lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
# the below rule might require ,RELATED if things fail, such as OpenVPN
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#-A INPUT -m conntrack --ctstate RELATED -j ACCEPT
#-A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

# enable traceroute rejections to get sent out
-A INPUT -p udp -m udp --dport 33434:33523 -j REJECT --reject-with icmp-port-unreachable

# DNS - accept from LAN and VPN
-A INPUT -i enp1s0 -p tcp --dport 53 -j ACCEPT
-A INPUT -i enp1s0 -p udp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p tcp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p udp --dport 53 -j ACCEPT

# SSH - accept from LAN and VPN; note that SSH on this machine uses a non-standard port
-A INPUT -i enp1s0 -p tcp --dport 123 -j ACCEPT
-A INPUT -i tun0 -p tcp --dport 123 -j ACCEPT

# OpenVPN - accept from WAN; note that OpenVPN on this machine uses port 443 to try to get past client network filtering
-A INPUT -i enp2s0 -p tcp --dport 443 -j ACCEPT
#-I INPUT -i tun0 -j ACCEPT
-I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# DHCP client requests - accept from LAN and VPN
-A INPUT -i enp1s0 -p udp --dport 67:68 -j ACCEPT
-A INPUT -i tun0 -p udp --dport 67:68 -j ACCEPT

# drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# drop connections from hosts that have more than 80 established connections (prevents connection attacks)
-A INPUT -p tcp -m connlimit --connlimit-above 80 -j REJECT --reject-with tcp-reset

# limit the new TCP connections that a client can establish per second, reducing connection attacks
-A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
-A INPUT -p tcp -m conntrack --ctstate NEW -j DROP

# block port scanning
-N port-scanning
-A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
-A port-scanning -j DROP

# block HTTPS ads
#-A INPUT -p udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
#-A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
#-A INPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable

# drop all other inbound traffic
-A INPUT -j DROP

# Forwarding rules

# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# forward from LAN (enp1s0) to WAN (enp2s0)
-A FORWARD -i enp1s0 -o enp2s0 -j ACCEPT

# forward from VPN (tun0) to WAN (enp2s0)
-A FORWARD -i tun0 -o enp2s0 -j ACCEPT

# drop all other forwarded traffic
-A FORWARD -j DROP

COMMIT

我缺少什么来允许 VPN 上的设备访问互联网?

答案1

听起来您的客户端(如果是 Android/iOS)启用了无缝隧道选项,或者 iptables NAT 启用命令正在干扰隧道(不太可能)。检查您的阻止规则,确保它们没有阻止错误的子网。

另外(如果您的服务器运行的是 Linux 版本),请确保内核中启用了 IP 转发。要执行此操作(以管理员身份运行):

echo 1 > /proc/sys/net/ipv4/ip_forward
Windows 有不同的启用 IP 转发的方法。本文应该对你有所帮助。

答案2

我在虚拟机中做了你正在尝试的事情。我创建了两台机器,机器 A 有两个以太网设备。一台设备连接到互联网,另一台连接到第二台虚拟机 B。

只需以下几行代码即可使机器 B 能够使用机器 A 的 Internet 或 VPN 连接。

vm1@vm1:~$ catfirewall01.sh
/bin/bash #!/bin/bash

#sudo iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
#sudo iptables -A FORWARD -i enp0s3 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
#sudo iptables -A FORWARD -i enp0s8 -o enp0s3 -j ACCEPT


sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o enp0s8 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i enp0s8 -o tun0 -j ACCEPT

我也确实编辑了/etc/sysctl.conf

# 取消注释下一行以启用 IPv4 数据包转发
网.ipv4.ip_forward=1

之后运行sudo sysctl -p以使更改立即生效。

  • enp0s3是连接到互联网的以太网设备。
  • enp0s8是连接到本地机器B的以太网设备。
  • tun0是从 openvpn 创建的以太网设备

为了测试目的,我将默认策略设置为接受。

vm1@vm1:~$ sudo iptables -L
链输入(策略接受)
目标 保护 优化 源 目标         

链转发(策略接受)
目标 保护 优化 源 目标         
接受所有 -- 任何地方任何地方状态 RELATED,ESTABLISHED
接受所有 -- 任何地方 任何地方            

链输出(策略接受)
目标 保护 优化 源 目标

顺便说一下,openvpn-client-script 看起来像这样:

客户
开发调谐
原始 UDP
远程服务器 IP 服务器端口
不绑定
解析-重试无限
验证 SHA512
密码 AES-256-CBC
密钥大小 256
康普
动词 2
静音重播警告
ns-cert-type 服务器
持久密钥
坚持-tun
方向键 1
ca /path/to/file.crt
tls-auth /path/to/file.key 1
auth-user-pass /路径/到/文件
身份验证无缓存
脚本安全 2
启动/etc/openvpn/update-resolv-conf
关闭/etc/openvpn/update-resolv-conf

---------------------------------------------

**编辑** 我希望这次能满足你的要求。

我刚刚创建了以下设置:

  • 计算机A上有一个openvpn-server
  • 我的笔记本电脑 B 上有一个 openvpn-client
  • 通过 umts 从我的笔记本电脑 B 到我家里的电脑 A 创建了一个 vpn 连接,这样我就可以使用电脑 A 的 ip 地址在笔记本电脑 B 上浏览网页

我使用以下脚本创建了我的 openvpn-server:

猫/etc/openvpn/server.conf
端口 11194
原始 UDP
开发tun10
tun-mtu 1500
mssfix 1450
ca /etc/openvpn/easy-rsa/keys/ca.crt
证书 /etc/openvpn/easy-rsa/keys/ca.crt
密钥 /etc/openvpn/easy-rsa/keys/ca.key
dh /etc/openvpn/easy-rsa/keys/dh2048.pem
服务器 10.9.0.0 255.255.255.0
推“重定向网关 def1 旁路-dhcp”
客户对客户
保持活动 5 60
康普
持久密钥
坚持-tun
#用户 openvpn
#group openvpn
状态 openvpn-SERVER-status.log
动词 6
密码 AES-256-CBC

通过 VPN 实现 DNS 重定向的最重要的设置应该是:推“重定向网关 def1 旁路-dhcp”

之后编辑以下行/etc/sysctl.conf

# 取消注释下一行以启用 IPv4 数据包转发
网.ipv4.ip_forward=1

然后运行sudo sysctl -p

接下来创建 iptables 规则:虽然每个策略都设置为接受我需要执行的命令如下:iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE

  • enp0s3 是计算机 A 连接到互联网的以太网卡。

vpn 客户端脚本

客户端笔记本电脑 B 使用以下脚本连接到计算机 A 上的 vpn 服务器

 
客户
#tls 客户端
#键方向 1
原始 UDP
端口 11194
远程 some.dyndns.org
开发调谐
#持久密钥
#persist-tun
#tun-mtu 1500
#mssfix 1450
#无约束
#resolv-retry 无限次
保持活动 5 60
康普
密码 AES-256-CBC
ca /home/alex/Downloads/dellvpn/ca.crt
证书 /home/alex/Downloads/dellvpn/dell-inspirion.crt
密钥 /home/alex/Downloads/dellvpn/dell-inspirion.key
动词 2
脚本安全 2
启动/etc/openvpn/update-resolv-conf
关闭/etc/openvpn/update-resolv-conf

对我来说最重要的台词是最后三行. 这些可以防止 Linux 系统上的 DNS 泄漏。https://dnsleaktest.com/what-is-a-dns-leak.html

此时我可以使用计算机 A 的 IP 使用笔记本电脑 B 进行浏览。


**IPTABLES 策略为 DROP**

当我将默认的 iptables 策略改为 drop 后,事情就变得复杂了。最后我成功使用了以下脚本:

/bin/bash #!/bin/bash

##SCRIPT-SNIPPET 取自 https://wiki.debianforum.de/Einfaches_Firewall-Script


IPTABLES="/sbin/iptables"

# 设置服务端口
#------------------------------------------------------------------------------

pSSH="22"
pDNS="53"
pHTTP="80"
pHTTPS="443"
pOPENVPN="-p UDP --dport 11194"
pNTP="123"

# 设置网络
#------------------------------------------------------------------------------
LOCALNET="192.168.178.0/24"
VPNNET="10.9.0.0/24"


# 默认策略。
#------------------------------------------------------------------------------

# 默认放弃一切。
$IPTABLES -P 输入删除
$IPTABLES -P 向前删除
$IPTABLES -P 输出删除

# 将 nat/mangle/raw 表的链设置为 ACCEPT
$IPTABLES -t nat -P 预路由接受
$IPTABLES -t nat -P 输出接受
$IPTABLES -t nat -P POSTROUTING 接受

$IPTABLES -t mangle -P 预路由接受
$IPTABLES -t mangle -P 输入接受
$IPTABLES -t mangle -P 转发接受
$IPTABLES -t mangle -P 输出接受
$IPTABLES -t mangle -P POSTROUTING 接受

# 清理。
#------------------------------------------------------------------------------

# 删除所有
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F

# 删除所有
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X

# 将所有数据包和计数器清零。
$IPTABLES -Z
$IPTABLES -t nat -Z
$IPTABLES -t mangle -Z


# 允许环回接口执行任何操作。
$IPTABLES -A 输入 -i lo -j 接受
$IPTABLES -A 输出 -o lo -j 接受

# 允许与现有允许连接相关的传入连接。
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许传出连接,除非无效
$IPTABLES -A OUTPUT -m 状态 --状态 ESTABLISHED,RELATED -j ACCEPT


# 转发 OpenVPN
#------------------------------------------------------------------------------
### 取自 https://github.com/Nyr/openvpn-install/blob/master/openvpn-install.sh 的安装脚本

IP = $(ip 地址 | grep'inet'| grep -v inet6 | grep -vE'127 \。[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3}'| grep -o -E'[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3}'| head -1)
$IPTABLES -t nat -A POSTROUTING -s $VPNNET -j SNAT --to $IP
$IPTABLES -I FORWARD -s $VPNNET -j ACCEPT
$IPTABLES -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT


# 有选择地允许某些出站连接,阻止其余连接。
#------------------------------------------------------------------------------

# 允许 DNS。如果没有这个,几乎什么都做不了。
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport $pDNS -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pDNS -j ACCEPT


# 允许 HTTP。
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pHTTP -j ACCEPT

# 允许 HTTPS。
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport $pHTTPS -j ACCEPT

# 允许 NTP。
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport $pNTP -j ACCEPT


# 有选择地允许某些入站连接,阻止其余连接。
#------------------------------------------------------------------------------

# 允许入站 OPENVPN 请求。
$IPTABLES -A INPUT -m state --state NEW $OPENVPN -j ACCEPT

# 允许来自指定 IP 范围的入站 SSH 请求。
$IPTABLES -A INPUT -m state --state NEW -s $LOCALNET -p tcp --dport $pSSH -j ACCEPT
$IPTABLES -A 输入 -m 状态 --state NEW -s $VPNNET -p tcp --dport $pSSH -j 接受

# 正常退出。
#------------------------------------------------------------------------------

    出口 0

最重要的布线应该是:

# 转发 OpenVPN
#------------------------------------------------------------------------------
### 取自 https://github.com/Nyr/openvpn-install/blob/master/openvpn-install.sh 的安装脚本

IP = $(ip 地址 | grep'inet'| grep -v inet6 | grep -vE'127 \。[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3}'| grep -o -E'[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3} \。[0-9]{1,3}'| head -1)
$IPTABLES -t nat -A POSTROUTING -s $VPNNET -j SNAT --to $IP
$IPTABLES -I FORWARD -s $VPNNET -j ACCEPT
$IPTABLES -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

确保$VPNNET在 openvpn-server.conf 中设置为适当的 IP

作为替代方案前向规则上面,我还能够成功创建隧道并使用以下几行浏览网页:

# 转发 OpenVPN
#------------------------------------------------------------------------------

$IPTABLES -t nat -A POSTROUTING -o tun10 -j MASQUERADE
$IPTABLES -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
$IPTABLES -I 转发 -o enp0s3 -i tun10 -j 接受
$IPTABLES -I 转发 -i enp0s3 -o tun10 -j 接受
  • enp0s3 是连接到互联网的以太网卡
  • tun10 是从我的 openvpn 服务器创建的以太网设备

相关内容