准备环境
- 创建tun设备
- 启动tun设备
- 设置ip
- 设置nat,将源地址改为对应的网关地址
- 允许tun设备上对应网段的进出流量
# Sets up a tun/tap device on Linux
sudo ip tuntap add name tun0 mode tun user $USER
sudo ip link set tun0 up
sudo ip addr add 192.0.2.1 peer 192.0.2.2 dev tun0
sudo iptables -t nat -A POSTROUTING -s 192.0.2.2 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -s 192.0.2.2 -j ACCEPT
sudo iptables -A FORWARD -o tun0 -d 192.0.2.2 -j ACCEPT
程序读写tun设备
# Sends a SYN packet to `example.com`
import struct
from fcntl import ioctl
def openTun(tunName):
tun = open("/dev/net/tun", "r+b", buffering=0)
LINUX_IFF_TUN = 0x0001
LINUX_IFF_NO_PI = 0x1000
LINUX_TUNSETIFF = 0x400454CA
flags = LINUX_IFF_TUN | LINUX_IFF_NO_PI
ifs = struct.pack("16sH22s", tunName, flags, b"")
ioctl(tun, LINUX_TUNSETIFF, ifs)
return tun
syn = b'E\x00\x00,\x00\x01\x00\x00@\x06\x00\xc4\xc0\x00\x02\x02"\xc2\x95Cx\x0c\x00P\xf4p\x98\x8b\x00\x00\x00\x00`\x02\xff\xff\x18\xc6\x00\x00\x02\x04\x05\xb4'
tun = openTun(b"tun0")
tun.write(syn)
reply = tun.read(1024)
print(repr(reply))
通过tcpdump抓包
(base) [root@iZ8vb0t5v537xbzma7j0ryZ ~]# tcpdump -ni tun0
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
21:54:45.179898 IP 192.0.2.2.30732 > 34.194.149.67.http: Flags [S], seq 4101019787, win 65535, options [mss 1460], length 0
21:54:45.408688 IP 34.194.149.67.http > 192.0.2.2.30732: Flags [S.], seq 3807671113, ack 4101019788, win 64480, options [mss 1240], length 0