class Client: def __init__(self): self.selectors = selectors.DefaultSelector() self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.tun = TunTapDevice(name='mytun', flags=IFF_TUN) self.selectors.register(self.tun, selectors.EVENT_READ, self.packetSender) self.selectors.register(self.sock, selectors.EVENT_READ) def packetSender(self, tun, mask): data = tun.read(100) data = self.dnsAssemble(data) self.sock.sendto(data, ('120.78.166.34', 53)) def dnsAssemble(self, data): packet = dnslib.DNSRecord.question("{}group-17.cs305.fun".format(data), "TXT") return packet.pack() def packetReader(self, conn, mask): data = conn.read(1024).decode() packet = dnslib.DNSRecord.parse(data) msg = packet.questions self.tun.write(msg) def run(self): while True: events = self.selectors.select() for key, mask in events: callback = key.data callback(key.fileobj, mask)
class MainHandler(websocket.WebSocketHandler): def __init__(self, *args, **kwargs): super(MainHandler, self).__init__(*args,**kwargs) self.thread = None def open(self): self.set_nodelay(True) self.tun = TunTapDevice(flags= (IFF_TAP | IFF_NO_PI)) self.tun.addr = '192.168.1.1' self.tun.dstaddr = '192.168.1.2' self.tun.netmask = '255.255.255.0' self.tun.mtu = 1500 self.tun.up() self.thread = TunThread(tun=self.tun, socket = self) self.thread.start() def on_message(self, message): print('wrote %s byte message to %s' % (len(message), self.tun.name)) print(':'.join('{0:x}'.format(ord(c)) for c in message)) self.tun.write(message) def on_close(self): print('Closing %s' % self.tun.name) self.tun.close() if self.thread is not None: self.thread.running = False
class TunThread(threading.Thread): def __init__(self, *args, **kwargs): super(TunThread, self).__init__(*args, **kwargs) self.running = True self.tun = TunTapDevice(flags=(IFF_TAP | IFF_NO_PI)) self.tun.addr = '10.5.0.1' self.tun.netmask = '255.255.0.0' self.tun.mtu = 1500 self.tun.up() def write(self, message): self.tun.write(message) def run(self): p = poll() p.register(self.tun, POLLIN) try: while (self.running): #TODO: log IP headers in the future pollret = p.poll(1000) for (f, e) in pollret: if f == self.tun.fileno() and (e & POLLIN): buf = self.tun.read( self.tun.mtu + 18) #MTU doesn't include header or CRC32 if len(buf): mac = buf[0:6] if mac == BROADCAST or (ord(mac[0]) & 0x1) == 1: for socket in macmap.values(): def send_message(): try: socket.rate_limited_downstream( str(buf)) except: pass loop.add_callback(send_message) elif macmap.get(mac, False): def send_message(): try: macmap[mac].rate_limited_downstream( str(buf)) except: pass loop.add_callback(send_message) except: logger.error('closing due to tun error') finally: self.tun.close()
class TapNode(object): def __init__(self): os.system('sudo ip tuntap add dev esp32 mode tap user ds') time.sleep(1) self.tap = TunTapDevice(name='esp32', flags=IFF_TAP) def write(self, pkt): self.tap.write('\x00\x00\x00\x00' + pkt) print 'Wrote %d WIFI bytes to host' % len(pkt) #hexdump.hexdump(pkt) def read(self): data = self.tap.read(2000)[4:] print 'Read %d bytes from TAP interface' % len(data) return (PktType.WIFI, data)
class backend: def __init__(self): self.tun = TunTapDevice(name='strangenet', flags=pytun.IFF_TUN | pytun.IFF_NO_PI) logging.debug('Created Linux tun device ' + self.tun.name) self.tun.addr = os.getenv('STRANGENET_IP', '10.0.0.1') logging.info('Assigned Linux tun device IP: ' + self.tun.addr) self.tun.netmask = os.getenv('STRANGENET_NETMASK', '255.255.255.0') logging.info('Configured Linux tun device netmask: ' + self.tun.netmask) self.tun.persist( True) # TODO figure out what this does and if we need it self.tun.mtu = 256 self.tun.up() logging.info('Linux tun device is up!') # setup polling self.poller = select.poll() self.poller.register(self.tun, select.POLLIN) def set_mtu(self, mtu): self.tun.mtu = mtu # called by main code when data is recieved from XBee def tx(self, payload): logging.info('Writing payload') print(payload) self.tun.write(payload) def poll(self, timeout): logging.debug('Checking for packets on TUN...') events = self.poller.poll(timeout) if events: # lists are true iff. they are non-empty # FIXME properly read the (fd, event) tuple, iterate list logging.debug("Select poller reports TUN is readable...") data = self.tun.read(self.tun.mtu) logging.debug("Incoming packets on TUN...") #sys.stdout.buffer.write(data) pack = ip.IP(data) return {"IP": pack.dst, "payload": data} else: logging.debug("No packets from TUN.") return None def phy_noroute(self, invalidip, datastart): pass
class Tun(): """ Initializes the tun device """ def __init__(self, name, address, netmask, mtu): self.name = name self.tun = TunTapDevice(self.name) self.tun.addr = address self.tun.netmask = netmask self.tun.mtu = mtu self.tun.up() """ Reads data from device """ def read(self, nbytes): return self.tun.read(nbytes + PSEUDO_HEADER_SIZE) """ Writes buffer to device """ def write(self, buf): return self.tun.write(buf)
class TunThread(threading.Thread): def __init__(self, *args, **kwargs): super(TunThread, self).__init__(*args, **kwargs) self.running = True self.tun = TunTapDevice(flags= (IFF_TAP | IFF_NO_PI)) self.tun.addr = '10.5.0.1' self.tun.netmask = '255.255.0.0' self.tun.mtu = 1500 self.tun.up() def write(self, message): self.tun.write(message) def run(self): p = poll() p.register(self.tun, POLLIN) try: while(self.running): #TODO: log IP headers in the future pollret = p.poll(1000) for (f,e) in pollret: if f == self.tun.fileno() and (e & POLLIN): buf = self.tun.read(self.tun.mtu+18) #MTU doesn't include header or CRC32 if len(buf): mac = buf[0:6] if mac == BROADCAST or (ord(mac[0]) & 0x1) == 1: for socket in macmap.values(): def send_message(): try: socket.rate_limited_downstream(str(buf)) except: pass loop.add_callback(send_message) elif macmap.get(mac, False): def send_message(): try: macmap[mac].rate_limited_downstream(str(buf)) except: pass loop.add_callback(send_message) except: logger.error('closing due to tun error') finally: self.tun.close()
class TunTap(object): def __init__(self): self.tun = TunTapDevice(name="fhdi") self.cs = Lock() def open(self): self.tun.addr = '172.16.0.1' self.tun.netmask = '255.255.255.0' self.tun.mtu = 1500 self.tun.up() def close(self): self.tun.close() def write(self, buf): self.cs.acquire() self.tun.write(buf) self.cs.release()
class TunTap(object): def __init__(self, name, ip, netmask): self.tun = TunTapDevice(name=name, flags=pytun.IFF_TUN | pytun.IFF_NO_PI) self.tun.addr = ip self.tun.netmask = netmask self.mtu = 1500 # self.tun.persist(True) self.tun.up() def getfd(self): return self.tun def recv(self): return self.tun.read(self.mtu) def send(self, buf): self.tun.write(buf)
class TUNReader(object): """TUN device""" def __init__(self, tun_dev, tun_addr, tun_remote_addr, tun_nm, tun_mtu, wsfactory): self.wsfactory = wsfactory try: self.tun = TunTapDevice(name=tun_dev, flags=(IFF_TUN|IFF_NO_PI)) except: log.msg("Couldn't open the TUN device. Are you root? Is the interface already in use?", logLevel=logging.WARN) sys.exit(ERR) self.tun.addr = tun_addr self.addr = tun_addr # used by mtcrypt self.tun.dstaddr = tun_remote_addr self.tun.netmask = tun_nm self.tun.mtu = int(tun_mtu) self.tun.up() reactor.addReader(self) logstr = ("Opened TUN device on %s") % (self.tun.name) log.msg(logstr, logLevel=logging.INFO) def fileno(self): return self.tun.fileno() def connectionLost(self, reason): log.msg("Connection lost", logLevel=logging.INFO) def doRead(self): """Read from host, send to WS to be sent to distant end""" data = self.tun.read(self.tun.mtu) self.wsfactory.tunnel_write(data) def doWrite(self, data): self.tun.write(data) def logPrefix(self): return "TUNReader"
def run(self): """ Method called when starting the daemon. """ try: logger.info("TapDaemon has started") tap0 = TunTapDevice(name="tap0", flags=IFF_TAP) tap0.hwaddr = '\x00\x11\x22\x33\x44\x55' tap0.addr = '192.168.0.1' tap0.dstaddr = '192.168.0.2' tap0.netmask = '255.255.255.0' tap0.mtu = 1500 tap0.persist(True) tap0.up() logger.info("tap0 interface created") except: logger.exception("exception: ") try: tap1 = TunTapDevice(name="tap1", flags=IFF_TAP) tap1.hwaddr = '\x00\x11\x22\x33\x44\x66' tap1.addr = '192.168.1.1' tap1.dstaddr = '192.168.1.2' tap1.netmask = '255.255.255.0' tap1.mtu = 1500 tap1.persist(True) tap1.up() logger.info("tap1 interface created") except: logger.exception("exception: ") try: while True: time.sleep(2) frame = Ethernet(dst="\x01\x02\x03\x04\x05\x06", src="\x0A\x0B\x0C\x0D\x0E\x0F", type = 0x9100, data = "\x02\x55\x44\x00\x11\x00\x00\x00\x33\x22\x00\x00" + "\x61"*40) # "\x11\x00\x00\x00\x33\x22\x00\x00" #"\x00\x03\x08\x00" tap0.write("\x11\x22\x33\x44" + str(frame)) logger.info("Frame send to tap0") logger.info("Waiting for frame in tap1...") buf = tap1.read(tap1.mtu) logger.info("Received %s", hexlify(buf)) logger.info("\n\n ---------------------------------------------------") except: logger.exception("exception: ")
def main(): parser = argparse.ArgumentParser() parser.add_argument('-s', '--source-addr', default='10.8.0.1') parser.add_argument('-d', '--dest-addr', default='10.8.0.2') parser.add_argument('-m', '--netmask', default='255.255.255.0') parser.add_argument('-l', '--mtu', default=1500, type=int) args = parser.parse_args() tun = TunTapDevice() try: tun.addr = args.source_addr tun.dstaddr = args.dest_addr tun.netmask = args.netmask tun.mtu = args.mtu while True: buf = tun.read(tun.mtu) print(buf) tun.write(buf) finally: tun.close()
sys.exit(ERROR) packetnumber = 0 try: while (True): raw_packet = tap.read(tap.mtu) # buf = tun.read(tun.mtu) eth_frame = eth.Ethernet_Frame(raw_packet) print(str(eth_frame)) if f.ETHER_TYPE[eth_frame.eth_type.hex()] == 'ARP': arp_packet = arp.ARP_packet(eth_frame.data) print(str(arp_packet)) if f.OP[arp_packet.op.hex()] == 'ARP_request': if arp_packet.conv_reply_packet(): eth_frame.src_mac_addr = arp_packet.sender_mac_addr eth_frame.dst_mac_addr = arp_packet.target_mac_addr eth_frame.data = arp_packet.packet print(str(arp_packet)) tap.write(eth_frame.frame) packetnumber += 1 except KeyboardInterrupt: tap.close() # tun.close() print('\nExit') sys.exit(SUCCESS)
class QRTun(object): def __init__(self, side): self.side = int(side) if self.side not in [1, 2]: print("Side must be 1 or 2") raise Exception("Invalid Side") self.tun = TunTapDevice(flags=IFF_TUN | IFF_NO_PI, name='qrtun%d' % self.side) self.tun.addr = '10.0.8.%d' % (self.side) if self.side == 1: self.other_side = 2 else: self.other_side = 1 self.tun.netmask = '255.255.255.0' #MTU must be set low enough to fit in a single qrcode self.tun.mtu = 500 self.epoll = select.epoll() self.epoll.register(self.tun.fileno(), select.EPOLLIN) self.tun.up() self.outfile = 'resources/toscreen%d.png' % (self.side) self.infile = 'resources/toscreen%d.png' % (self.other_side) self.indata = None self.olddata = "" self.outdata = "" self.running = False self.qr = qrtools.QR() self.vc = cv2.VideoCapture(0) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 720) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1280) def read_tun(self): events = self.epoll.poll(0) if events: self.outdata = self.tun.read(self.tun.mtu) return True return False def write_qrcode(self): #Base32 encode since alphanumeic qr code only allows A-Z, 0-9 and some # symbols, but base64 uses lowercase as well.... body = base64.b32encode(self.outdata).replace('=', '/') qr = qrtools.QR() qrb = qrtools.QR() qrb.data = " " qr.data = body #Had an issue where decoded data did not match encoded data... #So I just add plus symbols as padding until they match, then strip # on the other side.... while qr.data != qrb.data: qr.pixel_size = 12 qr.encode(self.outfile) qrb.decode(self.outfile) if qrb.data != qr.data: print("EncodingFailure", qr.data) qr.data += '+' self.msg_read = False def write_tun(self): try: if len(self.indata.get('body')) > 0: data = self.indata.get('body') if data != self.olddata: self.tun.write(data) #This is a hacky way to avoid dup packets... #surely a better way to do this... self.olddata = data except: print("Failed to write to tun!") def read_qrcode(self): qr = qrtools.QR() try: if not qr.decode(self.infile): return False body = base64.b32decode(qr.data.replace('/', '=').replace('+', '')) self.indata = {'body': body} self.write_tun() except: pass def run(self): self.running = True while self.running: if self.read_tun(): self.write_qrcode() rval, frame = self.vc.read() if not rval: running = False break scipy.misc.toimage(frame).save(self.infile) self.read_qrcode() if os.path.isfile(self.outfile): sprite = factory.from_image(self.outfile) spriterenderer.render(sprite) event = SDL_Event() while SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == SDL_QUIT: self.running = False break elif event.type == SDL_KEYDOWN and event.key.keysym.sym == SDLK_ESCAPE: self.running = False break try: os.unlink(self.outfile) os.unlink(self.infile) except: pass
class QRTun(object): def __init__(self, side): self.side = int(side) if self.side not in [1,2]: print("Side must be 1 or 2") raise Exception("Invalid Side") self.tun = TunTapDevice(flags=IFF_TUN|IFF_NO_PI, name='qrtun%d'%self.side) self.tun.addr = '10.0.8.%d'%(self.side) if self.side == 1: self.other_side = 2 else: self.other_side = 1 self.tun.netmask = '255.255.255.0' #MTU must be set low enough to fit in a single qrcode self.tun.mtu = 300 self.epoll = select.epoll() self.epoll.register(self.tun.fileno(), select.EPOLLIN) self.tun.up() #self.outfile = 'resources/toscreen%d.png'%(self.side) self.outfile = None self.infile = 'resources/toscreen%d.png'%(self.other_side) self.indata = None self.olddata = "" self.outdata = "" self.running = False self.vc = cv2.VideoCapture(0) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 720) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1280) self.scanner = zbar.ImageScanner() self.scanner.parse_config('enable') pygame.init() pygame.event.set_allowed(None) pygame.event.set_allowed([pygame.KEYDOWN, pygame.QUIT]) self.screen = pygame.display.set_mode((SIZE, SIZE)) self.scale = 12 self.display_cam = False pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) def read_tun(self): events = self.epoll.poll(0) if events: self.outdata = self.tun.read(self.tun.mtu) return True return False def write_qrcode(self): p = subprocess.Popen(['qrencode', '-o', '-', '-s', str(self.scale)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out, std_err = p.communicate(input=b32encode(self.outdata).replace('=', '/')) if std_err: raise Exception("qrencodeError", std_err.strip()) self.outfile = StringIO.StringIO(std_out) if self.display_cam: cimg = StringIO.StringIO() self.inframe.save(cimg, 'png') cimg.seek(0) cpimg = pygame.image.load(cimg) self.screen.blit(cpimg, (0,0)) pygame.display.flip() else: if self.outfile and not self.outfile.closed: pimg = pygame.image.load(self.outfile) if pimg.get_width() > self.screen.get_width() or pimg.get_height() > self.screen.get_height(): pygame.display.set_mode((pimg.get_width(), pimg.get_height())) self.screen.fill((0,0,0)) self.screen.blit(pimg, (0,0)) pygame.display.flip() self.msg_read = False def write_tun(self): try: if len(self.indata.get('body')) > 0: data = self.indata.get('body') if data != self.olddata: self.tun.write(data) #This is a hacky way to avoid dup packets... #surely a better way to do this... self.olddata = data except: print("Failed to write to tun!") def read_qrcode(self): p = subprocess.Popen(['zbarimg', '-q', '--raw', 'PNG:-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) temp_png = StringIO.StringIO() self.inframe.save(temp_png, 'png') std_out, std_err = p.communicate(input=temp_png.getvalue()) if len(std_out) == 0: return False if std_err: raise Exception("zbarimg", std_err.strip()) #p = subprocess.Popen(['iconv', '-f', 'UTF-8', '-t', 'ISO-8859-1'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) #std_out, std_err = p.communicate(input=std_out) #if std_err: # raise Exception("iconv", std_err.strip()) try: self.indata = {'body': b32decode(std_out.rstrip().replace('/', '='))} self.write_tun() except: pass def read_cam(self): rval, frame = self.vc.read() if not rval: return False self.inframe = scipy.misc.toimage(frame).convert('L') print "CAM" return True def run(self): self.running = True while self.running: if self.read_tun() or self.display_cam: self.write_qrcode() if not self.read_cam(): running = False break self.read_qrcode() event = pygame.event.poll() if event.type == pygame.QUIT: self.running = False pygame.quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False pygame.quit() elif event.key == pygame.K_UP: self.scale += 1 pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) self.write_qrcode() elif event.key == pygame.K_DOWN: self.scale -= 1 pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) self.write_qrcode() elif event.key == pygame.K_SPACE: self.display_cam = not self.display_cam self.write_qrcode() try: #os.unlink(self.outfile) os.unlink(self.infile) except: pass
print "Name %s" % tun1.name tun1.addr = '10.8.0.1' tun1.dstaddr = '10.8.0.2' tun1.netmask = '255.255.255.0' tun1.mtu = 1500 tun1.up() print "Name %s" % tun2.name tun2.addr = '10.8.0.2' tun2.dstaddr = '10.8.0.1' tun2.netmask = '255.255.255.0' tun2.mtu = 1500 tun2.up() while True: r = select([tun1, tun2], [], [])[0][0] try: buf = r.read(r.mtu) if r == tun1: read = tun1.name tun2.write("Hi tun1!") else: read = tun2.name tun1.write("Hi tun2!") print "Read from %s: %s" % (read, buf.encode('hex')) #time.sleep(5) except: tun1.close() tun2.close() exit()
class TLSTunnel(): def initialize (self): # parse arguments parser = argparse.ArgumentParser(description='TLS tunnel client') parser.add_argument('--mode', dest='mode', type=str, default="server") parser.add_argument('--priv_net_addr', dest='priv_net_addr', type=str, default='') parser.add_argument('--tap_mtu', dest='tap_mtu', type=int, default=1500) # server parser.add_argument('--listen_addr', dest='listen_addr', default = '0.0.0.0') parser.add_argument('--listen_port', dest='listen_port', type=int, default= 8082) parser.add_argument('--tb_rate', dest='tb_rate', type=int, default= 100) parser.add_argument('--tb_burst', dest='tb_burst', type=int, default= 1000) # client parser.add_argument('--server_addr', dest='server_addr', default = 'localhost') parser.add_argument('--server_port', dest='server_port', type=int, default= 8082) parser.add_argument('--server_sni_hostname', dest='server_sni_hostname', default = 'tunnel-server') self.args = parser.parse_args() self.tap_mtu = self.args.tap_mtu if self.args.mode == 'client': print("**Client**") self.server_port = self.args.server_port self.server_sni_hostname = self.args.server_sni_hostname self.server_cert = '/root/environments/tls/certs/server.crt' self.client_cert = '/root/environments/tls/certs/client.crt' self.client_key = '/root/environments/tls/certs/client.key' self.pkts_rcvd = [0] self.pkts_sent = 0 elif self.args.mode == 'server': print("**Server**") self.server_cert = '/root/environments/tls/certs/server.crt' self.server_key = '/root/environments/tls/certs/server.key' self.client_certs_path = '/root/environments/tls/certs/' self.tb_rate = self.args.tb_rate self.tb_burst = self.args.tb_burst self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) self.context.verify_mode = ssl.CERT_REQUIRED self.context.load_cert_chain(certfile=self.server_cert, keyfile=self.server_key) self.context.load_verify_locations(capath=self.client_certs_path) # List of active connections - dicts, with IP, port, socket object, # thread signal (to kill corresponding thread), and Common Name # example_connection = { # 'ip' : '10.0.0.2', # 'port' : 2000, # 'socket' : conn, # 'kill_signal' : False, # 'CN' : 'client' # } self.active_connections = [] else: print("Unnown mode -- choose between client and server") def create_tap(self): # identify interface for bridging, will may take some time to be created def get_interface_for_ip(addr): mon_if_name = '' addrs = psutil.net_if_addrs() for netif in addrs: for iface in addrs[netif]: #print (str(iface.family)) if str(iface.family) == 'AddressFamily.AF_INET': ip_addr = ipaddress.IPv4Network((addrs[netif][0].address, addrs[netif][0].netmask), strict=False) print(ip_addr.network_address) if self.args.priv_net_addr.split('/')[0] == str(addrs[netif][0].address): mon_if_name = netif break return mon_if_name mon_if_name = get_interface_for_ip (self.args.priv_net_addr) while mon_if_name == '' or mon_if_name is None: print("waiting for interface to be active " + self.args.priv_net_addr) r("/bin/sleep 2s") mon_if_name = get_interface_for_ip (self.args.priv_net_addr) # create tap self.tap_interface = 'tap0' addrs = psutil.net_if_addrs() if mon_if_name == '': print ('No interface specified') elif self.tap_interface not in addrs: print('Creating tap ' + self.tap_interface + ' for ' + mon_if_name) #os.system("/root/environments/tls/start-tap.sh " + mon_if_name + " 10.0.2.2/24") r("mkdir /dev/net") r("mknod /dev/net/tun c 10 200") r("ip tuntap add tap0 mode tap") r("brctl addbr br0") r("ip link set tap0 up") r("ip link set br0 up") r("brctl addif br0 tap0") r("brctl addif br0 " + mon_if_name) r("ip addr del " + self.args.priv_net_addr + " dev " + mon_if_name) r("ip addr add " + self.args.priv_net_addr + " dev br0") else: print('Tap already created') # Initialize a TAP interface and make it non-blocking self.tap = TunTapDevice(flags = IFF_TAP|IFF_NO_PI, name=self.tap_interface); self.tap.up() fcntl.fcntl(self.tap.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) self.tap.mtu = self.tap_mtu def srvThreadTapReadFunction(tap,conn_list): # Check for packets in tap interface and send them to every active connection print("Tap thread started") while True: try: # +20 for ethernet headear packet = tap.read(tap.mtu + 20) # Insert first 3 bytes with 0 and 2 byte big endian int with actual size. l = len(packet) b_packet_length = l.to_bytes(2, byteorder='big') bb1 = bytearray(b'\x00') bb2 = bytearray(b_packet_length) bb3 = bytearray(packet) buf = bytes(bb1+bb2+bb3) except Exception as e: if e.args[0] == errno.EAGAIN or e.args[0] == errno.EWOULDBLOCK: # Not an actual error, just no data to read yet # (this is expected, wait some more) sleep(0.1) # If we wish to insert a "fake packet", fill 'buf' # Otherwise, "continue", forcing a new tap read continue else: # Actual error - raise! print(e) raise for conn in conn_list: # Do not send when client is not the destination? / Apply some filtering here. # Decide if we should add padding to a given packet. if conn['kill_signal'] == False: try: conn['socket'].send(buf) except OSError as exc: print("Error while sending data to {}:{} ({})".format(conn['ip'], conn['port'], conn['CN'])) if exc.errno == errno.EPIPE: print("Broken pipe. Sending kill signal...") conn['kill_signal'] = True # per client read from ssl and write into tap def srvThreadTapWrite(self, clientsocket, addr, clienttap, conn_list, buckets): print("New TCP Connection: {}:{}".format(addr[0], addr[1])) try: conn = self.context.wrap_socket(clientsocket, server_side=True) except Exception as e: print("SSL connection not established.") print(e) print("") return print("SSL established.") print("Peer: {}".format(conn.getpeercert())) new_conn = { 'ip' : addr[0], 'port' : addr[1], 'socket' : conn, 'kill_signal' : False, 'CN' : [cn for ((n,cn),) in conn.getpeercert()['subject'] if n == 'commonName'][0] } conn_list.append(new_conn) conn.setblocking(0) while new_conn['kill_signal'] == False: try: # timestamp and add tokens to bucket ready = select.select([conn], [], [], 0.1) if ready[0]: data = self.get_packet_from_tls(conn) # data = conn.recv(clienttap.mtu) if data: if buckets.consume(new_conn['CN']): #print("tb OK", new_conn['CN'], buckets._storage.get_token_count(new_conn['CN'])) # Remove padding or fake packets. First bytes 2 dictate real size. # Also, apply a firewall here! (decide if a packet coming # from the TLS tunnel should go to the network interface) clienttap.write(data) else: #print("tb XX", new_conn['CN'], buckets._storage.get_token_count(new_conn['CN'])) pass else: sleep(0.05) except OSError as exc: if exc.errno == errno.ENOTCONN: print("Connection to {} closed by remote host.".format(addr[0])) break conn_list.remove(new_conn) try: conn.shutdown(socket.SHUT_RDWR) conn.close() print("Connection to {}:{} ({}) closed.".format(new_conn['ip'], new_conn['port'], new_conn['CN'])) except: pass def srvThreadServerFunction(self, listen_addr, listen_port, conn_list, buckets): bindsocket = socket.socket() bindsocket.bind((listen_addr, listen_port)) bindsocket.listen(5) print("Waiting for clients") # Wait for new connections and serve them, creating a thread for each client while True: newsocket, fromaddr = bindsocket.accept() # blocking call client_thread = threading.Thread(target=self.srvThreadTapWrite, args=(newsocket,fromaddr,self.tap,conn_list,buckets,)) client_thread.daemon = True; client_thread.start() def srvThreadCLI(clientsocket, addr, clienttap, conn_list): print("Available commands: close, block, list, exit") while True: try: inp = input('>> ') if inp == "close": print("\nActive connections:") for i, connection in enumerate(active_connections): print("{} - {}:{} ({})".format(i, connection['ip'], connection['port'], connection['CN'])) chosen_connection = input("Which connection to close? [0-{}] >> ".format(len(active_connections)-1)) try: c = active_connections[int(chosen_connection)] except: pass else: confirmation = input("Terminate connection to {}:{} ({})? (Y/n) >> ".format(c['ip'], c['port'], c['CN'])) if confirmation != "N" and confirmation != "n": c['kill_signal'] = True print("Kill signal sent.") elif inp == "block": print("\nActive clients:") cn_list = list(set([conn['CN'] for conn in active_connections])) for i, client in enumerate(cn_list): print("{} - {}".format(i, client)) chosen_connection = input("Which certificate to block? [0-{}] >> ".format(len(cn_list)-1)) try: chosen_cn = cn_list[int(chosen_connection)] except: pass else: confirmation = input("Terminate every connection from client [{}]? (Y/n) >> ".format(chosen_cn)) if confirmation != "N" and confirmation != "n": for conn in active_connections: if conn['CN'] == chosen_cn: conn['kill_signal'] = True print("Kill signal sent to {}:{}.".format(conn['ip'], conn['port'])) elif inp == "list": print("\nActive connections:") for i, connection in enumerate(active_connections): print("{} - {}:{} ({})".format(i, connection['ip'], connection['port'], connection['CN'])) print("\nActive clients:") cn_list = list(set([conn['CN'] for conn in active_connections])) for i, client in enumerate(cn_list): print("{} - {}".format(i, client)) elif inp == "update": context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) context.verify_mode = ssl.CERT_REQUIRED context.load_cert_chain(certfile=server_cert, keyfile=server_key) context.load_verify_locations(capath=client_certs_path) print("Updating client certificates...") elif inp == "exit": print("Terminating server. Closing connections...") for connection in active_connections: connection['kill_signal'] = True sleep(3) break except KeyboardInterrupt as e: print("\nKeyboard interrupt detected. Aborting.") for connection in active_connections: connection['kill_signal'] = True sleep(3) break def cliThreadTapReadFunction(self, conn): # Check for packets in tap interface and send them to every active connection print("Tap thread started") while True: try: # +20 for ethernet headear packet = self.tap.read(self.tap.mtu+20) # Insert first 3 bytes with 0 and 2 byte big endian int with actual size. l = len(packet) b_packet_length = l.to_bytes(2, byteorder='big') bb1 = bytearray(b'\x00') bb2 = bytearray(b_packet_length) bb3 = bytearray(packet) buf = bytes(bb1+bb2+bb3) except Exception as e: if e.args[0] == errno.EAGAIN or e.args[0] == errno.EWOULDBLOCK: # Not an actual error, just no data to read yet # (this is expected, wait some more) sleep(0.1) # If we wish to insert a "fake packet", fill 'buf' # Otherwise, "continue", forcing a new tap read continue else: # Actual error - raise! print(e) raise try: conn.send(buf) self.pkts_rcvd[0] = self.pkts_rcvd[0]+1 except OSError as exc: print("Error while sending data".format()) if exc.errno == errno.EPIPE: print("Broken pipe. Sending kill signal...") # assume connection is blocking def get_packet_from_tls(self, conn): # get first 3 bytes with '\x00' and 2 byte big endian int data = conn.recv(3) if data and len(data) == 3: check = data[0] if check == 0: packet_length = int.from_bytes(data[1:3], "big") packet = conn.recv(packet_length) return packet else: return False return False def cliTapWriteFunction(self, conn): while True: try: data = self.get_packet_from_tls(conn) if data: self.tap.write(data) self.pkts_sent+=1 #print("\rPackets sent:\t{:7d} | Packets received:\t{:7d}".format(self.pkts_sent, self.pkts_rcvd[0]), end='') except Exception as e: print("Exception occurred " + str(e)) raise break def cli_start_new_client(self): self.server_addr = resolve_hostname(self.args.server_addr) print("Connecting to TLS server at " + self.server_addr) context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=self.server_cert) context.load_cert_chain(certfile=self.client_cert, keyfile=self.client_key) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) conn = context.wrap_socket(s, server_side=False, server_hostname=self.server_sni_hostname) conn.connect((self.server_addr, self.server_port)) print("SSL Connection Established.") t = threading.Thread(target=self.cliThreadTapReadFunction, args=(conn,)) t.daemon = True t.start() self.cliTapWriteFunction(conn)
return None tun = TunTapDevice() tun.addr = '192.168.210.1' tun.dstaddr = '192.168.210.2' tun.netmask = '255.255.255.252' tun.mtu = 1500 tun.up() while True: buf = tun.read(tun.mtu) # pkt = ["%.2x "%c for c in list(buf)] pkt = list(buf) ethertype = pkt[2] << 8 | pkt[3] flags = pkt[0] << 8 | pkt[1] payload = pkt[4:] if ethertype == 0x0800: print("Got IPv4 packet") ret = parse4(payload) if ret is not None: buf = [0x00, 0x00, 0x08, 0x00] + ret # print( " sending "+" ".join(["%.2x"%x for x in buf])) tun.write(bytes(buf)) elif ethertype == 0x86DD: # print("Got IPv6 packet") parse6(payload) else: # print("Got unknown packet type") pass
class QRTun(object): def __init__(self, side): self.side = int(side) if self.side not in [1, 2]: print("Side must be 1 or 2") raise Exception("Invalid Side") self.tun = TunTapDevice(flags=IFF_TUN | IFF_NO_PI, name='qrtun%d' % self.side) self.tun.addr = '10.0.8.%d' % (self.side) if self.side == 1: self.other_side = 2 else: self.other_side = 1 self.tun.netmask = '255.255.255.0' #MTU must be set low enough to fit in a single qrcode self.tun.mtu = 500 self.epoll = select.epoll() self.epoll.register(self.tun.fileno(), select.EPOLLIN) self.tun.up() #self.outfile = 'resources/toscreen%d.png'%(self.side) self.outfile = None self.infile = 'resources/toscreen%d.png' % (self.other_side) self.indata = None self.olddata = "" self.outdata = "" self.running = False self.qr = qrtools.QR() self.vc = cv2.VideoCapture(0) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 720) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1280) pygame.init() pygame.event.set_allowed(None) pygame.event.set_allowed([pygame.KEYDOWN, pygame.QUIT]) self.screen = pygame.display.set_mode((SIZE, SIZE)) self.scale = 12 pygame.display.set_caption("qrtun - QR Code scale %d" % (self.scale)) def read_tun(self): events = self.epoll.poll(0) if events: self.outdata = self.tun.read(self.tun.mtu) return True return False def write_qrcode(self): p = subprocess.Popen( ['qrencode', '-o', '-', '-s', str(self.scale), '-8'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out, std_err = p.communicate(input=self.outdata) if std_err: raise Exception("qrencodeError", std_err.strip()) self.outfile = StringIO.StringIO(std_out) #code.png(self.outfile, scale=self.scale) self.outfile.seek(0) if self.outfile and not self.outfile.closed: pimg = pygame.image.load(self.outfile) if pimg.get_width() > self.screen.get_width() or pimg.get_height( ) > self.screen.get_height(): pygame.display.set_mode((pimg.get_width(), pimg.get_height())) self.screen.fill((0, 0, 0)) self.screen.blit(pimg, (0, 0)) pygame.display.flip() self.msg_read = False def write_tun(self): try: if len(self.indata.get('body')) > 0: data = self.indata.get('body') if data != self.olddata: self.tun.write(data) #This is a hacky way to avoid dup packets... #surely a better way to do this... self.olddata = data except: print("Failed to write to tun!") def read_qrcode(self): qr = qrtools.QR() try: if not qr.decode(self.infile): return False #Hack to convert unicde to python string body = qr.data.encode('latin-1') self.indata = {'body': body} self.write_tun() except: pass def run(self): self.running = True while self.running: if self.read_tun(): self.write_qrcode() rval, frame = self.vc.read() if not rval: running = False break scipy.misc.toimage(frame).save(self.infile) self.read_qrcode() event = pygame.event.poll() if event.type == pygame.QUIT: self.running = False pygame.quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False pygame.quit() elif event.key == pygame.K_UP: self.scale += 1 pygame.display.set_caption("qrtun - QR Code scale %d" % (self.scale)) self.write_qrcode() elif event.key == pygame.K_DOWN: self.scale -= 1 pygame.display.set_caption("qrtun - QR Code scale %d" % (self.scale)) self.write_qrcode() try: #os.unlink(self.outfile) os.unlink(self.infile) except: pass
import select import time from scapy.all import IP, ICMP from pytun import TunTapDevice, IFF_TAP, IFF_TUN, IFF_NO_PI tun = TunTapDevice(flags=IFF_TUN | IFF_NO_PI, name="FakePing") tun.addr = "10.10.10.1" tun.netmask = '255.255.255.0' tun.up() epoll = select.epoll() epoll.register(tun.fileno(), select.EPOLLIN) while True: while epoll.poll(0): data = tun.read(tun.mtu) packet = IP(data) icmp_part = packet.getlayer(ICMP) if icmp_part is not None: time.sleep(desire_time) respacket = IP(src=packet.dst, dst=packet.src, ttl=desire_ttl) respacket /= ICMP(type=0, seq=icmp_part.seq, id=icmp_part.id) respacket /= icmp_part.payload tun.write(bytes(respacket)) packet.show() respacket.show() time.sleep(0.01)
class QRTun(object): def __init__(self, side): self.side = int(side) if self.side not in [1, 2]: print("Side must be 1 or 2") raise Exception("Invalid Side") self.tun = TunTapDevice(flags=IFF_TUN | IFF_NO_PI, name='qrtun%d' % self.side) self.tun.addr = '10.0.8.%d' % (self.side) if self.side == 1: self.other_side = 2 else: self.other_side = 1 self.tun.netmask = '255.255.255.0' #MTU must be set low enough to fit in a single qrcode self.tun.mtu = 500 self.epoll = select.epoll() self.epoll.register(self.tun.fileno(), select.EPOLLIN) self.tun.up() self.seq = 0 self.ack = 0 self.outfile = 'resources/toscreen%d.png' % (self.side) self.infile = 'resources/toscreen%d.png' % (self.other_side) self.indata = None self.olddata = "" self.outdata = "" self.msg_read = True self.sent_time = None self.running = False self.qr = qrtools.QR() self.vc = cv2.VideoCapture(0) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 720) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1280) def read_tun(self): events = self.epoll.poll(0) if events: self.outdata = self.tun.read(self.tun.mtu) def write_qrcode(self): #Have a header with seq/ack format header = '%03d/%03d' % (self.seq, self.ack) #Base32 encode since alphanumeic qr code only allows A-Z, 0-9 and some # symbols, but base64 uses lowercase as well.... body = base64.b32encode(self.outdata).replace('=', '/') qr = qrtools.QR() qrb = qrtools.QR() qrb.data = " " qr.data = header + body #Had an issue where decoded data did not match encoded data... #So I just add plus symbols as padding until they match, then strip # on the other side.... while qr.data != qrb.data: qr.pixel_size = 12 qr.encode(self.outfile) qrb.decode(self.outfile) if qrb.data != qr.data: print("EncodingFailure", qr.data) qr.data += '+' self.msg_read = False def write_tun(self): try: if len(self.indata.get('body')) > 0: data = self.indata.get('body') if data != self.olddata: self.tun.write(data) #This is a hacky way to avoid dup packets... #Didn't think my seq/ack through very well, there is #surely a better way to do this... self.olddata = data except: print("Failed to write to tun!") def read_qrcode(self): qr = qrtools.QR() try: if not qr.decode(self.infile): return False header = map(int, qr.data[:7].split('/')) body = base64.b32decode(qr.data[7:].replace('/', '=').replace('+', '')) self.indata = {'header': header, 'body': body} #We read their message, need to ack that, unless we already saw it if self.ack != header[0]: # print("New Message") self.ack = header[0] self.write_tun() #Have they ready my message already? if header[1] == self.seq: print("Acked %d" % self.seq) self.msg_read = True self.seq += 1 if self.seq == 1000: self.seq = 0 except: pass def run(self): self.running = True while self.running: if self.msg_read: self.read_tun() #Very inefficient right now, constantly rewriting qr code, # even if nothing has changed.... self.write_qrcode() rval, frame = self.vc.read() if not rval: running = False break scipy.misc.toimage(frame).save(self.infile) self.read_qrcode() sprite = factory.from_image(self.outfile) #cam = factory.from_image(self.infile) # spriterenderer.render(cam) spriterenderer.render(sprite) event = SDL_Event() while SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == SDL_QUIT: self.running = False break elif event.type == SDL_KEYDOWN and event.key.keysym.sym == SDLK_ESCAPE: self.running = False break try: os.unlink(self.outfile) os.unlink(self.infile) except: pass
high = (short & 0xff00) >> 8 low = (short & 0x00ff) return chr(high) + chr(low) if __name__ == '__main__': tap = TunTapDevice(name='ipsec-tap', flags=IFF_TAP) tap.up() tap.persist(True) while True: try: buf = tap.read(tap.mtu) print 'old', hexlify(buf) # Valeri @ studentpub new_addr = struct.pack('4B', 192, 168, 10, 174) new_buf = buf[:34] + new_addr + buf[38:] ip_header = new_buf[18:38] checksum = ip_checksum([format(ord(c), "x") for c in ip_header], 20) print hex(checksum) final_buf = new_buf[:28] + shortToBytes(checksum) + new_buf[30:] print 'new', hexlify(final_buf) print tap.write(final_buf) # TODO encrypt buf # TODO send to wlan0 # TODO enable routing except KeyboardInterrupt: tap.close()
import hexdump from pytun import TunTapDevice, IFF_TAP tun = TunTapDevice(name='rfc6214') with open("captured_in.hex", "r") as the_file: hex = the_file.readline() buf = hexdump.dehex(hex) tun.write(buf) buf = tun.read(tun.mtu) hex = hexdump.dump(buf, 2, '') print(hex) with open('captured_out.hex', 'w') as the_file: the_file.write(hex)
class QRTun(object): def __init__(self, side): self.side = int(side) if self.side not in [1,2]: print("Side must be 1 or 2") raise Exception("Invalid Side") self.tun = TunTapDevice(flags=IFF_TUN|IFF_NO_PI, name='qrtun%d'%self.side) self.tun.addr = '10.0.8.%d'%(self.side) if self.side == 1: self.other_side = 2 else: self.other_side = 1 self.tun.netmask = '255.255.255.0' #MTU must be set low enough to fit in a single qrcode self.tun.mtu = 300 self.epoll = select.epoll() self.epoll.register(self.tun.fileno(), select.EPOLLIN) self.tun.up() #self.outfile = 'resources/toscreen%d.png'%(self.side) self.outfile = None self.infile = 'resources/toscreen%d.png'%(self.other_side) self.indata = None self.olddata = "" self.outdata = "" self.running = False self.vc = cv2.VideoCapture(0) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 720) self.vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1280) self.scanner = zbar.ImageScanner() self.scanner.parse_config('enable') pygame.init() pygame.event.set_allowed(None) pygame.event.set_allowed([pygame.KEYDOWN, pygame.QUIT]) self.screen = pygame.display.set_mode((SIZE, SIZE)) self.scale = 12 pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) def read_tun(self): events = self.epoll.poll(0) if events: self.outdata = self.tun.read(self.tun.mtu) return True return False def write_qrcode(self): #Sadly qrencode does not support \0 in binary mode!!! So I had to disable it and use the slower pyqrtools instead! #p = subprocess.Popen(['qrencode', '-o', '-', '-s', str(self.scale), '-8'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) #std_out, std_err = p.communicate(input=self.outdata) #if std_err: # raise Exception("qrencodeError", std_err.strip()) code = pyqrcode.create(b32encode(self.outdata).replace('=', '/'), mode='alphanumeric') self.outfile = StringIO.StringIO() code.png(self.outfile, scale=self.scale) self.outfile.seek(0) if self.outfile and not self.outfile.closed: pimg = pygame.image.load(self.outfile) if pimg.get_width() > self.screen.get_width() or pimg.get_height() > self.screen.get_height(): pygame.display.set_mode((pimg.get_width(), pimg.get_height())) self.screen.fill((0,0,0)) self.screen.blit(pimg, (0,0)) pygame.display.flip() self.msg_read = False def write_tun(self): try: if len(self.indata.get('body')) > 0: data = self.indata.get('body') if data != self.olddata: self.tun.write(data) #This is a hacky way to avoid dup packets... #surely a better way to do this... self.olddata = data except: print("Failed to write to tun!") def read_qrcode(self): width, height = self.inframe.size raw = self.inframe.tobytes() image = zbar.Image(width, height, 'Y800', raw) result = self.scanner.scan(image) if result == 0: return False else: print "QR!" for symbol in image: pass # clean up del(image) # Assuming data is encoded in utf8 try: self.indata = {'body': b32decode(symbol.data.replace('/', '='))} self.write_tun() return True except: return False def read_cam(self): rval, frame = self.vc.read() if not rval: return False self.inframe = scipy.misc.toimage(frame).convert('L') return True def run(self): self.running = True while self.running: if self.read_tun(): self.write_qrcode() if not self.read_cam(): running = False break self.read_qrcode() event = pygame.event.poll() if event.type == pygame.QUIT: self.running = False pygame.quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False pygame.quit() elif event.key == pygame.K_UP: self.scale += 1 pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) self.write_qrcode() elif event.key == pygame.K_DOWN: self.scale -= 1 pygame.display.set_caption("qrtun - QR Code scale %d"%(self.scale)) self.write_qrcode() try: #os.unlink(self.outfile) os.unlink(self.infile) except: pass
try: tun0.up() packets = 100000 print "Packets: " + str(packets) start = time.clock() for i in range(packets): packet1 = packet.copy() packet1[IP].src = '192.168.1.2' packet1[IP].dst = '192.168.1.1' packet1[Raw].load = "Hi! I'm UDP-packet" tun0.write(str(packet1)) finish = time.clock() est_time = (finish - start) * 1000000 print "Scapy time: {0}, mcs: {1}".format(est_time, est_time / packets) start = time.clock() for i in range(packets): packet2 = packet.copy() as_hex = to_hex(packet2) change_src_manual(as_hex, '192.168.1.2') change_dst_manual(as_hex, '192.168.1.1') change_payload_manual(as_hex, "Hi! I'm UDP-packet") ip_manual_change_checksum(as_hex, ip_calculate_chksum_hex(as_hex)) udp_manual_change_checksum(as_hex, udp_calculate_chksum_hex(as_hex))
for each in readables: if each == tun: buf = each.read(65536) # each.read(each.mtu) # write to socket who have got a peer possible = [x for x in xrange(0, len(peers)) if peers[x] != False] if len(possible) == 0: continue # drop the packet i = possible[random.randrange(0, len(possible))] workerSocket = reads[i + 1] # encrypt and sign buf workerSocket.sendto(encrypt(buf), peers[i]) debug("%s --> [%d]:\n%s\n" % (tun.name, i, showPacket(buf))) else: i = reads.index(each) - 1 buf, sender = each.recvfrom(65536) # buf = buf.rstrip() if buf.strip() == UDPCONNECTOR_WORD: # connection word received, answer peers[i] = sender each.sendto(UDPCONNECTOR_WORD, sender) debug("[%d] <==> %s:%d" % (i, sender[0], sender[1])) else: if peers[i] != sender: continue buf = decrypt(buf) if buf == False: # if decryption failed debug("[%d] --> %s: Bad packet." % (i, tun.name)) continue tun.write(buf) debug("[%d] --> %s:\n%s\n" % (i, tun.name, showPacket(buf)))
tun0 = TunTapDevice(name='tun0', flags=IFF_TUN + IFF_NO_PI) #'127.0.0.1' tun0.addr = '10.1.8.82' tun0.dstaddr = '10.1.8.83' tun0.netmask = '255.255.255.0' tun0.mtu = 1500 ip = IP(src="192.168.1.2", dst="192.168.1.1") udp = UDP(sport=4444, dport=4444) payload = Raw(load="Hi! I'm UDP-packet") packet = ip / udp / payload packet.show() new_packet = change_dst_ip(packet, "192.168.1.3") new_packet.show() try: tun0.up() while True: tun0.write(str(packet)) #tun0.write("Hi! I'm UDP-packet") time.sleep(5) tun0.write(str(new_packet)) time.sleep(5) finally: tun0.close()
def write_to_pytun_ignore_exceptions(dev: pytun.TunTapDevice, data: bytes): try: dev.write(data) except pytun.Error as e: print(e, file=sys.stderr)