ws-stunnel 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #!/usr/bin/python
  2. import socket, threading, thread, select, signal, sys, time, getopt
  3. # Listen
  4. LISTENING_ADDR = '0.0.0.0'
  5. #LISTENING_PORT = sys.argv[1]
  6. LISTENING_PORT = 2088
  7. #Pass
  8. PASS = ''
  9. # CONST
  10. BUFLEN = 4096 * 4
  11. TIMEOUT = 60
  12. DEFAULT_HOST = '127.0.0.1:587'
  13. #RESPONSE = 'HTTP/1.1 101 WebSocket by KaizenVPN\r\n\r\n'
  14. #RESPONSE = 'HTTP/1.1 101 WebSocket by KaizenVPN\r\nContent-Length: 104857600000\r\n\r\n'
  15. RESPONSE = 'HTTP/1.1 200 WebSocket by KaizenVPN\r\nContent-length: 0\r\n\r\nHTTP/1.1 200 Connection established\r\n\r\n' # lint:ok
  16. class Server(threading.Thread):
  17. def __init__(self, host, port):
  18. threading.Thread.__init__(self)
  19. self.running = False
  20. self.host = host
  21. self.port = port
  22. self.threads = []
  23. self.threadsLock = threading.Lock()
  24. self.logLock = threading.Lock()
  25. def run(self):
  26. self.soc = socket.socket(socket.AF_INET)
  27. self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  28. self.soc.settimeout(2)
  29. intport = int(self.port)
  30. self.soc.bind((self.host, intport))
  31. self.soc.listen(0)
  32. self.running = True
  33. try:
  34. while self.running:
  35. try:
  36. c, addr = self.soc.accept()
  37. c.setblocking(1)
  38. except socket.timeout:
  39. continue
  40. conn = ConnectionHandler(c, self, addr)
  41. conn.start()
  42. self.addConn(conn)
  43. finally:
  44. self.running = False
  45. self.soc.close()
  46. def printLog(self, log):
  47. self.logLock.acquire()
  48. print log
  49. self.logLock.release()
  50. def addConn(self, conn):
  51. try:
  52. self.threadsLock.acquire()
  53. if self.running:
  54. self.threads.append(conn)
  55. finally:
  56. self.threadsLock.release()
  57. def removeConn(self, conn):
  58. try:
  59. self.threadsLock.acquire()
  60. self.threads.remove(conn)
  61. finally:
  62. self.threadsLock.release()
  63. def close(self):
  64. try:
  65. self.running = False
  66. self.threadsLock.acquire()
  67. threads = list(self.threads)
  68. for c in threads:
  69. c.close()
  70. finally:
  71. self.threadsLock.release()
  72. class ConnectionHandler(threading.Thread):
  73. def __init__(self, socClient, server, addr):
  74. threading.Thread.__init__(self)
  75. self.clientClosed = False
  76. self.targetClosed = True
  77. self.client = socClient
  78. self.client_buffer = ''
  79. self.server = server
  80. self.log = 'Connection: ' + str(addr)
  81. def close(self):
  82. try:
  83. if not self.clientClosed:
  84. self.client.shutdown(socket.SHUT_RDWR)
  85. self.client.close()
  86. except:
  87. pass
  88. finally:
  89. self.clientClosed = True
  90. try:
  91. if not self.targetClosed:
  92. self.target.shutdown(socket.SHUT_RDWR)
  93. self.target.close()
  94. except:
  95. pass
  96. finally:
  97. self.targetClosed = True
  98. def run(self):
  99. try:
  100. self.client_buffer = self.client.recv(BUFLEN)
  101. hostPort = self.findHeader(self.client_buffer, 'X-Real-Host')
  102. if hostPort == '':
  103. hostPort = DEFAULT_HOST
  104. split = self.findHeader(self.client_buffer, 'X-Split')
  105. if split != '':
  106. self.client.recv(BUFLEN)
  107. if hostPort != '':
  108. passwd = self.findHeader(self.client_buffer, 'X-Pass')
  109. if len(PASS) != 0 and passwd == PASS:
  110. self.method_CONNECT(hostPort)
  111. elif len(PASS) != 0 and passwd != PASS:
  112. self.client.send('HTTP/1.1 400 WrongPass!\r\n\r\n')
  113. elif hostPort.startswith('127.0.0.1') or hostPort.startswith('localhost'):
  114. self.method_CONNECT(hostPort)
  115. else:
  116. self.client.send('HTTP/1.1 403 Forbidden!\r\n\r\n')
  117. else:
  118. print '- No X-Real-Host!'
  119. self.client.send('HTTP/1.1 400 NoXRealHost!\r\n\r\n')
  120. except Exception as e:
  121. self.log += ' - error: ' + e.strerror
  122. self.server.printLog(self.log)
  123. pass
  124. finally:
  125. self.close()
  126. self.server.removeConn(self)
  127. def findHeader(self, head, header):
  128. aux = head.find(header + ': ')
  129. if aux == -1:
  130. return ''
  131. aux = head.find(':', aux)
  132. head = head[aux+2:]
  133. aux = head.find('\r\n')
  134. if aux == -1:
  135. return ''
  136. return head[:aux];
  137. def connect_target(self, host):
  138. i = host.find(':')
  139. if i != -1:
  140. port = int(host[i+1:])
  141. host = host[:i]
  142. else:
  143. if self.method=='CONNECT':
  144. port = 587
  145. else:
  146. port = sys.argv[1]
  147. (soc_family, soc_type, proto, _, address) = socket.getaddrinfo(host, port)[0]
  148. self.target = socket.socket(soc_family, soc_type, proto)
  149. self.targetClosed = False
  150. self.target.connect(address)
  151. def method_CONNECT(self, path):
  152. self.log += ' - CONNECT ' + path
  153. self.connect_target(path)
  154. self.client.sendall(RESPONSE)
  155. self.client_buffer = ''
  156. self.server.printLog(self.log)
  157. self.doCONNECT()
  158. def doCONNECT(self):
  159. socs = [self.client, self.target]
  160. count = 0
  161. error = False
  162. while True:
  163. count += 1
  164. (recv, _, err) = select.select(socs, [], socs, 3)
  165. if err:
  166. error = True
  167. if recv:
  168. for in_ in recv:
  169. try:
  170. data = in_.recv(BUFLEN)
  171. if data:
  172. if in_ is self.target:
  173. self.client.send(data)
  174. else:
  175. while data:
  176. byte = self.target.send(data)
  177. data = data[byte:]
  178. count = 0
  179. else:
  180. break
  181. except:
  182. error = True
  183. break
  184. if count == TIMEOUT:
  185. error = True
  186. if error:
  187. break
  188. def print_usage():
  189. print 'Usage: proxy.py -p <port>'
  190. print ' proxy.py -b <bindAddr> -p <port>'
  191. print ' proxy.py -b 0.0.0.0 -p 8080'
  192. def parse_args(argv):
  193. global LISTENING_ADDR
  194. global LISTENING_PORT
  195. try:
  196. opts, args = getopt.getopt(argv,"hb:p:",["bind=","port="])
  197. except getopt.GetoptError:
  198. print_usage()
  199. sys.exit(2)
  200. for opt, arg in opts:
  201. if opt == '-h':
  202. print_usage()
  203. sys.exit()
  204. elif opt in ("-b", "--bind"):
  205. LISTENING_ADDR = arg
  206. elif opt in ("-p", "--port"):
  207. LISTENING_PORT = int(arg)
  208. def main(host=LISTENING_ADDR, port=LISTENING_PORT):
  209. print "\n:-------PythonProxy-------:\n"
  210. print "Listening addr: " + LISTENING_ADDR
  211. print "Listening port: " + str(LISTENING_PORT) + "\n"
  212. print ":-------------------------:\n"
  213. server = Server(LISTENING_ADDR, LISTENING_PORT)
  214. server.start()
  215. while True:
  216. try:
  217. time.sleep(2)
  218. except KeyboardInterrupt:
  219. print 'Stopping...'
  220. server.close()
  221. break
  222. ####### parse_args(sys.argv[1:])
  223. if __name__ == '__main__':
  224. main()