VLAN
虚拟局域网 使您能够细分 LAN。 Linux 可以接受 VLAN 标记的流量,并将每个 VLAN ID 显示为不同的网络接口(例如:VLAN ID 100
的 eth0.100
)。
本文介绍了如何使用 iproute2 和 systemd-networkd 或 netctl 配置 VLAN。
即时配置
在以下示例中,我们假设接口为 eth0
,分配的名称为 eth0.100
,VLAN ID 为 100
。
创建 VLAN 设备
使用以下命令添加 VLAN 接口
# ip link add link eth0 name eth0.100 type vlan id 100
运行 ip link
以确认已创建。
此接口的行为类似于普通接口。所有路由到它的流量都将通过主接口(在本例中为 eth0
),但带有 VLAN 标签。只有配置正确的 VLAN 感知设备才能接受它们,否则流量将被丢弃。
使用像 eth0.100
这样的名称只是一种约定,并非强制执行;您可以选择使用 eth0_100
或类似 IPTV
这样的描述性名称。要查看接口上的 VLAN ID(如果您使用了非常规名称)
# ip -details link show eth0.100
-details
(-d
) 标志显示接口的完整详细信息
# ip -details addr show 4: eth0.100@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 96:4a:9c:84:36:51 brd ff:ff:ff:ff:ff:ff promiscuity 0 vlan protocol 802.1Q id 100 <REORDER_HDR> inet6 fe80::944a:9cff:fe84:3651/64 scope link valid_lft forever preferred_lft forever
添加 IP 地址
现在为刚创建的 VLAN 链接添加 IPv4 地址,并激活该链接
# ip addr add 192.168.100.1/24 brd 192.168.100.255 dev eth0.100 # ip link set dev eth0.100 up
关闭设备
要在移除链接之前干净地关闭设置,您可以执行以下操作
# ip link set dev eth0.100 down
移除设备
移除 VLAN 接口明显不那么复杂
# ip link delete eth0.100
持久配置
systemd-networkd
单接口
使用以下数字前缀的配置文件(请记住文件内容区分大小写,并且可以更改数字前缀)
/etc/systemd/network/10-eth0.network
[Match] Name=eth0 [Network] DHCP=ipv4 ;these are arbitrary names, but must match the *.netdev and *.network files VLAN=eth0.100 VLAN=eth0.200
/etc/systemd/network/20-eth0.100.netdev
[NetDev] Name=eth0.100 Kind=vlan [VLAN] Id=100
/etc/systemd/network/21-eth0.200.netdev
[NetDev] Name=eth0.200 Kind=vlan [VLAN] Id=200
您将需要为每个 .netdev 关联 .network 文件,以处理寻址和路由。例如,要使用静态 IP 设置 eth0.100 接口,并使用 DHCP 设置 eth0.200 接口(但忽略提供的默认路由),请使用
/etc/systemd/network/30-eth0.100.network
[Match] Name=eth0.100 [Network] DHCP=no [Address] Address=192.168.0.25/24
/etc/systemd/network/31-eth0.200.network
[Match] Name=eth0.200 [Network] DHCP=yes [DHCP] UseRoutes=false
然后启用 systemd-networkd.service
。 有关详细信息,请参阅 systemd-networkd。
单接口多 VLAN,每个 VLAN 具有自己的网关
每个 vlan 都有自己的路由表和一个 RoutingPolicyRule,用于指定此路由应用于哪些源 IP 地址。
/etc/systemd/network/10-eth0.network
[Match] Name=eth0 [Network] VLAN=eth0.10 VLAN=eth0.11 DNS=192.168.100.101 DNS=192.168.100.102
/etc/systemd/network/20-eth0.10.netdev
[NetDev] Name=eth0.10 Kind=vlan [VLAN] Id=10
/etc/systemd/network/30-eth0.10.network
[Match] Name=eth0.10 [Network] Address=192.168.1.14/24 Address=192.168.1.24/24 [Route] Gateway=192.168.1.1 Table=10 [RoutingPolicyRule] From=192.168.1.0/24 Table=10
/etc/systemd/network/21-eth0.11.netdev
[NetDev] Name=eth0.11 Kind=vlan [VLAN] Id=11
/etc/systemd/network/31-eth0.11.network
[Match] Name=eth0.11 [Network] Address=192.168.100.54/24 [Route] Gateway=192.168.100.1 Table=11 [RoutingPolicyRule] From=192.168.100.0/24 Table=11
检查
# ip rule
0: from all lookup local 0: from 192.168.1.0/24 lookup 10 0: from 192.168.100.0/24 lookup 11 32766: from all lookup main 32767: from all lookup default
使用 ip route list table
。例如
# ip route list table 10
default via 192.168.1.1 dev enp1.10 proto static
# ip route list table 11
default via 192.168.100.1 dev enp1.11 proto static
Bonded 接口
与上面类似,您只是要堆叠更多概念。您需要确保在交换机中设置了 bond,并确保它是带有标记 VLAN 的 trunk,与您在下面创建的内容相对应。约定是创建一个名为 bond0
的 bond 接口,但是存在一个已知问题,即加载 bonding
模块时,会创建一个名为 bond0
的 bond 设备,systemd 然后拒绝配置该设备(因为 systemd 试图尊重地保留它没有创建的任何设备)。
bonding
模块创建初始 bond0
接口,请将 bonding 模块的 max_bonds
选项设置为 0
(默认值为 1
)/etc/modprobe.d/bonding.conf
options bonding max_bonds=0有关详细信息,请参阅内核模块#设置模块选项和Linux 以太网 Bonding 驱动程序 HOWTO(内核文档)。
为了本文的目的,我们将使用 bondname
,您可以自行选择。
首先,我们创建 bond 设备
/etc/systemd/network/bondname.netdev
[NetDev] Name=bondname Kind=bond [Bond] Mode=802.3ad LACPTransmitRate=fast
现在创建一个 .network 指令,该指令引用 VLAN 和接口载体。在本例中,我们将使用双端口光纤模块的约定
/etc/systemd/network/bondname.network
[Match] Name=bondname [Network] VLAN=vlan10 VLAN=vlan20 VLAN=vlan30 BindCarrier=enp3s0f0 enp3s0f1
我们在这里使用 vlan<number> 命名约定,您可以使用其他名称,但请注意这是一个命名引用,因此您必须拥有一组具有相同名称的对应文件。
我们现在将设置物理网络接口
/etc/systemd/network/enp3s0f0.network
[Match] Name=enp3s0f0 [Network] Bond=bondname
/etc/systemd/network/enp3s0f1.network
[Match] Name=enp3s0f1 [Network] Bond=bondname
此时您可以重新启动,并且可能应该重新启动,因为 bonded 接口是在启动时创建的。重新启动 systemd-networkd 通常会使用来自这些文件的更改,但设备创建似乎发生在启动时。
我们现在将设置 VLAN。您应该意识到,拥有多个 VLAN 可能会导致您的机器具有多个默认路由的情况,因此您需要在网络指令中指定 Destination 指令,以确保只有一个 VLAN 用于默认路由。在本例中,我们将使用 ID 为 10 的 VLAN 作为我们的默认路由。
/etc/systemd/network/vlan10.netdev
[NetDev] Name=vlan10 Kind=vlan [VLAN] Id=10
现在创建关联的网络指令以设置地址
/etc/systemd/network/vlan10.network
[Match] Name=vlan10 [Network] VLAN=vlan10 [Address] Address=10.10.10.2/24 [Route] Destination=0.0.0.0/0 Gateway=10.10.10.1
我们将为 ID 为 20 的 VLAN 创建类似的成对文件
/etc/systemd/network/vlan20.netdev
[NetDev] Name=vlan20 Kind=vlan [VLAN] Id=20
/etc/systemd/network/vlan20.network
[Match] Name=vlan20 [Network] VLAN=vlan20 [Address] Address=10.10.20.2/24 [Route] Destination=10.10.20.0/24 Gateway=10.10.20.1
再次为 ID 为 30 的 VLAN 创建类似的成对文件
/etc/systemd/network/vlan30.netdev
[NetDev] Name=vlan30 Kind=vlan [VLAN] Id=30
/etc/systemd/network/vlan30.network
[Match] Name=vlan30 [Network] VLAN=vlan30 [Address] Address=10.10.30.2/24 [Route] Destination=10.10.30.0/24 Gateway=10.10.30.1
请注意,vlan10
上的 Destination 设置为 0.0.0.0/0
,这将匹配所有出站流量,成为默认路由。
netctl
您可以为此目的使用 netctl,请参阅 /etc/netctl/examples/vlan-{dhcp,static}
中不言自明的示例配置文件。
设置桥接 IP
有时您可能想要配置 docker 运行所在的桥接 IP,例如,当默认 IP 与网络中的其他 IP 地址冲突时。 Docker 有一个直接的方式通过 /etc/docker/daemon.json
设置 bip
(桥接 IP)。当此文件尚不存在时,您可以创建它。
/etc/docker/docker.json
{ "bip": "<desired ip range>/24" }
故障排除
udev 重命名虚拟设备
一个令人恼火的问题是,udev 可能会在添加虚拟设备时尝试重命名它们,从而忽略为它们配置的 name
(在本例中为 eth0.100
)
# ip link add link eth0 name eth0.100 type vlan id 100 # ip link show
这可能会生成以下输出
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff 3: rename1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state DOWN link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff
udev 忽略了配置的虚拟接口名称 eth0.100
,并将其命名为 rename1
。
解决方案是编辑 /etc/udev/rules.d/network_persistent.rules
并在物理接口配置行的末尾附加 DRIVERS=="?*"
。
例如,对于接口 aa:bb:cc:dd:ee:ff
(eth0
)
/etc/udev/rules.d/network_persistent.rules
SUBSYSTEM=="net", ATTR{address}=="aa:bb:cc:dd:ee:ff", NAME="eth0", DRIVERS=="?*"
重新启动应该意味着 VLAN 可以使用分配给它们的名称正确配置。