Last active
September 29, 2023 17:14
-
-
Save one2blame/09f149dd2c37ce4c2f3f23d8553456fa to your computer and use it in GitHub Desktop.
simple-https-server.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Requires Python 3.7 or greater | |
import ssl | |
import subprocess | |
import time | |
from argparse import ArgumentParser, Namespace | |
from http.server import HTTPServer, SimpleHTTPRequestHandler | |
from pathlib import Path | |
SERVER_DIRECTORY = "" | |
class HTTPDirectoryHandler(SimpleHTTPRequestHandler): | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, directory=SERVER_DIRECTORY, **kwargs) | |
def get_parsed_args() -> Namespace: | |
parser = ArgumentParser( | |
prog="simple-https-server", | |
description="automates the creation of an HTTPS server, openssl certs and all", | |
) | |
parser.add_argument( | |
"--ip-address", "-i", default="0.0.0.0", help="Specify IP address to serve from" | |
) | |
parser.add_argument("--port", "-p", default=443, help="Specify port to serve from") | |
parser.add_argument( | |
"--server-version", | |
"-s", | |
default=f"{SimpleHTTPRequestHandler.server_version}", | |
help="Specify 'Server' string in HTTP response header", | |
) | |
parser.add_argument( | |
"--server-directory", | |
"-d", | |
default=f"{str(Path.cwd())}", | |
help="Specify directory to serve", | |
) | |
parser.add_argument( | |
"--cert", "-c", default=None, help="Specify certificate (*.pem)" | |
) | |
parser.add_argument( | |
"--cert-directory", | |
"-e", | |
default="/tmp", | |
help="Specify directory to store certificate", | |
) | |
parser.add_argument( | |
"--domain-name", | |
"-n", | |
default="example.com", | |
help="Specify domain name for certificate", | |
) | |
return parser.parse_args() | |
def create_cert(opts: Namespace) -> str: | |
try: | |
certificate_path = Path.joinpath( | |
Path(opts.cert_directory), f"simple-https-server-{int(time.time())}.pem" | |
).resolve() | |
process = subprocess.run( | |
args=[ | |
"openssl", | |
"req", | |
"-x509", | |
"-newkey", | |
"rsa:4096", | |
"-sha256", | |
"-days", | |
"3650", | |
"-nodes", | |
"-keyout", | |
f"{str(certificate_path)}", | |
"-out", | |
f"{str(certificate_path)}", | |
"-subj", | |
f"/CN={opts.domain_name}", | |
"-addext", | |
f"subjectAltName=DNS:{opts.domain_name},DNS:www.{opts.domain_name},IP:{opts.ip_address}", | |
], | |
stdout=subprocess.DEVNULL, | |
stderr=subprocess.DEVNULL, | |
) | |
process.check_returncode() | |
except subprocess.CalledProcessError: | |
raise (RuntimeError("[!] Failed to create certificate with openssl!")) | |
print(f"[+] Successfully created new certificate at: {str(certificate_path)}") | |
return str(certificate_path) | |
if __name__ == "__main__": | |
opts = get_parsed_args() | |
if not opts.cert: | |
opts.cert = create_cert(opts) | |
else: | |
opts.cert = Path(opts.cert).resolve() | |
if not opts.cert.exists(): | |
raise ( | |
FileNotFoundError( | |
f"[-] Certificate provided '{opts.cert}' does not exist!" | |
) | |
) | |
SERVER_DIRECTORY = opts.server_directory | |
request_handler = HTTPDirectoryHandler | |
request_handler.server_version = opts.server_version | |
request_handler.sys_version = "" | |
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | |
context.check_hostname = False | |
try: | |
httpd = HTTPServer((opts.ip_address, int(opts.port)), request_handler) | |
context.load_cert_chain(certfile=str(opts.cert)) | |
httpd.socket = context.wrap_socket(httpd.socket, server_side=True) | |
print( | |
f"[*] Serving directory: '{opts.server_directory}' via HTTPS at port: '{opts.port}'..." | |
) | |
httpd.serve_forever() | |
except OverflowError: | |
raise (RuntimeError(f"[-] Port provided '{int(opts.port)}' too large!")) | |
except Exception as e: | |
raise (Exception(f"[-] Unhandled Exception: {e}")) | |
exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Useful for privately and quickly transferring things.