This code shows an implementation of tunneling. Though this code uses ssl as an example. It would not be hard to modify it to work for other situations as well.
The reason I use ssl as an example is because the standard python libraries do not support tunneling ssl through a proxy. Import pytunnel and give it a function w/the code you want to tunnel and your off.
For the latest code try: http://ftp.gnu.org/pub/savannah/cvs/pytunnel-cvs-latest.tar.gz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | import threading,socket,traceback,sys,httplib,pprint,select,base64,time
def recv_all(the_socket,timeout=''):
#setup to use non-blocking sockets
#assume proxy network connection is worse than locahost
#if no data arrives it assumes transaction is done
#recv() returns a string; it's an upper bound on len(sock.recv())
the_socket.setblocking(0)
total_data=[];data=''
begin=time.time()
if not timeout:
timeout=1
while 1:
#if you got some data, then break after wait sec
if total_data and time.time()-begin>timeout:
break
#if you got no data at all, wait a little longer
elif time.time()-begin>timeout*2:
break
wait=0
try:
data=the_socket.recv(4096)
if data:
total_data.append(data)
begin=time.time()
data='';wait=0
else:
time.sleep(0.1)
except:
pass
#When a recv returns 0 bytes, other side has closed
result=''.join(total_data)
return result
class thread_it ( threading.Thread ) :
done=0
def __init__(self,tid='',proxy='',server='',tunnel_client='',\
port=0,ip='',timeout=0,slow=0):
threading.Thread.__init__(self)
self.tid=tid
self.proxy=proxy
self.port=port
self.server=server
self.tunnel_client=tunnel_client
self.ip=ip;self._port=port
self.data={} #store data here to get later
self.timeout=timeout
def run ( self ): #overridden from threading library
try:
if self.proxy and self.server:
ins=[self.server,self.proxy]
ous=[];data={};adrs={}
new_socket=0
while not thread_it.done:
if not new_socket:
new_socket,address=self.server.accept()
else:
self.proxy.sendall(
recv_all(new_socket,timeout=self.timeout))
new_socket.sendall(
recv_all(self.proxy,timeout=self.timeout))
elif self.tunnel_client:
self.tunnel_client(self.ip,self.port)
thread_it.done=1
except Exception,error:
print traceback.print_exc(sys.exc_info()),error
thread_it.done=1
class build:
def __init__(self,host='',port=443,proxy_host='',proxy_port=80,
proxy_user='',proxy_pass='',proxy_type='',timeout=0):
#initialize variables
self._port=port;self.host=host;self._phost=proxy_host;self._puser=proxy_user
self._pport=proxy_port;self._ppass=proxy_pass;self._ptype=proxy_type
self.ip='127.0.0.1';self.timeout=timeout
#setup variables
self._server,self.server_port=self.get_server()
def get_proxy(self):
if not self._ptype:
proxy=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
proxy.connect((self._phost,self._pport))
proxy_authorization=''
if self._puser:
proxy_authorization='Proxy-authorization: Basic '+\
base64.encodestring(self._puser+':'+self._ppass).strip()+'\r\n'
proxy_connect='CONNECT %s:%sHTTP/1.0\r\n'%(self.host,self._port)
user_agent='User-Agent: pytunnel\r\n'
proxy_pieces=proxy_connect+proxy_authorization+user_agent+'\r\n'
proxy.sendall(proxy_pieces+'\r\n')
response=recv_all(proxy,timeout=0.5)
status=response.split()[1]
if int(status)/100 !=2:
print 'error',response
raise status
return proxy
def get_server(self):
port=2222
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#localhost = only visible to this machine
server.bind(('localhost',port))
server.listen(5)
return server,port
def run(self,func):
Threads=[]
Threads.append( thread_it(tid=0,proxy=self.get_proxy(),\
server=self._server,timeout=self.timeout))
Threads.append( thread_it(tid=1,tunnel_client=func,ip=self.ip,\
port=self.server_port,timeout=0.5))
for Thread in Threads: #now go thru list and start threads running
Thread.start() #call the run function
print 'error',response
raise status
return proxy
def get_server(self):
port=2222
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#localhost = only visible to this machine
server.bind(('localhost',port))
server.listen(5)
return server,port
def run(self,func):
Threads=[]
Threads.append( thread_it(tid=0,proxy=self.get_proxy(),\
server=self._server,timeout=self.timeout))
Threads.append( thread_it(tid=1,tunnel_client=func,ip=self.ip,\
port=self.server_port,timeout=0.5))
for Thread in Threads: #now go thru list and start threads running
Thread.start() #call the run function
for Thread in Threads: #make main thread wait for all in list to
Thread.join()
|
import pytunnel,httplib
def tunnel_this(ip,port): conn = httplib.HTTPSConnection(ip,port=port) conn.putrequest('GET', '/') conn.endheaders() response = conn.getresponse() print response.read()
tunnel=pytunnel.build(host='login.yahoo.com',proxy_host='h1', proxy_user='u',proxy_pass='p') tunnel.run(tunnel_this)
Note: Python versions 2.4 and earlier do support non-blocking sockets for ssl I/O. For this example, you may have issues if the proxy server uses non-blocking sockets.
At the moment it looks outdated:
link given does not work
example code is broken at line 112
Could someone fix it?