mirror of
https://github.com/gnh1201/caterpillar.git
synced 2025-02-06 06:55:00 +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]
|
||||
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)
|
||||
|
|
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 json
|
||||
import ssl
|
||||
import time
|
||||
from subprocess import Popen, PIPE
|
||||
from datetime import datetime
|
||||
from platform import python_version
|
||||
|
||||
|
@ -34,6 +36,11 @@ args = parser.parse_args()
|
|||
max_connection = args.max_conn
|
||||
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
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
@ -49,60 +56,76 @@ def start(): #Main Program
|
|||
try:
|
||||
conn, addr = sock.accept() #Accept connection from client browser
|
||||
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:
|
||||
sock.close()
|
||||
print("\n[*] Graceful Shutdown")
|
||||
sys.exit(1)
|
||||
|
||||
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 ://
|
||||
scheme = b'http' # check http/https or other protocol
|
||||
if http_pos == -1:
|
||||
temp = url
|
||||
else:
|
||||
temp = url[(http_pos+3):]
|
||||
scheme = url[0:http_pos]
|
||||
http_pos = url.find(b'://') #Finding the position of ://
|
||||
scheme = b'http' # check http/https or other protocol
|
||||
if http_pos == -1:
|
||||
temp = url
|
||||
else:
|
||||
temp = url[(http_pos+3):]
|
||||
scheme = url[0:http_pos]
|
||||
|
||||
port_pos = temp.find(b':')
|
||||
port_pos = temp.find(b':')
|
||||
|
||||
webserver_pos = temp.find(b'/')
|
||||
if webserver_pos == -1:
|
||||
webserver_pos = len(temp)
|
||||
webserver = ""
|
||||
port = -1
|
||||
if port_pos == -1 or webserver_pos < port_pos:
|
||||
port = 80
|
||||
webserver = temp[:webserver_pos]
|
||||
else:
|
||||
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
|
||||
webserver = temp[:port_pos]
|
||||
if port == 443:
|
||||
scheme = b'https'
|
||||
webserver_pos = temp.find(b'/')
|
||||
if webserver_pos == -1:
|
||||
webserver_pos = len(temp)
|
||||
webserver = ""
|
||||
port = -1
|
||||
if port_pos == -1 or webserver_pos < port_pos:
|
||||
port = 80
|
||||
webserver = temp[:webserver_pos]
|
||||
else:
|
||||
port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])
|
||||
webserver = temp[:port_pos]
|
||||
if port == 443:
|
||||
scheme = b'https'
|
||||
|
||||
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)))
|
||||
proxy_server(webserver, port, scheme, method, url, conn, addr, data)
|
||||
|
||||
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
|
||||
|
||||
def proxy_server(webserver, port, scheme, method, url, conn, addr, data):
|
||||
try:
|
||||
print("[*] Started Request. %s" % (str(addr[0])))
|
||||
|
||||
if scheme == b'https' and method == b'CONNECT':
|
||||
conn = proxy_connect(conn, url)
|
||||
if scheme in [b'https', b'tls', b'ssl'] and method == b'CONNECT':
|
||||
conn = proxy_connect(webserver, conn)
|
||||
|
||||
data = {
|
||||
proxy_data = {
|
||||
'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": 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")
|
||||
}
|
||||
}
|
||||
raw_data = json.dumps(data['data'])
|
||||
print (proxy_data)
|
||||
|
||||
raw_data = json.dumps(proxy_data['data'])
|
||||
|
||||
print("[*] Sending %s bytes..." % (str(len(raw_data))))
|
||||
|
||||
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):
|
||||
conn.send(chunk)
|
||||
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])))
|
||||
|
||||
conn.close()
|
||||
except socket.error:
|
||||
sock.close()
|
||||
except Exception as e:
|
||||
print("[*] f: proxy_server: %s" % (str(e)))
|
||||
conn.close()
|
||||
print(sock.error)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__== "__main__":
|
||||
start()
|
||||
|
|
Loading…
Reference in New Issue
Block a user