Fail-closed Tor session enforcement for Python HTTP(S) traffic
Project description
ProtoX GateKeeper
ProtoX GateKeeper is a small, opinionated Python library that enforces fail-closed Tor routing for HTTP(S) traffic.
The goal is simple:
If Tor is not active and verified, nothing runs.
GateKeeper is designed to be fire-and-forget: create a client once, then perform network operations with a hard guarantee that traffic exits through the Tor network.
What GateKeeper Is
- A Tor-verified HTTP client
- A thin wrapper around
requests.Sessionwith safe helpers - Fail-closed by default (no silent clearnet fallback)
- Observable (exit IP, optional geo info)
- Suitable for scripts, tooling, and automation
What GateKeeper Is NOT
- ❌ A Tor controller
- ❌ A crawler or scanner
- ❌ An anonymization silver bullet
- ❌ A replacement for Tor Browser
GateKeeper enforces transport routing only. You are still responsible for what you do with it.
Requirements
- A locally running Tor client
- SOCKS proxy enabled (default:
127.0.0.1:9150)
On Windows this usually means Tor Browser running in the background.
Installation
From PyPI
pip install protox-gatekeeper
From source (development)
pip install -e .
(Recommended while developing or testing.)
Basic Usage
import logging
from protox_gatekeeper import GateKeeper
logging.basicConfig(
level=logging.INFO,
format='[%(levelname)s] %(name)s - %(message)s'
)
gk = GateKeeper(geo=True)
gk.download(
"https://httpbin.org/bytes/1024",
"downloads/test.bin"
)
Example output
[INFO] gatekeeper.core - Tor verified: 89.xxx.xxx.xxx -> 185.xxx.xxx.xxx
[INFO] gatekeeper.core - Tor exit location: Brandenburg, DE
[INFO] gatekeeper.core - [Tor 185.xxx.xxx.xxx] downloading https://httpbin.org/bytes/1024 -> downloads/test.bin
This confirms:
- clearnet IP was measured
- Tor routing was verified
- all traffic used the Tor exit shown
HTTP requests
GateKeeper can also be used as a Tor-verified HTTP client:
with GateKeeper() as gk:
response = gk.get("https://httpbin.org/ip")
print(response.json())
All requests are guaranteed to use the verified Tor session.
API Overview
GateKeeper(...)
gk = GateKeeper(
socks_port=9150,
geo=False
)
Parameters:
socks_port(int) – Tor SOCKS port (default:9150)geo(bool) – Enable best-effort Tor exit geolocation (optional)
Raises RuntimeError if Tor routing cannot be verified.
request(method, url, **kwargs)
Performs an arbitrary HTTP request through the verified Tor session.
This is a thin passthrough to requests.Session.request, with enforced Tor routing and logging.
r = gk.request(
"GET",
"https://httpbin.org/ip",
timeout=10
)
print(r.json())
method– HTTP verb (GET, POST, PUT, DELETE, ...)url– Target URL**kwargs– Forwarded directly torequests
This is the core execution path used internally by helper methods like get() and post().
download(url, target_path)
Downloads a resource through the verified Tor session.
gk.download(url, target_path)
url– HTTP(S) URLtarget_path– Full local file path (directories created automatically)
download(url, target_path)
Downloads a resource through the verified Tor session.
gk.download(url, target_path)
url– HTTP(S) URLtarget_path– Full local file path (directories created automatically)
get(url, **kwargs)
Performs a Tor-verified HTTP GET request.
response = gk.get(url, timeout=10)
Returns a standard requests.Response.
post(url, data=None, json=None, **kwargs)
Performs a Tor-verified HTTP POST request.
response = gk.post(url, json={"key": "value"})
Returns a standard requests.Response.
Design Principles
- Fail closed: no Tor → no execution
- Single verification point (during construction)
- No global state
- No logging configuration inside the library
- Session reuse without re-verification
Logging is emitted by the library, but configured by the application.
Logging
GateKeeper uses standard Python logging:
import logging
logging.basicConfig(level=logging.INFO)
The library does not call logging.basicConfig() internally.
Security Notes
- Tor exit IPs may rotate over time
- Geo information is best-effort and may be unavailable (rate-limits, CAPTCHAs)
- GateKeeper guarantees routing, not anonymity
TLS Verification
All request methods forward arguments directly to requests. If you need to interact with legacy systems that have expired or self-signed certificates, you may disable TLS verification per request:
r = gk.request(
"GET",
"https://legacy.example.com",
verify=False
)
Or for downloads:
gk.download(url, "file.bin", verify=False)
Disabling certificate verification reduces transport security and should only be used when necessary.
License
MIT License
Status
- Version: v0.2.4
- Phase 2 in progress
- API intentionally minimal
Future versions may add optional features such as:
- circuit rotation
- ControlPort support
- higher-level request helpers
Without breaking the core contract.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file protox_gatekeeper-0.2.5.tar.gz.
File metadata
- Download URL: protox_gatekeeper-0.2.5.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6447ee83782ced450aa0b2593d4737764d02e6edd5a01722f7e349e5e4a2b25
|
|
| MD5 |
a8d80574b9a78b31584fbf3ff21b99db
|
|
| BLAKE2b-256 |
7be087143f3d7030f15886e78280eae904739dee588fd1443125ffc9c6bee14a
|
File details
Details for the file protox_gatekeeper-0.2.5-py3-none-any.whl.
File metadata
- Download URL: protox_gatekeeper-0.2.5-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52b4218ad565cb4edbebdf1d1aa6f096800be7729927539aa3a49e16fc3897f2
|
|
| MD5 |
446bb2aeab30a89a2bc1a8dd38888ec3
|
|
| BLAKE2b-256 |
32cb08eac08d041f2d0382401784f1dcb79915678c273371afa0a33d6ebdb4dd
|