我看到过一些涉及静态 DNS、openVPN 服务器推送等的问题,但它们都不适用,或者它们需要 GUI 工具,而我正在使用通过 SSH 进入的无头 Ubuntu Core。
root@redacted:~# lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 14.04.3 LTS
Release: 14.04
Codename: trusty
当机器仅通过 eth0 连接到本地网络时,一切正常。我可以直接 ping IP(8.8.8.8)并解析域名(google.com)。
wget -q -O - ipecho.net/plain #Shows my ISPs provided Public IP
当机器使用 VPN 网络通过 tun0 连接时,我可以直接 ping IP(8.8.8.8)并解析域名(google.com)。
wget -q -O - ipecho.net/plain #Shows my VPNs provided Public IP
到目前为止一切都如预期...
现在问题来了...我添加以下 iptables 规则来强制特定用户只能使用 tun0 适配器:
sudo iptables -A OUTPUT -m owner --gid-owner vpnonly -o lo -j ACCEPT
sudo iptables -A OUTPUT -m owner --gid-owner vpnonly -o eth0 -p tcp -d 192.168.x.x/24 --sport xxxx -j ACCEPT
sudo iptables -A OUTPUT -m owner --gid-owner vpnonly \! -o tun0 -j REJECT
如果你好奇的话,第二条规则允许以用户 vponly 身份运行的基于 Web 的 UI 在我的本地网络上访问。
所以现在,当我运行那些我不想通过我的公共 IP 进行通信的进程时,为了防止 VPN 出现故障/断开连接/等情况而发生泄漏,我只需在 vpnonly 下运行它们,而 vpnonly 的唯一组就是 vpnonly。然而当我以 vpnonly 身份运行进程时,我可以直接 ping IP(8.8.8.8)但是我不能解析域名(google.com)。
root@redacted:~# sudo -u vpnonly ping -c 2 google.com
ping: unknown host google.com
即使我可以让它再次解析域名,那也将令人满意,但我真正想做的是将 VPN 设置为使用单独的特定 DNS,同时让 eth0 使用 8.8.8.8、8.8.4.4。
我已经在 Google 上搜索了所有我能想到的与此相关的内容,但无法解决...我希望我已经添加了足够的细节,但很乐意根据要求添加更多内容
编辑 1:完整的 iptables
root@redacted:~# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere owner GID match vpnonly
ACCEPT tcp -- anywhere 192.168.x.x/24 owner GID match vpnonly tcp spt:xxxx
REJECT all -- anywhere anywhere owner GID match vpnonly reject-with icmp-port-unreachable
-
root@redacted:~# iptables -L -v
Chain INPUT (policy ACCEPT 16407 packets, 12M bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 6230 packets, 675K bytes)
pkts bytes target prot opt in out source destination
3751 2800K ACCEPT all -- any lo anywhere anywhere owner GID match vpnonly
6635 3332K ACCEPT tcp -- any eth0 anywhere 192.168.x.x/24 owner GID match vpnonly tcp spt:xxxx
4 224 REJECT all -- any !tun0 anywhere anywhere owner GID match vpnonly reject-with icmp-port-unreachable
编辑2:
在添加 iptables 规则之前,一切都运行正常,此时我遇到的唯一问题是域名解析。我的 vpn 还提供非日志 DNS。解决方案是将我的 /etc/network/interfaces 名称服务器条目从 192.168.x.1 更改为我的 VPN 提供的 DNS IP 地址,然后在拒绝之前允许所有到该 DNS IP 的连接吗?我想在尝试之前问一下,一是确保它像我认为的那样安全,二是我无论如何都会提供赏金。我想确保没有泄漏,并且不想通过 DNS 引入泄漏...
经过进一步的启发,我是否应该在拒绝之前明确允许 192.168.x.1 和 VPN DNS IP,而不是修改接口?
我真正想做的是强制这些 DNS 查询通过 tun0 适配器,尽可能使用户“vponly”与外界的任何通信都通过 VPN。
答案1
第一个问题是,您能访问您的 DNS 服务器吗?如果您阻止了除 tun0 之外的所有服务器的访问,则您很可能阻止了 DNS 访问。
如果您在本地运行某种 DNS 服务器,比如 Bind 或 dnsmasq,那么该服务也需要能够访问互联网。
我建议在拒绝之前向您的 iptables 添加一个日志条目,以查看哪些流量被拒绝。
使用端口 53 是破坏安全性的标准方法,因此打开 *:53 可能不明智,因此最好专门指定您的 DNS 服务器(本地和上游)作为可接受的流量目标。我假设 --sport xxxx 的意思是您正在为您的 Web 服务使用非标准端口而不是 :80。如果不是,您应该在 192.168 规则中指定它(对于 IP 也是如此,它应该是完整的 /32 地址)。
另外别忘了,如果您想使用 ping 进行测试,您需要为 ICMP 设置 iptable 条目。ICMP 8(echo)是 ping,ICMP 0 是 ping 回复。
还需要考虑您拥有哪些路由,因为您需要确保流量的默认路由是 tun0。如果 tun0 是唯一允许的接口,您需要确保所需的所有路由都通过该接口发送流量。
如果这不能诊断出您的问题,请使用 ethtool 进行一些网络嗅探,以查看哪些对话正在进行,哪些对话没有进行。这可能是一些奇怪的事情,例如允许 REQ,但 ACK 没有返回。
答案2
一种简单的方法是创建一个服务 .conf,它将保留您喜欢的任何 iptables 规则。
您可以安装一个包来执行此操作,但手动方式如下:
sudo vi /etc/init/persist-iptables.conf
你可以随意命名,只要确保它/etc/init/
以.conf
然后您要插入以下几行:
description "Persist IPTables on Boot"
start on runlevel [2345]
script
# Accept all loopback traffic localhost or 127.0.0.1
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Accept any DNS traffic, I use a DD-WRT router with
# Force DNS Redirection to a non-logging DNS
iptables -A OUTPUT -d 255.255.255.255 -j ACCEPT
iptables -A INPUT -s 255.255.255.255 -j ACCEPT
# Accept all local traffic from 192.168.1.1-192.168.1.255
iptables -A INPUT -s 192.168.1.0/24 -d 192.168.1.0/24 -j ACCEPT
iptables -A OUTPUT -s 192.168.1.0/24 -d 192.168.1.0/24 -j ACCEPT
# Forward all eth0, eth1, etc through tun interfaces
iptables -A FORWARD -i eth+ -o tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -o eth+ -j ACCEPT
# Postroute masquerade through tun interfaces
iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
# Drop any other traffic through eth adapters
iptables -A OUTPUT -o eth+ ! -d a.b.c.d -j DROP
end script
现在,当你的系统重新启动时(这会清除你的 IP 表),它将自动运行以再次更新 iptables。你也可以自己调用它sudo service persist-iptables start
该文件将允许所有本地主机流量,允许所有 DNS 流量(您需要确保它是来自路由器的正确 DNS),允许所有本地流量,将流量从 eth 适配器转发到 tun 适配器并对其进行后路由屏蔽,最后丢弃任何其他流量。