send traffic from docker containers through tor

this can offer a bit of extra protection against your tor hidden service being accidentally deanonymized by unsafe server software. however, keep in mind that docker is not a security device and can be escaped from if you're not careful.

hi says
if you do not need the docker part, it may be better to use orjail, which does a similar thing but using network namespaces directly instead of relying on docker
lacks ipv6 support. as of [2023-11-29 Wed] docker hides ipv6 behind an "experimental" config parameter. ipv6 also depends on icmp so it cannot just be dropped

make a docker network

docker network create tor --subnet 10.42.0.0/24

have tor listen for connections

TransPort 10.42.0.1:9040
DNSPort 10.42.0.1:5353

should be added to your torrc, then restart it

add iptables rules

iptables -t nat -I PREROUTING -s 10.42.0.0/24 -p tcp --syn -j REDIRECT --to-ports 9040
iptables -t nat -I PREROUTING -s 10.42.0.0/24 -p udp -j REDIRECT --to-ports 5353
iptables -I DOCKER-USER -s 10.42.0.0/24 -p tcp --syn --dst 10.42.0.1 -j DROP
iptables -I DOCKER-USER -s 10.42.0.0/24 -p icmp -j DROP

this sends all tcp traffic over tor, and since tor does not support udp, it sends all udp traffic to tor's dns resolver (which amusingly means that any routable ip can resolve dns). icmp also cannot be sent over tor, so just drop it.

hi says
this blocks opening direct connections to the host. if you do want to allow that, change -I DOCKER-USER to -t nat -I PREROUTING and DROP to ACCEPT on the third line.

it can also be made into a systemd oneshot service, ensuring that it'll still work after rebooting

[Unit]
Description=add iptables rules
After=docker.service
Before=tor.service

[Service]
Type=oneshot
ExecStart=iptables -t nat -I PREROUTING -s 10.42.0.0/24 -p tcp --syn -j REDIRECT --to-ports 9040
ExecStart=iptables -t nat -I PREROUTING -s 10.42.0.0/24 -p udp -j REDIRECT --to-ports 5353
ExecStart=iptables -I DOCKER-USER -s 10.42.0.0/24 -p tcp --syn --dst 10.42.0.1 -j DROP
ExecStart=iptables -I DOCKER-USER -s 10.42.0.0/24 -p icmp -j DROP
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

connect a container to the network

use the --network flag during docker run, or you can add an existing container with docker network connect

docker network connect tor yourcontainerid

(replacing yourcontainerid with the container id that you want to send through tor)