Get different Tor IP address for each connection

Hi,

I am looking for a way to connect via curl to hosts using different Tor exit IP address:

  • for each destination host
  • for each individual connection (session) to the same site

with the idea to improve anonymity by reducing the possibility to correlate activity.

So far, on my GNU/Linux systems, I have been doing it this way:

/etc/tor/torrc:

SocksPort 9050 IsolateClientProtocol IsolateDestAddr
...
ExcludeExitNodes {some},{countries},{i don't want to be related to},{??}
StrictNodes 1

and in the curl calls I used:

curl --proxy socks5h://<user>:<pass>@127.0.0.1:9050 ...

where user and pass are different for each call.

Now, in Qubes OS I created a new qube and set sys-whonix as its Net qube. When testing, I found out that a direct curl call without special options (like --proxy) does use Tor indeed. However, the exit IP address I get for all sites seems to be the same. Additionally, I can’t use the socks5h://user:pass approach because curl refuses the connection by failing to connect to 127.0.0.1. Obviously, a different approach is necessary but even after digging the web for 2 hours I could not find my way.

So, what is the correct way to do this in Qubes OS? (hopefully without influencing other qubes which would not work well with it)

Qubes OS provides both the Whonix-Gateway (sys-whonix) and the Whonix-Workstation (anon-whonix and whonix-workstation-16-dvm). See the Whonix documentation on how to install and configure them.

Within the Whonix-Workstation, curl is stream-isolated by default.

You can simply:

curl <URL>

to get the stream isolation protections.

1 Like

I have chosen to install whonix during Qubes OS installation. This documentation says that the right way to anonymize a qube is to simply set it’s NetVM to sys-whonix - that is exactly what I have done. Unfortunately, it does not provide stream isolation. Does it mean the documentation is wrong/incomplete, or that there is a bug? I don’t know.

You seem to suggest to run curl inside whonix-ws itself. I am still learning about Qubes OS and I am careful not to mess up any installation-created qube by doing “my stuff” inside of it. IOW I still don’t know what is the purpose of whonix-ws.

The documentation about multiple whonix-workstation says all one needs to do is:

  1. Create a qube using whonix-ws-16 as a template
  2. Make sure it uses sys-whonix as net qube

Is using whonix-ws as a template (instead of fedora, as I have done so far) the key? If ‘yes’, does that mean that qubes based on other (non whonix-ws) templates cannot be stream isolated? Or, if they can - how?

I hope you can clarify.

Use 10.152.152.10. (That’s where port 9050 on 127.0.0.1 would automatically be redirected to, in a whonix-ws-based VM.)

Sort of: uwt isolates a program (e.g. curl) from other programs, but not from other invocations of the same program in the same VM. TORSOCKS_ISOLATE_PID=1 curl should work though. You’re right, /etc/tor/torsocks.conf already has IsolatePID 1.

1 Like

The linked documentation contains instructions on how to tunnel a non-Whonix qube’s network traffic through Tor. While it is easy to tunnel the network of an app qube based on Fedora or Debian through Tor, it does not provide the same protection as using an app qube based on Whonix tunneled through Tor.

Correct. Fedora and Debian based app qubes are not designed to be “Tor-aware.” They will not take advantage of features such as stream isolation.

You should run curl in an app qube based on a Whonix-Workstation template. The app qube should have its netvm set to a service qube that is based on the Whonix-Gateway template.

Yes. If the initial installation of Qubes OS setup Whonix for you, you should have a red app qube called “anon-whonix.”

Open up Qubes Tools > Qube Manager from the menu to list all your qubes.

In my case, the default Whonix installation created a red app qube called “anon-whonix.” Within anon-whonix is where curl should be run for stream isolation.
Anon-whonix is based on the whonix-ws-16 (workstation) template. It’s netvm is set to “sys-whonix.”
Further down is the black app qube “sys-whonix.” This is the service qube that takes the network traffic it receives and tunnels it through Tor. It is based on the whonix-gw-16 (gateway) template.

In summary:
Use “anon-whonix” as an example of an app qube that should be used for a Tor related workspace.

1 Like

@rustybird Thank you for looking into that.

Based on this documentation, I ran a similar command to test curl within an unmodified Whonix-Workstation app qube.

scurl --silent "https://check.torproject.org/" | grep IP

It produced a different IP address with each invocation.

1 Like

Thank you guys.

Here are my results:

Use 10.152.152.10. (That’s where port 9050 on 127.0.0.1 would automatically be redirected to, in a whonix-ws-based VM.)

In the fedora based VM the result is:

curl: (97) Unable to receive initial SOCKS5 response.

Adding port number 9050 in the call works fine.

In a whonix-ws based VM (which I have just created) the result is:

curl: (7) Couldn't connect to server

Adding port number 9050 does not change the result.

fedora based vm:

TORSOCKS_ISOLATE_PID=1 curl https://ipinfo.io/ip
TORSOCKS_ISOLATE_PID=0 curl https://ipinfo.io/ip

always show the same IP address.

whonix-ws based vm:

TORSOCKS_ISOLATE_PID=1 curl https://ipinfo.io/ip shows a different IP address on each call.
TORSOCKS_ISOLATE_PID=0 curl https://ipinfo.io/ip always shows the same IP address.

Questions:

  1. How do you know this IP address: 10.152.152.10?
  2. Are there any other useful IP addresses I can read about?
  3. What is your advice regarding using other SocksPorts (9051, 9052 etc) which seem set in whonix in relation to this thread?
  4. Without the ability to lock the used stream using a user:pass for an explicit socks5h proxy connection in the whonix-ws based VM (which is obviously the one I should use) it is not clear how one can make sure that certain connections are within the same stream. Suppose a scenario in which one needs to make sequential calls to the same host (e.g. as in a session or for some other reason) within the same stream. TORSOCKS_ISOLATE_PID=0 does lock the IP address but it cannot give isolated streams to the same host. So, how should that be done?

In a whonix-ws based VM use 127.0.0.1 (and maybe bypass uwt), otherwise 10.152.152.10. Either way always include the port number, so that it doesn’t default to the conventional Socks port 1080.

That variable does nothing in Fedora, where curl etc. are not wrapped with torsocks by default.

https://github.com/Whonix/qubes-whonix/blob/master/lib/systemd/system/qubes-whonix-redirect-9050.service

A notable alternative port is 9150, which in whonix-gw based VMs uses isolation flags “like Tor Browser” (IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth ExtendedErrors), compared to port 9050 which uses the default isolation without any added flags.

1 Like

Thank you @rustybird!

Is this how we are supposed to learn about things like 10.152.152.10? By reading the source code? :slight_smile:

So, after figuring the way to have a different IP address for both fedora and whonix-ws based VM, what is the difference between using:

a) Simply running curl in a whonix-based VM
b) Running curl --proxy socks5h://user:pass@10.152.152.10 in a fedora-based VM,

considering that I would also like to add other options to curl (HTTP headers etc.)?

Would a) and b) be equivalent anonymity- and stream isolation-wise? Or has any of them dis/advantages?

Hmm maybe it’s documented somewhere on the Whonix wiki.

The only difference I can think of is that a) is probably more like socks5:// instead of socks5h:// (which would be observable for the exit node and, due to timing, for the website). And of course, different curl versions in different OSs.

The only difference I can think of is that a) is probably more like socks5:// instead of socks5h://

AFAIK socks5h:// makes the SOCKS proxy also resolve the hostname. Why would the whonix-based VM resolve it not through SOCKS (= not through Tor)?

Both would go through the Tor network if the VM has a whonix-gw based netvm. The difference is that using socks5h:// to download https://example.com makes a request to the exit node for something like “connect me to example.com on port 443”, whereas socks5:// (or transparently torified, or torified via torsocks e.g. through the uwt wrapper) makes two requests to the exit note: "what is the IP address for example.com", then “connect me to <that IP address> on port 443”

You can observe this in the whonix-gw based netvm’s Onion Circuits application.

But how would socks5h:// connect me to example.com without knowing (having a cache) or asking for its IP address? Even if that is somehow possible (e.g. through some secondary/implicit resolving), it is still unclear to me if a) or b) is better or worse along the lines of anonymity.

Sorry for so many questions but you really caught my interest :slight_smile:

The Tor protocol allows you to ask an exit node to connect to a hostname, in which case the exit node resolves the IP address on its end and connects to the result (but doesn’t tell you what that result was).

Neither per se, but it’s a difference in behavior and as such it’s fingerprintable from the view of the exit node as well as the website. That aside, socks5h:// is more elegant.

1 Like

Thank you for explaining.

Considering:

The Tor protocol allows you to ask an exit node to connect to a hostname, in which case the exit node resolves the IP address on its end and connects to the result (but doesn’t tell you what that result was).

do you think it can also be considered more secure to use socks5h://, as leaving the DNS resolving to the exit node (which may be compromised in some way) may have unexpected consequences?

The exit node has to resolve the hostname to an IP address either way…

If you use TLS (by downloading from https://example.com instead of http://example.com) then that would ensure the integrity of the connection.

The exit node has to resolve the hostname to an IP address either way…

Then what is more elegant about using socks5h://?

It uses one combined resolve-and-connect step instead of two separate steps, so latency is a bit lowered by avoiding one round trip, and there’s less opportunity for failure. Also, when you’re making two separate Tor protocol requests for each step, those two requests could be split across two circuits, possibly even ending in two different exit nodes - which doesn’t seem ideal. Although I have no idea how often that happens in practice.

1 Like

Thank you.
You know so much. Where can I educate myself about these things?

Oh thanks, those are bits and pieces I’ve picked up chaotically over time…

One thing that’s been useful to get some ground truth about circuit use is to play around with a Tor control port connection. E.g. tor-ctrl -w SETEVENTS CIRC STREAM in sys-whonix - and then trying all kinds of different requests (like socks5:// vs. socks5h://) to see the difference, while looking at control-spec.txt (in this case, section 4.1.1 and especially 4.1.2) to make just barely enough sense of it.