In this exercise, we will add support for a basic tunneling protocol to the IP router that you completed in the previous assignment. The basic switch forwards based on the destination IP address. Your jobs is to define a new header type to encapsulate the IP packet and modify the switch code, so that it instead decides the destination port using a new tunnel header
需求提取;
遇到隧道标签就先交给parse_tunnel处理,标识type是0x1212(MyTunnel);
我们可以看到只要带上了隧道标签的数据包的type字段都被处理成0x1212(我们自定义的一个值用于标签),同时最后dst_ip为h3的但带上了隧道标签也走了隧道,证明了我们在parse里的解析逻辑是正确的。
我们打开s1runtime.json里可以看到面对dst_id=2的都是会发往s1的port2,即发往h2;
为Scapy添加了对我们新的自定义头的支持。
导入 Scapy 和其他必要的模块:
from scapy.all import *
import sys, os
定义自定义协议头的 EtherType 值:
TYPE_MYTUNNEL = 0x1212
TYPE_IPV4 = 0x0800
这里 TYPE_MYTUNNEL
代表自定义隧道协议的 EtherType,而 TYPE_IPV4
是标准的 IPv4 协议的 EtherType。
定义自定义协议头 MyTunnel
:
class MyTunnel(Packet):
name = "MyTunnel"
fields_desc = [
ShortField("pid", 0),
ShortField("dst_id", 0)
]
这个类继承自 Scapy 的 Packet
类,并定义了两个字段:pid
和 dst_id
。这些字段使用 ShortField
定义,意味着它们是 16 位的数值。
定义 mysummary
方法:
def mysummary(self):
return self.sprintf("pid=%pid%, dst_id=%dst_id%")
mysummary
方法提供了一种格式化的方式来输出 MyTunnel
头部的简要信息。
绑定层:
bind_layers(Ether, MyTunnel, type=TYPE_MYTUNNEL)
bind_layers(MyTunnel, IP, pid=TYPE_IPV4)
这里使用 bind_layers
函数将 MyTunnel
层绑定到 Ether
层,当 Ether
类型字段是 TYPE_MYTUNNEL
时。然后将 IP
层绑定到 MyTunnel
层,当 MyTunnel
的 pid
字段是 TYPE_IPV4
时。这样,Scapy 在解析数据包时就能根据 EtherType 值识别自定义协议头,并在需要时能够正确地解析或构造 IP 数据包。
这段代码的作用是告诉 Scapy 如何解析和处理您定义的自定义协议 MyTunnel
。当 Scapy 遇到 EtherType 为 0x1212 的帧时,它会知道这个帧包含了 MyTunnel
协议头,并且会使用您提供的字段定义来解析这个头。如果 MyTunnel
头中的 pid
字段指示了一个 IPv4 数据包(0x0800),Scapy 会继续解析接下来的内容作为 IPv4 数据包。这样一来,您就能够在 Scapy 中发送、接收并处理这种自定义封装的数据包了。