IPTABLES:丟棄所有退出 eth0 接入點的非 VPN 數據包
項目:
我正在使用Raspberry Pi 3 B+和OpenVPN為我辦公室的每個工作站建構一個攜帶式 VPN 盒,每個都配備一個 LCD 螢幕和按鈕,以便我的員工可以即時選擇 VPN 提供商、伺服器和網路。通過wlan0提供網路連接,通過tun0/VPN路由並轉發到eth0,後者充當工作機器的安全訪問點。我正在使用 Raspberry Pi 進行路由,因為我真的很喜歡網路隔離的想法和我認為合適的修改設備的能力。
問題:
IPTABLES 被用於審核網路流量,以防止非 VPN 數據包離開網路,除非它的目標是 VPN 伺服器。我使用的規則執行良好,並且為工作站提供了安全網路,但是,一旦 OpenVPN 被終止,非 vpn 數據包仍會轉發到工作站。即使通過關閉 OpenVPN 刪除了 tun0 介面,工作站仍然保持工作連接。數據包在 Pi 本身上丟棄得很好。
我試圖通過 DHCP 掛鉤、DHCPCD 掛鉤(系統和使用者掛鉤)和 if.down/if.up 腳本插入/刪除tun0 MASQUERADE規則來解決此問題。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 up/down 腳本,我通過 OpenVPN 中的up、down和down-pre選項使用它們。
摘自 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
您的基本邏輯是不安全的 - 您的預設轉發策略是接受,**然後您的 VPN 丟棄策略只匹配與 VPN 介面相關的內容。**這是你的問題..
如果您想要一個安全的設計,請顛倒您的邏輯 - 從拒絕一切開始,然後允許您想要的例外。
如果您使用的是 NAT,您可能還希望允許已建立的和相關的流量。此外,您應該全域允許 ICMP 並查看 MTU 箝位,因為這些將抵消一些由 VPN 成本引起的問題。