Building a Custom HTTP Server with Python
In this blog post, we’ll dive into the creation of a custom HTTP server using Python, explore its functionality, and discuss how it can be leveraged for legitimate purposes like file sharing, as well as for security testing scenarios such as Server-Side Request Forgery (SSRF) and cookie theft.
Understanding the HTTP Server Code
Imports and Setup

We imports SimpleHTTPRequestHandler
and HTTPServer
from the http.server
module, os
for system commands, and Thread
from the threading
module. These allow the server to handle HTTP requests and run port forwarding in a separate thread.
Custom Handler Class

We create the get_headers
class inherits from SimpleHTTPRequestHandler
. The do_GET
method overrides the default behavior to iterate over self.headers.items()
, printing each header and its value in the format header:value
. The super().do_GET()
call ensures the default GET request handling (serving files) continues.
Server Function

The run_server
function creates an HTTPServer
instance bound to the specified port with the get_headers
handler and runs it indefinitely with serve_forever()
.
Port Forwarding

The forword_port
function starts the server in a new thread and uses an SSH command (ssh -R 80:localhost:port nokey@localhost.run
) to forward the local port to a public URL via localhost.run
.
Main Execution

When run, the script sets port=1234
and calls forword_port
, initiating the server and tunneling.
This setup creates a server that logs headers (e.g., host:example.com
, user-agent:Mozilla/5.0
) and serves files from the current directory, accessible locally or publicly via the tunnel.
Full code
from http.server import SimpleHTTPRequestHandler, HTTPServer
import os
from threading import Thread
class get_headers(SimpleHTTPRequestHandler):
def do_GET(self):
for header, value in self.headers.items():
print(header+":"+value)
return super().do_GET()
def run_server(port):
HTTPServer(("", port), get_headers).serve_forever()
def forword_port(port):
thread = Thread(target=run_server, args=(port,))
thread.start()
cmd = "ssh -R 80:localhost:"+str(port)+" nokey@localhost.run"
os.system(cmd)
if __name__ == "__main__":
port=1234
forword_port(port)
What is localhost.run and How to Use It?
localhost.run
is a free service that provides temporary public URLs to access local servers by tunneling through SSH. It’s ideal for testing web applications or sharing files without a static IP or domain. Here’s how it works and how to enhance it with a long connection:
- Basic Usage: The script uses
ssh -R 80:localhost:port nokey@localhost.run
to forward port 1234 to a random subdomain (e.g.,https://random-id.lhr.life
). Thenokey
option allows anonymous access, but connections expire after a short period. - Registration for Long Connections: To maintain a stable, long-lasting connection, register an account at localhost.run. After signing up, you’ll receive an API key. Use this key with the command:
ssh -R 80:localhost:1234 -i ~/.ssh/your-key your-username@localhost.run
Replace your-key
with the private key path and your-username
with your registered username. This keeps the tunnel active until manually stopped.
- Benefits: A registered account provides a custom subdomain (e.g.,
https://yourname.lhr.life
) and extended session duration, making it suitable for prolonged testing or file sharing.
Always secure your key and avoid exposing sensitive data, as localhost.run
tunnels are accessible publicly.
Applications for Hackers and Bug Testers
This HTTP server, combined with localhost.run
, becomes a powerful tool for hackers and bug testers. Below are key use cases:
File Sharing
The server can share files from the current directory by placing them there and accessing the public URL. For example, drop a file document.pdf
in the directory, run the script, and share https://random-id.lhr.life/document.pdf
. This is handy for quick collaboration but requires caution, as anyone with the URL can access the files. Use password protection or restrict access in production scenarios.
Server-Side Request Forgery (SSRF) Testing
SSRF vulnerabilities occur when a server makes unintended requests based on user input. This server can simulate such scenarios:
- Localhost Access: Modify the handler to accept a query parameter (e.g.,
?url=http://127.0.0.1/admin
) and fetch it. If the server processes this, it could expose internal interfaces (e.g.,http://localhost:8080/admin
). - Internal Network Scanning: Use payloads like
?url=http://192.168.1.1
to probe private IPs, revealing open ports or services behind firewalls. - Bypass Techniques: Test bypasses like
?url=http://127.0.0.1@evil.com
or IPv6 formats (?url=http://[::1]
) to evade filters.
Testers can log responses or time differences to identify vulnerabilities, but ethical use is critical—always obtain permission.
Cookie Theft
Cookie theft exploits trust in HTTP requests. With this server:
- Header Logging: The current
do_GET
already logs theCookie
header. Enhance it to save cookies to a file: - Trick Delivery: Host a malicious page (e.g.,
steal.html
) with JavaScript to send cookies to the server: - Exploitation: Access the page from a target site, and the server logs the cookies, which could include session tokens.
This requires user interaction and is illegal without consent—use it only in controlled, authorized environments.
Ethical Considerations and Legal Boundaries
While this server is a valuable tool for learning and testing, its misuse can violate laws like the Computer Fraud and Abuse Act (CFAA). Always:
- Obtain explicit permission from system owners.
- Use it on your own networks or authorized test environments.
- Document intentions and share findings responsibly.
Ethical hacking strengthens security; unauthorized actions harm trust and legality.
This blog explored building a custom HTTP server with Python, leveraging localhost.run
for public access, and its applications in file sharing, SSRF testing, and cookie theft. The script provides a foundation for understanding HTTP handling and tunneling, while its extensions offer insights into security vulnerabilities. Whether you’re a developer sharing files or a tester probing defenses, this setup is a practical starting point. Use it wisely, enhance it with your needs, and always prioritize ethical practices in your explorations.