Metadata-Version: 2.4
Name: protox-gatekeeper
Version: 0.2.5
Summary: Fail-closed Tor session enforcement for Python HTTP(S) traffic
Author: Tom Erik Harnes
License: MIT License
        
        Copyright (c) 2026 Tom Erik Harnes
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/ProtoXCode/protox-gatekeeper
Project-URL: Repository, https://github.com/ProtoXCode/protox-gatekeeper
Project-URL: Issues, https://github.com/ProtoXCode/protox-gatekeeper/issues
Keywords: tor,privacy,networking,security,proxy
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: pysocks
Dynamic: license-file

[![PyPI version](https://img.shields.io/pypi/v/protox-gatekeeper.svg)](https://pypi.org/project/protox-gatekeeper/)
[![Python versions](https://img.shields.io/pypi/pyversions/protox-gatekeeper.svg)](https://pypi.org/project/protox-gatekeeper/)
[![License](https://img.shields.io/pypi/l/protox-gatekeeper.svg)](https://pypi.org/project/protox-gatekeeper/)

# 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.Session` with 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

```bash
pip install protox-gatekeeper
```

### From source (development)

```bash
pip install -e .
```

(Recommended while developing or testing.)

---

## Basic Usage

```python
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:

```python
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(...)`

```python
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.

```python
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 to `requests`

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**.

```python
gk.download(url, target_path)
```

- `url` – HTTP(S) URL
- `target_path` – Full local file path (directories created automatically)

---

### `download(url, target_path)`

Downloads a resource **through the verified Tor session**.

```python
gk.download(url, target_path)
```

- `url` – HTTP(S) URL
- `target_path` – Full local file path (directories created automatically)

---

### `get(url, **kwargs)`

Performs a Tor-verified HTTP GET request.

```python
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.

```python
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:

```python
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:

```python
r = gk.request(
    "GET",
    "https://legacy.example.com",
    verify=False
)
```

Or for downloads:

```python
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.
