2

I have been trying to get the IP address of the tor exit node from a bash script. I have tried torifying the usual methods found in various posts in forums for getting one's local IP address. For example:

torify wget -qO- http://ipecho.net/plain ; echo
torify curl -s https://check.torproject.org/ | grep "Your IP address appears to be:" | grep -o '\(\d\{1,3\}\.\)\{3\}\d\{1,3\}'

All these methods return a different IP address than that given by check.torproject.org or any IP identifying site from the browser configured to use tor as a proxy.

I modified the stem script from https://stackoverflow.com/a/17130011 to get the exit relays and compare the results with that given by the bash shell command:

#!/usr/bin/python

from stem import Signal
import os
import time

from stem import CircStatus
from stem.control import Controller

with Controller.from_port(port = 9051) as controller:
  controller.authenticate()
  controller.signal(Signal.NEWNYM) # get new tor identity

time.sleep(5)

print
print "Exit relays:"

with Controller.from_port(port = 9051) as controller:
  controller.authenticate()

  for circ in controller.get_circuits():
    if circ.status != CircStatus.BUILT:
      continue

    exit_fp, exit_nickname = circ.path[-1]
    exit_desc = controller.get_network_status(exit_fp, None)
    exit_address = exit_desc.address if exit_desc else 'unknown' # get relay IP

    print exit_address

print
print "wget:"

os.system("torify wget -qO- http://ipecho.net/plain ; echo")
os.system("open 'https://check.torproject.org/'")
print

and I find that the first address is usually the correct address of the exit node and the second address is usually that given by the bash command:

Exit relays:
178.63.97.34
5.104.224.5
188.138.1.229
128.204.203.103

wget:
5.104.224.5

Exit relays:
91.109.244.104
31.172.30.4

wget:
31.172.30.4

Exit relays:
193.14.16.36
128.204.203.103
89.248.168.6
91.109.244.104
31.172.30.4

wget:
128.204.203.103

Exit relays:
46.182.106.190
178.32.181.96
217.14.208.233
188.226.194.35

wget:
178.32.181.96

So is the address gotten by wget or curl the entry node or what…, and why? How can I get the EXIT node from bash?

  • If you install and run iftop, you can see the IPs of all directly-connected Tor relays. In none of my tests did I see direct connections to an IP reported by "torify wget -qO- ipecho.net/plain ; echo". Could it be the exit-associated DNS server? – mirimir Jul 27 '14 at 9:13
  • Also, browsing ipecho.net/plain reports the same exit IP that check.torproject.org reports. What does "wget -qO-" accomplish? The wget manpage doesn't clearly say. – mirimir Jul 27 '14 at 9:21
  • That's what I was saying in the OP. -q = --quiet and -O- = --output-document=stdout. – hmj6jmh Jul 27 '14 at 16:20
  • What filters and options did you use for iftop? Is there any way to show only port 9050 traffic? What exact command did you use? As for direct connections to torify wget IP, stem does report them as shown in my examples. – hmj6jmh Jul 27 '14 at 16:21
  • I just run "sudo iftop". I still don't get wget -qO-. Accessing ipecho.net in Tor browser gives the exit relay's IP. So what is wget reporting? Whatever it is, it's a Tor relay. – mirimir Jul 28 '14 at 5:57
3

If your configured Tor socks port is 9150, then you can try this command:

curl --socks5-hostname localhost:9150 http://ipecho.net/plain

You also can configure it by editing your config file (usually named torrc) or pass an option named socksport as command-line argument when executing Tor.

  • Yes it is configured for port 9150 by default. This command yielded curl: (7) couldn't connect to host. I don't understand how this would work differently though. torify would send the command through the same port wouldn't it? – hmj6jmh Jul 27 '14 at 8:23
1

The browser and bash are using different circuits, with different exits. The stem script shows exits for all active circuits.

Also, try my tweaked exit_used.py script.

  • The stem script doesn't show all the exit nodes and hops that tor shows. tor: Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at 89.46.100.197' First hop: finished sending CREATE_FAST cell to '$22BCD0DFD148209C9860C7F89907AB4DEE974A08~Fastnet at 188.40.51.232' Chose exit server '$E34E25D958D46DDE5092385B14117C9B301DC0E9=AccessNow13 at 176.10.100.228' First hop: finished sending CREATE_FAST cell to '$7C1542958F11DB68B9D812F92E655CDE49AC28AA~PPTOR0035 at 193.105.134.50' stem script: Exit relays: 176.10.100.228 89.46.100.197 93.184.21.102 212.83.145.8 – hmj6jmh Jul 31 '14 at 17:10
  • OK, true. The question then is how to know which circuit is being used for which process. Is there a variable from stem to indicate that? Or maybe link to something from netstat? – mirimir Jul 31 '14 at 17:49
  • I tried your modified script and it shows the entry node when I run my script above and the exit node when I open ipecho.net/plain in the browser. – hmj6jmh Jul 31 '14 at 22:17
  • That's confusing :( But I still think that you're just looking at exit relays for multiple circuits. Opening the saved "plain" file from running "torify wget ipecho.net/plain", I see a different IP address than from browsing "ipecho.net/plain". They're getting the same page, but through different circuits. – mirimir Jul 31 '14 at 23:16
  • Yes, I agree. See my partial answer. – hmj6jmh Jul 31 '14 at 23:21
1

Answer to question 1, part 1 (NOT the final answer):

I think I have the answer to the first half of my first question: is the address gotten by 'wget' or 'curl' the entry node?

My script gives:

Exit relays:
176.10.100.228
89.46.100.197
93.184.21.102
212.83.145.8

wget:
89.46.100.197

tor gives:

Jul 29 06:37:47.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at 89.46.100.197'
Jul 29 06:37:48.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$E34E25D958D46DDE5092385B14117C9B301DC0E9=AccessNow13 at 176.10.100.228'

Going by the order that tor shows, the first 'exit server' 89.46.100.197 is the entry node. Note that it is what wget gives. The last 'exit server' 176.10.100.228 is the exit node. This is what the browser shows. I have tested this numerous times with my script and it is consistent.

What puzzles and alarms me is part 2 of question 1, why?. Somehow wget and curl are only getting as far as the entry node, which is then decrypting (that is, IF the traffic is even encrypted) and relaying the traffic to the destination IP, completely bypassing the rest of the tor circuit. The entry node is acting like a single-node circuit. Yet tor and the browser are showing the exit node of the multi-node circuit. Isn't this a serious breach of tor design philosophy? Think about it, some traffic is being short-circuited and decrypted and sent to its destination without the aid of all the hops and tor circuit nodes in between. Both wget and curl are the premier tools available to the command line for downloading information. Clearly any use of these tools is not being safeguarded, as expected, by the entire tor circuit. Protecting the identity of a user of these tools is just as important as protecting the identity of the browser user, maybe even more important. I want to know why and how come this hasn't been discovered and reported as a bug?

  • I think that you're misinterpreting the Tor log output that you've quoted. The two lines (89.46.100.197 and 176.10.100.228) are both exit servers, and wget is using 89.46.100.197. Your "Exit relays" output shows them plus exits for two reserve circuits. – mirimir Aug 1 '14 at 0:21
  • The other two exit relays are just intermediary nodes. This has nothing to do with the fact that wget is only using the first node in the circuit. – hmj6jmh Aug 1 '14 at 0:45
  • No, torify wget is NOT using the first node in the circuit. You can see what you're connecting directly to with netstat or iftop. If torify wget IS showing an IP that you see with netstat or iftop, you have in fact IDed a huge bug in Tor. But I'm like 99.999% sure that you haven't. – mirimir Aug 1 '14 at 0:57
  • How are you concluding that when wget is getting the IP of the first node consistently? That means the first node is relaying traffic directly to the destination and not through the next node in the circuit. – hmj6jmh Aug 1 '14 at 2:53
  • You keep saying that, but this is the Tor log line that you've quoted: "Jul 29 06:37:47.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at 89.46.100.197'" It says exit server, right? And that is what torify wget is using, right? – mirimir Aug 1 '14 at 3:55
1

Answer to question 1 -- part 2 (but NOT question 2):

OK, I finally found the ultimate tool for analyzing the tor circuit--arm. I'm really surprised and disappointed that no one here pointed to this useful tool. It would have saved a lot of time on my part and mirimir's. This tool shows exactly what I wanted to know. Tor actually creates multiple circuits and distributes the bandwidth among them. I always thought it only created one circuit at a time. How come no one pointed this out?

wget is using one of 4 circuits:

$ torify wget -qO- http://ipecho.net/plain ; echo 93.184.66.227

wget

The torified browser is using another:

browser

browser arm

It should be noted that only these 2 circuits get reported to the tor log.

So mirimir's guess was right though, unfortunately, he provided no evidence.

Upon examining in detail the Tor Path Specification document, I found the following:

Building circuits

  • Clients build circuits preemptively
    • When running as a client, Tor tries to maintain at least a certain number of clean circuits, so that new streams can be handled quickly
    • On startup Tor tries to maintain one clean fast exit circuit that allows connections to port 80, and at least two fast clean stable internal circuits in case we get a resolve request or hidden service request
      • After that, Tor will adapt the circuits that it preemptively builds based on the requests it sees from the user: it tries to have two fast clean exit circuits available for every port seen within the past hour
  • Path selection and constraints
    • We choose the path for each new circuit before we build it
      • We choose the exit node first, followed by the other nodes in the circuit
    • If we're using Guard nodes, the first node must be a Guard
    • For "fast" circuits, we only choose nodes with the Fast flag
    • For all circuits, we weight node selection according to router bandwidth
    • We also weight the bandwidth of Exit and Guard flagged nodes depending on the fraction of total bandwidth that they make up and depending upon the position they are being selected for

So that explains the multiple circuits and that, therefore, wget is being routed to a different circuit than the one the browser gets routed to, and not to the first node in a single circuit like I surmised. But it doesn't explain why. Speculation--maybe it has to do with bandwidth load balancing?

In any case, question 2 remains open:

How can I get the EXIT node from bash?

By exit node, I mean the one that the browser sees.

  • Your bash commands are reporting the exit node for the circuits that they're using. – mirimir Aug 4 '14 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.