python-pytun scapy
Preface
好几天没写博客了,今天睡前写一篇糊弄一下吧。内容主要有2:
- 用 python-pytun 和 scapy 试着弄个包转发工具
- Depression 与自我恢复
python-pytun
有些 ISP 会对大流量的 UDP 包进行 QoS,导致的现象就是 上行UDP包100%丢包率 下行没问题,而且还能ping得通服务器。借助这一点,可以琢磨着弄个 ICMP Tunnel,显然 GitHub 上已经有轮子实现这个了,但是我怎么弄都没法让它转发 IP 包。于是干脆自己试着用 python 写一个。(当然,还没写出来,但新学的知识已经够写个笔记了) 选择 python 原因有2:
- 调试方便一些,写一点调试一下,不用像 Java 那样还得等编译
- 主要原因还是有
python-pytun
这个现成的库,可以直接在 Linux 下创建 tun 设备(豚设备) 而不用自己搞什么 FileDescriptor ioctl 之类的东西
现在这个世界就是不缺轮子。
TUN / TAP 设备
直接由 Linux 内核提供。
- tun 设备:就是 tunnel 设备,可以收发 Network layer (Layer 3,比如 IP, ICMP)的包.
- tap 设备:就是 tap 设备(反正我没找到 tap 是什么的简写),可以收发 Data link layer(Layer 2,比如 ARP, IEEE 802.3)的包
Linux tun 设备多给了我 4 bytes 的信息
默认情况下,从 tun 设备读出来的包前面会多出来 4 bytes 的数据,大致是这样:
- 2 bytes: Ethernet
- 2 bytes: IP Header
- Various: IP Packet
只有后面的 IP Packet 才是我要的,前面的 4 bytes 目前没什么用。想关掉它的话,需要在创建 TunTapDevice
对象时加个构造函数参数:
"""
IFF_TUN: 表示我想创建一个 tun 设备
IFF_NO_PI: 不要提供包信息(Do not provide packet information)
"""
tun = pytun.TunTapDevice("pytun0", pytun.IFF_TUN | pytun.IFF_NO_PI)
使用上面的代码后,tun.read(tun.mtu)
读出的包就只有 IP Packet 的信息了,可以直接扔给 scapy,像这样:
from scapy import all as scapy3k
lPacketIP = scapy3k.IP(tun.read(tun.mtu))
lPacketIP.show2()
一个 ICMP echo-request(也就是 ping)包的输出大概是这样:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 84
id = 18507
flags = DF
frag = 0
ttl = 64
proto = icmp
chksum = 0xce59
src = 10.0.8.1
dst = 10.0.8.4
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = 0xb85c
id = 0x3ddd
seq = 0x1
###[ Raw ]###
load = b'\xc6\xeb\nY\x00\x00\x00\x00i\xad\x08\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
不出意外的话,明天应该开始看 IP 包和 ICMP 包的结构了。 收工,睡觉.
#Python #python-pytun #scapy #Linux #tun #tap #Packet Tunneling #Depression