如何在 NetworkManager 管理的 NIC 上永久启用混杂模式?

如何在 NetworkManager 管理的 NIC 上永久启用混杂模式?

我正在尝试将多个 NIC 中的两个桥接起来,使其充当交换集线器。
为此,需要在 NIC 上启用混杂模式。
即使我使用“ip link”命令将其设置为“promisc on”,当我重新启动 PC 时,该设置也会被重置。

如何才能永久启用混杂模式,即使我重新启动电脑?

环境是Ubuntu Desktop 20.04 LTS,
因此网络配置以NetworkManager为基础。

最低配置示例如下所示:

Vagrant.configure("2") do |config|
  config.vm.define :bridge do |machine|
    machine.vm.box = "bento/ubuntu-20.04"
    machine.vm.network :private_network, auto_config: false, virtualbox__intnet: "intnet_a"
    machine.vm.network :private_network, auto_config: false, virtualbox__intnet: "intnet_b"

    machine.vm.provision "shell", inline: <<-SHELL
      apt-get update
      apt-get install -y network-manager
      cat > /etc/netplan/50-bridge.yaml <<'EOS'
network:
  version: 2
  ethernets:
    eth1:
      addresses:
        - 0.0.0.0/32
    eth2:
      addresses:
        - 0.0.0.0/32
  bridges:
    br0:
      interfaces:
        - eth1
        - eth2
EOS
      echo 'network: { version: 2, renderer: NetworkManager }' > /etc/netplan/99-NetworkManager.yaml
      netplan apply
    SHELL
  end
end

“ip link”命令激活NIC的PROMISC状态,如下所示。

$ sudo ip link set dev eth1 promisc on
$ sudo ip link set dev eth2 promisc on
$ ip addr
[...]
3: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:48:57 brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
[...]

然而,重新启动操作系统后,PROMISC 状态将被重置。

$ sudo reboot
[...]
$ ip addr
[...]
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:48:57 brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
[...]

在此示例中,我使用 Vagrant 是为了展示可重现的环境。Vagrant
不是必需的,我真正想使用的是在物理 PC 上使用 Ubuntu。
只需通过 Vagrant 配置运行启用混杂模式即可才不是解决这个问题。

答案1

我找到了几种方法并自己解决了。

方法 1:使用 NetworkManager-dispatcher

$ sudo bash -c 'cat > /etc/NetworkManager/dispatcher.d/50-promisc' <<'EOS'
#!/usr/bin/bash -e
case "$2" in
    up)
        if [[ "$1" = "eth1" ]] || [[ "$1" = "eth2" ]]; then
            ip link set dev $1 promisc on
        fi
        ;;
esac
EOS
$ sudo chmod u=rwx,g=rx,o=rx /etc/NetworkManager/dispatcher.d/50-promisc
$ sudo reboot
[...]
$ ip addr
[...]
3: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:48:57 brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
[...]

注册一个脚本,NetworkManager-dispatcher当目标 NIC(eth1 或 eth2)处于启动状态时启用 promisc。

方法 2:在 systemd 中注册一个一次性服务,该服务会延迟到 network-online.target 单元启动

$ sudo bash -c 'cat > /etc/systemd/system/bridge-promisc.service' <<'EOS'
[Unit]
Description=Makes interfaces run in promiscuous mode at boot
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/ip link set dev eth1 promisc on
ExecStart=/usr/sbin/ip link set dev eth2 promisc on
TimeoutStartSec=0
RemainAfterExit=yes

[Install]
WantedBy=default.target
EOS
$ sudo systemctl enable bridge-promisc
$ sudo reboot
[...]
$ ip addr
[...]
3: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:48:57 brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether xx:xx:xx:xx:c4:f5 brd ff:ff:ff:ff:ff:ff
[...]

我觉得这个方法可以应用于不使用NetworkManager的模式。

相关内容