mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-20 17:52:50 +00:00
config: add reveal-IP-address=False
This adds a safety flag named `[node] reveal-IP-address`, for which the default value is True. When this is set to False, any configuration that might reveal the node's IP address (to servers, or the external network) will cause a PrivacyError to be raised at startup, terminating the node before it gets a chance to betray the user's privacy. It also adds docs and tests. refs ticket:1010
This commit is contained in:
parent
325028c967
commit
d47fc0fd27
@ -324,6 +324,23 @@ set the ``tub.location`` option described below.
|
||||
used for files that usually (on a Unix system) go into ``/tmp``. The
|
||||
string will be interpreted relative to the node's base directory.
|
||||
|
||||
``reveal-IP-address = (boolean, optional, defaults to True)``
|
||||
|
||||
This is a safety flag. If False, any of the following configuration
|
||||
problems will cause ``tahoe start`` to throw a PrivacyError instead of
|
||||
starting the node:
|
||||
|
||||
* ``[node] tub.location`` contains any ``tcp:`` hints
|
||||
|
||||
* ``[node] tub.location`` uses ``AUTO``, or is missing/empty (because
|
||||
that defaults to AUTO)
|
||||
|
||||
* ``[connections] tcp =`` is set to ``tcp`` (or left as the default),
|
||||
rather than being set to ``tor``
|
||||
|
||||
These configuration problems would reveal the node's IP address to
|
||||
servers and external networks.
|
||||
|
||||
|
||||
Connection Management
|
||||
=====================
|
||||
@ -334,6 +351,10 @@ also controls when Tor and I2P are used: for all TCP connections (to hide
|
||||
your IP address), or only when necessary (just for servers which declare that
|
||||
they need Tor, because they use ``.onion`` addresses).
|
||||
|
||||
Note that if you want to protect your node's IP address, you should set
|
||||
``[node] reveal-IP-address = False``, which will refuse to launch the node if
|
||||
any of the other configuration settings might violate this privacy property.
|
||||
|
||||
``[connections]``
|
||||
-----------------
|
||||
|
||||
|
@ -76,6 +76,9 @@ class UnescapedHashError(Exception):
|
||||
return ("The configuration entry %s contained an unescaped '#' character."
|
||||
% quote_output("[%s]%s = %s" % self.args))
|
||||
|
||||
class PrivacyError(Exception):
|
||||
"""reveal-IP-address = false, but the node is configured in such a way
|
||||
that the IP address could be revealed"""
|
||||
|
||||
class Node(service.MultiService):
|
||||
# this implements common functionality of both Client nodes and Introducer
|
||||
@ -99,6 +102,7 @@ class Node(service.MultiService):
|
||||
assert type(self.nickname) is unicode
|
||||
|
||||
self.init_tempdir()
|
||||
self.check_privacy()
|
||||
self.init_connections()
|
||||
self.set_tub_options()
|
||||
self.create_main_tub()
|
||||
@ -181,6 +185,10 @@ class Node(service.MultiService):
|
||||
twlog.msg(e)
|
||||
raise e
|
||||
|
||||
def check_privacy(self):
|
||||
self._reveal_ip = self.get_config("node", "reveal-IP-address", True,
|
||||
boolean=True)
|
||||
|
||||
def _make_tcp_handler(self):
|
||||
# this is always available
|
||||
from foolscap.connections.tcp import default
|
||||
@ -279,6 +287,10 @@ class Node(service.MultiService):
|
||||
% (tcp_handler_name, tcp_handler_name))
|
||||
self._default_connection_handlers["tcp"] = tcp_handler_name
|
||||
|
||||
if not self._reveal_ip:
|
||||
if self._default_connection_handlers["tcp"] == "tcp":
|
||||
raise PrivacyError("tcp = tcp, must be set to 'tor'")
|
||||
|
||||
def set_tub_options(self):
|
||||
self.tub_options = {
|
||||
"logLocalFailures": True,
|
||||
@ -339,6 +351,8 @@ class Node(service.MultiService):
|
||||
# addresses. Don't probe for local addresses unless necessary.
|
||||
split_location = location.split(",")
|
||||
if "AUTO" in split_location:
|
||||
if not self._reveal_ip:
|
||||
raise PrivacyError("tub.location uses AUTO")
|
||||
local_addresses = iputil.get_local_addresses_sync()
|
||||
# tubport must be like "tcp:12345" or "tcp:12345:morestuff"
|
||||
local_portnum = int(tubport.split(":")[1])
|
||||
@ -348,6 +362,10 @@ class Node(service.MultiService):
|
||||
new_locations.extend(["tcp:%s:%d" % (ip, local_portnum)
|
||||
for ip in local_addresses])
|
||||
else:
|
||||
if not self._reveal_ip:
|
||||
hint_type = loc.split(":")[0]
|
||||
if hint_type == "tcp":
|
||||
raise PrivacyError("tub.location includes tcp: hint")
|
||||
new_locations.append(loc)
|
||||
return ",".join(new_locations)
|
||||
|
||||
|
@ -5,12 +5,13 @@ from twisted.trial import unittest
|
||||
from twisted.internet import reactor, endpoints
|
||||
from ConfigParser import SafeConfigParser
|
||||
from foolscap.connections import tcp
|
||||
from ..node import Node
|
||||
from ..node import Node, PrivacyError
|
||||
|
||||
class FakeNode(Node):
|
||||
def __init__(self, config_str):
|
||||
self.config = SafeConfigParser()
|
||||
self.config.readfp(BytesIO(config_str))
|
||||
self._reveal_ip = True
|
||||
|
||||
BASECONFIG = ("[client]\n"
|
||||
"introducer.furl = \n"
|
||||
@ -230,3 +231,58 @@ class Connections(unittest.TestCase):
|
||||
e = self.assertRaises(ValueError, n.init_connections)
|
||||
self.assertIn("'tahoe.cfg [connections] tcp='", str(e))
|
||||
self.assertIn("uses unknown handler type 'unknown'", str(e))
|
||||
|
||||
class Privacy(unittest.TestCase):
|
||||
def test_flag(self):
|
||||
n = FakeNode(BASECONFIG)
|
||||
n.check_privacy()
|
||||
self.assertTrue(n._reveal_ip)
|
||||
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = true\n")
|
||||
n.check_privacy()
|
||||
self.assertTrue(n._reveal_ip)
|
||||
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n")
|
||||
n.check_privacy()
|
||||
self.assertFalse(n._reveal_ip)
|
||||
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-ip-address = false\n")
|
||||
n.check_privacy()
|
||||
self.assertFalse(n._reveal_ip)
|
||||
|
||||
def test_connections(self):
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n")
|
||||
n.check_privacy()
|
||||
e = self.assertRaises(PrivacyError, n.init_connections)
|
||||
self.assertEqual(str(e), "tcp = tcp, must be set to 'tor'")
|
||||
|
||||
def test_tub_location_auto(self):
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n")
|
||||
n._portnumfile = "missing"
|
||||
n.check_privacy()
|
||||
e = self.assertRaises(PrivacyError, n.get_tub_location, None)
|
||||
self.assertEqual(str(e), "tub.location uses AUTO")
|
||||
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n" +
|
||||
"tub.location = AUTO\n")
|
||||
n._portnumfile = "missing"
|
||||
n.check_privacy()
|
||||
e = self.assertRaises(PrivacyError, n.get_tub_location, None)
|
||||
self.assertEqual(str(e), "tub.location uses AUTO")
|
||||
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n" +
|
||||
"tub.location = AUTO,tcp:hostname:1234\n")
|
||||
n._portnumfile = "missing"
|
||||
n.check_privacy()
|
||||
e = self.assertRaises(PrivacyError, n.get_tub_location, None)
|
||||
self.assertEqual(str(e), "tub.location uses AUTO")
|
||||
|
||||
def test_tub_location_tcp(self):
|
||||
n = FakeNode(BASECONFIG+"[node]\nreveal-IP-address = false\n" +
|
||||
"tub.location = tcp:hostname:1234\n")
|
||||
n._portnumfile = "missing"
|
||||
n.check_privacy()
|
||||
e = self.assertRaises(PrivacyError, n.get_tub_location, None)
|
||||
self.assertEqual(str(e), "tub.location includes tcp: hint")
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user