2020-04-17 13:30:31 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2020-04-17 14:53:10 +00:00
|
|
|
import sys
|
2020-04-17 13:30:31 +00:00
|
|
|
import pytun
|
2020-04-17 14:35:11 +00:00
|
|
|
import struct
|
|
|
|
import ipaddress
|
2020-04-17 14:53:10 +00:00
|
|
|
import json
|
2020-04-17 15:10:05 +00:00
|
|
|
import socket
|
2020-04-17 14:35:11 +00:00
|
|
|
|
2020-04-17 15:24:40 +00:00
|
|
|
class Config:
|
|
|
|
def __init__(self, data):
|
|
|
|
if data['mode'] == 'server':
|
|
|
|
self.is_server = True
|
|
|
|
elif data['mode'] == 'client':
|
|
|
|
self.is_server = False
|
|
|
|
else:
|
|
|
|
raise RuntimeError('invalid mode "%s"' % data['mode'])
|
|
|
|
|
|
|
|
self.address = data['address']
|
|
|
|
self.port = data['port']
|
|
|
|
|
|
|
|
self.iface_name = data['iface_name']
|
|
|
|
self.iface_netmask = data['iface_netmask']
|
|
|
|
self.iface_mtu = data['iface_mtu']
|
|
|
|
|
2020-04-17 15:28:29 +00:00
|
|
|
self.iface_addr = ipaddress.IPv4Address(data['iface_addr'])
|
|
|
|
self.iface_dstaddr = ipaddress.IPv4Address(data['iface_dstaddr'])
|
|
|
|
|
2020-04-17 15:17:42 +00:00
|
|
|
class IpPacket:
|
|
|
|
def __init__(self, header, body):
|
|
|
|
self.header = header
|
|
|
|
self.body = body
|
|
|
|
|
2020-04-17 14:35:11 +00:00
|
|
|
class IpHeader:
|
|
|
|
def __init__(self, raw):
|
|
|
|
self.ver_ihl, \
|
|
|
|
self.tos, \
|
|
|
|
self.total_length, \
|
|
|
|
self.ident, \
|
|
|
|
self.flags_fragoffset, \
|
|
|
|
self.ttl, \
|
|
|
|
self.proto, \
|
|
|
|
self.chksum, \
|
|
|
|
src, \
|
|
|
|
dst, \
|
|
|
|
self.opt1, \
|
|
|
|
self.opt2, \
|
|
|
|
self.pad = struct.unpack('>BBHHHBBHIIHBB', raw)
|
|
|
|
|
|
|
|
self.src = ipaddress.IPv4Address(src)
|
|
|
|
self.dst = ipaddress.IPv4Address(dst)
|
2020-04-17 13:30:31 +00:00
|
|
|
|
|
|
|
def main():
|
2020-04-17 14:53:10 +00:00
|
|
|
config_filename = sys.argv[1]
|
|
|
|
|
|
|
|
with open(config_filename) as config_file:
|
2020-04-17 15:24:40 +00:00
|
|
|
config = Config(json.load(config_file))
|
2020-04-17 14:53:10 +00:00
|
|
|
|
2020-04-17 13:30:31 +00:00
|
|
|
tun_iface = pytun.TunTapDevice()
|
|
|
|
|
|
|
|
print(tun_iface.name)
|
|
|
|
|
2020-04-17 15:28:29 +00:00
|
|
|
tun_iface.addr = str(config.iface_addr)
|
|
|
|
tun_iface.dstaddr = str(config.iface_dstaddr)
|
2020-04-17 15:24:40 +00:00
|
|
|
tun_iface.netmask = config.iface_netmask
|
|
|
|
tun_iface.mtu = config.iface_mtu
|
2020-04-17 13:30:31 +00:00
|
|
|
|
|
|
|
tun_iface.up()
|
|
|
|
|
2020-04-17 15:24:40 +00:00
|
|
|
addr_and_port = (config.address, config.port)
|
2020-04-17 15:10:05 +00:00
|
|
|
|
2020-04-17 15:24:40 +00:00
|
|
|
if config.is_server:
|
2020-04-17 15:10:05 +00:00
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
print('binding to %s, port %s' % addr_and_port)
|
|
|
|
sock.bind(addr_and_port)
|
|
|
|
sock.listen(1)
|
|
|
|
print('waiting for incoming connection')
|
|
|
|
conn, client_addr = sock.accept()
|
|
|
|
print('accepted incoming connection from %s' % client_addr[0])
|
2020-04-17 15:24:40 +00:00
|
|
|
|
2020-04-17 15:10:05 +00:00
|
|
|
else:
|
2020-04-17 15:24:40 +00:00
|
|
|
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
print('connecting to %s, port %s' % addr_and_port)
|
|
|
|
conn.connect(addr_and_port)
|
|
|
|
print('connected!')
|
2020-04-17 15:10:05 +00:00
|
|
|
|
2020-04-17 13:30:31 +00:00
|
|
|
while True:
|
|
|
|
buf = tun_iface.read(tun_iface.mtu)
|
2020-04-17 14:35:11 +00:00
|
|
|
|
|
|
|
flags = buf[:2]
|
|
|
|
proto = buf[2:4]
|
|
|
|
|
|
|
|
if proto != b'\x08\x00':
|
|
|
|
continue
|
|
|
|
|
2020-04-17 15:17:42 +00:00
|
|
|
ip_packet = IpPacket(IpHeader(buf[4:28]), buf[28:])
|
2020-04-17 14:35:11 +00:00
|
|
|
|
2020-04-17 15:17:42 +00:00
|
|
|
handle_ip_packet(ip_packet, conn, tun_iface, config)
|
2020-04-17 14:35:11 +00:00
|
|
|
|
2020-04-17 15:17:42 +00:00
|
|
|
def handle_ip_packet(ip_packet, conn, tun_iface, config):
|
|
|
|
print(
|
|
|
|
ip_packet.header.src,
|
|
|
|
'→',
|
|
|
|
ip_packet.header.dst,
|
|
|
|
'len: %d' % ip_packet.header.total_length,
|
|
|
|
)
|
2020-04-17 13:30:31 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|