class TUNReader(object): """TUN device""" def __init__(self, tun_dev, tun_addr, tun_remote_addr, tun_nm, tun_mtu, wsfactory): self.wsfactory = wsfactory self.tun = TunTapDevice(name=tun_dev, flags=(IFF_TUN|IFF_NO_PI)) self.tun.addr = tun_addr 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.WARN) def doRead(self): data = self.tun.read(self.tun.mtu) self.wsfactory.tunnel_write(data) def logPrefix(self): return "TUNReader"
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 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: #print 'sending broadcast frame:' #print ':'.join('{0:02x}'.format(ord(c)) for c in buf) for socket in macmap.values(): def send_message(): try: socket.write_message(str(buf), binary=True) except: pass loop.add_callback(send_message) elif macmap.get(mac, False): def send_message(): try: macmap[mac].write_message(str(buf), binary=True) except: pass loop.add_callback(send_message) else: print( "couldn't find recipient for mac %s from %s " % (':'.join('{0:02x}'.format(ord(c)) for c in mac), ':'.join( '{0:02x}'.format(ord(c)) for c in buf[6:12]))) except: print 'closing due to tun error' finally: self.tun.close()
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 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 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: #print 'sending broadcast frame:' #print ':'.join('{0:02x}'.format(ord(c)) for c in buf) for socket in macmap.values(): def send_message(): try: socket.write_message(str(buf),binary=True) except: pass loop.add_callback(send_message) elif macmap.get(mac, False): def send_message(): try: macmap[mac].write_message(str(buf),binary=True) except: pass loop.add_callback(send_message) else: print("couldn't find recipient for mac %s from %s " % (':'.join('{0:02x}'.format(ord(c)) for c in mac), ':'.join('{0:02x}'.format(ord(c)) for c in buf[6:12]))) except: print 'closing due to tun error' finally: self.tun.close()
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 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"
from tornado import ioloop from ws4py.client.tornadoclient import TornadoWebSocketClient from pytun import TunTapDevice, IFF_TAP, IFF_NO_PI import sys io_loop = ioloop.IOLoop.instance() tap = TunTapDevice(flags=IFF_TAP|IFF_NO_PI, name='vpn-ws%d') class VpnWSClient(TornadoWebSocketClient): def received_message(self, m): tap.write(str(m)) def closed(self, code, reason=None): print "ooops" ws = VpnWSClient(sys.argv[1]) ws.connect() def tap_callback(fd, event): ws.send(tap.read(tap.mtu), binary=True) io_loop.add_handler(tap.fileno(), tap_callback, io_loop.READ) io_loop.start()
from tornado import ioloop from ws4py.client.tornadoclient import TornadoWebSocketClient from pytun import TunTapDevice, IFF_TAP, IFF_NO_PI import sys io_loop = ioloop.IOLoop.instance() tap = TunTapDevice(flags=IFF_TAP | IFF_NO_PI, name='vpn-ws%d') class VpnWSClient(TornadoWebSocketClient): def received_message(self, m): tap.write(str(m)) def closed(self, code, reason=None): print "ooops" ws = VpnWSClient(sys.argv[1]) ws.connect() def tap_callback(fd, event): ws.send(tap.read(tap.mtu), binary=True) io_loop.add_handler(tap.fileno(), tap_callback, io_loop.READ) io_loop.start()
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
# 'socket' : conn, # 'kill_signal' : False, # 'CN' : 'client' # } active_connections = [] rate_per_key = 10 # frames per second max_capacity = 20 # token capacity - defines burst size buckets = token_bucket.Limiter(rate_per_key, max_capacity, token_bucket.MemoryStorage()) # Initialize a TAP interface and make it non-blocking tap = TunTapDevice(flags=IFF_TAP | IFF_NO_PI, name='tap0') tap.up() fcntl.fcntl(tap.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) tap_thread = threading.Thread(target=ThreadTapFunction, args=( tap, active_connections, )) tap_thread.daemon = True tap_thread.start() t = threading.Thread(target=ServerFunction, args=( listen_addr, listen_port, active_connections, buckets,
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
desire_time = 1 ################################################################# 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()
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
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)
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
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