IPTABLES:丢弃所有离开 eth0 接入点的非 VPN 数据包

IPTABLES:丢弃所有离开 eth0 接入点的非 VPN 数据包

项目:
我正在为办公室的每个工作站构建一个便携式 VPN 盒,使用树莓派 3 B+OpenVPN,每个都配备了 LCD 屏幕和按钮,以便我的员工可以随时选择 VPN 提供商、服务器和网络。网络连接通过以下方式提供wlan0,通过tun0/VPN并转发至eth0它充当工作机器的安全接入点。我使用 Raspberry Pi 进行路由,因为我非常喜欢网络隔离的想法以及根据需要修改设备的能力。

问题:
IPTABLES 用于审核网络流量,以防止非 VPN 数据包离开网络,除非其目的地是 VPN 服务器。我使用的规则运行良好,工作站拥有安全网络,但是,一旦 OpenVPN 被关闭,非 VPN 数据包仍会转发到工作站。即使通过关闭 OpenVPN 删除了 tun0 接口,工作站仍会保持工作连接。数据包在 Pi 上丢失得很好。

我尝试通过插入/删除来解决这个问题tun0 伪装通过 DHCP 钩子、DHCPCD 钩子(系统和用户钩子)和 if.down/if.up 脚本来控制规则。DHCPCD 钩子与非 tun0接口。不过我更愿意在数据包级别解决这个问题,因为这似乎是最安全的途径。任何建议都将不胜感激。

摘自 Bash 脚本:

# INTERFACES
NIC_WLAN=wlan0
NIC_ETH=eth0
NIC_TUN=tun0

# ISOLATE SERVER URL & WLAN GATEWAY ADDRESS
VPN_SERVER=`cat $vpn_file | grep -m 1 "remote*" | tr -s " " | cut -d " " -f2`
GATEWAY=`route -n | grep $NIC_WLAN | egrep "^0\.0\.0\.0" | tr -s " " | cut -d " " -f2`

# START OPENVPN
openvpn --config $vpn_file --auth-user-pass ./express_vpn/auth.conf &

# FLUSH IPTABLE RULES & USER CHAINS
iptables -F
iptables -X VPN

# IPTABLES POLICY
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

# CREATE NEW IPTABLE CHAINS
iptables -N VPN

# TUN0/ETH0 FORWARDING
iptables -t nat -A POSTROUTING -o $NIC_TUN -j MASQUERADE
iptables -A FORWARD -i $NIC_TUN -o $NIC_ETH -m state --state RELATED,ESTABLISHED -j RETURN
iptables -A FORWARD -i $NIC_ETH -o $NIC_TUN -j RETURN

# PACKET EXCEPTIONS
iptables -A VPN -o lo -j RETURN
iptables -A VPN -o $NIC_TUN -j RETURN
iptables -A VPN -o $NIC_ETH -j RETURN
iptables -A VPN -d 127.0.0.1 -j RETURN
iptables -A VPN -d $GATEWAY -j RETURN
iptables -A VPN -d $VPN_SERVER -j RETURN

# DROP REMAINING PACKETS
iptables -A VPN -j DROP

# OUTBOUND TRAFFIC RULES
iptables -A OUTPUT -p tcp --syn -j VPN
iptables -A OUTPUT -p icmp -j VPN
iptables -A OUTPUT -p udp -j VPN

# DNS HANDLER: CLOUDFLARE
echo "nameserver 1.1.1.1" > /etc/resolv.conf

iptables -S

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N PIBOX
-N VPN
-A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j RETURN
-A FORWARD -i eth0 -o tun0 -j RETURN
-A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j VPN
-A OUTPUT -p icmp -j VPN
-A OUTPUT -p udp -j VPN
-A VPN -o lo -j RETURN
-A VPN -o tun0 -j RETURN
-A VPN -o eth0 -j RETURN
-A VPN -d 127.0.0.1/32 -j RETURN
-A VPN -d 192.168.0.1/32 -j RETURN
-A VPN -d 185.192.16.18/32 -j RETURN
-A VPN -d 185.192.16.3/32 -j RETURN
-A VPN -d 185.192.16.8/32 -j RETURN
-A VPN -d 185.192.16.13/32 -j RETURN
-A VPN -j DROP

iptables -t nat -L

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

lsb_release -a

No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster


2019 年 11 月 16 日更新

如果您想要一个安全的设计,请颠倒您的逻辑 - 首先拒绝一切,然后允许您想要的例外。

经过几个小时的表格操作和手册阅读,这个建议似乎非常有效!数据包在工作站上顺利丢弃。此外,这种方法确实帮助我在反复试验期间直观地了解了路由过程,尽管我离您这些网络专家还有很长的路要走。

下面提供的是新的 Raspi IPTABLES 和tun0我正在使用的上/下脚本向上向下下行OpenVPN 中的选项。

摘自 Bash 脚本:

# INTERFACES
NIC_WLAN=wlan0
NIC_ETH=eth0
NIC_TUN=tun0

# ISOLATE VPN PORT, WLAN GATEWAY, ETH0 INET
GATEWAY_WLAN=`route -n | grep $NIC_WLAN | egrep "^0\.0\.0\.0" | tr -s " " | cut -d " " -f2`
VPN_PORT=`cat $vpn_file | grep -m 1 "remote*" | cut -d " " -f3`
INET_ETH=`route -n | grep $NIC_ETH | cut -d " " -f1`

# CLEAR IPTABLES
iptables -F
iptables -X
iptables -t nat -F

# SET IPTABLES POLICY TO DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# ALLOW LOCAL HOST COMMUNICATION
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# ALLOW ETH > ETH COMMUNICATION
iptables -A INPUT -s $INET_ETH/24 -d $INET_ETH/24 -j ACCEPT
iptables -A OUTPUT -s $INET_ETH/24 -d $INET_ETH/24 -j ACCEPT

# ALLOW OUTBOUND UDP PACKETS VIA VPN PORT
iptables -A OUTPUT -p udp --dport $VPN_PORT -j ACCEPT

# ALLOW TUN IFACE TRAFFIC
iptables -A INPUT -i $NIC_TUN -j ACCEPT
iptables -A OUTPUT -o $NIC_TUN -j ACCEPT

# ALLOW TUN/ETH FORWARDING
iptables -A FORWARD -i $NIC_TUN -o $NIC_ETH -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $NIC_ETH -o $NIC_TUN -j ACCEPT

# ALLOW ESTABLISHED & RELATED INPUTS
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# LOG & DROP ALL REMAINING PACKETS
if [[ $1 = "log" ]] || [[ $1 = "LOG" ]]; then
    iptables -A INPUT -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
    iptables -A FORWARD -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
    iptables -A OUTPUT -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
fi
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
iptables -A OUTPUT -j DROP

# DNS HANDLER: CLOUDFLARE
echo "nameserver 1.1.1.1" > /etc/resolv.conf

# START OPENVPN
openvpn --config $vpn_file --auth-user-pass ./$vpn_provider/auth.conf &

/etc/openvpn/tun_up

#!/bin/bash
NIC_TUN=tun0
NIC_ETH=eth0
iptables -t nat -I POSTROUTING -o $NIC_TUN -j MASQUERADE
iptables -I INPUT 1 -i $NIC_ETH -d 255.255.255.255 -j ACCEPT

/etc/openvpn/tun_down

#!/bin/bash
NIC_TUN=tun0
NIC_ETH=eth0
iptables -t nat -D POSTROUTING -o $NIC_TUN -j MASQUERADE
iptables -D INPUT -i $NIC_ETH -d 255.255.255.255 -j ACCEPT

iptables -S

-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
-A INPUT -d 255.255.255.255/32 -i eth0 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s 192.168.0.0/24 -d 192.168.0.0/24 -j ACCEPT
-A INPUT -s 192.168.220.0/24 -d 192.168.220.0/24 -j ACCEPT
-A INPUT -i tun0 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
-A INPUT -j DROP
-A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o tun0 -j ACCEPT
-A FORWARD -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -s 192.168.0.0/24 -d 192.168.0.0/24 -j ACCEPT
-A OUTPUT -s 192.168.220.0/24 -d 192.168.220.0/24 -j ACCEPT
-A OUTPUT -p udp -m udp --dport 1195 -j ACCEPT
-A OUTPUT -o tun0 -j ACCEPT
-A OUTPUT -j LOG --log-prefix "IPT_DROPPED: " --log-level 7
-A OUTPUT -j DROP

iptables -t nat -S

-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-A POSTROUTING -o tun0 -j MASQUERADE

DNS 泄漏在使用这些规则的工作站上发生了一些问题,在 OpenVPN 被终止后,ping 请求得到解决,因此我执行了以下命令来进一步加强 CloudFlare 名称服务器的使用:

echo "resolv-file=/etc/resolv.conf" > /etc/dnsmasq.conf
sed -i '/dnsmasq_resolv=/d' /etc/resolvconf.conf

答案1

你的基本逻辑不安全 - 你的默认转发策略是接受,然后您的 VPN 丢弃策略仅匹配与 VPN 接口相关的内容。这就是你的问题……

如果您想要一个安全的设计,请颠倒您的逻辑 - 首先拒绝一切,然后允许您想要的例外。

如果您使用 NAT,您可能还希望允许已建立和相关的流量。此外,您应该全局允许 ICMP 并查看 MTU 限制,因为这些将抵消 VPN 开销引起的一些问题。

相关内容