18 ipbytes = map(ord,ip.decode("hex"))
19 return '.'.join(map(str,ipbytes))
25 '8863' : 'PPPoE discover',
30 def etherProto(packet, len=len):
32 if packet[12] == "\x81" and packet[13] == "\x00":
41 def formatPacket(packet, ether_mode):
43 stripped_packet = etherStrip(packet)
44 if not stripped_packet:
45 packet = packet.encode("hex")
47 return "malformed eth " + packet.encode("hex")
49 if packet[24:28] == "8100":
51 ethertype = tagtype.get(packet[32:36], 'eth')
52 return ethertype + " " + ( '-'.join( (
53 packet[0:12], # MAC dest
54 packet[12:24], # MAC src
55 packet[24:32], # VLAN tag
56 packet[32:36], # Ethertype/len
57 packet[36:], # Payload
61 ethertype = tagtype.get(packet[24:28], 'eth')
62 return ethertype + " " + ( '-'.join( (
63 packet[0:12], # MAC dest
64 packet[12:24], # MAC src
65 packet[24:28], # Ethertype/len
66 packet[28:], # Payload
69 packet = stripped_packet
70 packet = packet.encode("hex")
72 return "malformed ip " + packet
74 return "ip " + ( '-'.join( (
76 packet[1:2], #header length
77 packet[2:4], #diffserv/ECN
78 packet[4:8], #total length
80 packet[12:16], #flags/fragment offs
82 packet[18:20], #ip-proto
83 packet[20:24], #checksum
84 ipfmt(packet[24:32]), # src-ip
85 ipfmt(packet[32:40]), # dst-ip
86 packet[40:48] if (int(packet[1],16) > 5) else "", # options
87 packet[48:] if (int(packet[1],16) > 5) else packet[40:], # payload
90 def _packetReady(buf, ether_mode=False, len=len, str=str):
101 _,totallen = struct.unpack('HH',buf[0][:4])
102 totallen = socket.htons(totallen)
103 rv = len(buf[0]) >= totallen
104 if not rv and len(buf) > 1:
105 # collapse only first two buffers
106 # as needed, to mantain len(buf) meaningful
108 buf[0] = p1+str(buf[0])
113 def _pullPacket(buf, ether_mode=False, len=len, buffer=buffer):
117 _,totallen = struct.unpack('HH',buf[0][:4])
118 totallen = socket.htons(totallen)
119 if len(buf[0]) > totallen:
120 rv = buffer(buf[0],0,totallen)
121 buf[0] = buffer(buf[0],totallen)
126 def etherStrip(buf, buffer=buffer, len=len):
129 if buf[12:14] == '\x08\x10' and buf[16:18] == '\x08\x00':
130 # tagged ethernet frame
131 return buffer(buf, 18)
132 elif buf[12:14] == '\x08\x00':
133 # untagged ethernet frame
134 return buffer(buf, 14)
138 def etherWrap(packet):
140 "\x00"*6*2 # bogus src and dst mac
143 "\x00"*4, # bogus crc
146 def piStrip(buf, len=len):
152 def piWrap(buf, ether_mode, etherProto=etherProto):
154 proto = etherProto(buf)
158 "\x00\x00", # PI: 16 bits flags
159 proto, # 16 bits proto
163 _padmap = [ chr(padding) * padding for padding in xrange(127) ]
166 def encrypt(packet, crypter, len=len, padmap=_padmap):
168 padding = crypter.block_size - len(packet) % crypter.block_size
169 packet += padmap[padding]
172 return crypter.encrypt(packet)
174 def decrypt(packet, crypter, ord=ord):
177 packet = crypter.decrypt(packet)
180 padding = ord(packet[-1])
181 if not (0 < padding <= crypter.block_size):
183 raise RuntimeError, "Truncated packet %s"
184 packet = packet[:-padding]
190 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
192 fcntl.fcntl(fd, fcntl.F_SETFL, fl)
195 traceback.print_exc(file=sys.stderr)
199 def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, SUSPEND,
200 stderr = sys.stderr, reconnect = None, rwrite = None, rread = None,
201 tunqueue = 1000, tunkqueue = 1000, cipher = 'AES', accept_local = None,
202 accept_remote = None, slowlocal = True, queueclass = None,
203 bwlimit = None, len = len, max = max, min = min, buffer = buffer,
204 OSError = OSError, select = select.select, selecterror = select.error,
205 os = os, socket = socket,
206 retrycodes=(os.errno.EWOULDBLOCK, os.errno.EAGAIN, os.errno.EINTR) ):
211 if cipher_key and cipher:
214 __import__('Crypto.Cipher.'+cipher)
217 cipher = getattr(Crypto.Cipher, cipher)
218 hashed_key = hashlib.sha256(cipher_key).digest()
220 if ciphername == 'AES':
221 hashed_key = hashed_key[:16]
222 elif ciphername == 'Blowfish':
223 hashed_key = hashed_key[:24]
224 elif ciphername == 'DES':
225 hashed_key = hashed_key[:8]
226 elif ciphername == 'DES3':
227 hashed_key = hashed_key[:24]
229 crypter = cipher.new(
234 # We don't want decription to work only on one side,
235 # This could break things really bad
238 traceback.print_exc(file=sys.stderr)
241 if stderr is not None:
243 print >>stderr, "Packets are transmitted in CIPHER"
245 print >>stderr, "Packets are transmitted in PLAINTEXT"
247 if hasattr(remote, 'fileno'):
248 remote_fd = remote.fileno()
250 def rwrite(remote, packet, os_write=os.write):
251 return os_write(remote_fd, packet)
253 def rread(remote, maxlen, os_read=os.read):
254 return os_read(remote_fd, maxlen)
256 rnonblock = nonblock(remote)
257 tnonblock = nonblock(tun)
259 # Pick up TUN/TAP writing method
264 # We have iovec, so we can skip PI injection
265 # and use iovec which does it natively
267 twrite = iovec.ethpiwrite
268 tread = iovec.piread2
270 twrite = iovec.ippiwrite
271 tread = iovec.piread2
273 # We have to inject PI headers pythonically
274 def twrite(fd, packet, oswrite=os.write, piWrap=piWrap, ether_mode=ether_mode):
275 return oswrite(fd, piWrap(packet, ether_mode))
277 # For reading, we strip PI headers with buffer slicing and that's it
278 def tread(fd, maxlen, osread=os.read, piStrip=piStrip):
279 return piStrip(osread(fd, maxlen))
281 # No need to inject PI headers
289 if accept_local is not None:
290 def tread(fd, maxlen, _tread=tread, accept=accept_local):
291 packet = _tread(fd, maxlen)
292 if accept(packet, 0):
297 if accept_remote is not None:
299 def decrypt_(packet, crypter, decrypt_=decrypt_, accept=accept_remote):
300 packet = decrypt_(packet, crypter)
301 if accept(packet, 1):
306 def rread(fd, maxlen, _rread=rread, accept=accept_remote):
307 packet = _rread(fd, maxlen)
308 if accept(packet, 1):
313 maxbkbuf = maxfwbuf = max(10,tunqueue-tunkqueue)
314 tunhurry = max(0,maxbkbuf/2)
316 if queueclass is None:
317 queueclass = collections.deque
321 maxfwbuf = maxbkbuf = 2000000000
331 # backwards queue functions
332 # they may need packet inspection to
333 # reconstruct packet boundaries
334 if ether_mode or udp:
336 pullPacket = queueclass.popleft
337 reschedule = queueclass.appendleft
339 packetReady = _packetReady
340 pullPacket = _pullPacket
341 reschedule = queueclass.appendleft
343 # forward queue functions
344 # no packet inspection needed
346 fpullPacket = queueclass.popleft
347 freschedule = queueclass.appendleft
354 maxbwfree = bwfree = 1500 * tunqueue
361 # The SUSPEND flag has been set. This means we need to wait on
362 # the SUSPEND condition until it is released.
363 while SUSPEND and not TERMINATE:
367 if packetReady(bkbuf):
369 if remoteok and fpacketReady(fwbuf) and (not bwlimit or bwfree > 0):
373 if len(fwbuf) < maxfwbuf:
375 if remoteok and len(bkbuf) < maxbkbuf:
384 rdrdy, wrdy, errs = select(rset,wset,eset,1)
385 except selecterror, e:
386 if e.args[0] == errno.EINTR:
390 traceback.print_exc(file=sys.stderr)
391 # If the SUSPEND flag has been set, then the TUN will be in a bad
392 # state and the select error should be ignores.
400 if reconnect is not None and remote in errs and tun not in errs:
402 if hasattr(remote, 'fileno'):
403 remote_fd = remote.fileno()
404 elif udp and remote in errs and tun not in errs:
405 # In UDP mode, those are always transient errors
406 # Usually, an error will imply a read-ready socket
407 # that will raise an "Connection refused" error, so
408 # disable read-readiness just for now, and retry
417 # check to see if we can write
418 #rr = wr = rt = wt = 0
423 for x in xrange(maxbatch):
424 packet = pullPacket(fwbuf)
427 packet = encrypt_(packet, crypter)
429 sentnow = rwrite(remote, packet)
433 if not udp and 0 <= sentnow < len(packet):
434 # packet partially sent
435 # reschedule the remaining part
436 # this doesn't happen ever in udp mode
437 freschedule(fwbuf, buffer(packet,sentnow))
439 if not rnonblock or not fpacketReady(fwbuf):
442 # This except handles the entire While block on PURPOSE
443 # as an optimization (setting a try/except block is expensive)
444 # The only operation that can raise this exception is rwrite
445 if e.errno in retrycodes:
447 freschedule(fwbuf, packet)
451 if reconnect is not None:
452 # in UDP mode, sometimes connected sockets can return a connection refused.
453 # Give the caller a chance to reconnect
455 if hasattr(remote, 'fileno'):
456 remote_fd = remote.fileno()
458 # in UDP mode, we ignore errors - packet loss man...
460 #traceback.print_exc(file=sys.stderr)
466 for x in xrange(maxtbatch):
467 packet = pullPacket(bkbuf)
468 twrite(tunfd, packet)
471 # Do not inject packets into the TUN faster than they arrive, unless we're falling
472 # behind. TUN devices discard packets if their queue is full (tunkqueue), but they
473 # don't block either (they're always ready to write), so if we flood the device
474 # we'll have high packet loss.
475 if not tnonblock or (slowlocal and len(bkbuf) < tunhurry) or not packetReady(bkbuf):
479 # Give some time for the kernel to process the packets
482 # This except handles the entire While block on PURPOSE
483 # as an optimization (setting a try/except block is expensive)
484 # The only operation that can raise this exception is os_write
485 if e.errno in retrycodes:
487 reschedule(bkbuf, packet)
491 # check incoming data packets
494 for x in xrange(maxbatch):
495 packet = tread(tunfd,2000) # tun.read blocks until it gets 2k!
501 if not tnonblock or len(fwbuf) >= maxfwbuf:
504 # This except handles the entire While block on PURPOSE
505 # as an optimization (setting a try/except block is expensive)
506 # The only operation that can raise this exception is os_read
507 if e.errno not in retrycodes:
512 for x in xrange(maxbatch):
513 packet = rread(remote,2000)
518 packet = decrypt_(packet, crypter)
522 if not udp and packet == "":
523 # Connection broken, try to reconnect (or just die)
524 raise RuntimeError, "Connection broken"
530 if not rnonblock or len(bkbuf) >= maxbkbuf:
533 # This except handles the entire While block on PURPOSE
534 # as an optimization (setting a try/except block is expensive)
535 # The only operation that can raise this exception is rread
536 if e.errno not in retrycodes:
539 if reconnect is not None:
540 # in UDP mode, sometimes connected sockets can return a connection refused
541 # on read. Give the caller a chance to reconnect
543 if hasattr(remote, 'fileno'):
544 remote_fd = remote.fileno()
546 # in UDP mode, we ignore errors - packet loss man...
548 traceback.print_exc(file=sys.stderr)
552 delta = tnow - lastbwtime
554 delta = int(bwlimit * delta)
556 bwfree = min(bwfree+delta, maxbwfree)
559 #print >>sys.stderr, "rr:%d\twr:%d\trt:%d\twt:%d" % (rr,wr,rt,wt)
561 def udp_connect(TERMINATE, local_addr, local_port, peer_addr, peer_port):
562 rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
565 # TERMINATE is a array. An item can be added to TERMINATE, from
566 # outside this function to force termination of the loop
568 raise OSError, "Killed"
570 rsock.bind((local_addr, local_port))
573 # wait a while, retry
574 print >>sys.stderr, "%s: Could not bind. Retrying in a sec..." % (time.strftime('%c'),)
575 time.sleep(min(30.0,retrydelay))
578 rsock.bind((local_addr, local_port))
579 print >>sys.stderr, "Listening UDP at: %s:%d" % (local_addr, local_port)
580 print >>sys.stderr, "Connecting UDP to: %s:%d" % (peer_addr, peer_port)
581 rsock.connect((peer_addr, peer_port))
584 def udp_handshake(TERMINATE, rsock):
587 while not endme and not TERMINATE:
597 keepalive_thread = threading.Thread(target=keepalive)
598 keepalive_thread.start()
599 for i in xrange(900):
601 raise OSError, "Killed"
603 heartbeat = rsock.recv(10)
608 heartbeat = rsock.recv(10)
610 keepalive_thread.join()
612 def udp_establish(TERMINATE, local_addr, local_port, peer_addr, peer_port):
613 rsock = udp_connect(TERMINATE, local_addr, local_port, peer_addr,
615 udp_handshake(TERMINATE, rsock)
618 def tcp_connect(TERMINATE, stop, rsock, peer_addr, peer_port):
621 # The peer has a firewall that prevents a response to the connect, we
622 # will be forever blocked in the connect, so we put a reasonable timeout.
629 raise OSError, "Killed"
631 rsock.connect((peer_addr, peer_port))
635 # wait a while, retry
636 print >>sys.stderr, "%s: Could not connect. Retrying in a sec..." % (time.strftime('%c'),)
637 time.sleep(min(30.0,retrydelay))
640 rsock.connect((peer_addr, peer_port))
643 print >>sys.stderr, "tcp_connect: TCP sock connected to remote %s:%s" % (peer_addr, peer_port)
646 print >>sys.stderr, "tcp_connect: disabling NAGLE"
647 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
650 def tcp_listen(TERMINATE, stop, lsock, local_addr, local_port):
653 # We try to bind to the local virtual interface.
654 # It might not exist yet so we wait in a loop.
659 raise OSError, "Killed"
661 lsock.bind((local_addr, local_port))
664 # wait a while, retry
665 print >>sys.stderr, "%s: Could not bind. Retrying in a sec..." % (time.strftime('%c'),)
666 time.sleep(min(30.0,retrydelay))
669 lsock.bind((local_addr, local_port))
671 print >>sys.stderr, "tcp_listen: TCP sock listening in local sock %s:%s" % (local_addr, local_port)
672 # Now we wait until the other side connects.
673 # The other side might not be ready yet, so we also wait in a loop for timeouts.
678 raise OSError, "Killed"
679 rlist, wlist, xlist = select.select([lsock], [], [], timeout)
683 sock,raddr = lsock.accept()
684 print >>sys.stderr, "tcp_listen: TCP connection accepted in local sock %s:%s" % (local_addr, local_port)
689 def tcp_handshake(rsock, listen, hand):
690 # we are going to use a barrier algorithm to decide wich side listen.
691 # each side will "roll a dice" and send the resulting value to the other
697 peer_hand = rsock.recv(4)
699 print >>sys.stderr, "tcp_handshake: connection reset by peer"
702 print >>sys.stderr, "tcp_handshake: hand %r, peer_hand %r" % (hand, peer_hand)
706 elif hand > peer_hand:
713 def tcp_establish(TERMINATE, local_addr, local_port, peer_addr, peer_port):
714 def listen(stop, hand, lsock, lresult):
716 rsock = tcp_listen(TERMINATE, stop, lsock, local_addr, local_port)
718 win = tcp_handshake(rsock, True, hand)
720 lresult.append((win, rsock))
722 def connect(stop, hand, rsock, rresult):
724 rsock = tcp_connect(TERMINATE, stop, rsock, peer_addr, peer_port)
726 win = tcp_handshake(rsock, False, hand)
728 rresult.append((win, rsock))
732 for i in xrange(0, 50):
736 raise OSError, "Killed"
737 hand = struct.pack("!L", random.randint(0, 2**30))
741 lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
742 rsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
743 listen_thread = threading.Thread(target=listen, args=(stop, hand, lsock, lresult))
744 connect_thread = threading.Thread(target=connect, args=(stop, hand, rsock, rresult))
745 connect_thread.start()
746 listen_thread.start()
747 connect_thread.join()
749 (lwin, lrsock) = lresult[0]
750 (rwin, rrsock) = rresult[0]
751 if not lrsock or not rrsock:
757 # both socket are connected
767 raise OSError, "Error: tcp_establish could not establish connection."