Tormap – World map of Tor nodes – 5 years later

5 years ago I forked Moritz’s tormap project, updated it a bit and wrote about it. Tormap kept running for years until some changes in googlemaps broke it, not all KMLs were loading as they should. I later on figured out that googlemaps didn’t like that some of the KML files were larger than 3Mb. I didn’t have much time to play with it until recently, so a few days ago I decided to make it work again. I used newer googlemaps v3 API calls and compressed KML (KMZ) files to make it work. Then @iainlearmonth and @nusenu_ suggested making even more changes…

Their first suggestion was to use onionoo instead of parsing consensus on my own and running geoip on it, onionoo already provides that in a nice json output. Their other suggestion was to switch tormap to use OpenStretMap instead of googlemaps mostly because googlemaps block some Tor exit nodes and the tiles didn’t appear on the map when visiting over Tor. Both of these issues are fixed now.

I used leaflet.js and a couple of plugins like leaflet-plugins (for KML parsing) and leaflet-color-markers for the switch to OpenStreetMap. I will admit that using googlemaps APIs was far more convenient for someone without any javascript knowledge like me.

Maybe in the next 5 years I will have time again to implement their other suggestion, creating maps of nodes based on custom searches for relay attributes. Unless someone else wants to implement that, feel free to fork it!

World city map of Tor nodes

Some months ago I started playing with the idea of creating a world map that would have every Tor node on it. Obviously I wan’t the first one…I soon discovered Moritz Bartl’s post on the same topic. Luckilly he had his code posted on Github so I could fork it and add features that I wanted. The original python script parsed the consensus and the misrodescriptors, put Tor nodes into some classes and created a KML file with some description on each node.

Some differences
I changed some parts of the python script to better suit my needs.
a. Create a separate kml files for each Tor node class.
b. Add new classes: Bad, Authority and Named.
c. Pay more attention on requesting every external URL over HTTPS.
d. Generate HTML code that displays those KMLs on a Google Maps overlay.
e. Add some small randomization to each nodes’s coordinates so that nodes in the same city don’t overlap.

You can find a complete changelog at kargig/tormap GitHub repo.

And here’s the outcome: World city map of Tor nodes at
One of my main goals was to have selectable classes of nodes that will appear on the map.

To produce the map overlay, a cron script runs every hour, which is also the period it takes for Tor Authority nodes to produce a new consensus, and creates some static files which are then served by nginx.

I’m not a web developer/designer and I don’t really know any javascript. So please, feel free to fork my code and make it look better, run faster and add your own features. I’ll happily accept patches/pull requests!

On kargig/tormap repo you will also find a handy script, ‘’, that downloads all necessary files that need to be parsed by the python script.

Missplaced nodes on the map
Well, blame MaxMind’s GeoIP City database for that. But I think it’s kinda funny to see Tor nodes in Siberia and in the middle of the sea though (look at the West coast of Africa), heh. For those wondering, these nodes are gathered there because their geoip Lat,Long is set to 0,0.
Really though, what’s “Ben’s Cat Shaque” diplayed there next to all those nodes in the west coast of Africa? Anyone has some clue ?

Conspriracy people
I’m sure that people who love conspriracy theories will start posting about those ‘Bad’ Tor nodes in Iran and Syria. Why do you think these are there ? What does it mean ? Let the flames begin!

Future TODO
a. OpenStreetMap
I have started working on an OpenStreetMap implementation of the above using OpenLayers. The biggest hurdle is that OSM does not provide a server that serves map tiles over HTTPS. Makes me wonder…is that actually so difficult ?
b. More stats
I would like to add small graphs on how the number of nodes in each class evolves.

Other Tor mapping efforts

Don’t forget, you can always help Tor by running a node/bridge or sending some money to Tor or EFF!

GrRBL goes django

I’ve had this thought for some time now, I needed a nice interface for GrRBL so that it would make it easier for others, read more, people to contribute. Many people have been, politely, complaining about lack of features, policy and so on.

Right now most people use either the submission form or they bounce their emails to grrbl [at] void [dot] gr. Then their emails get manually processed, filtered and if everything goes well the “useful” parts of their email end up in the DNS RBL or the email address blacklist. This process is not automated at all, entries are manually added to a database, and is therefore quite time consuming. What’s worse is that people who are listed don’t have an ‘easy’ way to opt-out, apart from emailing us. The algorithm of adding someone to these lists is also not well-defined. The main rule that is followed is that an IP or email address is added to these lists when at least 3 people have submitted them on different days.

Hopefully this is about to change soon (I don’t know how soon, but soon!). During the past month I’ve been trying to code an interface in django, even though I had no prior experience in it. It’s mostly a self educating process and I like it very much. This django application will be generic enough to cover submissions and listings for IPs, emails and possibly URLs.

  • Short term goals:
  • Anonymous users will only get to see details about an IP they search for. People though will be able to register and add their own entries to a database. These registered users will be able to see the complete listings. Each user will belong to a group and every group will have a different weight which will depend on his ‘expertise’ (I know this is broad, but read on). For example, the group of the individual users will certainly have less weight than the group of the postmasters of Greek ISPs (yeap there are some who regularly contribute). Using their weights users will be able to vote on each entry that’s inside the database. Upon a certain score these entries will be flagged as eligible to be on the blacklist. Listed people will be able to opt-out but this process will be moderated by the superusers, that means that spammers like the infamous sofokleous10 will never get a chance to opt-out even for a single second.
    Most of this functionality is already coded and is working quite well.

  • Mid term goals:
  • Various export formats will be supported (BIND/RBLDNSD, Spamassassin/Postifix/Exim/sendmail/etc). Selective/custom export of entries will be provided. Users will be able to select if they want to export/use a strict blacklist, that is hosts that are scored very high, a moderate one and a very broad/risky one. Levels have yet to be defined. An API will be published so that entries can be re-used in other applications (json format ?)

  • Long term goals:
  • A method/interface that someone would copy/paste their email and it would automagically parse it, provide the user with the discovered malicious entries (IP, emails, URLs) and propose him to add them to the database. Maybe automate this even further so that they are added on a separate moderated queue without user interaction, that would be suitable for submitting entries via email plugins for clients such as mutt/thunderbird/etc.

  • The code:
  • The django application code resides in github for now: Everyone is welcome to submit ideas (as issues) and code! Feel free to download, test and provide feedback.

  • Greek Adblock Plus Filter
  • Since the code is very flexible I am thinking whether Greek Adblock Plus Filter can also be benefited by this voting system. It probably can, so expect some changes to that list as well. One interface to rule them all.

    Many thanks go to @apoikos who has been helping me a lot with the tons of questions I still have on django stuff.

    nicotine+ 1.2.12 ebuild

    I’ve uploaded an ebuild for the latest version of nicotine+ on gentoo’s bugzilla. Nicotine+ is a great p2p app written in PyGtK2 to connect to the Soulseek network.

    I’ve also added psyco as a USE flag since it makes nicotine+ faster…but sadly, a bit more unstable as well. Test it and see if it makes any difference to you.

    Ebuild: nicotine+-1.2.12.ebuild