I want to support Tails users. My program is written in python, and I need to download something over Tor using python.

When running python as the amnesia user, the following code does not work:

import urllib2


This should work on any system, but on Tails, I get the following error:

urllib2.URLError: <urlopen error [Errno 111] Connection refused>

So how do I load http/s pages in python on Tails as the amnesia user?

  • In Tails you can use torify and torsocks to run that script. Commented Nov 20, 2015 at 18:08

1 Answer 1


The Tails firewall will prevent you from doing this. Only applications that have been explicitly whitelisted are allowed to communicate with the outside world. This is by design.

Have a read of the Network Filter page on the Tails site.

You'll have to whitelist your application/script to allow it to connect to a foreign IP address. To do this you'll need to edit the file /etc/ferm/ferm.conf. The file should be commented well enough to allow you to work out the config you'll need to add. (In theory... )


In the OnionShare code mentioned by the OP, they're effectively doing the same thing using a different method.

ferm is a tool that allows firewall rules to be written and stored in a separate config file. If you look at the contents of a ferm file, you'll see the syntax is a simplified version of the options you would pass to the iptables command, which is what they use in the OnionShare code.

For details on how an iptables command translates to a ferm statement, see here.

iptables isn't available to the amnesia user, which is why their script has to be run as root. (There are probably other reasons, too.)

Their code simply spawns iptables as a separate process. For something more Pythonic, you could have a look at the python-iptables package. (Note, I haven't used this myself. You'd have to ensure the code in this package is "safe" from the perspective on anonimity... )

Finally, opening holes in firewalls is dangerous. You'd have to ensure these holes couldn't be accidentally left open if, for example, your script died unexpectedly. (So if your script did spawn a separate child process, like the OnionShare code does, you would need to ensure that that child dies with its parent. The OnionShare code doesn't seem to do this - if the main script dies after line 238 but before 267, the firewall is left open. To protect against this you'd want the kernel to kill the child, as described in this thread.)

  • @ Richard: I don't think I should have to edit /etc/ferm/ferm.conf. I say that, because in the OnionShare project [1], that config file is not edited. For some reason, they are able to 'simply' use urllib2.urlopen() to load a .onion, as can be seen in their code [2]. Now, in the tails_root method on line 238 of the same file, it seems like they are opening and closing a hole in the firewall. Should I be using a similar trick to allow requests for ports 80 and 443? Is there some pythonic way of being able to open and close the firewall (or do some other trick to load a url on tails), withou
    – user8206
    Commented Aug 24, 2015 at 14:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .