树莓派 iptables 通过 VPN 转发 DNS 请求

树莓派 iptables 通过 VPN 转发 DNS 请求

我已经使用并稍微修改了rpi-wifi 脚本使用标准 WiFi 连接设置 WiFi 接入点。一切正常。

我想设置 ExpressVPN 并让所有流量都通过它。这也能短暂地起作用,但它开始失败,因为 DNS 查找失败。

我不确定您需要什么信息,所以我将概述我已设置的内容。

  • 我已经wlan0设置为标准无线接口(192.168.1.0/24)。
  • 使用rpi-wifi上面的脚本,我创建了一个接入点接口ap0(10.10.1.1/24)
  • 当我连接 ExpressVPN 时,它会创建一个隧道接口tun0
  • dnsmasqhostapd用于dhcpcd危害上述

与 iptables 脚本唯一的不同之处就是执行以下操作:

#sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE # Allows data over non-VPN connection
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

当 Pi 启动时(VPN 未连接,且顶部 iptables 行未注释),一切都运行正常。设备可以通过界面连接ap0、浏览并执行您期望的所有操作。

当我连接到 VPN 时,这种情况会持续一小会儿(直到 DNS 需要重新查询)。如果我尝试通过 IP 地址连接到服务,一切正常,这意味着连接正常,但 DNS 查找不正常。

从每个阶段来看/etc/resolv.conf,一切都很好。当 VPN 断开连接时,名称服务器就是我的宽带路由器。当 ExpressVPN 连接时,它会设置自己的名称服务器,但通过 SSH 访问 Pi wlan0,并且一切都按命令行上的预期工作。源自 Pi 的所有流量(包括 DNS)都通过 VPN 进行。

当设备连接到ap0接口时,它会被告知名称服务器是 10.10.1.1(地址ap0和默认网关)。这似乎没问题,因为如果我动作快的话,DNS 缓存会在 VPN 连接后记住一段时间的 IP 地址。

我知道,非常关于 iptables 和所有那些废话,我知之甚少。

那么,我尝试了什么呢?嗯,很多东西。目前唯一有意义的事情(记住我之前的评论)并且考虑到我可以随时从 PI 看到我的宽带路由器,就是对来自ap0DNS 端口接口的任何东西做一些类似 NAT 的事情。我认为就是这样:

sudo iptables -t nat -A PREROUTING -i ap0 -p tcp --dport 53 -j DNAT --to 192.168.1.254:53
sudo iptables -t nat -A PREROUTING -i ap0 -p udp --dport 53 -j DNAT --to 192.168.1.254:53

这不起作用,所以我尝试了 VPN 名称服务器,因为所有其他流量都流经那里……

sudo iptables -t nat -A PREROUTING -i ap0 -p tcp --dport 53 -j DNAT --to 10.27.0.1:53
sudo iptables -t nat -A PREROUTING -i ap0 -p udp --dport 53 -j DNAT --to 10.27.0.1:53

网络上的一些脚本似乎想要设置反向连接或随时执行一些ACCEPT命令。我尝试了几十个与此类内容相关的示例:

sudo iptables -A FORWARD -i tun0 -o ap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i ap0 -o tun0 -j ACCEPT

但一切都失败了。我还尝试了一些-j MASQUERADE东西,一些-j REDIRECT事情,发现这个-o标志不起作用PREROUTING

以下是当 DNS 之外的所有东西都正常工作时我的输出iptables -S和内容(我确实注意到端口 53 流量有一个 UDP 连接,但没有 TCP 连接,添加 TCP 条目没有任何作用)。resolv.conf

pi@trmnr:~ $ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N xvpn
-N xvpn_dns
-N xvpn_dns_iface_exceptions
-N xvpn_dns_ip_exceptions
-N xvpn_ks
-N xvpn_ks_iface_exceptions
-N xvpn_ks_ip_exceptions
-A OUTPUT -j xvpn
-A xvpn -j xvpn_dns
-A xvpn -j xvpn_ks
-A xvpn_dns -j xvpn_dns_iface_exceptions
-A xvpn_dns -j xvpn_dns_ip_exceptions
-A xvpn_dns ! -o lo -p udp -m udp --dport 53 -j DROP
-A xvpn_dns_ip_exceptions -d 10.44.0.1/32 -p udp -m udp --dport 53 -j ACCEPT
-A xvpn_ks -j xvpn_ks_iface_exceptions
-A xvpn_ks -j xvpn_ks_ip_exceptions
-A xvpn_ks -p udp -m udp --dport 67:68 -j ACCEPT
-A xvpn_ks ! -o lo -j DROP
-A xvpn_ks_iface_exceptions -o tun0 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 10.0.0.0/8 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 172.16.0.0/12 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 192.168.0.0/16 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 169.254.0.0/16 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 224.0.0.0/24 -j ACCEPT
-A xvpn_ks_ip_exceptions -d 78.157.221.58/32 -j ACCEPT

pi@trmnr:~ $ cat /etc/resolv.conf
# Generated by expressvpn
search expressvpn
nameserver 10.44.0.1

pi@trmnr:~ $ sudo iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-A POSTROUTING -o tun0 -j MASQUERADE

pi@trmnr:~ $ sudo iptables -S -t mangle
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
pi@trmnr:~ $ 

这是我的/etc/dnsmasq.conf文件。

interface=lo,ap0
no-dhcp-interface=lo,wlan0
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=10.10.1.50,10.10.1.150,12h

就这server一点而言,我认为 ExpressVPN 可能会过滤掉 Google 名称服务器以解决 DNS 泄漏问题,因此我将其更改为我的宽带路由器 (192.168.1.254),该路由器在盒子上可见(如果您已通过 ssh 登录),但这仍然不起作用。我曾经想过设置 PiHole,然后通过它路由所有流量,但如果我能做到这一点,我无论如何都能将流量重定向到我的宽带路由器。

列表中还设置了一条路由,以便 Google DNS 能够通过wlan0。但这并不能解决问题。

pi@trmnr:/tmp $ sudo route add -host 8.8.8.8 gw 192.168.1.254
pi@trmnr:/tmp $ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.128.0.5      128.0.0.0       UG    0      0        0 tun0
default         192.168.1.254   0.0.0.0         UG    0      0        0 wlan0
dns.google      192.168.1.254   255.255.255.255 UGH   0      0        0 wlan0
10.0.0.0        192.168.1.254   255.0.0.0       UG    0      0        0 wlan0
10.10.1.0       0.0.0.0         255.255.255.0   U     0      0        0 ap0
10.128.0.1      10.128.0.5      255.255.255.255 UGH   0      0        0 tun0
10.128.0.5      0.0.0.0         255.255.255.255 UH    0      0        0 tun0
46.244.28.176   192.168.1.254   255.255.255.255 UGH   0      0        0 wlan0
128.0.0.0       10.128.0.5      128.0.0.0       UG    0      0        0 tun0
172.16.0.0      192.168.1.254   255.240.0.0     UG    0      0        0 wlan0
192.168.0.0     192.168.1.254   255.255.0.0     UG    0      0        0 wlan0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 wlan0

那么,有人可以帮助我从具有 VPN 连接的客户端进行 DNS 查找吗?请随时询问更多信息,以便我可以诊断发生了什么。

谢谢。

答案1

以下是它不起作用的原因:dnsmasq已设置将 DNS 查询转发到 Google 的 DNS,并添加了一条路由以始终直接路由到该主机,但是:

-A OUTPUT -j xvpn
-A xvpn -j xvpn_dns
-A xvpn_dns -j xvpn_dns_iface_exceptions
-A xvpn_dns_ip_exceptions -d 10.44.0.1/32 -p udp -m udp --dport 53 -j ACCEPT
-A xvpn_dns ! -o lo -p udp -m udp --dport 53 -j DROP

此 iptables 规则链(显然是由 ExpressVPN 添加的)将所有 DNS 流量丢弃到非本地主机接口,链内部没有出现异常xvpn_dns_iface_exceptions

因此,解决方案要么是配置 ExpressVPN 不丢弃任何非 VPN DNS 流量,要么“快速而粗糙地”在 iptables 中添加例外(请注意,使用插入命令而不是附加命令,以确保位于规则前面-A xvpn):

iptables -I OUTPUT 1 -p udp --dport 53 -d 8.8.8.8 -j ACCEPT

相关内容