This appears to be due to a8835170 on 4 Feb 2015, released in 0.2.6.3-alpha.
Also in the same commit, connection_ap_get_original_destination doesn't have any code to call destination_from_socket when TRANS_TPROXY is defined. This is most likely a bug, too.
It's based on maint-0.2.6 and split it into several commits, in order of importance:
Make connection_ap_get_original_destination & destination_from_socket work with TRANS_TPROXY
Make destination_from_socket only call the TRANS_PF code under TPT_PF_DIVERT
Clean up error handling and logging code
There's still some duplicate getsockname code in destination_from_socket, split off into legacy/trac#18105 (moved) (it's tough to get rid of, and not worth backporting).
Trac: Keywords: N/Adeleted, 026-backport, 027-backport added Milestone: N/Ato Tor: 0.2.8.x-final Status: new to needs_review Version: N/Ato Tor: 0.2.6.3-alpha
Can somebody test this patch on an OpenBSD box with TPROXY?
Tor's source says that TPROXY is a Linux-specific feature. Did we get that wrong?
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {#if !defined(__linux__) REJECT("TPROXY is a Linux-specific feature.");#else options->TransProxyType_parsed = TPT_TPROXY;#endif
It appears to me that TPROXYing only works for me when connection tracking is active. When I apply the patch TPROXYing works for me no matter if conntection tracking is active or not.
Steps to reproduce:
Make sure no conntrack modules are loaded.
lsmod | grep conntrack
should print nothing.
Flush your firewall rules:
iptables -t raw -F
iptables -t mangle -F
iptables -t nat -F
iptables -t filter -F
You also want to make sure the default policy is set to ACCEPT for your chains:
iptables -t filter -P INPUT ACCEPT
iptables -t filter -P OUTPUT ACCEPT
and so on...
Setup TPROXYing with iptables:
iptables -t mangle -A PREROUTING -m socket --transparent -j ACCEPT
Start Tor with the following config:
SOCKSPort 0
TransPort 9052 IsolateClientProtocol IsolateDestAddr
TransProxyType TPROXY
DNSPort 9053
AutomapHostsOnResolve 1
Log notice stdout
DataDirectory /tmp/tor
User tor
tor -f ./
[notice] Opening DNS listener on 127.0.0.1:9053
[notice] Opening Transparent pf/netfilter listener on 127.0.0.1:9052
Verify traffic to 127.192.0.0/10 is routed properly to localhost (should always be):
ip route get to 127.192.0.0/10 from 127.0.0.1
local 127.192.0.0 from 127.0.0.1 dev lo uid 0
cache
Ask Tor to automap an onion for us:
drill -p 9053 duskgytldkxiuqc6.onion @127.0.0.1
Make sure no conntrack modules are loaded (or more precisely: connection tracking is not active for the path to 127.192.0.0/10), otherwise curl will succeed! Use the IP address reported by drill.
curl 127.192.A.B
Tor will report:
[warn] getsockopt() failed: No such file or directory
[warn] Fetching original destination failed. Closing.
Call curl again but this time with loaded conntrack modules.
modprobe nf_conntrack_ipv4
curl 127.192.A.B
It should succeed now.
Looking at the code it seems that getsockopt() is called. The patch activates a code path where getsockname() is called instead which seems to make it work even if no connection tracking is active. Maybe the author of that code can shed more light into that?
It appears to me that TPROXYing only works for me when connection tracking is active. When I apply the patch TPROXYing works for me no matter if conntection tracking is active or not.
...
Looking at the code it seems that getsockopt() is called. The patch activates a code path where getsockname() is called instead which seems to make it work even if no connection tracking is active. Maybe the author of that code can shed more light into that?
I think the behaviour you describe is what we want.
I re-wrote the code to make it behave consistently and improve how it was structured back in early 2016.
I don't know enough about transparent proxying to say anything else with any confidence.
Hm. Okay, I will need some confirmation about what to actually merge and what has actually been tested. Teor's branch? The small patch from d4fq0fQAgoJ above? Both? Neither?
I've been using the patched version (0001-trans_tproxy.patch) with a TPROXY iptables setup since I commented here and so far it's been working as expected for me.
The only real documentation about the TPROXY feature I found is from the kernel documentation (Documentation/networking/tproxy.txt). Unfortunately it does not say anything about getsockname() or getsockopt(SO_ORIGINAL_DST).
It seems that the TPROXY kernel feature enables transparent proxy capabilities without the need to DNAT (what else would be it's purpose then?). The above experiment backs this up because TPROXYing works without conntrack kernel modules loaded (conntracking is required for NAT). This only works with the above patch applied which utilizes getsockname() instead of getsockopt(SO_ORIGINAL_DST). Therefore it seems that getsockname() is the correct way.
Okay, sounds good. I've put your patch in a new branch bug18100_029 in my public repository, along with a commit message and a changes file. I'm merging it into master now. If nothing goes wrong (and I don't expect it will) we can backport to 0.2.9 and 0.3.0. Thanks!
Trac: Milestone: Tor: 0.3.1.x-final to Tor: 0.3.0.x-final Keywords: nickwants029, tor-03-unspecified-201612, lorax, isaremoved deleted, 029-backport 030-backport added Status: merge_ready to needs_review