Reputation: 321
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?
Upvotes: 15
Views: 10881
Reputation: 3332
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()
Upvotes: 0
Reputation: 2954
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.
Upvotes: 10
Reputation: 3652
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.
Upvotes: 0