我有以下拓扑,配置为在我的桌面和无线路由器之间运行 GRE 隧道。
在PC上:
ip link add l2gre0 type gretap remote 192.168.0.103 local 192.168.0.10
在路由器上:
ip link add l2gre0 type gretap remote 192.168.0.10 local 192.168.0.103
我的客户端从 PC 上的 DHCP 服务器获取了一个 IP 地址10.10.10.102
。我尝试10.10.10.1
从客户端 ping 网关 IP。ping 成功。
我想了解的是软件如何将这个 Ping 数据包从 路由到lan0
(l2gre0
都在桥下br0
),然后通过eth0
电线跨越到enp3s0
(在 PC 上)。
我打开数据包捕获lan0
,可以看到捕获结果显示了以太网帧。然后我打开l2gre0
(在无线路由器上)数据包捕获。可以看到与 中相同的帧lan0
。这意味着从到br0
重复了该帧。lan0
l2gre0
如果我在 eth0 接口上进行数据包捕获,则 GRE 封装已经发生,这意味着在 l2gre0 和 eth0 之间,连接到 l2gre0 的软件堆栈可能已经封装了帧。但是 l2gre0 只知道远程 192.168.0.10 和本地 192.168.0.103 端点,那么它如何决定这个数据包(目标 IP:10.10.10.1)需要封装?
无线路由器上的路由:
/ # ip r
default via 192.168.0.10 dev eth0
169.254.0.0/16 dev eth0 proto kernel scope link src 169.254.32.107
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.103
答案1
但是 l2gre0 仅了解远程 192.168.0.10 和本地 192.168.0.103 端点,那么它如何决定这个数据包(目标 IP:10.10.10.1)需要被封装?
没有。您说的端点是tunnel source address
(192.168.0.103) 和tunnel destination address
(192.168.0.10)。这些地址是内核用来发送和接收封装的有效负载的地址,它们本身不参与内核路由。
这里具体发生的情况是,您的内核 IP 堆栈将发往 GRE 隧道的数据包路由10.10.10.1
出去,因为它是一个直接连接的 IP 接口,l2gre0
并且此地址被指定为其远程对等体tunnel remote address
。同样,您的l2gre0
接口也有,这些地址被分配给隧道接口本身,将它们视为“隧道内本地和远程端的名称”,您可以在大多数现代发行版上tunnel local address
获得它们。ip a l
内核将任何路由到 GRE 隧道的内容封装并发送到tunnel destination address
,接口不会检查给定的有效负载(就像任何其他接口一样)并将其发送到远程端进行处理。
答案2
因为lan0
和l2gre0
是桥接,数据包从 转发到lan0
,l2gre0
并且它将在内部(由内核“ br_flood
/ br_forward
”)l2gre0
通过“ipgre_xmit“首先封装会发生,然后路线 抬头将发生在外部目标 IP 地址上,这会将数据包推出eth0
接口。