15

I want to monitor the status of running Tor instances.

I am already able to get information via a TCP connection to the control ports. E.g. "GETINFO stream-status" returns data, but I am not able to determine the IP address of the currently chosen exit node.

It would be possible to simply request something like whatismyip.org, but that is too slow and does not scale well.

So what is the best way to get the exit node IP address of a Tor connection?

pintpint
  • 321
  • 1
  • 3
  • 5

4 Answers4

10

This is a great question! Here's a short script for doing it using stem...

from stem import CircStatus
from stem.control import Controller

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'

    print "Exit relay"
    print "  fingerprint: %s" % exit_fp
    print "  nickname: %s" % exit_nickname
    print "  address: %s" % exit_address
    print

Thanks for the question. I've added this to our FAQ.

Damian
  • 2,944
  • 2
  • 18
  • 15
  • 2
    How do I know which of these Tor will use? – Tyilo Aug 20 '13 at 05:40
  • Yes, how do we know which of these is being used by Tor ? – rdsoze Jan 30 '14 at 12:07
  • How does this python/stem usage translate into Tor control protocol? I guess it's `GETINFO circuit-status`. – Markus Malkusch Mar 13 '16 at 15:00
  • You use `circuit-status` to obtain list of BUILT circuit, the first one is used one. Then you extract the last node ID to get info with `ns/id/$NODEID` – HugoPoi Dec 08 '16 at 10:47
  • sure i don't know tor internals well but using this code two addresses are reported how to find out which one is selected – pouya Nov 19 '17 at 16:48
  • playing more with the code in some cases three or more addresses are reported and they don't come in sequence – pouya Nov 19 '17 at 16:56
0

You can use tor control api. But I don't see the point.

You know the exit node id~name, you know the ip address that it is listening on. You don't know what network interface and what ip address it will use to process your query.

I've just checked that about 5% of tor exit nodes uses unpublished ipv4 addresses.

The world is moving to ipv6. These ip addresses are cheap. Each exit node can have a bag of ipv6 unpiblished addresses.

puchu
  • 3,294
  • 6
  • 38
  • 62
0

The exit circuit might be any one of the circuits returned by controller.get_circuits(), the following is how you get the exit circuit and the ip address:
source and tutorial link

## https://stem.torproject.org/tutorials/examples/exit_used.html
import functools

from stem import StreamStatus
from stem.control import EventType, Controller

def main():
  print("Tracking requests for tor exits. Press 'enter' to end.")
  print("")

  with Controller.from_port() as controller:
    controller.authenticate()

    stream_listener = functools.partial(stream_event, controller)
    controller.add_event_listener(stream_listener, EventType.STREAM)

    input()  # wait for user to press enter


def stream_event(controller, event):
  if event.status == StreamStatus.SUCCEEDED and event.circ_id:
    circ = controller.get_circuit(event.circ_id)

    exit_fingerprint = circ.path[-1][0]
    exit_relay = controller.get_network_status(exit_fingerprint)

    print("Exit relay for our connection to %s" % (event.target))
    print("  address: %s:%i" % (exit_relay.address, exit_relay.or_port))
    print("  fingerprint: %s" % exit_relay.fingerprint)
    print("  nickname: %s" % exit_relay.nickname)
    print("  locale: %s" % controller.get_info("ip-to-country/%s" % exit_relay.address, 'unknown'))
    print("")


if __name__ == '__main__':
  main()

Iceberg
  • 2,744
  • 19
  • 19
-1

According to the Tor control protocol spec, the correct syntax is "GETINFO address", which should render the best guess at our external IP address. If we have no guess, return a 551 error. (Added in 0.1.2.2-alpha)".

Darin Kolev
  • 3,401
  • 13
  • 31
  • 46
  • 5
    The `GETINFO address` provides your own IP address (ie, the address other people will see if you opt to be a relay). What the poster is asking about is the exit relay address of his present circuits. – Damian Jun 16 '13 at 03:26
  • ``getinfo circuit-status`` current circuits built and ready. This will contain the OR name (name of router/hop) and ID. With this you can get up with ``getinfo ns/id/`` or ``getinfo ns/name/`` might allow you to determine the ip – gesell Jul 03 '15 at 12:30