题记
- hacker
A hacker is any highly skilled computer expert. - script kiddie
A script kiddie is an unskilled individual who uses scripts or programs developed by others to attach computer systems and networks and deface websites
ping命令
ping 这个名字来源于航海的声纳定位操作。其操作类似于声纳定位。只不过在网络里发送的是ICMP数据包而不是声波。该命令的目的是用于确定 某个主机 是否可达,距离 当前主机 多远。
其实,我们2台网络设备互ping,是有两种case的。
- 同一网段
如上图,主机A,来ping主机B,那么主机A,就要封装 二层报文 ,他会先查自己的MAC地址表,如果没有B的MAC地址,就会向外发送一个ARP广播包【在之前的网络篇已经讲的很清楚了,这里不再啰嗦】。
交换机会收到这个报文后,交换机有学习MAC地址的功能,所以他会检索自己有没有保存主机B的MAC。
如果有,就返回给主机A,如果没有,就会向所有端口发送ARP广播,其它主机收到后,发现不是在找自己,就纷纷丢弃了该报文,不去理会。
直到主机B收到了报文后,就立即相应,我的MAC地址是多少,同时学到主机A的MAC地址,并按同样的ARP报文格式返回给主机A,如图:
这时候主机A学到了主机B的MAC,就把这个MAC封装到ICMP协议的二层报文中向主机B发送,报文格式如下:
| 目的地址 | 源地址 | 源IP | 目的IP | ICMP报文 |
|---|---|---|---|---|
| 00-50-56-C0-00-03 | 00-50-56-C0-00-01 | 1.1.1.1 | 1.1.1.3 | Echo request |
当主机B收到了这个报文后,发现是主机A 的ICPM回显请求,就按 同样 的格式,返回一个值给主机A,这样就完成了 同一网段内 的ping过程~~
| 目的地址 | 源地址 | 源IP | 目的IP | ICMP报文 |
|---|---|---|---|---|
| 00-50-56-C0-00-01 | 00-50-56-C0-00-03 | 1.1.1.3 | 1.1.1.1 | Echo answer |
而实际上,我啰嗦了这么久的的局域网内的PING,实际过程的发生不到 1毫秒~~
- 不同网段
主机A要ping主机C,那么主机A发现主机C的IP和自己 不是 同一网段。
主机A就去找 网关 转发,但是他也不知道网关的MAC情况下呢?
他就会向之前那个步骤一样先发送一个ARP广播,学到网关的MAC,再发封装ICMP报文给 网关路由器 。
报文格式如下:
| 目的地址 | 源地址 | 源IP | 目的IP | ICMP报文 |
|---|---|---|---|---|
| 00-50-56-C0-00-02 | 00-50-56-C0-00-01 | 1.1.1.1 | 2.1.1.3 | Echo request |
当 路由器 收到主机A发过来的ICMP报文。
发现自己的目的地址是其本身MAC地址,根据目的的IP2.1.1.1,查 路由表,发现2.1.1.1/24的路由表项。
得到一个 出口指针,去掉原来的MAC头部.加上自己的MAC地址向主机C转发…
如果网关也没有主机C的MAC地址,还是要向前面一个步骤一样,ARP广播一下即可相互学到….
路由器2端口能学到主机C的MAC,主机C也能学到路由器2端口的MAC..
报文格式如下:
| 目的地址 | 源地址 | 源IP | 目的IP | ICMP报文 |
|---|---|---|---|---|
| 00-50-56-C0-00-05 | 00-50-56-C0-00-04 | 1.1.1.1 | 2.1.1.1 | Echo request |
最后,在主机C已学到路由器2端口MAC,路由器2端口转发给路由器1端口。
路由1端口学到主机A的MAC的情况下,他们就不需要再做ARP解析,就将ICMP的回显请求回复过来..
| 目的地址 | 源地址 | 源IP | 目的IP | ICMP报文 |
|---|---|---|---|---|
| 00-50-56-C0-00-04 | 00-50-56-C0-00-05 | 2.1.1.1 | 1.1.1.1 | Echo Answer |
代码篇
既然已经明白了ping命令和ICMP的原理,那么我们就可以用代码来实现 自动化 工具~~~
赵四.尼古拉斯基 曾经说过:不要重复造轮子 。
那么,我们来介绍一下Python处理网络协议的 网络层、传输层、链路层 的能手 scapy ,和 爬虫框架 scrapy 表兄弟关系,开个玩笑~~
- Scapy 介绍
Scapy 是一个可以让用户 发送、侦听 和 解析 并伪装网络报文的
Python程序。这些功能可以用于制作 侦测、扫描 和 攻击网络 的工具。
- 安装
pip3 install scapy
- API
- 建立一个数据包
>>> a=IP(ttl=10) >>> a < IP ttl=10 |> >>> a.src ’127.0.0.1’ >>> a.dst="192.168.1.1" >>> a < IP ttl=10 dst=192.168.1.1 |> >>> a.src ’192.168.8.14’ >>> del(a.ttl) >>> a < IP dst=192.168.1.1 |> >>> a.ttl 64- 堆加层次(网络5层模型)
**/**操作符在两层之间起到一个 组合 的作用。
当使用该操作符时,下层 可以根据其 上层,使它的 一个 或 多个 默认字段被重载。 (您仍可以赋予您想要的值)一个字符串也可以被用作原料层(raw layer)。
>>> IP() <IP |> >>> IP()/TCP() <IP frag=0 proto=TCP |<TCP |>> >>> Ether()/IP()/TCP() <Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>> >>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n" <IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>> >>> Ether()/IP()/IP()/UDP() <Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>> >>> IP(proto=55)/TCP() <IP frag=0 proto=55 |<TCP |>>- 发送
>>> a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n" >>> hexdump(a) 00 02 15 37 A2 44 00 AE F3 52 AA D1 08 00 45 00 ...7.D...R....E. 00 43 00 01 00 00 40 06 78 3C C0 A8 05 15 42 23 .C....@.x<....B# FA 97 00 14 00 50 00 00 00 00 00 00 00 00 50 02 .....P........P. 20 00 BB 39 00 00 47 45 54 20 2F 69 6E 64 65 78 ..9..GET /index 2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A .html HTTP/1.0 . 0A . >>> b=str(a) >>> b '\x00\x02\x157\xa2D\x00\xae\xf3R\xaa\xd1\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06x<\xc0 \xa8\x05\x15B#\xfa\x97\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00 \xbb9\x00\x00GET /index.html HTTP/1.0 \n\n'
原理 和API都明白啦,是时候表演我们 真正的技术 啦
1. 构建一个ICMP包
2. 发送并且接受目的主机的回应
3. 如果目的主机可达,已3为结束码并退出进程
Python构建了一个探测工具,判断目的主机的网络连通性。
但仅仅如此还不够智能,我们需要加入多进程扫描整个网络中的活动主机,所以:
- 通过要扫描的I
P,计算出当前区域网的所有主机 - 多线程调用之前我们的探测工具,循环探测网络中的每个主机
- 讲能够连通的主机保存下来
- 为后面我们要做的事情做铺垫
关注微信公众账号【mindev】,回复【ping】可以获取单进程ping的源代码,加入群主星球即可获取所有源代码。
愿意与大家分享交流各种技术,个人公众账号[mindev],以及 知识星球[极客世界]