The issue is likely docker-proxy
. I used a small python script to illustrate this, having set up -j REDIRECT
for a user and tested it inside and outside of docker
.
The script itself looks like this:
#!/usr/bin/env python3
import socket
from struct import unpack
if __name__ == '__main__':
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0',9040))
s.listen(1)
conn, addr = s.accept()
orig = conn.getsockopt(socket.SOL_IP, 80, 16) # 80 is socket.SO_ORIGINAL_DST but python doesn't define it.
port, ip = unpack("!2xH4s8x", orig)
print('{}:{}'.format(socket.inet_ntoa(ip), port))
Then we load up our docker
ised python script, with 9040 exposed and try to curl https://check.torproject.org
from our transparently proxied user.
# docker run -it --rm --name origdest -p "9040:9040" -v "$PWD":/usr/src/myapp -w /usr/src/myapp python:3 python origdest.py
172.17.0.2:9040
We see that the docker
ised script believes the original destination is the internal container IP address, not the intended destination. Compare this to the non-docker
ised script
# python3 origdest.py
138.201.14.212:443
Transparent proxying works by Tor querying the original destination through getsockopt
. It gets it from the conntrack table in the kernel, but because docker-proxy
is forwarding on behalf of the user to the Tor running inside of the container when it tries to look up the original destination it sees it's own TransProxy
port and the connection fails.
-j REDIRECT
ed packets.-j REDIRECT
'ingdocker-proxy
.