mirror of
https://github.com/gnh1201/caterpillar.git
synced 2025-09-06 18:01:07 +00:00
Add HTTPS decryption (Experimental)
This commit is contained in:
parent
1105633d9d
commit
20bda58945
|
@ -15,7 +15,11 @@ HTTP proxy over the web hosting!
|
||||||
```
|
```
|
||||||
[settings]
|
[settings]
|
||||||
PORT=5555
|
PORT=5555
|
||||||
PROXY_URL=http://example.org
|
SERVER_URL=http://example.org
|
||||||
|
CA_KEY=ca.key
|
||||||
|
CA_CERT=ca.crt
|
||||||
|
CERT_KEY=cert.key
|
||||||
|
CERT_DIR=certs/
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run `python server.py` and set HTTP proxy in your web browser (e.g. Firefox)
|
2. Run `python server.py` and set HTTP proxy in your web browser (e.g. Firefox)
|
||||||
|
|
19
ca.crt
Normal file
19
ca.crt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDFzCCAf+gAwIBAgIUIAYwMh8vYN/qC9An+j30JshXQjkwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwGzEZMBcGA1UEAwwQcGhwLWh0dHBwcm94eSBDQTAeFw0yMjExMjUwNjE1MTla
|
||||||
|
Fw0zMjExMjIwNjE1MTlaMBsxGTAXBgNVBAMMEHBocC1odHRwcHJveHkgQ0EwggEi
|
||||||
|
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxyrzGXNu+2Vs9ll36RMnOOcHH
|
||||||
|
thQqGg9qOJj2wdH3kvOWviIDSn4qOGA2Ff+719AtB24pIS1XdqW2TMXPwjuh+T3Z
|
||||||
|
WeYMpUlaOhWgP4Kx5Auc9num9MFqS1Mf8S4t8ZTgt5/XFC8QOW4hKEe8ZFSZ6MTA
|
||||||
|
TXbKAl0G0fFVhDzPxcvjtE+u1GFXkSv2nq+2iZ3gajqdvoTmPwgrhtaiep6Pg+KV
|
||||||
|
8CvHMsvhBtGluvPo7IHI0opx1fhkcZbHsu3r1ZD/TRWvYvA4BkH9g5hXoi88eakF
|
||||||
|
fsruzWjmnHzMVxOX7thECinOKs7iv0hR6TOY4wlgbqhK3Phas/iPUL5FoIIbAgMB
|
||||||
|
AAGjUzBRMB0GA1UdDgQWBBSzqXvDv/BeSLGduMqiBXcp9bJjmjAfBgNVHSMEGDAW
|
||||||
|
gBSzqXvDv/BeSLGduMqiBXcp9bJjmjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4IBAQArNyClOJJkKhn7Wp3zH89SoVZQJUdvXZ52XKSnBp4f4XDUuqz/
|
||||||
|
3PAE4G22uqUOkgcM+3B46HNn1OxG4/7DHcG2LfXQD3DxF56cj5ljkJRZ8CTuM01V
|
||||||
|
PqkRtncWakaoFLcvhw7SB95x9VpTZqnh8TSX/NU+YnjyAsBWdyVYUIG0xSEILzLL
|
||||||
|
jUVr94SQI9jNu5wKbC4rQY++fIAgXMJ9CdiWEWPm6wRPH0TFia+FRHmtTaqq/2DR
|
||||||
|
LF6UBDBvsFs/Z4IDq2htGqYXrkdjf6VdUGJEJLj4lJubUzcowGM6a4lbIOdhollK
|
||||||
|
fjh9nl7i86XUxIknkA7HzImH7TJOdsNBqFEz
|
||||||
|
-----END CERTIFICATE-----
|
28
ca.key
Normal file
28
ca.key
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxyrzGXNu+2Vs9
|
||||||
|
ll36RMnOOcHHthQqGg9qOJj2wdH3kvOWviIDSn4qOGA2Ff+719AtB24pIS1XdqW2
|
||||||
|
TMXPwjuh+T3ZWeYMpUlaOhWgP4Kx5Auc9num9MFqS1Mf8S4t8ZTgt5/XFC8QOW4h
|
||||||
|
KEe8ZFSZ6MTATXbKAl0G0fFVhDzPxcvjtE+u1GFXkSv2nq+2iZ3gajqdvoTmPwgr
|
||||||
|
htaiep6Pg+KV8CvHMsvhBtGluvPo7IHI0opx1fhkcZbHsu3r1ZD/TRWvYvA4BkH9
|
||||||
|
g5hXoi88eakFfsruzWjmnHzMVxOX7thECinOKs7iv0hR6TOY4wlgbqhK3Phas/iP
|
||||||
|
UL5FoIIbAgMBAAECggEARv1kku/Q7ktrmxPHQn7k9WsqbMvPEWCGdytSKHULmYcb
|
||||||
|
rD0O57F+3uzTvcTa7+4kOVaWLeYJbLr7P+c3tNUhanNSts6mhLYaq+Q1bl7tmIot
|
||||||
|
+OaSSP/BmueosUBj6ARmJbQsJnzwrdHAn4yt2BNXlHzU0tQbcl2vN2HssvCyN2Nf
|
||||||
|
T1TrpYQmchnEhwHudZP29nlmm1BbiNzEDEzvSdBDJiawZJWwiIZ8PNfQKZawiZst
|
||||||
|
SCid2hMU3aA7MfxVLSsMudZZM0PawvnEVErdJMVGhTjlWtCgxXvNv0S8qPDpdJHz
|
||||||
|
qyr1c1l+l1nt/4VvmElIyRq/MDPyss0e6w/8Ij4tAQKBgQC7YmuKMV3rQr39xB8t
|
||||||
|
EgWDbcIObI/uAOO/N56B4XlExFRSWB5pqjNpKXDukoASDHSWaWHAgVsjrOnhbtrk
|
||||||
|
32c8rBA4+SMXG8OV6w3G3qjVwJyOdgpo7s0DzR1k+N2VV1qy4/9Jl7LMK8GcvSQK
|
||||||
|
TceDdPluTJGICdUWOKW37ZRA8QKBgQDy5Rttf3/kczVqI7iq3/j8DsoC0qZYCdMO
|
||||||
|
8vVxuUL3HnCxZKgmdu6XMwuz8l7c2XVE87E4G6wRrWJeX+RowAsmplLTEdi3T968
|
||||||
|
hsSJjUyC8GdexRW6JKmRrgQuT3e/eGzvApv4aanYcbj7FSrBicm6LSorQD16vLg0
|
||||||
|
g3IOijEzywKBgQCk+VKauTnp3bntyJR2Fs651pEqJ9RUA35/pFUuHjepHnzqfmBQ
|
||||||
|
QSPAK1cdA+gze7nNjvwcAwcdkqfa7MFVDYcTuJ0Tu+xz9OKug+J+OxxEDK8JEc26
|
||||||
|
crwW46hEdIKJb/4PT4I75Y3qCYANIcywMag9CWhs/oaGUbnENZ1ZIJcM0QKBgBlc
|
||||||
|
mMePJ5B4AxzJDBAzgLD47ljrG9lXdUU7UyuDt51L/WJYa0JQ6sq41sD8TrFqt1by
|
||||||
|
xw9fvFDANOQ7yQKzArcPaNiHJYTGfzBaNg1SxqlpZrG7jHA6QcZnUCJxw8QnU+CE
|
||||||
|
+jou9kAWZ8U3yZYZyAl7i8qmU4UMTYOWMgOYpFiPAoGATiYTE9NA8kQRzvKLYTbj
|
||||||
|
L+oGSNlFrCFu3F2CrN6Czitzko8V8kjiBC8Ei3jBiHg3kU/lmAA8mO3zamzhSus3
|
||||||
|
qM/yY7bL2hrRFoNMZ4oH0VzPeb2z/SPy+slI0peKabJ4ig9qsQAc/D2kesuGPC+J
|
||||||
|
6xc1CD1cKRe/zST99+z+J4M=
|
||||||
|
-----END PRIVATE KEY-----
|
28
cert.key
Normal file
28
cert.key
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQC05OxXm2Icl3JU
|
||||||
|
5HrPWso+xtLj8xqwtTtIu4yDrr2X3SDWUZFhd1loB5rV817ZNr74ow8uU0FTz8x5
|
||||||
|
BcQTvMJawomuBjX0Xq4HQFpLJOxOssqu0nqcdn/9UdD8scj+0odhhwb1KsAVTZo0
|
||||||
|
mJAK2jlXNTy33BY24xu2Dn3wASux0FATwlrEoJ7F4K8wVRO8T0CqW7iDDBTb2a9Y
|
||||||
|
ytwpQCj2lsuWac5BmvqPD63yCYVd6TnVcTEIRVbqOCrwjNXnhIXKLMqRF+Iiihjv
|
||||||
|
yMyew5fFCmeNea9OZRlqMHWLuDPi0crfI26X3XJOUIgC97Dxb4swGMsVXUGCX1W9
|
||||||
|
GNWeSUWpAgMBAAECgf88VVlDkEEBlwt3bG519YNXu5ZMcRew7CPtgMerwYi14wsQ
|
||||||
|
vzeWrPzWK9qMbdq+l/oGVjUIyEXGmsNJS2fzLVC5Q4u74bjiF0+lQuUpjXXhGIXj
|
||||||
|
8J5+VfQLnT4+bHAnUq4jim+MkQRsPev1xk8xAKupL3rpiRwHCxr37KJjQu0BJeg7
|
||||||
|
H80VPHpPLH9RANjCMer0Y6ZeyR2adjf3WVheA91c8wKiGbkIV3cN7rO4VImya/0P
|
||||||
|
bXqmdgDGoSoRRRLgG3U5QDA5oMEwALXdS67TfwgtrhGsHxfsQ8yhGvG7UyjKf7iu
|
||||||
|
Yy/tkosR7Ly+tAmp1arP6kfW+1u/h4dGyhrVPhkCgYEA+9rhEy/p3nDlvKjXRx2J
|
||||||
|
1tWWkBtIY7OZuYyDdpowSh5FODiDIZZycttqzNhqmJWsSwZm0y24+awwzSNLFzlK
|
||||||
|
mC6IoXHeLjqXovPUsjSFf0GML6YNuFKxF5LKFdl/MuyfomaHhK8CIG2TVasxGa63
|
||||||
|
L12K3GVb2i0xB7XtIpXYnYcCgYEAt98SE8J/VUxWoFa2C5q5svQjSaUwtRCb0te5
|
||||||
|
FiZtu871lna1LLsb98D7Z3JRHvpn2cJ96OvLcYUC7tq3LHyPL0SlAEHoz+eFcrE2
|
||||||
|
CXHHDfUim6IfZ9v0fnf5aS301UF7zq1T4+PPwlgvtLeM5JNcur+C0ISNQ3jNw4oj
|
||||||
|
aA6MT08CgYEA8kVMTAvEOjF6HfCBHizhAqN18Wv9R8Nl9iKf98A9AZ960Kk0I2Q4
|
||||||
|
9hnx89mfOOaJ1aXz1eNe0/X6/+qael2nTxs8XalOpEPCyIMrsL1rSc4BD3j6K7yI
|
||||||
|
FHglI72UaaVLropYhJ9hOVaO61MBqYXzO4INaROrtwXP623rDmD8/hMCgYB4Lxms
|
||||||
|
ysPaKESzFxp06VSaERQDrjLxFwMTRKgZP1MYoEVMbRktPLwiLATn8APwILLC1mrg
|
||||||
|
VUesUsnBADscm+ondlH3oh0fz/AdMJHmiHUYvXM6kTS/+TiNdbQTuNNAlUXsqMSd
|
||||||
|
v6lsGaJNGHDCc0P4WPeTfiCryomMV32fJWs25wKBgA8B0ZZTmefhaS5AJfPcewJj
|
||||||
|
JzS+6HPdEGkDMbCMT5JvUrrRbYxBlnkG3FaYIw5gKib2pKaZBIWiCAN222xlyo+H
|
||||||
|
h2BUyy3NFCdOQ+7qm7hhKYqcbAsnPmfT2OowP0icE8qmXWBMWSMI/ihVZ5XQKdTp
|
||||||
|
pdM4tpCckvB/T0XZkl7x
|
||||||
|
-----END PRIVATE KEY-----
|
101
server.py
101
server.py
|
@ -11,6 +11,8 @@ from _thread import *
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import ssl
|
import ssl
|
||||||
|
import time
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from platform import python_version
|
from platform import python_version
|
||||||
|
|
||||||
|
@ -34,6 +36,11 @@ args = parser.parse_args()
|
||||||
max_connection = args.max_conn
|
max_connection = args.max_conn
|
||||||
buffer_size = args.buffer_size
|
buffer_size = args.buffer_size
|
||||||
|
|
||||||
|
cakey = config('CA_KEY')
|
||||||
|
cacert = config('CA_CERT')
|
||||||
|
certkey = config('CERT_KEY')
|
||||||
|
certdir = config('CERT_DIR')
|
||||||
|
|
||||||
def start(): #Main Program
|
def start(): #Main Program
|
||||||
try:
|
try:
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
@ -49,60 +56,76 @@ def start(): #Main Program
|
||||||
try:
|
try:
|
||||||
conn, addr = sock.accept() #Accept connection from client browser
|
conn, addr = sock.accept() #Accept connection from client browser
|
||||||
data = conn.recv(buffer_size) #Recieve client data
|
data = conn.recv(buffer_size) #Recieve client data
|
||||||
start_new_thread(conn_string, (conn,data, addr)) #Starting a thread
|
start_new_thread(conn_string, (conn, data, addr)) #Starting a thread
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sock.close()
|
sock.close()
|
||||||
print("\n[*] Graceful Shutdown")
|
print("\n[*] Graceful Shutdown")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def conn_string(conn, data, addr):
|
def conn_string(conn, data, addr):
|
||||||
try:
|
first_line = data.split(b'\n')[0]
|
||||||
first_line = data.split(b'\n')[0]
|
|
||||||
|
|
||||||
method, url = first_line.split()[0:2]
|
method, url = first_line.split()[0:2]
|
||||||
|
|
||||||
http_pos = url.find(b'://') #Finding the position of ://
|
http_pos = url.find(b'://') #Finding the position of ://
|
||||||
scheme = b'http' # check http/https or other protocol
|
scheme = b'http' # check http/https or other protocol
|
||||||
if http_pos == -1:
|
if http_pos == -1:
|
||||||
temp = url
|
temp = url
|
||||||
else:
|
else:
|
||||||
temp = url[(http_pos+3):]
|
temp = url[(http_pos+3):]
|
||||||
scheme = url[0:http_pos]
|
scheme = url[0:http_pos]
|
||||||
|
|
||||||
port_pos = temp.find(b':')
|
port_pos = temp.find(b':')
|
||||||
|
|
||||||
webserver_pos = temp.find(b'/')
|
webserver_pos = temp.find(b'/')
|
||||||
if webserver_pos == -1:
|
if webserver_pos == -1:
|
||||||
webserver_pos = len(temp)
|
webserver_pos = len(temp)
|
||||||
webserver = ""
|
webserver = ""
|
||||||
port = -1
|
port = -1
|
||||||
if port_pos == -1 or webserver_pos < port_pos:
|
if port_pos == -1 or webserver_pos < port_pos:
|
||||||
port = 80
|
port = 80
|
||||||
webserver = temp[:webserver_pos]
|
webserver = temp[:webserver_pos]
|
||||||
else:
|
else:
|
||||||
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
|
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
|
||||||
webserver = temp[:port_pos]
|
webserver = temp[:port_pos]
|
||||||
if port == 443:
|
if port == 443:
|
||||||
scheme = b'https'
|
scheme = b'https'
|
||||||
|
|
||||||
proxy_server(webserver, port, scheme, method, url, conn, addr, data)
|
proxy_server(webserver, port, scheme, method, url, conn, addr, data)
|
||||||
except Exception as e:
|
|
||||||
print("[*] Warning: %s, Line %s" % (str(e), str(sys.exc_info()[-1].tb_lineno)))
|
|
||||||
|
|
||||||
def proxy_connect(webserver, conn):
|
def proxy_connect(webserver, conn):
|
||||||
# TODO
|
hostname = webserver.decode('utf-8')
|
||||||
|
certpath = "%s/%s.crt" % (certdir.rstrip('/'), hostname)
|
||||||
|
|
||||||
|
conn.send(b'HTTP/1.1 200 Connection Established\r\n')
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not os.path.isfile(certpath):
|
||||||
|
epoch = "%d" % (time.time() * 1000)
|
||||||
|
p1 = Popen(["openssl", "req", "-new", "-key", certkey, "-subj", "/CN=%s" % hostname], stdout=PIPE)
|
||||||
|
p2 = Popen(["openssl", "x509", "-req", "-days", "3650", "-CA", cacert, "-CAkey", cakey, "-set_serial", epoch, "-out", certpath], stdin=p1.stdout, stderr=PIPE)
|
||||||
|
p2.communicate()
|
||||||
|
except Exception as e:
|
||||||
|
print("[*] Skipped generating the key. %s" % (str(e)))
|
||||||
|
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
context.load_cert_chain(certpath, certkey)
|
||||||
|
|
||||||
|
# what the heck? why hang?
|
||||||
|
conn = context.wrap_socket(conn, server_side=True)
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def proxy_server(webserver, port, scheme, method, url, conn, addr, data):
|
def proxy_server(webserver, port, scheme, method, url, conn, addr, data):
|
||||||
try:
|
try:
|
||||||
print("[*] Started Request. %s" % (str(addr[0])))
|
print("[*] Started Request. %s" % (str(addr[0])))
|
||||||
|
|
||||||
if scheme == b'https' and method == b'CONNECT':
|
if scheme in [b'https', b'tls', b'ssl'] and method == b'CONNECT':
|
||||||
conn = proxy_connect(conn, url)
|
conn = proxy_connect(webserver, conn)
|
||||||
|
|
||||||
data = {
|
proxy_data = {
|
||||||
'headers': {
|
'headers': {
|
||||||
"User-Agent": "php-httpproxy/0.1.2 (Client; Python " + python_version() + ")",
|
"User-Agent": "php-httpproxy/0.1.3-dev (Client; Python " + python_version() + ")",
|
||||||
},
|
},
|
||||||
'data': {
|
'data': {
|
||||||
"data": base64.b64encode(data).decode("utf-8"),
|
"data": base64.b64encode(data).decode("utf-8"),
|
||||||
|
@ -116,12 +139,14 @@ def proxy_server(webserver, port, scheme, method, url, conn, addr, data):
|
||||||
"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
|
"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
raw_data = json.dumps(data['data'])
|
print (proxy_data)
|
||||||
|
|
||||||
|
raw_data = json.dumps(proxy_data['data'])
|
||||||
|
|
||||||
print("[*] Sending %s bytes..." % (str(len(raw_data))))
|
print("[*] Sending %s bytes..." % (str(len(raw_data))))
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
relay = requests.post(server_url, headers=data['headers'], data=raw_data, stream=True)
|
relay = requests.post(server_url, headers=proxy_data['headers'], data=raw_data, stream=True)
|
||||||
for chunk in relay.iter_content(chunk_size=buffer_size):
|
for chunk in relay.iter_content(chunk_size=buffer_size):
|
||||||
conn.send(chunk)
|
conn.send(chunk)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -130,11 +155,9 @@ def proxy_server(webserver, port, scheme, method, url, conn, addr, data):
|
||||||
print("[*] Request Done. %s" % (str(addr[0])))
|
print("[*] Request Done. %s" % (str(addr[0])))
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
except socket.error:
|
except Exception as e:
|
||||||
sock.close()
|
print("[*] f: proxy_server: %s" % (str(e)))
|
||||||
conn.close()
|
conn.close()
|
||||||
print(sock.error)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
start()
|
start()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user