设置br0,无需 VPN

设置br0,无需 VPN

我试图强制来自来宾(Windows 或 Linux)的所有流量都通过主机(Linux)的 VPN。为了确保访客无法访问 VPN 之外的互联网,我在主机系统上建立了连接,这会创建一个新接口tun0。 VPN 隧道在主机上运行良好。

设置br0,无需 VPN

为了在访客中无需 VPN 即可访问互联网,我创建了一个桥接设备br0并连接enp7s0到它。这样,互联网就可以在访客中运行。

ip link add name br0 type bridge
ip link set br0 up
ip link set enp7s0 master br0

在主机上,vnet5已添加设备并桥接至br0。但与此同时,从主机到远程的 ping 操作不再起作用。

## On the Host
sudo ip a
# ...
# 14: vnet5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UNKNOWN group default qlen 1000
# link/ether ab:ab:ab:ab:ab:ab brd ff:ff:ff:ff:ff:ff
# inet6 fe80::fc54:ff:fe92:5aa9/64 scope link
# valid_lft forever preferred_lft forever
ping www.google.com
# ping: www.google.com: Temporary failure in name resolution
ping 8.8.8.8
# From 192.168.1.100 icmp_seq=1 Destination Host Unreachable

然后我启动虚拟机virt-manager并检查连接。客人有互联网:

## On the Guest
ip a
# 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
# ...
# 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
#     link/ether 52:54:00:92:5a:a9 brd ff:ff:ff:ff:ff:ff
#     inet 192.168.1.221/24 brd 192.168.1.255 scope global dynamic noprefixroute enp1s0
#        valid_lft 67432sec preferred_lft 67432sec
ping www.google.ch
# PING www.google.ch (172.217.168.35) 56(84) bytes of data.
# 64 bytes from zrh04s14-in-f3.1e100.net (172.217.168.35): icmp_seq=1 ttl=117 time=2.47 ms

我想除了设置之外,ip link set enp7s0 master br0我还可以在br0和之间创建路由规则enp7s0

使用 VPN 和tun0接口

当我建立 VPN 连接时,tun0会创建一个无法分配给网桥的接口。因此,无论如何我都需要创建路由规则。所以我猜情况和上面的情况是类似的。首先,我enp7s0再次从 中删除br0

ip link set enp7s0 nomaster
sudo openvpn my_vpn_tcp.ovpn
# ...
# Initialization Sequence Completed
sudo ip a
# ...
# 3: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
# link/ether ab:ab:ab:ab:ab:ab brd ff:ff:ff:ff:ff:ff permaddr ab:ab:ab:ab:ab:ab
# inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic noprefixroute enp7s0
# valid_lft 82702sec preferred_lft 82702sec
# ...
# 10: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
# link/none
# inet 10.7.7.5/24 scope global tun0
# valid_lft forever preferred_lft forever
# ...
# 12: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
# link/ether 72:eb:06:e5:1e:5a brd ff:ff:ff:ff:ff:ff
# inet6 fe80::70eb:6ff:fee5:1e5a/64 scope link
# valid_lft forever preferred_lft forever

无需进一步操作,主机上使用VPN连接,即可。

ping www.google.com
# PING www.google.com (172.217.168.3) 56(84) bytes of data.
# 64 bytes from lala.net (172.217.168.3): icmp_seq=1 ttl=117 time=9.64 ms
# ...
ping www.google.com -I tun0
# PING www.google.com (172.217.168.3) from 10.7.7.5 tun0: 56(84) bytes of data.
# 64 bytes from lala.net (172.217.168.3): icmp_seq=2 ttl=117 time=10.0 ms
# ...
ping www.google.com -I enp7s0
# PING www.google.com (172.217.168.3) from 192.168.1.100 enp7s0: 56(84) bytes of data.
# 64 bytes from lala.net (172.217.168.3): icmp_seq=1 ttl=115 time=4.59 ms
# ...

但正如已经说过的,我无法添加tun0br0.因此,客人也无法上网。

sudo ip link set tun0 master br0
# RTNETLINK answers: Invalid argument

我搜索了解决方案,但找不到有效的解决方案,或者我的情况略有不同,这需要对我没有的网络有更多的了解。例如(这没有完成这项工作)或(这并不完全适合我的情况)。

答案1

同一个问题中有两个问题,它们实际上并不相互依赖。我仍然会回答两个。

此外,noprefixroute地址选项暗示网络配置的一部分由一些附加工具(如 NetworkManager)管理以添加路由。这个答案不会尝试处理网络工具的集成。这包括处理 DHCP 配置,如果未正确重新配置,该配置可能会覆盖以后的更改。当界面关闭或删除时,许多设置都会消失,并且必须再次完成,因此最好通过各种负责的网络工具的各种挂钩来完成。

设置br0,无需 VPN

设置为桥接端口的接口将放弃参与路由

一旦设置为桥接端口,与该接口关联的路由将被忽略。保留地址时可能仍然存在有害的副作用。详细信息可以在博客中找到Linux 桥的正确隔离

  1. 将框架移交给特定于设备的接收处理程序,如果有的话,
  2. 将帧移交给全局或设备特定的协议处理程序(例如 IPv4、ARP、IPv6)

对于桥接接口,内核已经配置了一个特定于设备的接收处理程序,br_handle_frame().此功能不允许在传入接口的上下文中进行任何其他处理,STP 和 LLDP 帧除外,或者启用“路由”时除外。所以,协议处理程序永远不会被执行在这种情况下。

在成为网桥端口的接口上设置的 IP 地址应该移动到特殊网桥的自身接口(br0:网桥本身),这是唯一能够参与路由的接口(还有其他选项,但让我们保持简单)。相关路线也是如此。

假设 OP 的默认网关是 192.168.1.1/24。让我们针对第一种情况重写:

ip link add name br0 up type bridge
ip link set dev enp7s0 master br0

ip address flush dev enp7s0
# previous command will also have removed all associated routes as a side effect
ip address add 192.168.1.100/24 dev br0
# previous command added the LAN route too as a side effect (no noprefixroute here)
ip route add default via 192.168.1.1

这样主机和虚拟机就都可以访问Internet了。

注意,对于VM部分来说,vnet5也是一个桥接端口,也不参与路由。主机只是在虚拟机和路由器(192.168.1.1)之间交换帧:不涉及路由。

使用 VPN 和tun0接口

OpenVPN 依赖于 TUN/TAP 驱动程序(在 Linux 上由内核模块提供)tun)。司机可以提供:

  • 第 2 层 TAP 接口

    它的行为类似于以太网设备,可以设置为以太网桥接端口:vnet5由 VM 管理程序创建。

  • 或第 3 层 TUN 接口

    它不包含帧信息(以太网 MAC 地址),也不处理帧,而仅处理第 3 层或第 3 层以上的协议:IPv4 或 IPv6。因此不能将其设置为以太网桥端口。这是tun0OpenVPN 在 TUN 模式下创建的 OP。

OpenVPN也可以使用TAP模式,可以桥接,但这需要重新配置远程服务器侧面以及所有网络布局:远程服务器也将是 192.168.1.0/24 LAN 的一部分。 OP似乎无法控制它。

因此,让我们考虑一下 OP 的 TUN 接口可以做什么:这将在第 3 层(路由)完成,而不是在第 2 层。

仅对受信任的虚拟机重复使用以前的设置

如果主机不包含高级防火墙,包括防火墙限制和/或桥接路径的更改,则它无法强制虚拟机将自身用作网关:像以前一样桥接的虚拟机可以简单地忽略主机并保留 192.168.1.1作为网关并使其流量tun0最终不使用主机的接口。

如果 VM 可以信任并重新配置,则可以保留br0上述内容,应用基于的任何 OpenVPN 设置br0(将任何enp7s0引用替换为br0),并在 VM 运行(地址为 192.168.1.221)且 VPN 启动后执行此操作:

  • 在主机上

    使用基于策略/源的路由为此特定源选择不同的路由结果:

    ip rule add from 192.168.1.221 lookup 1000
    ip rule add iif tun0 lookup 1000
    ip route add 192.168.1.0/24 dev br0 table 1000
    ip route add default dev tun0 table 1000
    

    设置为路由器:

    sysctl -w net.ipv4.ip_forward=1
    

如果没有类似的 NAT 规则来处理这种情况:

  iptables -t nat -A POSTROUTING -s 192.168.1.221 -o tun0 -j MASQUERADE
  • 在 (Linux) VM 上,使用主机作为网关而不是主机的路由器

    ip route flush to default
    ip route add default via 192.168.1.100
    

建议不受信任的虚拟机:不要将主机主接口设置为桥接端口

这使得强制执行虚拟机流量变得更加容易,tun0因为它无法查看不应篡改的网络部分。

  • 更改虚拟机设置以使用其自己的 IP 网络

    示例:192.168.100.0/24 和静态 IP 192.168.100.2/24(而不是主机的网络 DHCP),默认网关为 192.168.100.1。在 Linux 虚拟机上:

    ip address add 192.168.100.2/24 dev enp1s0
    ip route add default via 192.168.100.1
    
  • 在主机上,从初始配置开始(不桥接enp7s0

    甚至可以使用下面的零桥(即:直接ip address add 192.168.100.1/24 dev vnet5vnet5设置为桥端口),但是库虚拟机可能会让这变得更加困难。

    只需为虚拟机设置一个专用桥(此处使用地址 192.168.100.1/24,尽管通常库虚拟机提供默认网桥virbr0192.168.122.1/24):

    ip link add name br0 up type bridge
    ip address add 192.168.100.1/24 dev br0
    ip link set dev vnet5 master br0
    

    并且还使用策略路由更改与两个相关接口的虚拟机相关的流量行为:br0tun0。与往常一样,它涉及对备用路由表中现有路由的一些复制和更改。这里tun0假设只为主机及其虚拟机提供服务。最终目标是:无论来自 VM 端的内容都将路由到 tun 端,无论来自 TUN 端的内容都将路由到 VM 端,忽略任何不需要的端。

    ip rule add iif br0 lookup 2000
    ip rule add iif tun0 lookup 2000
    ip route add 192.168.100.0/24 dev br0 table 2000
    ip route add default dev tun0 table 2000 # layer 3 interfaces don't need a gateway
    

    注意:来自tun0主机的传入数据包(即:未路由)已由主机处理当地的路由表,不需要表 2000 中的任何额外路由。

    设置为路由器:

    sysctl -w net.ipv4.ip_forward=1
    

    然后完成 NAT,因为远程 OpenVPN 服务器不知道 192.168.100.0/24:

    iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o tun0 -j MASQUERADE
    

如果虚拟机仍然能够访问 192.168.1.0/24 LAN:

  • 再次更新表 2000 以适应这一点

    将 LAN 路由从主表复制到表 2000:

    ip route add 192.168.1.0/24 dev enp7s0 table 2000
    
  • 并再次添加适当的 MASQUERADE 规则

    ...因为VM现在位于其他系统不知道的不同LAN中:

    iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o enp7s0 -j MASQUERADE
    

    (可以完成一些 iptables 规则分解)。

相关内容