jmcore.tor_isolation
jmcore.tor_isolation
Tor stream isolation via SOCKS5 authentication.
Tor's IsolateSOCKSAuth flag (enabled by default on every SocksPort)
ensures that connections carrying different SOCKS5 username/password pairs are
routed through independent circuits. This module provides helpers that tag
each connection category with a unique credential pair so that, for example,
directory-server traffic and notification traffic never share a circuit.
No Tor configuration changes are required -- IsolateSOCKSAuth is already
the default.
References
- Tor proposal 171: https://spec.torproject.org/proposals/171-separate-streams.html
- Tails stream isolation design: https://tails.net/contribute/design/stream_isolation/
Classes
IsolationCategory
Bases: StrEnum
Well-known connection categories for stream isolation.
Each value becomes the SOCKS5 username; the password is a per-process random token so that different process instances also get distinct circuits.
Source code in jmcore/src/jmcore/tor_isolation.py
27 28 29 30 31 32 33 34 35 36 37 38 39 | |
Attributes
DIRECTORY = 'jm-directory'
class-attribute
instance-attribute
HEALTH_CHECK = 'jm-health-check'
class-attribute
instance-attribute
MEMPOOL = 'jm-mempool'
class-attribute
instance-attribute
NOTIFICATION = 'jm-notification'
class-attribute
instance-attribute
PEER = 'jm-peer'
class-attribute
instance-attribute
UPDATE_CHECK = 'jm-update-check'
class-attribute
instance-attribute
IsolationCredentials
dataclass
SOCKS5 username/password pair for stream isolation.
Source code in jmcore/src/jmcore/tor_isolation.py
48 49 50 51 52 53 | |
Attributes
password: str
instance-attribute
username: str
instance-attribute
NormalizedProxyURL
dataclass
A SOCKS5 proxy URL normalized for python-socks / httpx-socks.
The socks5h:// scheme (remote DNS via proxy) is the standard way to
request that the SOCKS proxy resolves hostnames -- required for .onion
addresses. However, python-socks (used by httpx-socks) does not
recognise the h suffix and raises ValueError.
This dataclass carries a socks5:// URL together with an rdns flag
that should be forwarded to AsyncProxyTransport.from_url(..., rdns=rdns).
Source code in jmcore/src/jmcore/tor_isolation.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
Attributes
rdns: bool
instance-attribute
Whether DNS should be resolved remotely by the proxy.
url: str
instance-attribute
Proxy URL with socks5:// scheme (never socks5h://).
Functions
build_isolated_proxy_url(host: str, port: int, category: IsolationCategory, *, resolve_dns_remotely: bool = True) -> str
Build a SOCKS5 proxy URL with stream-isolation credentials embedded.
Args:
host: SOCKS proxy host (e.g. "127.0.0.1").
port: SOCKS proxy port (e.g. 9050).
category: The isolation category for this connection.
resolve_dns_remotely: If True use socks5h:// (DNS resolved by
proxy, required for .onion addresses). If False use
socks5://.
Returns:
URL like socks5h://jm-directory:a1b2c3...@127.0.0.1:9050.
Source code in jmcore/src/jmcore/tor_isolation.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
get_isolation_credentials(category: IsolationCategory) -> IsolationCredentials
Return SOCKS5 credentials that isolate category onto its own circuit.
The username is the category tag; the password is a per-process random
token. Two connections with the same (username, password) will share
a circuit (Tor groups them), while connections with different usernames
will be isolated.
Source code in jmcore/src/jmcore/tor_isolation.py
56 57 58 59 60 61 62 63 64 | |
normalize_proxy_url(proxy_url: str) -> NormalizedProxyURL
Normalize a SOCKS5(h) proxy URL for use with httpx-socks.
Converts socks5h:// to socks5:// with rdns=True so that
AsyncProxyTransport.from_url(result.url, rdns=result.rdns) works
correctly even for .onion addresses.
Plain socks5:// URLs are returned unchanged with rdns=False.
Source code in jmcore/src/jmcore/tor_isolation.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |