tahoe.cfg: add tub.location, to override the location hints we include in our FURL. This replaces advertised_ip_addresses, which doesn't remain useful enough to retain it. Helps with #517 (Tor).

This commit is contained in:
Brian Warner 2008-11-12 18:44:58 -07:00
parent 74ce1cdc00
commit 9976bd439a
5 changed files with 111 additions and 68 deletions

7
NEWS
View File

@ -53,9 +53,10 @@ connection. docs/frontends/webapi.txt has details.
The Tahoe node is now configured with a single INI-format file, named
"tahoe.cfg", in the node's base directory. Most of the previous
multiple-separate-files are still read for backwards compatibility (the
embedded SSH debug server is the exception), but new directives will only be
added to tahoe.cfg . The "tahoe create-client" command will create a
tahoe.cfg for you, with sample values commented out. (ticket #518)
embedded SSH debug server and the advertised_ip_addresses files are the
exceptions), but new directives will only be added to tahoe.cfg . The "tahoe
create-client" command will create a tahoe.cfg for you, with sample values
commented out. (ticket #518)
tahoe.cfg now has controls for the foolscap "keepalive" and "disconnect"
timeouts (#521).

View File

@ -77,22 +77,83 @@ tub.port = (integer, optional)
port. The port will be written to a separate file (named client.port or
introducer.port), so that subsequent runs will re-use the same port.
advertised_ip_addresses = (comma-separated host[:port] string, optional)
tub.location = (string, optional)
The node normally uses tools like 'ifconfig' to determine the set of IP
addresses on which it can be reached from nodes both near and far. The node
introduces itself to the rest of the grid with a FURL that contains a series
of (ipaddr, port) pairs which other nodes will use to contact this one. By
providing this file, you can add to this list. This can be useful if your
node is running behind a firewall, but you have created a port-forwarding to
allow the outside world to access it. Each line must have a dotted-quad IP
address and an optional :portnum specification, like:
In addition to running as a client, each Tahoe node also runs as a server,
listening for connections from other Tahoe clients. The node announces its
location by publishing a "FURL" (a string with some connection hints) to the
Introducer. The string it publishes can be found in
$BASEDIR/private/storage.furl . The "tub.location" configuration controls
what location is published in this announcement.
123.45.67.89
44.55.66.77:8098
If you don't provide tub.location, the node will try to figure out a useful
one by itself, by using tools like 'ifconfig' to determine the set of IP
addresses on which it can be reached from nodes both near and far. It will
also include the TCP port number on which it is listening (either the one
specified by tub.port, or whichever port was assigned by the kernel when
tub.port is left unspecified).
Lines that do not provide a port number will use the same client.port as the
automatically-discovered addresses.
You might want to override this value if your node lives behind a firewall
that is doing inbound port forwarding, or if you are using other proxies
such that the local IP address or port number is not the same one that
remote clients should use to connect. You might also want to control this
when using a Tor proxy to avoid revealing your actual IP address through the
Introducer announcement.
The value is a comma-separated string of host:port location hints, like
this:
123.45.67.89:8098,tahoe.example.com:8098,127.0.0.1:8098
A few examples:
Emulate default behavior, assuming your host has IP address 123.45.67.89
and the kernel-allocated port number was 8098:
tub.port = 8098
tub.location = 123.45.67.89:8098,127.0.0.1:8098
Use a DNS name so you can change the IP address more easily:
tub.port = 8098
tub.location = tahoe.example.com:8098
Run a node behind a firewall (which has an external IP address) that has
been configured to forward port 7912 to our internal node's port 8098:
tub.port = 8098
tub.location = external-firewall.example.com:7912
Run a node behind a Tor proxy (perhaps via tsocks), in client-only mode
(i.e. we can make outbound connections, but other nodes will not be able to
connect to us). The literal 'unreachable.example.org' will not resolve, but
will serve as a reminder to human observers that this node cannot be
reached. "Don't call us.. we'll call you":
tub.port = 8098
tub.location = unreachable.example.org:0
Run a node behind a Tor proxy, and make the server available as a Tor
"hidden service". (this assumes that other clients are running their node
with tsocks, such that they are prepared to connect to a .onion address).
The hidden service must first be configured in Tor, by giving it a local
port number and then obtaining a .onion name, using something in the torrc
file like:
HiddenServiceDir /var/lib/tor/hidden_services/tahoe
HiddenServicePort 29212 127.0.0.1:8098
once Tor is restarted, the .onion hostname will be in
/var/lib/tor/hidden_services/tahoe/hostname . Then set up your tahoe.cfg
like:
tub.port = 8098
tub.location = ualhejtq2p7ohfbb.onion:29212
Most users will not need to set tub.location .
Note that the old 'advertised_ip_addresses' file from earlier releases is no
longer supported. Tahoe 1.3.0 and later will ignore this file.
log_gatherer.furl = (FURL, optional)
@ -345,7 +406,7 @@ exists, it will take precedence over the corresponding item in tahoe.cfg .
[node]tub.port : BASEDIR/client.port (for Clients, not Introducers)
[node]tub.port : BASEDIR/introducer.port (for Introducers, not Clients)
(note that, unlike other keys, tahoe.cfg overrides the *.port file)
[node]advertised_ip_addresses : BASEDIR/advertised_ip_addresses (one per line)
[node]tub.location : replaces BASEDIR/advertised_ip_addresses
[node]log_gatherer.furl : BASEDIR/log_gatherer.furl (one per line)
[node]timeout.keepalive : BASEDIR/keepalive_timeout
[node]timeout.disconnect : BASEDIR/disconnect_timeout
@ -367,6 +428,13 @@ file provided the ssh public keys to accept. Support for these files has been
removed completely. To ssh into your Tahoe node, add [node]ssh.port and
[node].ssh_authorized_keys_file statements to your tahoe.cfg .
Likewise, the functionality of [node]tub.location is a variant of the
now-unsupported BASEDIR/advertised_ip_addresses . The old file was additive
(the addresses specified in advertised_ip_addresses were used in addition to
any that were automatically discovered), whereas the new tahoe.cfg directive
is not (tub.location is used verbatim).
== Example ==
The following is a sample tahoe.cfg file, containing values for all keys
@ -374,8 +442,10 @@ described above. Note that this is not a recommended configuration (most of
these are not the default values), merely a legal one.
[node]
port = 34912
advertised_ip_addresses = 123.45.67.89,44.55.66.77:8098
nickname = Bob's Tahoe Node
tub.port = 34912
tub.location = 123.45.67.89:8098,44.55.66.77:8098
web.port = 8123
log_gatherer.furl = pb://soklj4y7eok5c3xkmjeqpw@192.168.69.247:44801/eqpwqtzm
timeout.keepalive = 240
timeout.disconnect = 1800
@ -384,8 +454,6 @@ ssh.authorized_keys_file = ~/.ssh/authorized_keys
[client]
introducer.furl = pb://ok45ssoklj4y7eok5c3xkmj@tahoe.example:44801/ii3uumo
nickname = Bob's Tahoe Node
web.port = 8123
helper.furl = pb://ggti5ssoklj4y7eok5c3xkmj@helper.tahoe.example:7054/kk8lhr
[storage]

View File

@ -50,7 +50,6 @@ class Node(service.MultiService):
NODETYPE = "unknown NODETYPE"
PORTNUMFILE = None
CERTFILE = "node.pem"
LOCAL_IP_FILE = "advertised_ip_addresses"
def __init__(self, basedir="."):
service.MultiService.__init__(self)
@ -116,21 +115,6 @@ class Node(service.MultiService):
except EnvironmentError:
pass
try:
addresses = []
ipfile = os.path.join(self.basedir, self.LOCAL_IP_FILE)
tubport = int(self.get_config("node", "tub.port", "0"))
for addrline in open(ipfile, "rU"):
mo = ADDR_RE.search(addrline)
if mo:
(addr, dummy, aportnum,) = mo.groups()
if aportnum is None:
aportnum = tubport
addresses.append("%s:%d" % (addr, int(aportnum),))
self.set_config("node", "advertised_ip_addresses",
",".join(addresses))
except EnvironmentError:
pass
copy("keepalive_timeout", "node", "timeout.keepalive")
copy("disconnect_timeout", "node", "timeout.disconnect")
@ -320,18 +304,16 @@ class Node(service.MultiService):
# running, which means after startService.
l = self.tub.getListeners()[0]
portnum = l.getPortnum()
# record which port we're listening on, so we can grab the same one next time
# record which port we're listening on, so we can grab the same one
# next time
open(self._portnumfile, "w").write("%d\n" % portnum)
addresses = [ "%s:%d" % (addr, portnum,) for addr in local_addresses ]
extra_addresses = self.get_config("node", "advertised_ip_addresses", "")
if extra_addresses:
extra_addresses = extra_addresses.split(",")
addresses.extend(extra_addresses)
location = ",".join(addresses)
base_location = ",".join([ "%s:%d" % (addr, portnum)
for addr in local_addresses ])
location = self.get_config("node", "tub.location", base_location)
self.log("Tub location set to %s" % location)
self.tub.setLocation(location)
return self.tub
def when_tub_ready(self):

View File

@ -73,7 +73,7 @@ def write_node_config(c, config):
c.write("web.port = %s\n" % webport)
c.write("web.static = public_html\n")
c.write("#tub.port =\n")
c.write("#advertised_ip_addresses =\n")
c.write("#tub.location = \n")
c.write("#log_gatherer.furl =\n")
c.write("#timeout.keepalive =\n")
c.write("#timeout.disconnect =\n")

View File

@ -29,11 +29,12 @@ class TestCase(unittest.TestCase, testutil.SignalMixin):
d.addCallback(flushEventualQueue)
return d
def test_advertised_ip_addresses(self):
basedir = "test_node/test_advertised_ip_addresses"
def test_location(self):
basedir = "test_node/test_location"
fileutil.make_dirs(basedir)
f = open(os.path.join(basedir, 'advertised_ip_addresses'),'w')
f.write('1.2.3.4:5')
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write("[node]\n")
f.write("tub.location = 1.2.3.4:5\n")
f.close()
n = TestNode(basedir)
@ -47,31 +48,22 @@ class TestCase(unittest.TestCase, testutil.SignalMixin):
d.addCallback(_check_addresses)
return d
def test_advertised_ip_addresses2(self):
basedir = "test_node/test_advertised_ip_addresses2"
def test_location2(self):
basedir = "test_node/test_location2"
fileutil.make_dirs(basedir)
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write("[node]\n")
f.write("tub.location = 1.2.3.4:5,example.org:8091\n")
f.close()
n = TestNode(basedir)
n.setServiceParent(self.parent)
d = n.when_tub_ready()
# this lets the 'port' file get written
d.addCallback(lambda res: n.disownServiceParent())
def _new_node(res):
f = open(os.path.join(basedir, 'advertised_ip_addresses'),'w')
f.write('1.2.3.4\n')
f.write("6.7.8.9\n")
f.close()
n2 = self.node = TestNode(basedir)
n2.setServiceParent(self.parent)
return n2.when_tub_ready()
d.addCallback(_new_node)
def _check_addresses(ignored_result):
portfile = os.path.join(basedir, self.node.PORTNUMFILE)
port = int(open(portfile, "r").read().strip())
furl = self.node.tub.registerReference(n)
self.failUnless(("1.2.3.4:%d" % port) in furl, furl)
self.failUnless(("6.7.8.9:%d" % port) in furl, furl)
furl = n.tub.registerReference(n)
self.failUnless("1.2.3.4:5" in furl, furl)
self.failUnless("example.org:8091" in furl, furl)
d.addCallback(_check_addresses)
return d