-
-
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/