Hi!
Thanks for the comments. Sorry if my reply is long-winded, but you left me no other choice. :)
On Sun, May 19, 2013 at 6:55 PM, Jacob Appelbaum jacob@appelbaum.net wrote:
Could you open a ticket on trac?
Done: https://trac.torproject.org/projects/tor/ticket/8908
It seems to me that this requires a bit of documentation
Sure. Sorry, I should have included some info about how to use this thing :)
Since systemd has no way of knowing which ports Tor actually needs, there needs to be another systemd unit file called tor.socket (in addition to the regular tor.service)
Given for example a torrc: SocksPort 9050 ControlPort 9051 TransPort 9040 DNSPort 9053
You need to have an accompanying tor.socket file with: [Socket] ListenStream=127.0.0.1:9050 ListenStream=127.0.0.1:9051 ListenStream=127.0.0.1:9040 ListenDatagram=127.0.0.1:9053 [Install] WantedBy=sockets.target
Normally you'd put it in /etc/systemd/system. Then run "systemctl daemon-reload; systemctl enable tor.socket"
The matching of listening ports to services is done in Tor based on socket type, bind address and port.
If torrc has some ports that tor.socket doesn't define, then those aren't involved in socket activation. But when Tor starts (e.g. started manually or by activation on other ports), it will bind the remaining ports as usual.
In other cases, if the two config files don't match up, Tor will log a warning (and might fail to start up). Fortunately systemd provides easy access to log messages (via "systemctl status tor")
do you expect to run Tor as say, some-tor-user as usual (what is it on Fedora, anyway?)?
Yeah, it gets started as usual. The user is "tor" on Arch Linux, not sure about Fedora. This is unrelated to socket activation.
An extra benefit of socket activation is that systemd can bind privileged ports like 443 on behalf of Tor, even if Tor starts as an unprivileged user.
How do you expect UDP to be handled as Tor does not actually support UDP (excepting DNSPort, of course)
DNSPort is the use case I had in mind. If a ListenDatagram socket doesn't match up to a DNSPort in torrc then a warning is logged and the socket is closed.
Do you expect this to be used by Tor only in client mode? Or do you expect it to be used by bridges or relays? It seems that socket activation is generally a reasonable idea - though I expect it will simply result in a Tor running nearly all of the time, no?
That's up to the user, really. I agree it's not very useful for running a relay, but it doesn't hurt either.
I expect distros to ship a tor.socket file that matches their default torrc configuration (just 9050) and use that by default. If the user wants to customize it, they have to keep the two in sync, or use the old way of launching it.
If it's installed with "systemctl enable tor.service" then it gets started at boot. "systemctl enable tor.socket" will enable socket activation.
If nothing else, I suspect it will often allow the control port controllers to easily connect - even if Tor isn't started.
Yeah, I tried and it works nicely with Vidalia.
If anything, we may have an easy way to ensure that any authorized Tor controller may start a Tor, which is actually quite nice!
Hmm, making sure that the starter is actually authorized can get complicated. I'd prefer not having to write that dirty code. :)
I have a bunch of questions that come to mind about anti-forensics - for example, if we restart Tor, what happens to data sitting in buffers in memory? The data stays queued, right?
During a restart all the client connections are dropped and their buffers are presumably deallocated. Only the listen sockets persist.
But new inbound connects will be queued and any data sent on those will be buffered in the kernel's TCP buffers as usual, until Tor catches up and handles it. However, the data will stay in buffers longer during startup. Not sure if this is a concern or not.
systemd itself doesn't buffer data, it only grabs the listening socket and passes it on.
How do we ensure that Tor, if started for SOCKS will allow only the right configurations?
Sorry, I don't understand this question.
Will this need to be enabled on all Tor Gnu/Linux builds or should we only enable this code for systemd supporting systems and only with a configuration option, even if we have it compiled into Tor?
I think it's easiest to enable it always. There are no extra dependencies and it doesn't do anything if it's not started by systemd.
src/ext/README should include information on the author as well as the original location of the source.
Will do.
---
I suspect we want to ensure that we only include mqueue.h if we have it.
...
What priviledges are required or set for /dev/mqueue I wonder?
This code is already disabled, I added this to sd-daemon.h: #define SD_DAEMON_DISABLE_MQ 1
Now that you mention it, I realized that this doesn't work -- sd-daemon.h gets included too late. Will fix.
There is a mix of !defined() and defined()
...
Shouldn't 'foosddaemonhfoo' be a bit more... Torish? :)
Well this code (sd-daemon.c and .h) comes from systemd upstream; I think we shouldn't modify it unless really necessary.
Or if we do want to modify it, we should just delete all the parts that we don't use. Should I do that?
I tend to prefer code like: if (NULL != e) { to code like: if (!e) {
I also tend to be more specific with my ints - rather than int, why not uint32_t?
I tried to follow patterns already used in the connection.c file. File descriptors, socket types, booleans and return codes seem to be using type "int". Should I change them all or...?
Furthermore - will the stats leave behind a trace?
The stats?
Will all logging be redirected into the Tor logging subsystem?
Erm, I'm using Tor's log_* functions, so yes.
This code seems to be optimized for your use path:
- s = get_pending_socket(type, socktype, &addr, usePort);
...
s = tor_open_socket(tor_addr_family(&addr), socktype, is_tcp ?
what happens if we never take your path? Is there a performance hit?
Well this code is only executed when the configuration gets loaded (at startup/reload), once for each *Port definition. And the overhead is pretty small if the pending_sockets list is empty (when not using socket activation).
Doing it the other way around seems silly (try to bind the socket, then go down the other path if it returned EADDRINUSE) and it seems wouldn't work for UDP.
When you apply this patch and enable debugging, do you see any warnings?
Do you mean "Log debug syslog", or what kind of debugging?
Apart from the fact that hibernation is broken (as stated in the initial mail), I don't see any warnings.
On what platform did you test it where you expect it to work? How about other platforms where it shouldn't work but also shouldn't do harm?
I tested this on Linux (Arch Linux x86_64)
On other platforms sd_listen_fds() will return 0, in which case it works just as if socket activation isn't used.
Unfortunately I don't have a development environment on any other platform, but I'm fairly confident it will work.
Regards, Marti