DHCP 和 macvlan:只有第一个虚拟接口适用于单播 DHCPREQUEST

DHCP 和 macvlan:只有第一个虚拟接口适用于单播 DHCPREQUEST

我正在尝试做什么?

我正尝试通过单个物理 ISP 上行电缆上的 DHCP 获取 3 个公共 IP 地址。

出了什么问题?

更新有点不对劲。从接口来看,当 virtual0 尝试通过单播连接到 DHCP 服务器进行更新时,它工作正常。virtual1 和 virtual2 接口在单播方面失败。它们进入回退模式以使用广播并成功使用它们,但日志中充满了一些不好的东西。我正在运行 Debian 8 和 isc-dhcp-client v. 4.3.1 。

我在启动时设置了如下接口:

IF_VIRTUAL_BASE=eth0
IF_PUB0=虚拟0
IF_PUB1=虚拟1
IF_PUB2=虚拟2
IF_LAN=eth2

ifconfig "$IF_VIRTUAL_BASE" 启动
ip link 添加链接“$IF_VIRTUAL_BASE”地址 00:90:0b:ff:10:5b“$IF_PUB0”类型 macvlan
ip link 设置“$IF_PUB0”
ip link 添加链接“$IF_VIRTUAL_BASE”地址 00:90:0b:ff:11:5b“$IF_PUB1”类型 macvlan
ip link 设置“$IF_PUB1”
ip link 添加链接“$IF_VIRTUAL_BASE”地址 00:90:0b:ff:12:5b“$IF_PUB2”类型 macvlan
ip link 设置“$IF_PUB2”

# 启用转发
echo 1 > /proc/sys/net/ipv4/ip_forward

unset new_routers在完成 virtual1 和 virtual2 的 dhcprequest 时我也这么做。

猜猜看,这种怪异的行为是有效的:

7 月 11 日 20:45:43 gw dhclient:virtual0 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:43 gw dhclient:虚拟 1 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:43 gw ifup[582]: virtual0 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:43 gw ifup[592]: 虚拟 1 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:43 gw dhclient:virtual2 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:43 gw ifup[634]: virtual2 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:46 gw dhclient:虚拟 1 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:46 gw ifup[592]: 虚拟 1 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:46 gw dhclient:来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:46 gw ifup[592]: 来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:46 gw 记录器:virtual1(重新启动):IP:-> 88.113.75.59;GW:-> 88.113.75.1

7 月 11 日 20:45:47 gw dhclient:virtual0 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:47 gw ifup[582]: virtual0 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:47 gw dhclient:来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:47 gw ifup[582]: 来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:47 gw 记录器:virtual0(重新启动):IP:-> 88.113.75.65;GW:-> 88.113.75.1

7 月 11 日 20:45:50 gw dhclient:virtual2 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:50 gw ifup[634]: virtual2 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 20:45:50 gw dhclient:来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:50 gw ifup[634]: 来自 88.113.75.2 的 DHCPACK
7 月 11 日 20:45:50 gw 记录器:virtual2(重新启动):IP:-> 88.113.75.61;GW:-> 88.113.75.1

所以它们起作用了,对吧?而且它们是广播请求。好的,快进一个小时左右,我们得到了以下信息:

7 月 11 日 21:45:09 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:11 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:22 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:25 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:32 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:43 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:46 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:45:56 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:05 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:11 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:21 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:30 gw dhclient:virtual2 上的 DHCPREQUEST 发送至 195.74.6.55 端口 67
7 月 11 日 21:46:33 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:42 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:46:47 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:47:00 gw dhclient:virtual2 上的 DHCPREQUEST 发送至 195.74.6.55 端口 67
7 月 11 日 21:47:01 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 21:47:09 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67

virtual1 和 virtual2 接口拼命尝试通过与之前的 DHCP 服务器 195.74.6.55 的单播连接来更新其 IP。它们因单播而失败。但接下来发生了一些有趣的事情,最终它们切换到广播作为后备并成功了!

7 月 11 日 22:30:41 gw dhclient:virtual1 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 22:30:47 gw dhclient:virtual2 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 22:30:52 gw dhclient:虚拟 1 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 22:30:52 gw dhclient:来自 88.113.75.2 的 DHCPACK
7 月 11 日 22:30:52 gw 记录器:virtual1(更新):IP:88.113.75.59 -> 88.113.75.59;GW:88.113.75.1 -> 88.113.75.1

7 月 11 日 22:30:58 gw dhclient:virtual2 上的 DHCPREQUEST 到 255.255.255.255 端口 67
7 月 11 日 22:30:58 gw dhclient:来自 88.113.75.2 的 DHCPACK
7 月 11 日 22:30:59 gw 记录器:virtual2(更新):IP:88.113.75.61 -> 88.113.75.61;GW:88.113.75.1 -> 88.113.75.1

观察virtual0接口:

7 月 11 日 22:38:17 gw dhclient:virtual0 上的 DHCPREQUEST 到 195.74.6.55 端口 67
7 月 11 日 22:38:18 gw dhclient:来自 195.74.6.55 的 DHCPACK
7 月 11 日 22:38:18 gw 记录器:virtual0(更新):IP:88.113.75.65 -> 88.113.75.65;GW:88.113.75.1 -> 88.113.75.1

结论是,对于虚拟 0 接口,单播 (dhclient) DHCP 请求有效,而对于虚拟 1 和虚拟 2,只有广播 DHCP 更新有效。所以,这一定是路由问题,对吧?以下是 ip route 在典型启动后显示的内容:

root@gw:~# ip 路由
默认通过 88.113.75.1 dev virtual0
88.113.75.0/24 dev virtual0 proto 内核范围链接 src 88.113.75.65
88.113.75.0/24 dev virtual1 proto 内核范围链接 src 88.113.75.59
88.113.75.0/24 dev virtual2 proto 内核范围链接 src 88.113.75.61
172.16.8.0/28 通过 172.16.8.2 dev tun0 # 对于 openvpn
172.16.8.0/24 dev eth2 proto kernel scope link src 172.16.8.254 # 对于 LAN
172.16.8.2 dev tun0 proto kernel scope link src 172.16.8.1 #对于 openvpn

如何使基于 macvlan 的接口 virtual1 和 virtual2 上的 dhclient 正确路由其单播续订请求并适当地接收响应?

我在 Google 上搜索了很多次,尝试过改变许多设置,包括防火墙策略、基于策略的路由、eth0 promisc 模式和 sysctl 变量、剥离通用网络设置等。我目前正在 dhclient 上进行 strace。这些设置中的一个组合必须有效。如果需要更多信息,我非常乐意提供。

编辑1:dhclient strace 已准备就绪。

这在一开始就会发生:

绑定(5,{sa_family = AF_PACKET,proto = 0x7669,if1635087474,pkttype = PACKET_HOST,addr(0)={12652,},16)= 0
绑定(6,{sa_family = AF_INET,sin_port = htons(68),sin_addr = inet_addr(“0.0.0.0”)},16)= 0
sendto(5, "......", 342, 0, {sa_family=AF_PACKET, proto=0x7669, if1635087474, pkttype=PACKET_HOST, addr(0)={12652, }, 18) = 342

据我所知,“sendto(5)”是第一次成功的基于广播的 dhclient 发送。

然后,第一个失败的单播发送:

sendto(6, "......", 300, 0, {sa_family=AF_INET, sin_port=htons(67), sin_addr=inet_addr("195.74.6.55")}, 16) = 300

下一次成功广播发送:

sendto(5, "......", 342, 0, {sa_family=AF_PACKET, proto=0x7669, if1635087474, pkttype=PACKET_HOST, addr(0)={12652, }, 18) = 342

答案1

我能够修复它!虽然方法有点不寻常,但还是可以的。

那么我做了什么?我只是卸载了 isc-dhcp-client 4.3.1 并安装了 dhcpcd 6.0.5(由 Roy Marples 开发,debian 软件包名称为 dhcpcd5)。就是这样。

我在 23:00 左右重启了机器,检查所有接口是否正常,然后设置 tcpdump 运行。大约在 00:02 时,其中一个 DHCP 计时器到期,所有 3 个接口都顺利地获得了 IP 地址,没有任何问题:

https://i.stack.imgur.com/xGQpq.png

基本上我不需要更改 /etc/dhcpcd.conf 中的任何内容。看来 dhcpcd 的构建方式比 dhclient 更智能。至少在我的场景中是这样。

(旁注:我必须说从 isc-dhcp-client 迁移到 dhcpcd 非常容易。Debian 8 具有内置支持;似乎如果你安装 dhcpcd5 并删除 isc-dhcp-client 并重新启动,系统就会自动选择新的客户端。关于脚本,似乎没有用于 dhcpcd 的脚本目录,但所有进入钩子都有一个文件,所有退出钩子都有一个文件。文件被命名为:/etc/dhcpcd.enter-hook 和 /etc/dhcpcd.exit-hook 。如果将 dhclient 钩子脚本放入这些文件中,它们无需修改即可工作。我印象深刻!)

相关内容