A LD_PRELOAD-based solution to transparently route application traffic through the Tor network using SOCKS5.
Table of Contents
- Introduction
- Features
- Architecture & How It Works
- What Is SOCKS5?
- Installation
- Usage
- Security & Privacy Considerations
- Troubleshooting
- Development & Building from Source
- Advanced Topics
- DNS Leakage
- IPv6 Details
- Intercepting Domain Names (SOCKS5 ATYP=3)
- Timeouts and Partial Reads/Writes
Toralizer aims to “torify” your networked applications by intercepting system calls (connect()
) at runtime and funneling them through Tor via a SOCKS5 proxy (by default, 127.0.0.1:9050
).
Why use Toralizer?
- You don’t have to modify the source code of the application you want to tunnel through Tor.
- You can transparently wrap programs such as
curl
,wget
, or any other dynamically-linked binaries, forcing them to route TCP connections via the Tor network. - It’s an easy-to-use script +
.so
library approach with minimal overhead.
- LD_PRELOAD Hooking: Leverages the dynamic linker’s
LD_PRELOAD
mechanism to intercept theconnect()
system call. - SOCKS5 Implementation: Communicates with Tor’s SOCKS5 interface, enabling secure and anonymous outbound connections.
- IPv4 & IPv6 Support: The hooking library checks the
sa_family
and handles bothAF_INET
(IPv4) andAF_INET6
(IPv6). - Flexible Installation:
- Local usage (no system-wide changes).
- Global installation (system-wide availability of
toralize
command).
- Optional command-line flags:
--help
,--version
,--install
,--uninstall
.
-
LD_PRELOAD:
When you setLD_PRELOAD=/path/to/toralizer.so
, the dynamic loader injects our library before the standard C library. Our implementation ofconnect()
overrides the system’s default connect function. -
Intercepting
connect()
:- Whenever an application attempts to establish a TCP connection, it calls
connect()
. - Our custom
connect()
function detects the target address and, instead, opens a new socket to your local Tor SOCKS5 proxy (127.0.0.1:9050
by default). - We then perform the SOCKS5 handshake with Tor, instructing it to connect to the original target IP and port.
- If successful, Tor returns a success code, and we
dup2()
the proxy socket onto the original file descriptor, so the application is none the wiser—it thinks it’s directly connected to the remote server.
- Whenever an application attempts to establish a TCP connection, it calls
-
Result:
All TCP traffic from that application flows through Tor. You get the anonymity benefits of Tor (though note DNS Leakage below).
SOCKS5 is a network proxy protocol widely supported by Tor. Key features:
-
Client–Server handshake:
- Greeting: The client advertises supported authentication methods (e.g., “no auth”).
- Server Response: The server picks an auth method.
- Client Connect Request: The client requests a connection to a specific hostname/IP + port.
- Server Reply: Indicates success or an error code.
-
DNS via Proxy: SOCKS5 can handle domain names (ATYP=0x03).
However, if your application callsgetaddrinfo()
first (resolving the domain to an IP locally), that IP is used in the handshake. This can cause DNS leakage. -
No Additional Encryption: SOCKS5 itself doesn’t encrypt data (beyond the TCP connection). The anonymity comes from the Tor network.
Toralizer can be used locally (no special privileges, no system changes) or globally (requires root
or sudo
).
- Build (if not pre-built). See Development & Building from Source.
- Keep
toralize.sh
andtoralizer.so
in one folder. - Run
toralize.sh your_command [args...]
to torify your desired program.
Nothing is installed to system directories. Everything remains in that local folder.
- Build or obtain the
.so
library and thetoralize.sh
script. - Run:
sudo ./toralize.sh --install
- Follow the prompt:
- Press
G
to install globally:- The script copies
toralizer.so
into/usr/local/share/toralizer/
. - Installs a new script in
/usr/local/bin/toralize
that setsLD_PRELOAD
automatically.
- The script copies
- Press
L
to do nothing (keep local).
- Press
After a successful global install, you can:
toralize curl http://check.torproject.org
No need to reference toralize.sh
or set LD_PRELOAD
manually anymore.
Run:
sudo ./toralize.sh --uninstall
This removes:
/usr/local/bin/toralize
/usr/local/share/toralizer/
In local mode:
# Use the script in the same directory as toralizer.so
./toralize.sh curl http://check.torproject.org
Behind the scenes:
LD_PRELOAD
is set totoralizer.so
.curl
’sconnect()
calls are intercepted and routed through Tor.
-
Check Tor:
./toralize.sh curl -s https://check.torproject.org
If the HTML states “Congratulations, this browser is configured to use Tor,” it worked.
-
Download a file:
./toralize.sh wget https://example.com/somefile.zip
-
SSH over Tor: Potentially:
./toralize.sh ssh user@host.example
(Note: This may have other implications, such as DNS leakage if
host.example
is resolved locally.)
--help
Displays a help message describing usage, flags, and examples.
--version
Prints the current version (e.g., 1.0.0
).
--install
Runs an interactive install process:
- Prompts whether to install globally or keep local.
- If globally installed, requires
sudo
or root, copies.so
to/usr/local/share/toralizer/
and a script to/usr/local/bin/toralize
.
--uninstall
Removes any previously installed global files.
(No flags)
Any arguments after the script are treated as the command to run with LD_PRELOAD
set.
-
DNS Leakage
If the application resolves domain names before callingconnect()
, your system’s DNS resolver is used. This means DNS requests go outside Tor, potentially revealing your real IP or location (unless your system’s DNS also goes through Tor or is otherwise anonymized). See DNS Leakage. -
Infinite Recursion
The hooking library must detect when it’s connecting to the Tor SOCKS proxy itself (127.0.0.1:9050
or[::1]:9050
) to avoid recursively hooking that connection. Our code includes a check to skip hooking in that situation. -
Partial Coverage
- Only dynamically-linked applications that use
connect()
from glibc (or similar) will be intercepted. - Statically-linked binaries bypass
LD_PRELOAD
. - Some applications may bypass standard library calls or have their own networking stack, in which case this hooking won’t work.
- Only dynamically-linked applications that use
-
System Configuration
- Ensure Tor is running locally on
127.0.0.1:9050
. - Alternatively, update
TOR_PROXY_IP
andTOR_PROXY_PORT
in the code if your Tor is bound elsewhere.
- Ensure Tor is running locally on
-
Tor not running
If you see errors likeconnect(tor-proxy): Connection refused
, ensure Tor is running and listening on127.0.0.1:9050
. -
SOCKS5 error codes (
SOCKS5 CONNECT failed, REP=0xXX
)
Common issues:- Tor’s
SocksPolicy
might be rejecting direct IP connections or a particular address range. - The remote is unreachable or blocked by Tor exit policies.
- Tor’s
-
Permission denied
Installing globally requires root/sudo. If not, you’ll see permission errors. -
Not connecting
Try a verbose approach:TORALIZER_DEBUG=1 ./toralize.sh curl -v http://check.torproject.org
(If you add debug prints to the C code, you can conditionally show them with an env variable.)
- gcc or another C compiler
- make
- libc6-dev (standard libraries/headers)
- Tor (to actually route traffic via SOCKS5)
A minimal Makefile
might look like this:
CC = gcc
CFLAGS = -Wall -Wextra -fPIC -shared -ldl -D_GNU_SOURCE
SRCS = toralize.c
TARGET = toralizer.so
all: $(TARGET)
$(TARGET): $(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
clean:
rm -f $(TARGET)
- Clone or copy the
toralize.c
andMakefile
. - Run
make
. - You should end up with
toralizer.so
.
Then you can test locally:
export LD_PRELOAD=/path/to/toralizer.so
curl http://check.torproject.org
unset LD_PRELOAD
For easier usage, use the provided toralize.sh
script.
DNS leakage occurs when an application resolves a hostname outside Tor, typically by calling getaddrinfo()
. By the time Toralizer intercepts connect()
, the OS has already performed DNS resolution.
- Solution: Use SOCKS5 domain-based resolution (ATYP=0x03) or intercept
getaddrinfo()
as well. This is more complex but ensures DNS is done via Tor.
Toralizer checks sa_family
:
- If
AF_INET6
, it uses ATYP=0x04 in the SOCKS5 handshake. - Tor must allow and handle IPv6 exits. Some Tor exit nodes don’t support IPv6, so your connection might fail if the remote site is IPv6-only and your chosen Tor exit doesn’t route IPv6.
To pass raw domain names to Tor (so Tor does the DNS resolution):
- You’d need to catch the domain before the system resolver. Typically, that means hooking
getaddrinfo()
or rewriting library calls. - Then send a SOCKS5 handshake with
ATYP=0x03
, length of domain, etc. - This is beyond the minimal example we provide, but crucial for full anonymity.
The code in toralize.c
uses simplistic recv()
and send()
loops. In production, you may want to:
- Implement timeouts to handle unresponsive or slow SOCKS5 servers.
- Handle partial reads/writes more robustly.
This project is typically distributed under an open-source license (e.g., MIT, GPL, etc.).
Replace this section with your actual license text. For example, the MIT License:
MIT License
Copyright (c) 2025 ...
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files...
- Legal Compliance: The Tor network and usage of anonymizing software may be regulated or restricted in certain jurisdictions. Ensure you comply with local laws and regulations.
- Not Bulletproof: Simply routing traffic through Tor does not guarantee perfect anonymity. Browser fingerprinting, DNS leaks, misconfigurations, or application-level data (e.g., cookies) can still deanonymize you.
- Use at Your Own Risk: I am not liable for any misuse or damages arising from its usage.
- Tor Project – Official Documentation
- SOCKS5 RFC 1928
- LD_PRELOAD Tricks
- Preventing DNS Leaks with Tor
Happy Torifying!