Added pinhole (TCP port forwarding w/ measurement)
[bwmon.git] / pinhole.py
blob80af44c03f964895c826f650f4ff2d4b35b160d0
1 """
2 usage 'pinhole port host [newport]'
4 Pinhole forwards the port to the host specified.
5 The optional newport parameter may be used to
6 redirect to a different port.
8 eg. pinhole 80 webserver
9 Forward all incoming WWW sessions to webserver.
11 pinhole 23 localhost 2323
12 Forward all telnet sessions to port 2323 on localhost.
13 """
15 import sys
16 from socket import *
17 from threading import Thread
18 import time
20 LOGGING = 1
22 def log( s ):
23 if LOGGING:
24 print '%s:%s' % ( time.ctime(), s )
25 sys.stdout.flush()
27 class PipeThread( Thread ):
28 pipes = []
29 def __init__( self, source, sink ):
30 Thread.__init__( self )
31 self.source = source
32 self.sink = sink
33 self.traffic = 0
35 log( 'Creating new pipe thread %s ( %s -> %s )' % \
36 ( self, source.getpeername(), sink.getpeername() ))
37 PipeThread.pipes.append( self )
38 log( '%s pipes active' % len( PipeThread.pipes ))
40 def run( self ):
41 while 1:
42 try:
43 data = self.source.recv( 1024 )
44 if not data: break
45 self.traffic += len(data)
46 print >>sys.stderr, ' %20d (%s -> %s)' % (self.traffic,
47 self.source.getpeername(),
48 self.sink.getpeername())
49 self.sink.send( data )
50 except:
51 break
53 log( '%s terminating' % self )
54 print >>sys.stderr, 'Closing: (%s->%s) with total traffic %d' % (self.source.getpeername(),
55 self.sink.getpeername(), self.traffic)
56 PipeThread.pipes.remove( self )
57 log( '%s pipes active' % len( PipeThread.pipes ))
59 class Pinhole( Thread ):
60 def __init__( self, port, newhost, newport ):
61 Thread.__init__( self )
62 log( 'Redirecting: localhost:%s -> %s:%s' % ( port, newhost, newport ))
63 self.newhost = newhost
64 self.newport = newport
65 self.sock = socket( AF_INET, SOCK_STREAM )
66 self.sock.bind(( '', port ))
67 self.sock.listen(5)
69 def run( self ):
70 while 1:
71 newsock, address = self.sock.accept()
72 log( 'Creating new session for %s %s ' % address )
73 fwd = socket( AF_INET, SOCK_STREAM )
74 fwd.connect(( self.newhost, self.newport ))
75 PipeThread( newsock, fwd ).start()
76 PipeThread( fwd, newsock ).start()
78 if __name__ == '__main__':
80 print 'Starting Pinhole'
82 import sys
83 sys.stdout = open( 'pinhole.log', 'w' )
85 if len( sys.argv ) > 1:
86 port = newport = int( sys.argv[1] )
87 newhost = sys.argv[2]
88 if len( sys.argv ) == 4: newport = int( sys.argv[3] )
89 Pinhole( port, newhost, newport ).start()
90 else:
91 Pinhole( 80, 'hydrogen', 80 ).start()
92 Pinhole( 23, 'hydrogen', 23 ).start()