为什么即使配置了 sysctl.conf,重启后 IPv6 也会被禁用?

为什么即使配置了 sysctl.conf,重启后 IPv6 也会被禁用?

首先,我很好奇有多少文章在强制关闭 Linux 服务器上的 IPv6。来吧,大家,赶快行动起来吧!:D

root@hodor:~# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 10 (buster)
Release:        10
Codename:       buster
root@hodor:~# uname -a
Linux hodor 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux

我遇到了一个重复出现的问题,在重新启动后,我的一个桥接接口和该桥接的所有子/从属接口都禁用了 IPv6。这导致在主机上设置 ipv6 地址失败等。这是我看到的

net.ipv6.conf.br0.disable_ipv6 = 1
net.ipv6.conf.enp175s0f0.disable_ipv6 = 1
net.ipv6.conf.enp175s0f1.disable_ipv6 = 1
net.ipv6.conf.hostveth0.disable_ipv6 = 1

我在 /etc/sysctl.d/* 中找不到任何相关内容。这是我的 sysctl.conf:

root@hodor:~# grep -v ^\# /etc/sysctl.conf






net.ipv4.ip_forward=1

net.ipv6.conf.all.forwarding=1



net.ipv6.conf.br0.disable_ipv6 = 0
net.ipv6.conf.br0/5.disable_ipv6 = 0
net.ipv6.conf.br0/90.disable_ipv6 = 0
net.ipv6.conf.enp175s0f0.disable_ipv6 = 0
net.ipv6.conf.enp175s0f1.disable_ipv6 = 0
net.ipv6.conf.hostveth0.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.all.disable_ipv6 = 0

之后sysctl -p我可以手动设置我的 ipv6 并修复所有其他小细节,但这很糟糕。

也认为也许 grub 是我的罪魁祸首,但我没有看到任何与这个内核参数有关的内容。

root@hodor:~# grep -v ^\# /etc/default/grub

GRUB_DEFAULT=0
GRUB_TIMEOUT=1
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="console=tty1 console=ttyS0,115200 intel_iommu=on"
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

这是 /etc/network/interfaces(已混淆),并且没有任何内容 /etc/network/interfaces.d/:

source /etc/network/interfaces.d/*

auto lo
auto enp5s0
auto enp6s0
iface lo inet loopback
iface enp5s0 inet manual
iface enp6s0 inet manual


auto enp175s0f0
iface enp175s0f0 inet manual


auto enp175s0f1
iface enp175s0f1 inet manual

auto br0
iface br0 inet static
bridge_ports enp175s0f1 enp175s0f0 hostveth0
bridge_stp off
bridge_maxwait 5
address 172.16.10.35
netmask 255.255.254.0
gateway 172.16.10.1
dns-nameservers 172.16.10.1
hwaddress ether 9e:7d:01:6c:32:1b
        pre-up ip link add name hostveth0 type veth peer name dockerveth0
        pre-up ip link set hostveth0 up
        pre-up ip link set dockerveth0 up

iface br0 inet6 static
        address 2600:####:####:###0::face/64
        dns-nameservers 2600:####:####:###0::1
        gateway 2600:####:####:####0::1

auto virttap0
iface virttap0 inet manual
        pre-up modprobe dummy
        pre-up ip link add name virttap0 type dummy
        post-up ip link set virttap0 arp on multicast on

iface br0.5 inet manual
        vlan-raw-device br0

iface br0.90 inet manual
        vlan-raw-device br0

auto br5
iface br5 inet manual
bridge_ports br0.5
bridge_stp off
bridge_maxwait 5

auto br90
iface br90 inet manual
bridge_ports br0.90
bridge_stp off
bridge_maxwait 5

希望这很简单。如果可以的话请帮忙!

答案1

我假设您正在使用这三个包来提供正在使用的选项:下拉桥梁工具虚拟局域网。后面两个提供了命令brctlvconfig,都已经过时了,但更重要的是它们提供了 Debian 特定的插件脚本来下拉。虽然brctl在这些脚本中仍然使用,但vconfig甚至不再使用(并被现代ip link命令取代)。

问题是由于 是br0VLAN 子接口的父级,而该子接口是由桥梁工具脚本(不是来自虚拟局域网包裹)。

桥梁工具下拉插件脚本阻止桥接端口参与路由:

# ls -l /etc/network/if-pre-up.d/bridge
lrwxrwxrwx. 1 root root 29 Jan 28  2019 bridge -> /lib/bridge-utils/ifupdown.sh

这是一个 Debian 特定的脚本,属于桥梁工具包。以下是相关内容(抱歉,这是一个罕见的包,似乎不在https://salsa.debian.org,因此没有链接):

      if [ -f /proc/sys/net/ipv6/conf/$port/disable_ipv6 ]
      then
        echo 1 > /proc/sys/net/ipv6/conf/$port/disable_ipv6
      fi

这是桥接端口所需的设置。

但在 OP 的设置中,桥接接口旨在接收地址以参与路由,并成为 VLAN 子接口的父接口,而子接口本身又隶属于桥接。这是 OP 所不希望的拓扑桥梁工具

上述脚本调用/lib/bridge-utils/bridge-utils.sh包括:

create_vlan_port()
{
# port doesn't yet exist
if [ ! -e "/sys/class/net/$port" ]
then
  local dev="${port%.*}"
  # port is a vlan and the device exists?
  if [ "$port" != "$dev" ] && [ -e "/sys/class/net/$dev" ]
  then
    if [ -f /proc/sys/net/ipv6/conf/$dev/disable_ipv6 ]
    then
      echo 1 > /proc/sys/net/ipv6/conf/$dev/disable_ipv6
    fi
    ip link set "$dev" up
    ip link add link "$dev" name "$port" type vlan id "${port#*.}"
  fi
fi
}

当子接口不存在时(因为使用此脚本根本不需要创建配置),其父接口将被禁用 IPv6(而端口本身将从上一个脚本中禁用它),原因与桥接情况类似:父接口应该只承载 VLAN 标记流量,因此可以防止干扰任何路由,例如通过接收自动 IPv6 地址。这也是通常这是一个理想的设置,但不适用于 OP 的情况,因为 OP 要求同一个接口同时承载标记和未标记的流量。

在 OP 的设置中,子接口在配置中定义,并打算通过来自以下插件脚本在系统上创建:虚拟局域网包,但由于没有任何auto br0.5,因此auto br0.90接口不是在系统级别创建的桥梁工具的脚本已检查,因此它执行以下# port doesn't yet exist块:创建它们,但首先禁用其父接口上的 IPv6。这里重要的是不要混淆如图所示的逻辑接口下拉与系统上的真实界面,尽管它们在几乎所有设置中都有相同的名称。

解决方案

以下三种方法中的任何一种都应该能得到预期的结果。我还建议使用第四种方法,但与 Docker 等应用程序的集成并不简单。

  • 通过适应(相当过时的)的特性来解决这个问题桥梁工具包:提前调出配置的子接口,这样它们就存在于系统级别。然后上面的脚本不会在其父接口上禁用 IPv6(它不会匹配# port doesn't yet exist)。来自虚拟局域网这次创建了 VLAN 子接口的包。

    auto br0.5
    iface br0.5 inet manual
            vlan-raw-device br0
    
    auto br0.90
    iface br0.90 inet manual
            vlan-raw-device br0
    

    并确保它在配置br5和之前发生br90(现在就是这种情况)。此后,只有这些接口将禁用 IPv6,正如应该的那样:br0.5br0.90以及enp175s0f1,,enp175s0f0hostveth0

    ifup虽然这是一个简单的更改,但如果和ifdown以“错误的顺序”使用,它不会阻止以后出现问题,br0在这种情况下,IPv6 可能会再次被禁用,或者一些应该禁用的接口(端口)不会被禁用。唯一保证有效的顺序是配置中的顺序:

    ifdown br90
    ifdown br5
    ifdown br0.90 # even if they have now disappeared from the system
    ifdown br0.5  # they are still up for ifupdown's logic
    ifdown br0
    ifup br0
    ifup br0.5
    ifup br0.90
    ifup br5
    ifup br90
    
  • 保持桥梁仅仅是桥梁,并使用额外的一对韦特接口,一端位于桥接器上,一端参与路由。这样可以清晰地区分桥接器和路由器(并且不会产生任何副作用,例如使用 Docker 时,但同时可能需要更改您当前的 Docker 设置):

    auto routing0
    iface routing0 inet static
        pre-up ip link add name routing0 address 9e:7d:01:6c:32:1b type veth peer name br0routing0 || :
        address 172.16.10.35
        netmask 255.255.254.0
        gateway 172.16.10.1
        dns-nameservers 172.16.10.1
    
    iface routing0 inet6 static
        address 2600:####:####:###0::face/64
        dns-nameservers 2600:####:####:###0::1
        gateway 2600:####:####:####0::1
    
    auto br0
    iface br0 inet manual
    bridge_ports br0routing0 enp175s0f1 enp175s0f0 hostveth0
    bridge_stp off
    bridge_maxwait 5
            pre-up ip link add name hostveth0 type veth peer name dockerveth0 || :
            pre-up ip link set hostveth0 up
            pre-up ip link set dockerveth0 up
    

    我不知道硬件地址是新的(在上述配置中假设)还是属于enp175s0f1并且由于某种原因需要它(在这种情况下routing0不能使用它,并且为了避免复杂性,不要使用此解决方案)。您可能必须调整br0其配置中任何不相关服务的配置并使用routing0

  • 切换到ifupdown2这是一个下拉完全重新实施Cumulus 网络提供运行 Linux 的交换机和路由器:

    ifupdown2 是 debian 网络接口管理器 ifupdown 的新实现。它理解接口依赖关系、简化接口配置、扩展 ifquery 以支持接口配置验证、支持 JSON 等。

    它具有内置桥接和 VLAN 处理功能,并且不依赖于桥梁工具或者虚拟局域网包裹了。

    通常,切换管理网络的工具可能会导致连接问题,因此需要进行远程控制台访问。

    保持配置原样应该可以正常工作,但是从此评论来看ifupdown2的版本接口(5)

    内置接口

    ifupdown 可以理解某些接口(例如物理接口或点表示法的 vlan 接口(例如 eth1.100))的 iface 部分。 如果这些接口依赖于其他接口,则它们不需要在接口文件中输入条目并且不需要任何特定配置,如地址等。

    您应该从配置中完全删除br0.5和的定义(当然条目除外)。br0.90bridge_ports

    此类配置将再次仅在桥接端口上禁用 IPv6:,br0.5以及br0.90,,enp175s0f1enp175s0f0hostveth0仍然预计在使用任意ifdown/ifup命令时可能出现问题。

  • 仅建议:ifupdown2也可以是配置为使用 VLAN 感知桥接器,将设置变成桥梁和VLAN子接口。

    这应该是最好的设置,但目前没有多少应用程序支持在桥接端口上配置 VLAN ID(例如:使用bridge vlan命令)。我认为 Docker 不支持这个功能,所以这对 OP 的设置来说没用。

答案2

我最终按照上面@AB 的建议得到了这个工作:

“切换到 ifupdown2,这是由 Cumulus Networks 制作的 ifupdown 完全重新实现,它提供运行 Linux 的交换机和路由器:”

从 ifupdown 切换到 ifupdown2 时,我们学到了很多教训:

  1. 正如 @AB 所警告的,从 ifupdown 升级到 ifupdown2 时立即出现了网络问题。主要问题是我的接口被重命名(交换)。enp175s0f0 变成了 enp175s0f1,反之亦然。大约 45 分钟的 tcpdump 等让我在这里找到了解决方案。
  2. 自 2020 年 10 月 21 日起,Debian 存储库提供了旧版本的 ifupdown2
# apt-cache madison ifupdown2
 ifupdown2 |    1.2.5-1 | http://deb.debian.org/debian buster/main amd64 Packages
 ifupdown2 |    1.2.5-1 | http://deb.debian.org/debian buster/main i386 Packages
 ifupdown2 |    1.2.5-1 | http://deb.debian.org/debian buster/main Sources

我试用这个版本后感到非常沮丧,仍然无法让 /etc/network/interfaces 中的配置为我的网桥或任何接口分配 IPv6 地址。这里不讨论语法,因为语法在更高版本上有效。请...从这里轻松编译最新的 .deb:Cumulus Github使用此版本 ifupdown2(ver.3) 后,我的 /etc/network/interfaces 配置文件在我的接口上生成了所需的 IPv6 IP。

  1. 重要的是要注意@AB 关于“内置接口”的警告,当指定现有的接口时,没有对它们进行进一步的配置,例如auto enp175s0f0iface enp175s0f0 inet manual导致奇怪的问题,特别是我的 KVM 客户机无法自动启动;并且由于其中一个使用 PCI 直通 NIC,这些 NIC 决定从基础设施中提取 IPv4 和 IPv6 地址,这让我更加困惑。
  2. DNS...我的 /etc/network/interfaces 中的 DNS 条目被完全忽略,我费了很大劲才找到正确的方法使用 ifupdown2 设置 DNS 设置。
  • 我尝试过使用 NetworkManager 并最终将其删除,但仍然不允许我使用 /etc/network/interfaces 设置 DNS...
  • 我一直都知道,在现代 Linux 系统上,您无法手动编辑 /etc/resolv.conf,因为这些条目最终会被 NetworkManager 或 ifupdown(2) 或其他程序覆盖。Debian 文档中有关此事的内容
  • 我了解到 ifupdown2 利用包 resolvconf 来解释 /etc/network/interfaces 中的 dns 设置并将其部署到 /etc/resolv.conf。 仅仅因为您有目录 /etc/resolvconf/ 并不意味着您已经安装了 resolvconf 包!你必须安装它。之后我就可以开始做生意了。

这是我的最终 /etc/network/interfaces(简单得多):

grep -v ^\# /etc/network/interfaces

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback




auto br0
iface br0 inet manual
bridge_ports enp175s0f1 enp175s0f0 hostveth0
bridge_stp off
bridge_maxwait 5
        up echo $IFACE is up;
        address 172.16.10.35/23
        address 2600:####:####:###0::face/64
        gateway 172.16.10.1
        gateway 2600:####:####:###0::1
        dns-nameservers 172.16.10.1 2600:####:####:###0::1
        dns-search ####.tld
        hwaddress ether 9e:7d:01:6c:32:1b
        pre-up ip link add name hostveth0 type veth peer name dockerveth0
        pre-up ip link set hostveth0 up
        pre-up ip link set dockerveth0 up


auto virttap0
iface virttap0 inet manual
        pre-up modprobe dummy
        pre-up ip link add name virttap0 type dummy
        post-up ip link set virttap0 arp on multicast on

auto br5
iface br5 inet manual
bridge_ports br0.5
bridge_stp off
bridge_maxwait 5


auto br90
iface br90 inet manual
bridge_ports br0.90
bridge_stp off
bridge_maxwait 5

相关内容