Iptables

IPTABLES:丟棄所有退出 eth0 接入點的非 VPN 數據包

  • November 16, 2019

項目:

我正在使用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 中的updowndown-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 成本引起的問題。

引用自:https://serverfault.com/questions/991217