我有一个 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_forwardWindows 有不同的启用 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 服务器创建的以太网设备