284 lines
8.4 KiB
Python
284 lines
8.4 KiB
Python
|
|
#!/usr/bin/env python
|
|||
|
|
# encoding: utf-8
|
|||
|
|
import socket, threading, thread, select, signal, sys, time, getopt
|
|||
|
|
|
|||
|
|
# Listen
|
|||
|
|
LISTENING_ADDR = '0.0.0.0'
|
|||
|
|
if sys.argv[1:]:
|
|||
|
|
LISTENING_PORT = sys.argv[1]
|
|||
|
|
else:
|
|||
|
|
LISTENING_PORT = 80
|
|||
|
|
#Pass
|
|||
|
|
PASS = ''
|
|||
|
|
# CONST
|
|||
|
|
BUFLEN = 4096 * 4
|
|||
|
|
TIMEOUT = 60
|
|||
|
|
DEFAULT_HOST = '127.0.0.1:22'
|
|||
|
|
#MSG = '<span style=color: #ff0000;><strong><span style=color: #ff9900;>By</span>-<span style=color: #008000;>@drowkid01</span>-ADM</strong></span>'
|
|||
|
|
MSG = '<span style=color: #ff0000;><strong><span style="color: #ff0000;">✧</span><span style="color: #ff9900;"> | </span><span style="color: #008000;">ᴅ</span><span style="color: #0000ff;">ʀ</span><span style="color: #ff0000;">ᴏ</span><span style="color: #ff9900;">ᴡ</span><span style="color: #008000;">ᴋ</span><span style="color: #0000ff;">ɪ</span><span style="color: #ff0000;">ᴅ</span><span style="color: #ff9900;"> | </span><span style="color: #008000;">✧</span><span style="color: #0000ff;"></span></strong></span>'
|
|||
|
|
|
|||
|
|
STATUS_RESP = '101'
|
|||
|
|
FTAG = '\r\nContent-length: 0\r\n\r\nHTTP/1.1 Connection established\r\n\r\n'
|
|||
|
|
|
|||
|
|
if STATUS_RESP == '101':
|
|||
|
|
STATUS_TXT = '<font color="green">Protocolo Websocket</font>'
|
|||
|
|
else:
|
|||
|
|
STATUS_TXT = '<font color="red">Connection established</font>'
|
|||
|
|
|
|||
|
|
RESPONSE = "HTTP/1.1 " + str(STATUS_RESP) + ' ' + str(STATUS_TXT) + ' ' + str(MSG) + ' ' + str(FTAG)
|
|||
|
|
#RESPONSE = "HTTP/1.1 " + str(STATUS_RESP) + ' ' + str(MSG) + ' ' + str(FTAG)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Server(threading.Thread):
|
|||
|
|
def __init__(self, host, port):
|
|||
|
|
threading.Thread.__init__(self)
|
|||
|
|
self.running = False
|
|||
|
|
self.host = host
|
|||
|
|
self.port = port
|
|||
|
|
self.threads = []
|
|||
|
|
self.threadsLock = threading.Lock()
|
|||
|
|
self.logLock = threading.Lock()
|
|||
|
|
|
|||
|
|
def run(self):
|
|||
|
|
self.soc = socket.socket(socket.AF_INET)
|
|||
|
|
self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|||
|
|
self.soc.settimeout(2)
|
|||
|
|
intport = int(self.port)
|
|||
|
|
self.soc.bind((self.host, intport))
|
|||
|
|
self.soc.listen(0)
|
|||
|
|
self.running = True
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
while self.running:
|
|||
|
|
try:
|
|||
|
|
c, addr = self.soc.accept()
|
|||
|
|
c.setblocking(1)
|
|||
|
|
except socket.timeout:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
conn = ConnectionHandler(c, self, addr)
|
|||
|
|
conn.start()
|
|||
|
|
self.addConn(conn)
|
|||
|
|
finally:
|
|||
|
|
self.running = False
|
|||
|
|
self.soc.close()
|
|||
|
|
|
|||
|
|
def printLog(self, log):
|
|||
|
|
self.logLock.acquire()
|
|||
|
|
print log
|
|||
|
|
self.logLock.release()
|
|||
|
|
|
|||
|
|
def addConn(self, conn):
|
|||
|
|
try:
|
|||
|
|
self.threadsLock.acquire()
|
|||
|
|
if self.running:
|
|||
|
|
self.threads.append(conn)
|
|||
|
|
finally:
|
|||
|
|
self.threadsLock.release()
|
|||
|
|
|
|||
|
|
def removeConn(self, conn):
|
|||
|
|
try:
|
|||
|
|
self.threadsLock.acquire()
|
|||
|
|
self.threads.remove(conn)
|
|||
|
|
finally:
|
|||
|
|
self.threadsLock.release()
|
|||
|
|
|
|||
|
|
def close(self):
|
|||
|
|
try:
|
|||
|
|
self.running = False
|
|||
|
|
self.threadsLock.acquire()
|
|||
|
|
|
|||
|
|
threads = list(self.threads)
|
|||
|
|
for c in threads:
|
|||
|
|
c.close()
|
|||
|
|
finally:
|
|||
|
|
self.threadsLock.release()
|
|||
|
|
|
|||
|
|
|
|||
|
|
class ConnectionHandler(threading.Thread):
|
|||
|
|
def __init__(self, socClient, server, addr):
|
|||
|
|
threading.Thread.__init__(self)
|
|||
|
|
self.clientClosed = False
|
|||
|
|
self.targetClosed = True
|
|||
|
|
self.client = socClient
|
|||
|
|
self.client_buffer = ''
|
|||
|
|
self.server = server
|
|||
|
|
self.log = 'Connection: ' + str(addr)
|
|||
|
|
|
|||
|
|
def close(self):
|
|||
|
|
try:
|
|||
|
|
if not self.clientClosed:
|
|||
|
|
self.client.shutdown(socket.SHUT_RDWR)
|
|||
|
|
self.client.close()
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
finally:
|
|||
|
|
self.clientClosed = True
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
if not self.targetClosed:
|
|||
|
|
self.target.shutdown(socket.SHUT_RDWR)
|
|||
|
|
self.target.close()
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
finally:
|
|||
|
|
self.targetClosed = True
|
|||
|
|
|
|||
|
|
def run(self):
|
|||
|
|
try:
|
|||
|
|
self.client_buffer = self.client.recv(BUFLEN)
|
|||
|
|
|
|||
|
|
hostPort = self.findHeader(self.client_buffer, 'X-Real-Host')
|
|||
|
|
|
|||
|
|
if hostPort == '':
|
|||
|
|
hostPort = DEFAULT_HOST
|
|||
|
|
|
|||
|
|
split = self.findHeader(self.client_buffer, 'X-Split')
|
|||
|
|
|
|||
|
|
if split != '':
|
|||
|
|
self.client.recv(BUFLEN)
|
|||
|
|
|
|||
|
|
if hostPort != '':
|
|||
|
|
passwd = self.findHeader(self.client_buffer, 'X-Pass')
|
|||
|
|
|
|||
|
|
if len(PASS) != 0 and passwd == PASS:
|
|||
|
|
self.method_CONNECT(hostPort)
|
|||
|
|
elif len(PASS) != 0 and passwd != PASS:
|
|||
|
|
self.client.send('HTTP/1.1 400 WrongPass!\r\n\r\n')
|
|||
|
|
elif hostPort.startswith('127.0.0.1') or hostPort.startswith('localhost'):
|
|||
|
|
self.method_CONNECT(hostPort)
|
|||
|
|
else:
|
|||
|
|
self.client.send('HTTP/1.1 403 Forbidden!\r\n\r\n')
|
|||
|
|
else:
|
|||
|
|
print '- No X-Real-Host!'
|
|||
|
|
self.client.send('HTTP/1.1 400 NoXRealHost!\r\n\r\n')
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
self.log += ' - error: ' + e.strerror
|
|||
|
|
self.server.printLog(self.log)
|
|||
|
|
pass
|
|||
|
|
finally:
|
|||
|
|
self.close()
|
|||
|
|
self.server.removeConn(self)
|
|||
|
|
|
|||
|
|
def findHeader(self, head, header):
|
|||
|
|
aux = head.find(header + ': ')
|
|||
|
|
|
|||
|
|
if aux == -1:
|
|||
|
|
return ''
|
|||
|
|
|
|||
|
|
aux = head.find(':', aux)
|
|||
|
|
head = head[aux+2:]
|
|||
|
|
aux = head.find('\r\n')
|
|||
|
|
|
|||
|
|
if aux == -1:
|
|||
|
|
return ''
|
|||
|
|
|
|||
|
|
return head[:aux];
|
|||
|
|
|
|||
|
|
def connect_target(self, host):
|
|||
|
|
i = host.find(':')
|
|||
|
|
if i != -1:
|
|||
|
|
port = int(host[i+1:])
|
|||
|
|
host = host[:i]
|
|||
|
|
else:
|
|||
|
|
if self.method=='CONNECT':
|
|||
|
|
port = 22
|
|||
|
|
else:
|
|||
|
|
port = sys.argv[1]
|
|||
|
|
|
|||
|
|
(soc_family, soc_type, proto, _, address) = socket.getaddrinfo(host, port)[0]
|
|||
|
|
|
|||
|
|
self.target = socket.socket(soc_family, soc_type, proto)
|
|||
|
|
self.targetClosed = False
|
|||
|
|
self.target.connect(address)
|
|||
|
|
|
|||
|
|
def method_CONNECT(self, path):
|
|||
|
|
self.log += ' - CONNECT ' + path
|
|||
|
|
|
|||
|
|
self.connect_target(path)
|
|||
|
|
self.client.sendall(RESPONSE)
|
|||
|
|
self.client_buffer = ''
|
|||
|
|
|
|||
|
|
self.server.printLog(self.log)
|
|||
|
|
self.doCONNECT()
|
|||
|
|
|
|||
|
|
def doCONNECT(self):
|
|||
|
|
socs = [self.client, self.target]
|
|||
|
|
count = 0
|
|||
|
|
error = False
|
|||
|
|
while True:
|
|||
|
|
count += 1
|
|||
|
|
(recv, _, err) = select.select(socs, [], socs, 3)
|
|||
|
|
if err:
|
|||
|
|
error = True
|
|||
|
|
if recv:
|
|||
|
|
for in_ in recv:
|
|||
|
|
try:
|
|||
|
|
data = in_.recv(BUFLEN)
|
|||
|
|
if data:
|
|||
|
|
if in_ is self.target:
|
|||
|
|
self.client.send(data)
|
|||
|
|
else:
|
|||
|
|
while data:
|
|||
|
|
byte = self.target.send(data)
|
|||
|
|
data = data[byte:]
|
|||
|
|
|
|||
|
|
count = 0
|
|||
|
|
else:
|
|||
|
|
break
|
|||
|
|
except:
|
|||
|
|
error = True
|
|||
|
|
break
|
|||
|
|
if count == TIMEOUT:
|
|||
|
|
error = True
|
|||
|
|
if error:
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
|
|||
|
|
def print_usage():
|
|||
|
|
print 'Usage: proxy.py -p <port>'
|
|||
|
|
print ' proxy.py -b <bindAddr> -p <port>'
|
|||
|
|
print ' proxy.py -b 0.0.0.0 -p 80'
|
|||
|
|
|
|||
|
|
def parse_args(argv):
|
|||
|
|
global LISTENING_ADDR
|
|||
|
|
global LISTENING_PORT
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
opts, args = getopt.getopt(argv,"hb:p:",["bind=","port="])
|
|||
|
|
except getopt.GetoptError:
|
|||
|
|
print_usage()
|
|||
|
|
sys.exit(2)
|
|||
|
|
for opt, arg in opts:
|
|||
|
|
if opt == '-h':
|
|||
|
|
print_usage()
|
|||
|
|
sys.exit()
|
|||
|
|
elif opt in ("-b", "--bind"):
|
|||
|
|
LISTENING_ADDR = arg
|
|||
|
|
elif opt in ("-p", "--port"):
|
|||
|
|
LISTENING_PORT = int(arg)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main(host=LISTENING_ADDR, port=LISTENING_PORT):
|
|||
|
|
|
|||
|
|
print "\033[0;34m━"*8,"\033[1;32m PROXY PYTHON WEBSOCKET","\033[0;34m━"*8,"\n"
|
|||
|
|
print "\033[1;33mIP:\033[1;32m " + LISTENING_ADDR
|
|||
|
|
print "\033[1;33mPORTA:\033[1;32m " + str(LISTENING_PORT) + "\n"
|
|||
|
|
print "\033[0;34m━"*10,"\033[1;32m ChumoGH ADM - LITE","\033[0;34m━\033[1;37m"*11,"\n"
|
|||
|
|
|
|||
|
|
server = Server(LISTENING_ADDR, LISTENING_PORT)
|
|||
|
|
server.start()
|
|||
|
|
|
|||
|
|
while True:
|
|||
|
|
try:
|
|||
|
|
time.sleep(2)
|
|||
|
|
except KeyboardInterrupt:
|
|||
|
|
print 'Parando...'
|
|||
|
|
server.close()
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
parse_args(sys.argv[1:])
|
|||
|
|
main()
|