Relay traffic through OpenVPN to Tor inside docker container

I would like to have a VPN service that relays traffic through Tor. I setup services via docker by using following images with little changes for Tor making listen it on external interface instead of localhost as it’s done by original image.

I defined a docker network that is shared among these containers (openvpn, tor). Then according to this tor manual I added iptables rules to make traffic pass from OpenVPN tun0 to Tor host (docker container). In original the REDIRECT target is used to redirect to localhost. I replaced it with DNAT to redirect to separate host.

So, Tor listens on *:5353 for DNS and *:9040 for TCP inside docker container having IP 172.19.0.2 for eth0. OpenVPN host eth0 IP address is 172.19.0.3. Inside openvpn container iptables nat table looks like.

#  iptables -t nat -vL
Chain PREROUTING (policy ACCEPT 71 packets, 24535 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 9116  547K DNAT       tcp  --  tun0   any     192.168.255.0/24     anywhere             tcp flags:FIN,SYN,RST,ACK/SYN to:172.19.0.2:9040
  145  9500 DNAT       udp  --  tun0   any     192.168.255.0/24     anywhere             udp dpt:domain to:172.19.0.2:5353

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 60 packets, 4212 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  341 23987 DOCKER_OUTPUT  all  --  any    any     anywhere             127.0.0.11          

Chain POSTROUTING (policy ACCEPT 120 packets, 8424 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  341 23987 DOCKER_POSTROUTING  all  --  any    any     anywhere             127.0.0.11          
18337 1238K MASQUERADE  all  --  any    eth0    192.168.255.0/24     anywhere            
    0     0 MASQUERADE  all  --  any    eth0    192.168.254.0/24     anywhere            

Chain DOCKER_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  any    any     anywhere             127.0.0.11           tcp dpt:domain to:127.0.0.11:46653
  341 23987 DNAT       udp  --  any    any     anywhere             127.0.0.11           udp dpt:domain to:127.0.0.11:44292

Chain DOCKER_POSTROUTING (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 SNAT       tcp  --  any    any     127.0.0.11           anywhere             tcp spt:46653 to::53
    0     0 SNAT       udp  --  any    any     127.0.0.11           anywhere             udp spt:44292 to::53

The only change I made is two first rules that I added to the PREROUTING chain. Commands for these are:

iptables -t nat -A PREROUTING -i tun0 -p udp -s 192.168.255.0/24 --dport 53 -j DNAT --to-destination 172.19.0.2:5353
iptables -t nat -A PREROUTING -i tun0 -p tcp -s 192.168.255.0/24 --syn -j DNAT --to-destination 172.19.0.2:9040

After that DNS works fine. The issue is with TCP. The connection can be established, but there is no data response from remote side at all. The connection is just closed. E.g. the tcpdump of wget http://check.torproject.org looks like this. The origin host (192.168.255.6) is my workstation connected to the OpenVPN I’m trying to setup.

enter image description here

Iptables filter table chains are empty and have ACCEPT policy. Also I looked through similar posts on Server Fault and etc. (with the difference that they REDIRECT to localhost) and still have no idea how to resolve this. It’s Alpine Linux. Connection tracking is enabled I see the connection via conntrack tool, it’s closed immediately.

It looks like server reply packets where TCP flags (SYN, ACK etc.) are clear are not Un-DNATed that leads to source address (172.19.0.2) is not replaced with check.torproject.org’s actual IP (138.201.14.212) somehow.

Tor configuration is as follows

# cat /etc/torrc 
VirtualAddrNetworkIPv4 10.192.0.0/10
AutomapHostsOnResolve 1
TransPort 0.0.0.0:9040
DNSPort 0.0.0.0:5353

Routing table is

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.19.0.1      0.0.0.0         UG    0      0        0 eth0
172.19.0.0      *               255.255.0.0     U     0      0        0 eth0
192.168.254.0   192.168.255.2   255.255.255.0   UG    0      0        0 tun0
192.168.255.0   192.168.255.2   255.255.255.0   UG    0      0        0 tun0
192.168.255.2   *               255.255.255.255 UH    0      0        0 tun0

Where am I wrong?

And the minor question is I can’t realize how does Tor figure out what host to send packet to if original destination is replaced with it’s IP (172.19.0.2)? It would be great if someone cleared up this for me.

Source: StackOverflow