我想配置一个 Openvpn 实例,该实例能够根据客户端的子网限制访问。例如,有两个客户端组/子网 A 和 B,网络 A 的用户可以连接到网络 B 的客户端,但 B 的客户端看不到 A 客户端。
Openvpn-HowTo-Site 上有一个例子,它与我的目标部分相似(https://openvpn.net/community-resources/how-to/#policy)。我按照那里的解释操作,最终的 server.conf 如下所示(我删除了一些部分,例如 ca.crt/key 和密码的路径,因为它们对于这个问题并不重要):
port 1194
proto udp
dev tun
topology subnet
server 10.9.0.0 255.255.255.0
client-config-dir ccd
route 10.9.1.0 255.255.255.0
route 10.9.2.0 255.255.255.0
client-to-client
verb 3
通过此配置,我可以使用三个子网: - 10.9.0.0/24 - 10.9.1.0/24 - 10.9.2.0/24
因此,如果客户端连接并且其 CN 在 ccd 目录中没有文件,则该客户端将获得 10.9.0.0/24 网络的 IP。此方法有效,并且此网络内的客户端可以相互 ping 通,并可以 ping 服务器 10.9.0.1。
如果我现在在 ccd 目录中为 CN 创建一个文件,内容如下
ifconfig-push 10.9.2.2 255.255.255.0
客户端可以连接到服务器并获取 IP 10.9.2.2。我的日志中没有错误或警告,我认为最有趣的一行可能是这一行:
Mon Nov 12 15:06:40 2018 PUSH: Received control message: 'PUSH_REPLY,route-gateway 10.9.0.1,topology subnet,ping 10,ping-restart 120,ifconfig 10.9.2.2 255.255.255.0'
但是:我无法与服务器通信:
PING 10.9.0.1 (10.9.0.1) 56(84) bytes of data.
From 62.155.YYY.XXX icmp_seq=1 Destination Host Unreachable
From 62.155.YYY.XXX icmp_seq=2 Destination Host Unreachable
对 10.9.2.1 执行 ping 操作会导致 100% 数据包丢失。我的 VPN 配置中缺少什么才能与服务器通信?
我尝试添加一个 iptables 规则(服务器上启用了 ipv4 转发)
iptables -I FORWARD -i tun0 -s 10.9.2.0/24 -d 10.9.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
但没有效果。我还尝试了:
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d 10.66.4.4 -j ACCEPT
但也没有效果。不幸的是,我是 iptables 方面的新手,我希望有人能发现这个问题。但我也不确定这是否真的是 iptables 问题,因为也许我的服务器配置需要将路由推送到客户端?我没有找到关于这个问题的很好的解释,我尝试的所有推送路由都导致错误。
编辑:我还尝试在我的 server.conf 中推送路由:
push "route 10.9.0.0 255.255.255.0"
push "route 10.9.1.0 255.255.255.0"
push "route 10.9.2.0 255.255.255.0"
但这导致
Tue Nov 13 09:40:25 2018 /sbin/ip route add 10.9.0.0/24 via 10.9.0.1
RTNETLINK answers: Network is unreachable
Tue Nov 13 09:40:25 2018 ERROR: Linux route add command failed: external program exited with error status: 2
Tue Nov 13 09:40:25 2018 /sbin/ip route add 10.9.1.0/24 via 10.9.0.1
RTNETLINK answers: Network is unreachable
Tue Nov 13 09:40:25 2018 ERROR: Linux route add command failed: external program exited with error status: 2
Tue Nov 13 09:40:25 2018 /sbin/ip route add 10.9.2.0/24 via 10.9.0.1
RTNETLINK answers: Network is unreachable
Tue Nov 13 09:40:25 2018 ERROR: Linux route add command failed: external program exited with error status: 2
编辑2::我读过一篇 openvpn 论坛帖子,其中指出,上述 HOWTO-policy-example (https://openvpn.net/community-resources/how-to/#policy) 使用三个服务器实例,而不是一个。这一点我之前并不清楚,因为 HOWTO 中没有提到。我再也找不到这篇文章的 URL,但我很感兴趣,是否仍然可以配置一个带有多个子网的 openvpn-server
答案1
我设法通过将服务器设置为 /16 而不是 /24 并将客户端到客户端设置为 false 来实现这一点,因为流量在到达 OpenVPN 服务器的 IP 层之前将被转发,iptables 将无法限制流量(参见此帖)
server.conf
...
server 10.9.0.0 255.255.0.0 # Subnet mask /16 instead of /24
;route 10.9.1.0 255.255.255.0 # These were not needed when the subnet mask is /16
;route 10.9.2.0 255.255.255.0 # These were not needed when the subnet mask is /16
;client-to-client
...
对于 ccd 目录中的客户端配置,我们还需要更新子网掩码。从 255.255.255.0 到 255.255.0.0
ifconfig-push 10.9.2.2 255.255.0.0
现在你只需要添加适当的 iptable 规则。根据你的设置,可能需要更多配置。我遵循这因为我对 iptables 还不太熟悉,所以先看一个示例。下面是一些可能有用的示例。
# Make sure established packets are allowed
iptables -A FORWARD -i tun0 -o tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Allow traffic from one subnet to the other
iptables -A FORWARD -i tun0 -s 10.9.0.0/24 -d 10.9.2.0/24 -j ACCEPT
# Drop all traffic
iptables -A FORWARD -i tun0 -s 10.8.0.0/16 -d 10.8.0.0/16 -j DROP
答案2
我注意到您的server.conf
文件中有dev tun
,但您的 iptables 规则中却是tun0
。请将其更改tun0
为server.conf
。
使用最低限度的 itpables 规则可能是一个好主意。您可以备份它们,重置它们,然后逐一添加它们。
您需要备份当前规则,以便以后重新应用它们
iptables-save > /path/to/backup.txt
您可以稍后使用以下方法恢复
iptables-restore < /path/to/backup.txt
我运行以下命令来刷新所有 iptables 规则:
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
注意:我在另一篇文章中找到了刷新命令[https://superuser.com/questions/634469/need-iptables-rule-to-accept-all-incoming-traffic]
现在逐一添加规则。
答案3
使用iptables ... -i tun+
这样的规则对 tun0、tun1 等都有效。
net.ipv4.ip_forward = 1
应该设置sysctl 。
这对我有用:
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -d 1.2.3.4/32 -i tun+ -o eth0 -p tcp -m tcp --dport 22 -j ACCEPT
# also allow output
iptables -A OUTPUT -p tcp -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp -m state --state NEW -j ACCEPT
随后添加日志目标:
iptables -A FORWARD -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[IPTABLES] Block forward: "
iptables -A FORWARD -j DROP
dmesg
这样您就可以看到和journalctl -f
或中的错误tail -f /var/log/...