参考手册:https://fossies.org/dox/scapy-2.3.3/
当一台主机把以太网数据帧发送到位于同一个局域网上的另一台主机时,是根据48bit的以太网地址来确定目的接口的。
设备驱动程序从不检查IP数据包中的目的IP地址。
地址解析为这两种不同的地址形式提供映射:32bit的IP地址和数据链路曾使用的任何类型的地址。(FR环境)
ARP为IP地址到对应的硬件地址之间提供动态映射。我们之所以用动态这个词是因为这个过程是自动完成的,一般应用程序用户或系统管理员不必关心。
在ARP背后有有一个基本概念,那就是网络接口有一个硬件地址(一个48bit的值,标识不同的以太网或令牌环网络接口)。在硬件层次上进行的数据帧交换必须有正确的接口地址。但是TCP/IP有自己的地址:32bit的IP地址。知道主机的IP地址并不能让内核发送一帧数据给主机。内核(如以太网驱动程序)必须知道目的端的硬件地址才能发送数据。ARP的功能是在32bit的IP地址和采用不同网络技术的硬件地址之间提供动态映射。
点对点链路不使用ARP。当设置这些链路时(一般在引导过程进行),必须告知内核链路每一端的IP地址。像以太网地址这样的硬件地址并不涉及。
只有多路访问链路才需要ARP这样的技术。
<a href="https://s5.51cto.com/oss/201711/09/bd026c46612d8c05a571a8a2d1184d4d.png" target="_blank"></a>
<a href="https://s4.51cto.com/oss/201711/09/1362a196e266c72a6642320c05a4c27c.png" target="_blank"></a>
<a href="https://s2.51cto.com/oss/201711/09/3ebaa89c5e14ed66f7669aea729dc5ed.png" target="_blank"></a>
ARP高效运行的关键是由于每个主机上都有一个ARP高速缓存。这个高速缓存存放了最近Internet地址到硬件地址之间的映射记录。高速缓存中每一项的生存时间一般为20分钟,起始时间从被创建时开始算起。
▼ARP请求包样例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<code>#!/usr/bin/python3.4</code>
<code># -*- coding=utf-8 -*-</code>
<code>import</code> <code>logging</code>
<code>logging.getLogger(</code><code>"scapy.runtime"</code><code>).setLevel(logging.ERROR)</code><code>#清除报错</code>
<code>from</code> <code>scapy.</code><code>all</code> <code>import</code> <code>*</code>
<code>#配置各种信息,以便调用</code>
<code>localmac </code><code>=</code> <code>'00:0c:29:8d:5c:b6'</code>
<code>localip </code><code>=</code> <code>'202.100.1.138'</code>
<code>destip </code><code>=</code> <code>'202.100.1.139'</code>
<code>ifname </code><code>=</code> <code>'eno33554944'</code>
<code>#######################源MAC为本地MAC####目的MAC为广播#########操作码为1(请求)#######################################################由于多个网卡所以需要指派iface###########</code>
<code>result_raw </code><code>=</code> <code>srp(Ether(src</code><code>=</code><code>localmac, dst</code><code>=</code><code>'FF:FF:FF:FF:FF:FF'</code><code>)</code><code>/</code><code>ARP(op</code><code>=</code><code>1</code><code>, hwsrc</code><code>=</code><code>localmac, hwdst</code><code>=</code><code>'00:00:00:00:00:00'</code><code>, psrc</code><code>=</code><code>localip, pdst</code><code>=</code><code>destip), iface </code><code>=</code> <code>ifname, verbose </code><code>=</code> <code>False</code><code>)</code>
<code>'''</code>
<code>sr() function is for sending packets and receiving answers. The function #returns a couple of packet and answers, and the unanswered packets. </code>
<code>sr1() is a variant that only return one packet that answered the packet (or #the packet set) sent. The packets must be layer 3 packets (IP, ARP, etc.). </code>
<code>srp() do the same for layer 2 packets (Ethernet, 802.3, etc.).</code>
<code>send() function will send packets at layer 3. That is to say it will handle routing and layer 2 for you. </code>
<code>sendp() function will work at layer 2.</code>
<code>#print(result_raw)</code>
<code>#(<Results: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) 一个元组,[0]收到响应的数据包,[1]未收到响应的数据包</code>
<code>#print(type(result_raw[0]))</code>
<code>#<class 'scapy.plist.SndRcvList'> #https://fossies.org/dox/scapy-2.3.1/classscapy_1_1plist_1_1SndRcvList.html</code>
<code>result_list </code><code>=</code> <code>result_raw[</code><code>0</code><code>].res </code><code>#res: the list of packets,产生由收发数据包所组成的清单(list)</code>
<code>#print(result_list)</code>
<code>#[(<Ether dst=FF:FF:FF:FF:FF:FF src=00:0c:29:8d:5c:b6 type=ARP |<ARP op=who-has hwsrc=00:0c:29:8d:5c:b6 psrc=202.100.1.138 hwdst=00:00:00:00:00:00 pdst=202.100.1.139 |>>, <Ether dst=00:0c:29:8d:5c:b6 src=00:0c:29:43:52:cf type=ARP |<ARP hwtype=0x1 ptype=IPv4 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:43:52:cf psrc=202.100.1.139 hwdst=00:0c:29:8d:5c:b6 pdst=202.100.1.138 |<Padding load=‘\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00’ |>>>)]</code>
<code>#一个列表,每一个item为一个元组,元组内包括一次ARP请求与回应</code>
<code>#result_list[0][1][0],[0]表示第一组数据包(收发),[1],表示收包(0为发包),[0]表示以太网头部</code>
<code>#print(result_list[0][1][0].fields) 以太网头部字段</code>
<code>#{'dst': '00:0c:29:8d:5c:b6', 'type': 2054, 'src': '00:0c:29:43:52:cf'}</code>
<code>#result_list[0][1][0],[0]表示第一组数据包(收发),[1],表示收包(0为发包),[1]表示ARP头部</code>
<code>#print(result_list[0][1][1].fields) ARP头部字段</code>
<code>#{'pdst': '202.100.1.138', 'hwtype': 1, 'hwdst': '00:0c:29:8d:5c:b6', 'plen': 4, 'ptype': 2048, 'hwsrc': '00:0c:29:43:52:cf', 'op': 2, 'hwlen': 6, 'psrc': '202.100.1.139'}</code>
<code>print</code><code>(</code><code>'IP地址: '</code> <code>+</code> <code>result_list[</code><code>0</code><code>][</code><code>1</code><code>][</code><code>1</code><code>].fields[</code><code>'psrc'</code><code>] </code><code>+</code> <code>' MAC地址: '</code> <code>+</code> <code>result_list[</code><code>0</code><code>][</code><code>1</code><code>][</code><code>1</code><code>].fields[</code><code>'hwsrc'</code><code>])</code>
<a href="https://s5.51cto.com/oss/201711/09/1ccf59da24da649641629ff436b7daae.png" target="_blank"></a>
本文转自Grodd51CTO博客,原文链接:http://blog.51cto.com/juispan/1980254,如需转载请自行联系原作者