-
-
Save glacjay/585369 to your computer and use it in GitHub Desktop.
import fcntl | |
import os | |
import struct | |
import subprocess | |
# Some constants used to ioctl the device file. I got them by a simple C | |
# program. | |
TUNSETIFF = 0x400454ca | |
TUNSETOWNER = TUNSETIFF + 2 | |
IFF_TUN = 0x0001 | |
IFF_TAP = 0x0002 | |
IFF_NO_PI = 0x1000 | |
# Open TUN device file. | |
tun = open('/dev/net/tun', 'r+b') | |
# Tall it we want a TUN device named tun0. | |
ifr = struct.pack('16sH', 'tun0', IFF_TUN | IFF_NO_PI) | |
fcntl.ioctl(tun, TUNSETIFF, ifr) | |
# Optionally, we want it be accessed by the normal user. | |
fcntl.ioctl(tun, TUNSETOWNER, 1000) | |
# Bring it up and assign addresses. | |
subprocess.check_call('ifconfig tun0 192.168.7.1 pointopoint 192.168.7.2 up', | |
shell=True) | |
while True: | |
# Read an IP packet been sent to this TUN device. | |
packet = list(os.read(tun.fileno(), 2048)) | |
# Modify it to an ICMP Echo Reply packet. | |
# | |
# Note that I have not checked content of the packet, but treat all packets | |
# been sent to our TUN device as an ICMP Echo Request. | |
# Swap source and destination address. | |
packet[12:16], packet[16:20] = packet[16:20], packet[12:16] | |
# Under Linux, the code below is not necessary to make the TUN device to | |
# work. I don't know why yet, but if you run tcpdump, you can see the | |
# difference. | |
if True: | |
# Change ICMP type code to Echo Reply (0). | |
packet[20] = chr(0) | |
# Clear original ICMP Checksum field. | |
packet[22:24] = chr(0), chr(0) | |
# Calculate new checksum. | |
checksum = 0 | |
# for every 16-bit of the ICMP payload: | |
for i in range(20, len(packet), 2): | |
half_word = (ord(packet[i]) << 8) + ord(packet[i+1]) | |
checksum += half_word | |
# Get one's complement of the checksum. | |
checksum = ~(checksum + 4) & 0xffff | |
# Put the new checksum back into the packet. | |
packet[22] = chr(checksum >> 8) | |
packet[23] = chr(checksum & ((1 << 8) -1)) | |
# Write the reply packet into TUN device. | |
os.write(tun.fileno(), ''.join(packet)) |
Thnx bro. Thnx.
Thanks for code, could you tell me how to create device which survive reboot and how to remove that's devices?
Have you tried this with python3? I get an error on the open call:
tun = open('/dev/net/tun', 'r+b')
Traceback (most recent call last):
File "", line 1, in
io.UnsupportedOperation: File or stream is not seekable.
You'll need to make a few changes for it to work with Python3. Disable buffering on the open call, and use an array instead of a list for the packet data.
Something like this works for me: https://gist.github.com/shawnlower/928cc78614ba726aabab1a299c810f2e/revisions
Can you provide the code to get the ioctl constants ? I don't know how to find them on my FreeNAS device... Thanks !
Can you provide the code to get the ioctl constants ? I don't know how to find them on my FreeNAS device... Thanks !
The constants are defined in /linux/if_tun.h
i tried on python 3 but getting this error on ioctl call
fcntl.ioctl(tun, TUNSETIFF, ifr)
PermissionError: [Errno 1] Operation not permitted
i tried on python 3 but getting this error on ioctl call
fcntl.ioctl(tun, TUNSETIFF, ifr)
PermissionError: [Errno 1] Operation not permitted
You need to be root to do this kind of operations (touching system files).
Thank you very much. I found TUNSETIFF = -2147199798 on my router (OpenWrt on WR-703n). I don't know the reason, but it's running well only if I change TUNSETIFF to -2147199798. http://sorz.org/openwrt-py-tun/