Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've successfully set up Tor for transparent proxying using iptables (ie, all outgoing traffic is sent through Tor without the application's knowledge). In doing so, I discovered both an odd problem and an equally odd fix (workaround?).

My rules are as follows. No user-defined chains or other rules present, all policies are ACCEPT.

-t nat -A OUTPUT -o lo -j RETURN
-t nat -A OUTPUT -p tcp -m owner --uid-owner tor -j RETURN
-t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 54
-t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 55

-A INPUT -j ACCEPT

-A OUTPUT -o lo -j ACCEPT # Rule A
-A OUTPUT -d 127.0.0.1 -j ACCEPT # Rule B
-A OUTPUT -p tcp -m owner --uid-owner tor -j ACCEPT
-A OUTPUT -j REJECT # Rule C

In other words:

  • All traffic from/to localhost is untouched.
  • All traffic generated by Tor is untouched.
  • All outgoing TCP connections are sent through Tor (transparent proxying port is 54).
  • All outgoing DNS queries are resolved by Tor (DNS on port 55).
  • To prevent leakage, all other outgoing traffic is hit on the head with a brick and dropped in a ditch.

(While this setup has some problems, like failing to respond to connections from the LAN, those are irrelevant to the issue at hand.)

If Rule B is not present, all outgoing connections are immediately rejected by Rule C. I know they are rejected by Rule C because changing the rejection type (ex. --reject-with icmp-proto-unreachable) results in a different error. Example error messages without Rule B:

# With Rule C --reject-with icmp-port-unreachable, the default:
$ curl 213.155.151.153 # (google.com; DNS also doesn't work)
curl: (7) Failed connect to 213.155.151.153:80; Connection refused

# With Rule C --reject-with icmp-proto-unreachable:
$ curl 213.155.151.153
curl: (7) Failed connect to 213.155.151.153:80; Protocol not available

With Rule B, connections work fine.

Based on my understanding of iptables, when an outgoing TCP connection is made, the third rule in OUTPUT chain of nat will rewrite the packet's destination to 127.0.0.1:54. The packet will then enter OUTPUT chain of filter, and it should be matched by Rule A, since its outgoing interface is now the loopback interface. However, it is not matched by Rule A, and if Rule B (which does match it) is not present, the packet gets dragged into an alley and mugged by Rule C.

Why aren't Rule A and Rule B equivalent? How is matching the loopback interface different from matching the loopback address, in this situation?

share|improve this question
    
Further research indicates that this may be because there is no routing decision between nat OUTPUT and filter OUTPUT. So even if the packet's destination address is altered, its outgoing interface is not updated until after filter OUTPUT. I'm not sufficiently confident to make this an answer though. –  Samuel Harada Nov 15 '13 at 1:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.