Initial Commit
This commit is contained in:
commit
5d18904645
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.key
|
||||
*.crt
|
||||
certs/
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# CloudOnFire
|
||||
|
||||
This script accepts PROXY-Calls on 9097 and tunnels them into the Edge of the Cloudflare Infrastructure.
|
||||
This way you can access the Internet using a huge range of IPs, that change on every request and are considered clean.
|
||||
In order for this to work, we MITM all SSL-Trafic using our own certs. This means all websites with HSTS won't work.
|
||||
And browsers and other software might refuse to connect to a server, because the cert it gets looks rather suspicious...
|
166
main.py
Normal file
166
main.py
Normal file
@ -0,0 +1,166 @@
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import requests
|
||||
from urllib.parse import urlparse, urlsplit
|
||||
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from subprocess import Popen, PIPE
|
||||
import ssl
|
||||
import threading
|
||||
|
||||
class CFProxy(BaseHTTPRequestHandler):
|
||||
TOKEN_HEADER = 'H-Token'
|
||||
TOKEN_VALUE = 'agfjkewjkfvasfhgkzuc'
|
||||
HOST_HEADER = 'H-Host'
|
||||
IP_HEADER = 'H-IP'
|
||||
|
||||
PROXY_HOST = "blue-wind-f1c2.grogu.workers.dev" # "proxy.grogu.ml"
|
||||
UA = "User Agent"
|
||||
FAKE_IP = "1.1.1.1"
|
||||
PROXY = None
|
||||
|
||||
cakey = 'ca.key'
|
||||
cacert = 'ca.crt'
|
||||
certkey = 'cert.key'
|
||||
certdir = 'certs/'
|
||||
|
||||
lock = threading.Lock()
|
||||
|
||||
def __init__(self, *args):
|
||||
self.session = requests.Session()
|
||||
self.session.proxies.update({'https': self.PROXY,
|
||||
'http': self.PROXY})
|
||||
self.session.headers.update({'User-Agent': self.UA,
|
||||
self.TOKEN_HEADER: self.TOKEN_VALUE})
|
||||
self.proxy_host = self.PROXY_HOST
|
||||
self.fake_ip = self.FAKE_IP
|
||||
BaseHTTPRequestHandler.__init__(self, *args)
|
||||
|
||||
def do_GET_old(self):
|
||||
url = self.path
|
||||
print("[GET] "+url)
|
||||
req = self.get(url)
|
||||
self.send_response(req.status_code)
|
||||
self.end_headers()
|
||||
self.wfile.write(req.text.encode())
|
||||
|
||||
def do_CONNECT(self):
|
||||
hostname = self.path.split(':')[0]
|
||||
certpath = "%s/%s.crt" % (self.certdir.rstrip('/'), hostname)
|
||||
|
||||
with self.lock:
|
||||
if not os.path.isfile(certpath):
|
||||
epoch = "%d" % (time.time() * 1000)
|
||||
p1 = Popen(["openssl", "req", "-new", "-key", self.certkey, "-subj", "/CN=%s" % hostname], stdout=PIPE)
|
||||
p2 = Popen(["openssl", "x509", "-req", "-days", "3650", "-CA", self.cacert, "-CAkey", self.cakey, "-set_serial", epoch, "-out", certpath], stdin=p1.stdout, stderr=PIPE)
|
||||
p2.communicate()
|
||||
|
||||
#self.wfile.write(("%s %d %s\r\n" % (self.protocol_version, 200, 'Connection Established')).encode())
|
||||
self.send_response(200, 'Connection Established')
|
||||
self.end_headers()
|
||||
|
||||
self.connection = ssl.wrap_socket(self.connection, keyfile=self.certkey, certfile=certpath, server_side=True)
|
||||
self.rfile = self.connection.makefile("rb", self.rbufsize)
|
||||
self.wfile = self.connection.makefile("wb", self.wbufsize)
|
||||
|
||||
conntype = self.headers.get('Proxy-Connection', '')
|
||||
if self.protocol_version == "HTTP/1.1" and conntype.lower() != 'close':
|
||||
self.close_connection = 0
|
||||
else:
|
||||
self.close_connection = 1
|
||||
|
||||
print("[CON OK]")
|
||||
|
||||
def request_handler(self, req, req_body):
|
||||
pass
|
||||
|
||||
def response_handler(self, req, req_body, res, res_body):
|
||||
pass
|
||||
|
||||
def filter_headers(self, headers):
|
||||
# http://tools.ietf.org/html/rfc2616#section-13.5.1
|
||||
hop_by_hop = ('connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade')
|
||||
for k in hop_by_hop:
|
||||
del headers[k]
|
||||
|
||||
# accept only supported encodings
|
||||
if 'Accept-Encoding' in headers:
|
||||
ae = headers['Accept-Encoding']
|
||||
filtered_encodings = [x for x in re.split(r',\s*', ae) if x in ('identity', 'gzip', 'x-gzip', 'deflate')]
|
||||
headers['Accept-Encoding'] = ', '.join(filtered_encodings)
|
||||
|
||||
return headers
|
||||
|
||||
def do_ALL(self):
|
||||
if self.path == 'http://127.0.0.1/':
|
||||
self.send_cacert()
|
||||
return
|
||||
|
||||
req = self
|
||||
content_length = int(req.headers.get('Content-Length', 0))
|
||||
req_body = self.rfile.read(content_length) if content_length else None
|
||||
|
||||
if req.path[0] == '/':
|
||||
if isinstance(self.connection, ssl.SSLSocket):
|
||||
req.path = "https://%s%s" % (req.headers['Host'], req.path)
|
||||
else:
|
||||
req.path = "http://%s%s" % (req.headers['Host'], req.path)
|
||||
|
||||
req_body_modified = self.request_handler(req, req_body)
|
||||
if req_body_modified is False:
|
||||
self.send_error(403)
|
||||
return
|
||||
elif req_body_modified is not None:
|
||||
req_body = req_body_modified
|
||||
req.headers['Content-length'] = str(len(req_body))
|
||||
|
||||
u = urlsplit(req.path)
|
||||
scheme, netloc, path = u.scheme, u.netloc, (u.path + '?' + u.query if u.query else u.path)
|
||||
assert scheme in ('http', 'https')
|
||||
if netloc:
|
||||
req.headers['Host'] = netloc
|
||||
setattr(req, 'headers', self.filter_headers(req.headers))
|
||||
|
||||
res = self.get(req.path)
|
||||
self.send_response(res.status_code)
|
||||
self.end_headers()
|
||||
self.wfile.write(res.text.encode())
|
||||
|
||||
do_GET = do_ALL
|
||||
do_POST = do_ALL # wont work, because we drop the body...
|
||||
|
||||
def send_cacert(self):
|
||||
with open(self.cacert, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
self.wfile.write("%s %d %s\r\n" % (self.protocol_version, 200, 'OK'))
|
||||
self.send_header('Content-Type', 'application/x-x509-ca-cert')
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.send_header('Connection', 'close')
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
def get(self, url, **kwargs):
|
||||
return self.handleReq('GET', url, **kwargs)
|
||||
|
||||
def post(self, url, **kwargs):
|
||||
return self.handleReq('POST', url, **kwargs)
|
||||
|
||||
def handleReq(self, method, url, **kwargs):
|
||||
# Gestion des headers
|
||||
if 'headers' in kwargs:
|
||||
for k, v in kwargs.get('headers'):
|
||||
self.session.headers.update({k: v})
|
||||
kwargs.pop('headers')
|
||||
parsed_uri = urlparse(url)
|
||||
self.session.headers.update({self.HOST_HEADER: parsed_uri.hostname})
|
||||
self.session.headers.update({self.IP_HEADER: self.fake_ip})
|
||||
proxyfied_url = '{0}://{1}{2}'.format(parsed_uri.scheme, self.proxy_host, parsed_uri.path)
|
||||
return self.session.request(method, proxyfied_url, **kwargs)
|
||||
|
||||
PORT = 9097
|
||||
httpd = HTTPServer(('', PORT), CFProxy)
|
||||
print ("[i] Now serving at " + str(PORT))
|
||||
httpd.serve_forever()
|
||||
|
6
setup_https_intercept.sh
Normal file
6
setup_https_intercept.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
openssl genrsa -out ca.key 2048
|
||||
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=proxy2 CA"
|
||||
openssl genrsa -out cert.key 2048
|
||||
mkdir certs/
|
Loading…
Reference in New Issue
Block a user