Last active
August 1, 2024 18:33
-
-
Save abdelrahman-t/e39869f39ec6010ddea3cecb03aea648 to your computer and use it in GitHub Desktop.
TUN tunneling/routing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """tun_routing.py""" | |
| import logging as LOGGER | |
| import subprocess | |
| from ipaddress import IPv4Address | |
| from itertools import count | |
| from typing import Union | |
| # pip install pypacker | |
| from pypacker.layer3.ip import IP as IPv4Packet | |
| from pypacker.layer3.ip import IP_PROTO_UDP | |
| from pypacker.layer3.ip6 import IP6 as IPv6Packet | |
| from pypacker.layer4.udp import UDP | |
| # Module available at: https://gist.github.com/abdelrahman-t/a23f57986a40f54108a71d4b91f145b2 | |
| from tun import TUNInterface | |
| LOGGER.basicConfig(level=LOGGER.DEBUG) | |
| def packet_version(packet: bytes) -> int: | |
| # Credit: https://github.com/povilasb/iptun/blob/master/iptun/ip.py#L26 | |
| return packet[0] >> 4 | |
| def parse_packet(data: bytes) -> Union[IPv4Packet, IPv6Packet]: | |
| # Credit: https://github.com/povilasb/iptun/blob/master/iptun/ip.py#L30 | |
| packet_ver = packet_version(data) | |
| if packet_ver == 4: | |
| packet = IPv4Packet(data) | |
| elif packet_ver == 6: | |
| packet = IPv6Packet(data) | |
| else: | |
| raise ValueError(f'Unsupported IP packet version: {packet_ver}') | |
| return packet | |
| def test() -> None: | |
| # Enable IPv4 routing. | |
| subprocess.call(['/sbin/sysctl', '-w', 'net.ipv4.ip_forward=1']) | |
| interface = TUNInterface('custom-tunnel', address=IPv4Address('10.1.0.0')) | |
| interface.up() | |
| counter = count() | |
| while 1: | |
| packet = parse_packet(interface.read(4096) | |
| ) | |
| LOGGER.warning('[%-5s] %-25s -> %-25s', | |
| packet.highest_layer.__class__.__name__, | |
| packet.src_s, packet.dst_s) | |
| if packet[UDP]: | |
| # A UDP packet was received, Let's send a reply. | |
| # Packets written to the TUN interface should have the TUN interface as the destination address | |
| # and not originating interface (e.g. eth0). | |
| # The Linux kernel will automatically detect that a packet is a response to a previously sent packet and | |
| # automatically route it to the originating interface (e.g. eth0). | |
| echo = IPv4Packet(src_s=packet.dst_s, dst_s=str(interface.address), p=IP_PROTO_UDP) +\ | |
| UDP(sport=packet[UDP].dport, dport=packet[UDP].sport) | |
| echo[UDP].body_bytes = f'Reply: {next(counter)}! '.encode('UTF-8') | |
| interface.write(echo.bin()) | |
| if __name__ == '__main__': | |
| test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
will this work in android?