Redirecting All Container Traffic via SOCKS Proxy Using tun2socks
Published 17.06.2025
Sometimes it becomes necessary to route all outgoing traffic from a specific container through a proxy server. This can be useful for ensuring anonymity, bypassing geo-restrictions, or for testing network configurations. In this article, we’ll look at how to set up such a system using the tun2socks utility and iptables rules, as well as how to manage this process with systemd.
What is tun2socks?
tun2socks is a powerful tool that allows you to redirect network traffic intended for a TUN device through a SOCKS proxy. It creates a virtual network interface (TUN device), and all traffic flowing through it is encapsulated into a SOCKS connection. This is especially convenient when direct application-level proxying is impossible or undesirable.
Installing tun2socks
First, we need to install tun2socks. We’ll use pre-compiled binaries from GitHub.
Go to the tun2socks releases page: https://github.com/xjasonlyu/tun2socks/releases
Select the latest stable version and download the appropriate archive for your architecture (e.g.,
tun2socks-linux-amd64.tar.gz
for 64-bit Linux systems).Unpack the archive and move the executable file to a system path, for example,
/usr/local/bin/
:# Example for linux-amd64, replace version with the actual one wget https://github.com/xjasonlyu/tun2socks/releases/download/v2.5.1/tun2socks-linux-amd64.tar.gz tar -xvf tun2socks-linux-amd64.tar.gz sudo mv tun2socks-linux-amd64/tun2socks /usr/local/bin/tun2socks sudo chmod +x /usr/local/bin/tun2socks
Make sure the path to the binary in your script matches the actual one. In our example, it’s
/usr/local/bin/tun2socks
.
Traffic Redirection Script
Now, let’s look at the script that automates the process of setting up the TUN device, iptables, and starting tun2socks.
Important note: For correct operation with systemd, we’ll slightly modify the script so that tun2socks
runs in the background, allowing the script to exit while systemd manages the tun2socks
process.
#!/bin/bash
set -euo pipefail
# Configuration
TUN_DEV="tun0" # TUN device name
TUN_ADDR="10.0.0.2/24" # IP address for the TUN device
FWMARK="100" # Mark for traffic
ROUTE_TABLE="100" # Routing table number
CONTAINER_IP="172.29.172.2" # IP address of your container whose traffic needs to be redirected
SOCKS_PROXY="socks5://username:[email protected]:yyyy" # SOCKS5 proxy address (with authentication)
TUN2SOCKS_BIN="/usr/local/bin/tun2socks" # Path to the tun2socks executable
# Path to the PID file that systemd will use
PID_FILE="/var/run/tun2socks.pid"
# Function to clean up rules
cleanup() {
echo "[INFO] Cleaning up old routes and iptables..."
# Delete rules in reverse order of creation
iptables -t nat -D POSTROUTING -o "$TUN_DEV" -j MASQUERADE 2>/dev/null || true
iptables -t mangle -D PREROUTING -s "$CONTAINER_IP" -p tcp -j MARK --set-mark "$FWMARK" 2>/dev/null || true
ip route flush table "$ROUTE_TABLE" 2>/dev/null || true
ip rule del fwmark "$FWMARK" table "$ROUTE_TABLE" priority "$FWMARK" 2>/dev/null || true
ip link set "$TUN_DEV" down 2>/dev/null || true
ip tuntap del dev "$TUN_DEV" mode tun 2>/dev/null || true
# Remove PID file
rm -f "$PID_FILE" 2>/dev/null || true
}
# Check command line arguments
if [ "$#" -eq 1 ] && [ "$1" == "cleanup_only" ]; then
cleanup
echo "[INFO] Cleanup complete."
exit 0
fi
# Call cleanup at startup to ensure cleanliness, unless in cleanup_only mode
cleanup
echo "[INFO] Creating $TUN_DEV..."
ip tuntap add dev "$TUN_DEV" mode tun
ip addr add "$TUN_ADDR" dev "$TUN_DEV"
ip link set "$TUN_DEV" up
echo "[INFO] Configuring ip rule and iptables..."
ip rule add fwmark "$FWMARK" table "$ROUTE_TABLE" priority "$FWMARK"
ip route replace default dev "$TUN_DEV" table "$ROUTE_TABLE"
iptables -t mangle -A PREROUTING -s "$CONTAINER_IP" -p tcp -j MARK --set-mark "$FWMARK"
iptables -t nat -A POSTROUTING -o "$TUN_DEV" -j MASQUERADE
echo "[INFO] Starting tun2socks..."
"$TUN2SOCKS_BIN" \
--device "$TUN_DEV" \
--proxy "$SOCKS_PROXY" \
--nohup \
--log-level info &
# Save tun2socks PID for systemd
echo $! > "$PID_FILE"
echo "[INFO] Setup complete. tun2socks is running."
Script Breakdown
Let’s break down what each part of the script does:
Configuration
At the beginning of the script, key variables are defined:
- TUN_DEV: The name of the virtual network interface (e.g.,
tun0
). - TUN_ADDR: The IP address and subnet mask that will be assigned to
TUN_DEV
. This address will be used as the gateway for the container. - FWMARK: An arbitrary numerical mark that will be used to tag packets intended for redirection.
- ROUTE_TABLE: The number of a custom routing table where marked traffic will be directed.
- CONTAINER_IP: Crucial parameter! This is the IP address of your container whose traffic you want to redirect. You’ll need to find it.
- SOCKS_PROXY: The full address of your SOCKS5 proxy, including protocol, username, password, and port.
- PID_FILE: The path to the file where the PID of the
tun2socks
process will be written for systemd to track.
Cleanup Function
The cleanup()
function is responsible for removing all previously created iptables
rules, routes, and the TUN device itself. This is important to ensure a “clean” state before each new setup and when stopping the service. It also removes the PID file.
Startup and Cleanup Logic
The script checks command-line arguments. If it’s run with the cleanup_only
argument, it only executes the cleanup
function and exits. Otherwise, it first cleans up previous settings and then proceeds to create new ones.
Creating the TUN Device
ip tuntap add dev "$TUN_DEV" mode tun
: Creates a new TUN interface with the specified name.ip addr add "$TUN_ADDR" dev "$TUN_DEV"
: Assigns an IP address to the created TUN interface.ip link set "$TUN_DEV" up
: Activates the TUN interface.
Configuring ip rule and iptables
This is the core of the traffic redirection mechanism:
ip rule add fwmark "$FWMARK" table "$ROUTE_TABLE" priority "$FWMARK"
: Creates a routing rule that states: “any packet with markFWMARK
must be processed using routing tableROUTE_TABLE
.” TheFWMARK
priority ensures this rule is considered before others.ip route replace default dev "$TUN_DEV" table "$ROUTE_TABLE"
: Within our specialROUTE_TABLE
, we set a default route that points to our TUN device. This means all traffic that enters this table will be directed throughTUN_DEV
.iptables -t mangle -A PREROUTING -s "$CONTAINER_IP" -p tcp -j MARK --set-mark "$FWMARK"
: This is aniptables
rule in thePREROUTING
chain (which processes packets before they go through routing) in themangle
table (which is used for modifying packets). It says: “if a TCP packet originates fromCONTAINER_IP
, mark it withFWMARK
.” This is how we identify the traffic that needs to be redirected.iptables -t nat -A POSTROUTING -o "$TUN_DEV" -j MASQUERADE
: This rule is in thenat
table in thePOSTROUTING
chain (which processes packets immediately before they are sent out). It performs masquerading (SNAT), meaning it changes the source IP address of outgoing packets passing throughTUN_DEV
to the IP address associated withTUN_DEV
. This is necessary for the proxy to work correctly.
Starting tun2socks
"$TUN2SOCKS_BIN" --device "$TUN_DEV" --proxy "$SOCKS_PROXY" --nohup --log-level info &
: Startstun2socks
itself. It binds to the createdTUN_DEV
and uses the specifiedSOCKS_PROXY
to redirect all traffic that arrives atTUN_DEV
. The--nohup
flag allowstun2socks
to continue running even after the parent process (the script) exits, and&
runs it in the background.--log-level info
is useful for debugging.echo $! > "$PID_FILE"
: Saves the PID of the just-launched backgroundtun2socks
to a file so systemd can track it.
How to Use (with systemd)
Now that the script is ready, we can integrate it with systemd for convenient management.
Save the script: Create a file, for example,
/usr/local/bin/tun2socks_redirect.sh
, and paste the modified script content into it.sudo nano /usr/local/bin/tun2socks_redirect.sh
Make it executable:
sudo chmod +x /usr/local/bin/tun2socks_redirect.sh
Identify the container’s IP address: If you’re using Docker, you can find the container’s IP address by running
docker inspect <container_name> | grep "IPAddress"
.Update CONTAINER_IP and SOCKS_PROXY: Make sure to change the values of
CONTAINER_IP
andSOCKS_PROXY
in the/usr/local/bin/tun2socks_redirect.sh
script to your own.
Creating the Systemd Unit File
Let’s create a systemd unit file for our service.
Create the file
/etc/systemd/system/tun2socks-redirect.service
:sudo nano /etc/systemd/system/tun2socks-redirect.service
Paste the following content:
[Unit] Description=Tun2socks Traffic Redirection Service After=network-online.target Wants=network-online.target [Service] Type=forking # Use Type=forking because our script starts tun2socks in the background # and then exits. tun2socks itself daemonizes (thanks to --nohup). # PIDFile is used to track the tun2socks PID. PIDFile=/var/run/tun2socks.pid ExecStartPre=/usr/local/bin/tun2socks_redirect.sh # ExecStart is the command systemd will track. # Since our script starts tun2socks in the background, systemd will monitor tun2socks via PIDFile. ExecStart=/bin/true # ExecStopPost runs after the service exits, for cleanup ExecStopPost=/usr/local/bin/tun2socks_redirect.sh cleanup_only # User=root - because the script requires root privileges User=root Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
Explanations for the Unit File:
- [Unit]:
Description
: A brief description of the service.After=network-online.target
: The service will start after the network is fully configured.Wants=network-online.target
: Indicates a desired dependency on the network.
- [Service]:
Type=forking
: Informs systemd that the main service process will “fork” a child process (our tun2socks), and the parent process (the script) will exit. systemd will usePIDFile
to track the true service process.PIDFile=/var/run/tun2socks.pid
: The path to the file where our script saves the PID of the running tun2socks. This is critical forType=forking
.ExecStartPre=/usr/local/bin/tun2socks_redirect.sh
: A command that runs before the main service starts. Here, our script sets up the TUN device and iptables rules, and also starts tun2socks in the background.ExecStart=/bin/true
: Since tun2socks is already started by ourExecStartPre
script and systemd tracks it viaPIDFile
, we don’t need to start anything else inExecStart
./bin/true
simply returns a successful exit code.ExecStopPost=/usr/local/bin/tun2socks_redirect.sh cleanup_only
: A command that runs after the service stops. When called with thecleanup_only
argument, the script only cleans up the rules.User=root
: The service must run as root, as it modifies network settings and iptables rules.Restart=on-failure
: If the service exits with an error, systemd will attempt to restart it.RestartSec=5s
: Delay before attempting a restart.
- [Install]:
WantedBy=multi-user.target
: The service will be started during system boot in multi-user mode.
Enabling and Starting the Systemd Service
After creating the Unit file and refining the script:
Reload the systemd daemon:
sudo systemctl daemon-reload
Enable the service for automatic startup on boot:
sudo systemctl enable tun2socks-redirect.service
Start the service:
sudo systemctl start tun2socks-redirect.service
Check the service status:
sudo systemctl status tun2socks-redirect.service
You should see that the service is active (
active (running)
).Check the logs:
journalctl -u tun2socks-redirect.service -f
This will help you monitor the output of the script and tun2socks.
Now, your service will automatically start when the system boots and will attempt to keep tun2socks
and the routing rules operational. To stop the service, use sudo systemctl stop tun2socks-redirect.service
, and it will automatically clean up the rules. To restart, use sudo systemctl restart tun2socks-redirect.service
.
Conclusion
Thus, we have configured a system that redirects all TCP traffic from a specified container through a SOCKS proxy server. This method provides flexibility and control over network traffic, allowing you to easily manage its routing through external proxy services, and integration with systemd significantly increases reliability and ease of management.
I hope this article was helpful! If you have any questions or suggestions, feel free to leave comments.
Get in Touch
Ready to discuss your project and offer the best solution