]> Git — Sourcephile - sourcephile-nix.git/blob - nixos/modules/services/security/tor.nix
nftables: remote debugging ICMPv6 rule
[sourcephile-nix.git] / nixos / modules / services / security / tor.nix
1 { config, lib, pkgs, ... }:
2
3 with lib;
4
5 let
6 cfg = config.services.tor;
7 torDirectory = "/var/lib/tor";
8 torRunDirectory = "/run/tor";
9
10 opt = name: value: optionalString (value != null) "${name} ${value}";
11 optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}";
12
13 isolationOptions = {
14 type = types.listOf (types.enum [
15 "IsolateClientAddr"
16 "IsolateSOCKSAuth"
17 "IsolateClientProtocol"
18 "IsolateDestPort"
19 "IsolateDestAddr"
20 ]);
21 default = [];
22 example = [
23 "IsolateClientAddr"
24 "IsolateSOCKSAuth"
25 "IsolateClientProtocol"
26 "IsolateDestPort"
27 "IsolateDestAddr"
28 ];
29 description = "Tor isolation options";
30 };
31
32
33 torRc = ''
34 DataDirectory ${torDirectory}
35 ${optionalString cfg.enableGeoIP ''
36 GeoIPFile ${cfg.package.geoip}/share/tor/geoip
37 GeoIPv6File ${cfg.package.geoip}/share/tor/geoip6
38 ''}
39
40 ${optint "ControlPort" cfg.controlPort}
41 ${optionalString cfg.controlSocket.enable "ControlPort unix:${torRunDirectory}/control GroupWritable RelaxDirModeCheck"}
42 ''
43 # Client connection config
44 + optionalString cfg.client.enable ''
45 SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions}
46 SOCKSPort ${cfg.client.socksListenAddressFaster}
47 ${opt "SocksPolicy" cfg.client.socksPolicy}
48
49 ${optionalString cfg.client.transparentProxy.enable ''
50 TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions}
51 ''}
52
53 ${optionalString cfg.client.dns.enable ''
54 DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions}
55 AutomapHostsOnResolve 1
56 AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes}
57 ''}
58 ''
59 # Explicitly disable the SOCKS server if the client is disabled. In
60 # particular, this makes non-anonymous hidden services possible.
61 + optionalString (! cfg.client.enable) ''
62 SOCKSPort 0
63 ''
64 # Relay config
65 + optionalString cfg.relay.enable ''
66 ORPort ${toString cfg.relay.port}
67 ${opt "Address" cfg.relay.address}
68 ${opt "Nickname" cfg.relay.nickname}
69 ${opt "ContactInfo" cfg.relay.contactInfo}
70
71 ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
72 ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
73 ${opt "AccountingMax" cfg.relay.accountingMax}
74 ${opt "AccountingStart" cfg.relay.accountingStart}
75
76 ${if (cfg.relay.role == "exit") then
77 opt "ExitPolicy" cfg.relay.exitPolicy
78 else
79 "ExitPolicy reject *:*"}
80
81 ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) ''
82 BridgeRelay 1
83 ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed
84 ExtORPort auto
85 ${optionalString (cfg.relay.role == "private-bridge") ''
86 ExtraInfoStatistics 0
87 PublishServerDescriptor 0
88 ''}
89 ''}
90 ''
91 # Hidden services
92 + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: ''
93 HiddenServiceDir ${torDirectory}/onion/${v.name}
94 ${optionalString (v.version != null) "HiddenServiceVersion ${toString v.version}"}
95 ${flip concatMapStrings v.map (p: ''
96 HiddenServicePort ${toString p.port} ${p.destination}
97 '')}
98 ${optionalString (v.authorizeClient != null) ''
99 HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
100 ''}
101 ''))
102 + cfg.extraConfig;
103
104 torRcFile = pkgs.writeText "torrc" torRc;
105
106 in
107 {
108 imports = [
109 (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ])
110 (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.")
111 (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.")
112 ];
113
114 options = {
115 services.tor = {
116 enable = mkEnableOption ''Tor daemon.
117 By default, the daemon is run without
118 relay, exit, bridge or client connectivity.
119 '';
120
121 package = mkOption {
122 type = types.package;
123 default = pkgs.tor;
124 defaultText = "pkgs.tor";
125 example = literalExample "pkgs.tor";
126 description = ''
127 Tor package to use
128 '';
129 };
130
131 enableGeoIP = mkOption {
132 type = types.bool;
133 default = true;
134 description = ''
135 Whenever to configure Tor daemon to use GeoIP databases.
136
137 Disabling this will disable by-country statistics for
138 bridges and relays and some client and third-party software
139 functionality.
140 '';
141 };
142
143 extraConfig = mkOption {
144 type = types.lines;
145 default = "";
146 description = ''
147 Extra configuration. Contents will be added verbatim to the
148 configuration file at the end.
149 '';
150 };
151
152 controlPort = mkOption {
153 type = types.nullOr (types.either types.int types.str);
154 default = null;
155 example = 9051;
156 description = ''
157 If set, Tor will accept connections on the specified port
158 and allow them to control the tor process.
159 '';
160 };
161
162 controlSocket = {
163 enable = mkOption {
164 type = types.bool;
165 default = false;
166 description = ''
167 Whether to enable Tor control socket. Control socket is created
168 in <literal>${torRunDirectory}/control</literal>
169 '';
170 };
171 };
172
173 client = {
174 enable = mkOption {
175 type = types.bool;
176 default = false;
177 description = ''
178 Whether to enable Tor daemon to route application
179 connections. You might want to disable this if you plan
180 running a dedicated Tor relay.
181 '';
182 };
183
184 socksListenAddress = mkOption {
185 type = types.str;
186 default = "127.0.0.1:9050";
187 example = "192.168.0.1:9100";
188 description = ''
189 Bind to this address to listen for connections from
190 Socks-speaking applications. Provides strong circuit
191 isolation, separate circuit per IP address.
192 '';
193 };
194
195 socksListenAddressFaster = mkOption {
196 type = types.str;
197 default = "127.0.0.1:9063";
198 example = "192.168.0.1:9101";
199 description = ''
200 Bind to this address to listen for connections from
201 Socks-speaking applications. Same as
202 <option>socksListenAddress</option> but uses weaker
203 circuit isolation to provide performance suitable for a
204 web browser.
205 '';
206 };
207
208 socksPolicy = mkOption {
209 type = types.nullOr types.str;
210 default = null;
211 example = "accept 192.168.0.0/16, reject *";
212 description = ''
213 Entry policies to allow/deny SOCKS requests based on IP
214 address. First entry that matches wins. If no SocksPolicy
215 is set, we accept all (and only) requests from
216 <option>socksListenAddress</option>.
217 '';
218 };
219
220 socksIsolationOptions = mkOption (isolationOptions // {
221 default = ["IsolateDestAddr"];
222 });
223
224 transparentProxy = {
225 enable = mkOption {
226 type = types.bool;
227 default = false;
228 description = "Whether to enable tor transparent proxy";
229 };
230
231 listenAddress = mkOption {
232 type = types.str;
233 default = "127.0.0.1:9040";
234 example = "192.168.0.1:9040";
235 description = ''
236 Bind transparent proxy to this address.
237 '';
238 };
239
240 isolationOptions = mkOption isolationOptions;
241 };
242
243 dns = {
244 enable = mkOption {
245 type = types.bool;
246 default = false;
247 description = "Whether to enable tor dns resolver";
248 };
249
250 listenAddress = mkOption {
251 type = types.str;
252 default = "127.0.0.1:9053";
253 example = "192.168.0.1:9053";
254 description = ''
255 Bind tor dns to this address.
256 '';
257 };
258
259 isolationOptions = mkOption isolationOptions;
260
261 automapHostsSuffixes = mkOption {
262 type = types.listOf types.str;
263 default = [".onion" ".exit"];
264 example = [".onion"];
265 description = "List of suffixes to use with automapHostsOnResolve";
266 };
267 };
268
269 privoxy.enable = lib.mkEnableOption ''Privoxy system,
270 to use Tor's faster port, suitable for HTTP.
271
272 To have anonymity, protocols need to be scrubbed of identifying
273 information, and this can be accomplished for HTTP by Privoxy.
274
275 Privoxy can also be useful for KDE torification. A good setup would be:
276 setting SOCKS proxy to the default Tor port, providing maximum
277 circuit isolation where possible; and setting HTTP proxy to Privoxy
278 to route HTTP traffic over faster, but less isolated port.
279 '';
280 };
281
282 relay = {
283 enable = mkOption {
284 type = types.bool;
285 default = false;
286 description = ''
287 Whether to enable relaying TOR traffic for others.
288
289 See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" />
290 for details.
291
292 Setting this to true requires setting
293 <option>services.tor.relay.role</option>
294 and
295 <option>services.tor.relay.port</option>
296 options.
297 '';
298 };
299
300 role = mkOption {
301 type = types.enum [ "exit" "relay" "bridge" "private-bridge" ];
302 description = ''
303 Your role in Tor network. There're several options:
304
305 <variablelist>
306 <varlistentry>
307 <term><literal>exit</literal></term>
308 <listitem>
309 <para>
310 An exit relay. This allows Tor users to access regular
311 Internet services through your public IP.
312 </para>
313
314 <important><para>
315 Running an exit relay may expose you to abuse
316 complaints. See
317 <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies" />
318 for more info.
319 </para></important>
320
321 <para>
322 You can specify which services Tor users may access via
323 your exit relay using <option>exitPolicy</option> option.
324 </para>
325 </listitem>
326 </varlistentry>
327
328 <varlistentry>
329 <term><literal>relay</literal></term>
330 <listitem>
331 <para>
332 Regular relay. This allows Tor users to relay onion
333 traffic to other Tor nodes, but not to public
334 Internet.
335 </para>
336
337 <important><para>
338 Note that some misconfigured and/or disrespectful
339 towards privacy sites will block you even if your
340 relay is not an exit relay. That is, just being listed
341 in a public relay directory can have unwanted
342 consequences.
343
344 Which means you might not want to use
345 this role if you browse public Internet from the same
346 network as your relay, unless you want to write
347 e-mails to those sites (you should!).
348 </para></important>
349
350 <para>
351 See
352 <link xlink:href="https://www.torproject.org/docs/tor-doc-relay.html.en" />
353 for more info.
354 </para>
355 </listitem>
356 </varlistentry>
357
358 <varlistentry>
359 <term><literal>bridge</literal></term>
360 <listitem>
361 <para>
362 Regular bridge. Works like a regular relay, but
363 doesn't list you in the public relay directory and
364 hides your Tor node behind obfs4proxy.
365 </para>
366
367 <para>
368 Using this option will make Tor advertise your bridge
369 to users through various mechanisms like
370 <link xlink:href="https://bridges.torproject.org/" />, though.
371 </para>
372
373 <important>
374 <para>
375 WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVICE.
376 Consult with your lawer when in doubt.
377 </para>
378
379 <para>
380 This role should be safe to use in most situations
381 (unless the act of forwarding traffic for others is
382 a punishable offence under your local laws, which
383 would be pretty insane as it would make ISP
384 illegal).
385 </para>
386 </important>
387
388 <para>
389 See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" />
390 for more info.
391 </para>
392 </listitem>
393 </varlistentry>
394
395 <varlistentry>
396 <term><literal>private-bridge</literal></term>
397 <listitem>
398 <para>
399 Private bridge. Works like regular bridge, but does
400 not advertise your node in any way.
401 </para>
402
403 <para>
404 Using this role means that you won't contribute to Tor
405 network in any way unless you advertise your node
406 yourself in some way.
407 </para>
408
409 <para>
410 Use this if you want to run a private bridge, for
411 example because you'll give out your bridge address
412 manually to your friends.
413 </para>
414
415 <para>
416 Switching to this role after measurable time in
417 "bridge" role is pretty useless as some Tor users
418 would have learned about your node already. In the
419 latter case you can still change
420 <option>port</option> option.
421 </para>
422
423 <para>
424 See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" />
425 for more info.
426 </para>
427 </listitem>
428 </varlistentry>
429 </variablelist>
430 '';
431 };
432
433 bridgeTransports = mkOption {
434 type = types.listOf types.str;
435 default = ["obfs4"];
436 example = ["obfs2" "obfs3" "obfs4" "scramblesuit"];
437 description = "List of pluggable transports";
438 };
439
440 nickname = mkOption {
441 type = types.str;
442 default = "anonymous";
443 description = ''
444 A unique handle for your TOR relay.
445 '';
446 };
447
448 contactInfo = mkOption {
449 type = types.nullOr types.str;
450 default = null;
451 example = "admin@relay.com";
452 description = ''
453 Contact information for the relay owner (e.g. a mail
454 address and GPG key ID).
455 '';
456 };
457
458 accountingMax = mkOption {
459 type = types.nullOr types.str;
460 default = null;
461 example = "450 GBytes";
462 description = ''
463 Specify maximum bandwidth allowed during an accounting period. This
464 allows you to limit overall tor bandwidth over some time period.
465 See the <literal>AccountingMax</literal> option by looking at the
466 tor manual <citerefentry><refentrytitle>tor</refentrytitle>
467 <manvolnum>1</manvolnum></citerefentry> for more.
468
469 Note this limit applies individually to upload and
470 download; if you specify <literal>"500 GBytes"</literal>
471 here, then you may transfer up to 1 TBytes of overall
472 bandwidth (500 GB upload, 500 GB download).
473 '';
474 };
475
476 accountingStart = mkOption {
477 type = types.nullOr types.str;
478 default = null;
479 example = "month 1 1:00";
480 description = ''
481 Specify length of an accounting period. This allows you to limit
482 overall tor bandwidth over some time period. See the
483 <literal>AccountingStart</literal> option by looking at the tor
484 manual <citerefentry><refentrytitle>tor</refentrytitle>
485 <manvolnum>1</manvolnum></citerefentry> for more.
486 '';
487 };
488
489 bandwidthRate = mkOption {
490 type = types.nullOr types.int;
491 default = null;
492 example = 100;
493 description = ''
494 Specify this to limit the bandwidth usage of relayed (server)
495 traffic. Your own traffic is still unthrottled. Units: bytes/second.
496 '';
497 };
498
499 bandwidthBurst = mkOption {
500 type = types.nullOr types.int;
501 default = cfg.relay.bandwidthRate;
502 example = 200;
503 description = ''
504 Specify this to allow bursts of the bandwidth usage of relayed (server)
505 traffic. The average usage will still be as specified in relayBandwidthRate.
506 Your own traffic is still unthrottled. Units: bytes/second.
507 '';
508 };
509
510 address = mkOption {
511 type = types.nullOr types.str;
512 default = null;
513 example = "noname.example.com";
514 description = ''
515 The IP address or full DNS name for advertised address of your relay.
516 Leave unset and Tor will guess.
517 '';
518 };
519
520 port = mkOption {
521 type = types.either types.int types.str;
522 example = 143;
523 description = ''
524 What port to advertise for Tor connections. This corresponds to the
525 <literal>ORPort</literal> section in the Tor manual; see
526 <citerefentry><refentrytitle>tor</refentrytitle>
527 <manvolnum>1</manvolnum></citerefentry> for more details.
528
529 At a minimum, you should just specify the port for the
530 relay to listen on; a common one like 143, 22, 80, or 443
531 to help Tor users who may have very restrictive port-based
532 firewalls.
533 '';
534 };
535
536 exitPolicy = mkOption {
537 type = types.nullOr types.str;
538 default = null;
539 example = "accept *:6660-6667,reject *:*";
540 description = ''
541 A comma-separated list of exit policies. They're
542 considered first to last, and the first match wins. If you
543 want to _replace_ the default exit policy, end this with
544 either a reject *:* or an accept *:*. Otherwise, you're
545 _augmenting_ (prepending to) the default exit policy.
546 Leave commented to just use the default, which is
547 available in the man page or at
548 <link xlink:href="https://www.torproject.org/documentation.html" />.
549
550 Look at
551 <link xlink:href="https://www.torproject.org/faq-abuse.html#TypicalAbuses" />
552 for issues you might encounter if you use the default
553 exit policy.
554
555 If certain IPs and ports are blocked externally, e.g. by
556 your firewall, you should update your exit policy to
557 reflect this -- otherwise Tor users will be told that
558 those destinations are down.
559 '';
560 };
561 };
562
563 hiddenServices = mkOption {
564 description = ''
565 A set of static hidden services that terminate their Tor
566 circuits at this node.
567
568 Every element in this set declares a virtual onion host.
569
570 You can specify your onion address by putting corresponding
571 private key to an appropriate place in ${torDirectory}.
572
573 For services without private keys in ${torDirectory} Tor
574 daemon will generate random key pairs (which implies random
575 onion addresses) on restart. The latter could take a while,
576 please be patient.
577
578 <note><para>
579 Hidden services can be useful even if you don't intend to
580 actually <emphasis>hide</emphasis> them, since they can
581 also be seen as a kind of NAT traversal mechanism.
582
583 E.g. the example will make your sshd, whatever runs on
584 "8080" and your mail server available from anywhere where
585 the Tor network is available (which, with the help from
586 bridges, is pretty much everywhere), even if both client
587 and server machines are behind NAT you have no control
588 over.
589 </para></note>
590 '';
591 default = {};
592 example = literalExample ''
593 { "my-hidden-service-example".map = [
594 { port = 22; } # map ssh port to this machine's ssh
595 { port = 80; toPort = 8080; } # map http port to whatever runs on 8080
596 { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can
597 ];
598 }
599 '';
600 type = types.loaOf (types.submodule ({name, ...}: {
601 options = {
602
603 name = mkOption {
604 type = types.str;
605 description = ''
606 Name of this tor hidden service.
607
608 This is purely descriptive.
609
610 After restarting Tor daemon you should be able to
611 find your .onion address in
612 <literal>${torDirectory}/onion/$name/hostname</literal>.
613 '';
614 };
615
616 map = mkOption {
617 default = [];
618 description = "Port mapping for this hidden service.";
619 type = types.listOf (types.submodule ({config, ...}: {
620 options = {
621
622 port = mkOption {
623 type = types.either types.int types.str;
624 example = 80;
625 description = ''
626 Hidden service port to "bind to".
627 '';
628 };
629
630 destination = mkOption {
631 internal = true;
632 type = types.str;
633 description = "Forward these connections where?";
634 };
635
636 toHost = mkOption {
637 type = types.str;
638 default = "127.0.0.1";
639 description = "Mapping destination host.";
640 };
641
642 toPort = mkOption {
643 type = types.either types.int types.str;
644 example = 8080;
645 description = "Mapping destination port.";
646 };
647
648 };
649
650 config = {
651 toPort = mkDefault config.port;
652 destination = mkDefault "${config.toHost}:${toString config.toPort}";
653 };
654 }));
655 };
656
657 authorizeClient = mkOption {
658 default = null;
659 description = "If configured, the hidden service is accessible for authorized clients only.";
660 type = types.nullOr (types.submodule ({...}: {
661
662 options = {
663
664 authType = mkOption {
665 type = types.enum [ "basic" "stealth" ];
666 description = ''
667 Either <literal>"basic"</literal> for a general-purpose authorization protocol
668 or <literal>"stealth"</literal> for a less scalable protocol
669 that also hides service activity from unauthorized clients.
670 '';
671 };
672
673 clientNames = mkOption {
674 type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+");
675 description = ''
676 Only clients that are listed here are authorized to access the hidden service.
677 Generated authorization data can be found in <filename>${torDirectory}/onion/$name/hostname</filename>.
678 Clients need to put this authorization data in their configuration file using <literal>HidServAuth</literal>.
679 '';
680 };
681 };
682 }));
683 };
684
685 version = mkOption {
686 default = null;
687 description = "Rendezvous service descriptor version to publish for the hidden service. Currently, versions 2 and 3 are supported. (Default: 2)";
688 type = types.nullOr (types.enum [ 2 3 ]);
689 };
690 };
691
692 config = {
693 name = mkDefault name;
694 };
695 }));
696 };
697 };
698 };
699
700 config = mkIf cfg.enable {
701 # Not sure if `cfg.relay.role == "private-bridge"` helps as tor
702 # sends a lot of stats
703 warnings = optional (cfg.relay.enable && cfg.hiddenServices != {})
704 ''
705 Running Tor hidden services on a public relay makes the
706 presence of hidden services visible through simple statistical
707 analysis of publicly available data.
708
709 You can safely ignore this warning if you don't intend to
710 actually hide your hidden services. In either case, you can
711 always create a container/VM with a separate Tor daemon instance.
712 '';
713
714 users.groups.tor.gid = config.ids.gids.tor;
715 users.users.tor =
716 { description = "Tor Daemon User";
717 createHome = true;
718 home = torDirectory;
719 group = "tor";
720 uid = config.ids.uids.tor;
721 };
722
723 systemd.services.tor =
724 { description = "Tor Daemon";
725 path = [ pkgs.tor ];
726
727 wantedBy = [ "multi-user.target" ];
728 after = [ "network.target" ];
729 restartTriggers = [ torRcFile ];
730
731 serviceConfig = {
732 Type = "simple";
733 User = "tor";
734 Group = "tor";
735 #DynamicUser = true;
736 # Translated from the upstream contrib/dist/tor.service.in
737 ExecStartPre = "${cfg.package}/bin/tor -f ${torRcFile} --verify-config";
738 ExecStart = "${cfg.package}/bin/tor -f ${torRcFile}";
739 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
740 KillSignal = "SIGINT";
741 TimeoutSec = 30;
742 Restart = "on-failure";
743 LimitNOFILE = 32768;
744
745 # Hardening
746 # this seems to unshare /run despite what systemd.exec(5) says
747 PrivateTmp = true;
748 StateDirectoryMode = "0700";
749 StateDirectory = ["tor" "tor/onion"];
750 RuntimeDirectory = ["tor"];
751 RuntimeDirectoryMode = "0750";
752
753 AmbientCapabilities = [""] ++ lib.optional (cfg.relay.port < 1024) "CAP_NET_BIND_SERVICE";
754 CapabilityBoundingSet = [""] ++ lib.optional (cfg.relay.port < 1024) "CAP_NET_BIND_SERVICE";
755 /*
756 # ProtectClock= adds DeviceAllow=char-rtc r
757 DeviceAllow = "";
758 LockPersonality = true;
759 MemoryDenyWriteExecute = true;
760 NoNewPrivileges = true;
761 PrivateDevices = true;
762 PrivateMounts = true;
763 PrivateNetwork = mkDefault false;
764 PrivateTmp = true;
765 PrivateUsers = true;
766 ProtectClock = true;
767 ProtectControlGroups = true;
768 # ProtectHome=true would not allow BindPaths= to work accross /home,
769 # and ProtectHome=tmpfs would break statfs(),
770 # preventing transmission-daemon to report the available free space.
771 # However, RootDirectory= is used, so this is not a security concern
772 # since there would be nothing in /home but any BindPaths= wanted by the user.
773 ProtectHome = "read-only";
774 ProtectHostname = true;
775 ProtectKernelLogs = true;
776 ProtectKernelModules = true;
777 ProtectKernelTunables = true;
778 ProtectSystem = "strict";
779 RemoveIPC = true;
780 # AF_UNIX may become usable one day:
781 # https://github.com/transmission/transmission/issues/441
782 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
783 RestrictNamespaces = true;
784 RestrictRealtime = true;
785 RestrictSUIDSGID = true;
786 SystemCallFilter = [
787 "@system-service"
788 # Groups in @system-service which do not contain a syscall
789 # listed by perf stat -e 'syscalls:sys_enter_*' transmission-daemon -f
790 # in tests, and seem likely not necessary for transmission-daemon.
791 "~@aio" "~@chown" "~@keyring" "~@memlock" "~@resources" "~@setuid" "~@timer"
792 # In the @privileged group, but reached when querying infos through RPC (eg. with stig).
793 "quotactl"
794 ];
795 SystemCallArchitectures = "native";
796 SystemCallErrorNumber = "EPERM";
797 */
798 };
799 };
800
801 environment.systemPackages = [ cfg.package ];
802
803 services.privoxy = mkIf (cfg.client.enable && cfg.client.privoxy.enable) {
804 enable = true;
805 extraConfig = ''
806 forward-socks4a / ${cfg.client.socksListenAddressFaster} .
807 toggle 1
808 enable-remote-toggle 0
809 enable-edit-actions 0
810 enable-remote-http-toggle 0
811 '';
812 };
813 };
814 }