Hotaru's Notebook

python-pytun scapy

Preface

好几天没写博客了,今天睡前写一篇糊弄一下吧。内容主要有2:

python-pytun

有些 ISP 会对大流量的 UDP 包进行 QoS,导致的现象就是 上行UDP包100%丢包率 下行没问题,而且还能ping得通服务器。借助这一点,可以琢磨着弄个 ICMP Tunnel,显然 GitHub 上已经有轮子实现这个了,但是我怎么弄都没法让它转发 IP 包。于是干脆自己试着用 python 写一个。(当然,还没写出来,但新学的知识已经够写个笔记了) 选择 python 原因有2:

  1. 调试方便一些,写一点调试一下,不用像 Java 那样还得等编译
  2. 主要原因还是有 python-pytun 这个现成的库,可以直接在 Linux 下创建 tun 设备(豚设备) 而不用自己搞什么 FileDescriptor ioctl 之类的东西

现在这个世界就是不缺轮子。

TUN / TAP 设备

直接由 Linux 内核提供。

Linux tun 设备多给了我 4 bytes 的信息

默认情况下,从 tun 设备读出来的包前面会多出来 4 bytes 的数据,大致是这样:

只有后面的 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