![如何使用网络命名空间进行 VPN 分割隧道](https://linux22.com/image/219083/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E7%BD%91%E7%BB%9C%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E8%BF%9B%E8%A1%8C%20VPN%20%E5%88%86%E5%89%B2%E9%9A%A7%E9%81%93.png)
我的目标是通过我的 VPN 路由默认命名空间,并创建一个不通过 VPN 路由的新命名空间(这样我可以有选择地启动不应访问远程 VPN 网络的程序)。
LAN 地址:enp0s3 上的 10.0.2.15/24
VPN 地址:tun1 上的 10.111.0.10/24
# enable forwarding
sysctl -w net.ipv4.ip_forward=1
# create the network namespace
ip netns add sample_ns
# create the virtual nic and it's peer
ip link add virt_out type veth peer name virt_in
# assign the peer to the network namespace
ip link set virt_in netns sample_ns
# bring up interface
ip link set virt_out up
#Create a new bridge and change its state to up:
ip link add name bridge_name type bridge
#To add an interface (e.g. eth0) into the bridge, its state must be up:
ip link set enp0s3 up
#Adding the interface into the bridge is done by setting its master to bridge_name:
ip link set enp0s3 master bridge_name
ip link set virt_out master bridge_name
#To show the existing bridges and associated interfaces, use the bridge utility (also part of iproute2). See bridge(8) for details.
bridge link
# assign an ip address
ip addr add 10.0.3.1/24 dev virt_out
#network setup for network namespace
ip netns exec sample_ns ip link set lo up
ip netns exec sample_ns ip addr add 10.0.3.2/24 dev virt_in
ip netns exec sample_ns ip link set virt_in up
ip netns exec sample_ns ip route add default via 10.0.3.2 dev virt_in
# allow forwarding and add enable NAT
iptables -I FORWARD -s 10.0.3.0/24 -j ACCEPT
iptables -t nat -I POSTROUTING -s 10.0.3.0/24 -o enp0s3 -j MASQUERADE
# pop a shell in the namespace
ip netns exec sample_ns bash
# check that you're in the namespace
ip netns identify
# run the browser as your local user
runuser -u $USER google-chrome
#to access snap packages in ns run in the ns: (“error: cannot find tracking cgroup”)
sudo mount -t cgroup2 cgroup2 /sys/fs/cgroup
sudo mount -t securityfs securityfs /sys/kernel/security/
其目标基本上是与namespaced-openvpn相反(https://github.com/slingamn/namespaced-openvpn)因此 vpn protected 命名空间是默认命名空间,未连接 vpn 连接的命名空间是新命名空间。
我目前所做的不起作用,我想我应该以某种方式将 IP 地址添加到网桥/虚拟网卡或 enp0s3 中?
谢谢你的帮助!
其他来源:
https://forums.openvpn.net/viewtopic.php?f=15&t=25690
https://github.com/ausbin/nsdo
答案1
为此,使用其他虚拟化网络而不是网桥会更容易。
“不要使用veth+bridge!使用macvlan!”
(从https://unix.stackexchange.com/a/546090/568691)
添加命名空间
ip netns add sample_ns
创建 macvlan 链接,将其附加到父主机 enp0s3 (https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking/#macvlan)
ip link add mv1 link enp0s3 address 00:11:22:33:44:55 type macvlan mode bridge
如果省略地址 00:11:22:33:44:55 部分,则会生成随机 MAC 地址。如果您想使用与物理 enp0s3 或 eth0 等相同的 mac,则可以在第 2 层模式下使用 ipvlan 而不是 macvlan (https://www.kernel.org/doc/Documentation/networking/ipvlan.txt)。
将新接口 mv1 移动到新命名空间
ip link set mv1 netns sample_ns
调出接口
ip netns exec sample_ns ip link set dev lo up
ip netns exec sample_ns ip link set dev mv1 up
使用 dhclient 设置 IP 地址 - 通常这也会设置路由。
ip netns exec sample_ns dhclient mv1
#如果dhclient不起作用,请手动添加ip和路由:
#ip netns exec sample_ns ip addr add $your_ip/24 dev mv1
#ip netns exec sample_ns ip route add default via $your_gateway dev mv1
测试新命名空间是否具有所需的连接。请注意,我使用 fping 来检查 ping 是否成功(安装 fping)。
ip netns exec sample_ns sudo fping 1.1.1.1 &>/dev/null && echo "Internet connectivity okay"
ip netns exec sample_ns sudo fping 1.1.1.1 &>/dev/null || echo "No internet"
ip netns exec sample_ns sudo fping google.com &>/dev/null || echo "No DNS service"
现在只需使 xserver 可从新的网络名称空间访问 - 仅当您无法从新的名称空间打开程序时才需要这样做。
在默认命名空间中:
sudo -u $USER xhost +local:$USER
ip netns exec sample_ns bash export DISPLAY=:0
这会导出 DISPLAY 环境变量,您的环境变量可能会有所不同,例如:1 或:99。您可以使用以下命令检查默认名称空间
echo $DISPLAY
现在从新的命名空间运行一些程序
sudo ip netns exec sample_ns sudo -u $USER bash
/usr/bin/chromium-browser %U
或者如果您想立即执行此操作:
sudo ip netns exec sample_ns sudo -u $USER /usr/bin/chromium-browser %U
如果您想继续使用在这个新命名空间中打开的 bash,您可以在命令末尾添加 & 以使其独立于这个父 bash,如下所示:
/usr/bin/chromium-browser %U &
这样,如果您按 CTRL+C,程序将继续运行,但您可以恢复 bash 来运行其他程序。或者您可以打开多个终端。
故障排除:
#enable 转发
sysctl -w net.ipv4.ip_forward=1
#访问ns中的snap包,在ns中运行:(“错误:找不到跟踪cgroup”)
sudo mount -t cgroup2 cgroup2 /sys/fs/cgroup
sudo mount -t securityfs securityfs /sys/kernel/security/
其他来源:
尝试在网络命名空间中运行 OpenVPN
linux命名空间,如何在网络命名空间中连接互联网?
将unix程序绑定到特定的网络接口
https://networkstatic.net/configuring-macvlan-ipvlan-linux-networking/
答案2
我认为你不需要在这里架桥。你只需要路由。
我会消除以下内容(我假设 enp0s3 已经启动):
#Create a new bridge and change its state to up:
ip link add name bridge_name type bridge
#To add an interface (e.g. eth0) into the bridge, its state must be up:
ip link set enp0s3 up
#Adding the interface into the bridge is done by setting its master to bridge_name:
ip link set enp0s3 master bridge_name
ip link set virt_out master bridge_name
#To show the existing bridges and associated interfaces, use the bridge utility (also part of iproute2). See bridge(8) for details.
bridge link
我会改变:
ip netns exec sample_ns ip route add default via 10.0.3.2 dev virt_in
到:
ip netns exec sample_ns ip route add default via 10.0.3.1 dev virt_in
我猜想这应该允许您的新网络名称空间与本地 LAN 10.0.2.0/24 进行通信(例如 ping 服务提供商路由器),但此时访问 Internet 可能不起作用。您需要提供默认命名空间中的“ip Route show”、“ip Route Show Table All”、“ip Rule Show”、“iptables-save”、“cat /etc/resolv.conf”等命令的输出。以及来自新网络命名空间 bash 会话的“cat /etc/resolv.conf”。假设这些输出中没有敏感信息。