《Linux高性能服务器编程》阅读笔记:
1. ARP协议简析
ARP是属于数据链路层的协议,它的作用在于将网络层任意协议中携带的地址转换为物理(MAC)地址,工作原理为:
(1) 主机向自己所在的网络广播一个ARP请求数据报,该报含有目标机器的网络地址
(2) 所在网络上的其他机器都会收到这个请求,但只有目标机器才会回应ARP应答。应答数据报中包含了自身的物理地址
以基于以太网ARP请求/应答帧文为例:
以太网帧中的ARM数据报报文格式为(28Byte):
(1) 硬件类型:定义地址的物理类型,值为1表MAC地址
(2) 协议类型:定义协议地址类型,值为0x800表IP地址
(3) 硬件地址长度 / 协议地址长度:对MAC地址来说长度为6,对IP(v4)地址来说长度是4。单位为字节
(4) 操作:ARP请求(值为1)、ARP应答(值为2)、RARP请求(值为3)、RARP应答(值为4)
(5) 通信双方的以太网地址、IP地址:对发送端来说填充的是除了目的端以太网地址之外的其他3个字段;对接收端来说发现,发现该请求的目的IP地址是自身时,就把自己的以太网地址填充进去,并交换两个目的端地址和两个发送端地址,并返回该应答。
ARP的请求/应答包的长度为28字节,再加上以太网帧的头部/尾部功18字节,合计为46字节。但是有的实现要求以太网帧的数据部分至少为46字节,所以上述的28字节ARP应答/请求包的长度将要被填充。在这种情况下一个携带ARP请求/应答报文的以太网帧为64字节。
通常,为了访问效率,ARP会维护一个缓存,其间包含了经常访问或者最近访问的机器的IP地址到物理地址的映射。在Linux操作系统中,可以使用arp -a命令查看:
arp -d和arp -s分别用于删除/添加对应的ARP缓存项:
2. tcpdump观察ARP通信
网络框架如下图,在两个Linux主机中运行telnet服务。关于telnet服务的安装可参照http://blog.csdn.net/linux_ever/article/details/50519028和http://www.cnblogs.com/armstrong-cn/archive/2012/04/25/2469897.html。通过tcpdump工具抓取telnet的数据包。
在Ubuntu 14.04中:
(1) 清除ARP缓存中kingsine对应的项
$ sudo arp -d 192.168.1.166
(2) 执行tcpdump抓包命令
$ sudo tcpdump -i eth0 -ent '(dst 192.168.1.102 and src 192.168.1.166) or (dst 192.168.1.166 and src 192.168.1.102)'
(3) 在另一个终端中去连接Ubuntu9.10的telnet服务
$ sudo telnet 192.168.1.166 echo
在tcpdump抓取的数据包中,前面的两个就和ARP通信相关:
(1) 00:0c:29:99:5b:7f > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.166 tell 192.168.1.233, length 28
(2) 00:0c:29:f4:cd:f7 > 00:0c:29:99:5b:7f, ethertype ARP (0x0806), length 60: Reply 192.168.1.166 is-at 00:0c:29:f4:cd:f7, length 46
由tcpdump抓取的数据包本质上是以太网帧。
第一个数据包中:
ARP通信的源端的物理地址是00:0c:29:99:5b:7f(iter),目的端的物理地址是ff:ff:ff:ff:ff:ff,这是以太网的广播地址,用于表示整个局域网,该LAN的所有机器都会受到并处理这样的帧。0x0806是以太网帧的头部的类型字段,表示ARP模块;该以太网帧的长度为42字节(实际上是46字节,tcpdump委统计以太网帧尾部4字节的CRC字段),其中数据部分长度为28字节。Request表示这是一个ARP请求;”who-has 192.168.1.166 tell 192.168.1.233”表示iter要查询的目的主机的IP地址。
第二个数据包中:
ARP通信的源端物理地址是00:0c:29:f4:cd:f7(kingsine),目的端的物理地址是00:0c:29:99:5b:7f(iter),Reply表示这是一个ARP应答,192.168.1.166 is-at 00:0c:29:f4:cd:f7表示向目标机器(iter)报告kingsine的物理地址。