Hi everybody,
Michael Sonntag has extended the patch below to make it configurable and tested it on a separate instance here in Linz. Seems to work for our use case. If that seems a good option, then we'd like to request review for upstream inclusion.
------------------------------------------------------------------------------------------ Explanation of the patch: * Two new configuration options, but retain the old option for compatibility. Old configurations therefore remain fully valid. Configuration parsing is therefore a bit long, but not complex. * Ease of update: The old and new options can exist simultaneously, as long as they are for different protocols (IPv4 or IPv6) * Resiliency: If one address is missing, the other is substituted. Things should work at least somehow, even if some configuration is absent. Use the default only if no configuration for output traffic exists at all. * New function introduced for selecting the address to bind to, to factor out this logic. * Changes to other places the address was used before (policies.c and test_policy.c). * Documentation of new options and sample configuration added ------------------------------------------------------------------------------------------
best regards, Rene
On 2016-09-26 00:54, teor wrote:
I'm not sure if we want to tag Tor traffic with QoS values at Exits. Any tagging carries some degree of risk, because it makes traffic look more unique. I'm not sure how much of a risk QoS tagging represents.
I would prefer to add config options OutboundBindAddressOR and OutboundBindAddressExit, which would default to OutboundBindAddress when not set. (And could be specified twice, once for IPv4, and once for IPv6.)
The one concern I have about this is that Tor-over-Tor would stick out more, as it would look like Tor coming out the OutboundBindAddressExit IP. But we don't encourage Tor-over-Tor anyway.
I'd recommend a patch that modifies this section in connection_connect to use OutboundBindAddressOR and OutboundBindAddressExit, preferably with the Exit/OR/(all) and IPv4/IPv6 logic refactored into its own function.
if (!tor_addr_is_loopback(addr)) { const tor_addr_t *ext_addr = NULL; if (protocol_family == AF_INET && !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) ext_addr = &options->OutboundBindAddressIPv4_; else if (protocol_family == AF_INET6 && !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) ext_addr = &options->OutboundBindAddressIPv6_; if (ext_addr) { memset(&bind_addr_ss, 0, sizeof(bind_addr_ss)); bind_addr_len = tor_addr_to_sockaddr(ext_addr, 0, (struct sockaddr *) &bind_addr_ss, sizeof(bind_addr_ss)); if (bind_addr_len == 0) { log_warn(LD_NET, "Error converting OutboundBindAddress %s into sockaddr. " "Ignoring.", fmt_and_decorate_addr(ext_addr)); } else { bind_addr = (struct sockaddr *)&bind_addr_ss; } } }
Ideally, we would use 2 different providers to even further compartmentalize "incoming" (i.e. encrypted Tor network) from "outgoing" (for our exit node, mostly clearnet) traffic and make traffic correlation harder (doesn't help against a global adversary as we know, but at least a single ISP would not be able to directly correlate both sides of the relay). Although we don't have two different providers at this point, we still use two different network interfaces with associated IP addresses (one advertised as the Tor node for incoming traffic, and the other one with the default route assigned for outgoing traffic).
This sounds like an interesting setup. I'd be keen to see how it works out.
Some Exit providers (typically with their own AS) peer with multiple other providers, because this makes it harder for a single network tap to capture all their traffic.
Not quite the same as your setup, because OR and Exit traffic goes over all the links, rather than each going over a separate link.
... [The patch] Currently, both (clearnet) exit traffic as well as encrypted Tor traffic (to other nodes and hidden services) will use the outgoing interfaces, as the Tor daemon simply creates TCP sockets and uses the default route (which points at the outgoing interface). A patch as suggested by grarpamp above could solve that issue. In the meantime, we have created a slightly hacky patch as attached. The simplest way to only record exit traffic and separate that from outgoing Tor traffic seemed to mark those packets with a ToS value - which, as far as we can see, can be done with a minimally invasive patch adding that option at a single point in connection.c. At the moment, we use this ToS value in a filter expression at the monitoring server to make sure that we do not analyze outgoing Tor traffic. We also plan to also use it for policy routing rules at the Linux kernel level to send outgoing Tor traffic back out the "incoming" interface (to distinguish between Tor traffic and clear traffic). When that works, the ToS flag can actually be removed again before the packets leave the Tor node.
Binding to different IP addresses can also be used for filtering and traffic redirection. Does having separate bind addresses for OR and Exit traffic work for your use case?