From fea553028bbfbe4e82588eb8e22b72d64973764b Mon Sep 17 00:00:00 2001 From: Julien Moutinho <julm@sourcephile.fr> Date: Sat, 5 Sep 2020 08:23:00 +0200 Subject: [PATCH] tor: preparation --- flake.lock | 8 +- flake.nix | 14 +- machines/losurdo.nix | 2 +- machines/losurdo/fail2ban.nix | 2 +- machines/losurdo/networking.nix | 5 +- machines/losurdo/networking/nftables.nix | 219 +++-- machines/losurdo/networking/tor.nix | 62 ++ .../losurdo/nginx/sourcephile.fr/losurdo.nix | 3 + machines/losurdo/postgresql.nix | 28 +- machines/losurdo/prosody.nix | 9 +- machines/losurdo/users.nix | 1 + machines/mermet/networking/nftables.nix | 38 +- nixos/modules.nix | 4 + nixos/modules/services/security/tor.nix | 799 ++++++++++++++++++ nixos/profiles/hardware/dl10j.nix | 6 +- nixpkgs/patches/fix-ld-nix-apparmor.diff | 13 - nixpkgs/patches/fix-ld-nix.diff | 66 -- 17 files changed, 1097 insertions(+), 182 deletions(-) create mode 100644 machines/losurdo/networking/tor.nix create mode 100644 nixos/modules/services/security/tor.nix delete mode 100644 nixpkgs/patches/fix-ld-nix-apparmor.diff delete mode 100644 nixpkgs/patches/fix-ld-nix.diff diff --git a/flake.lock b/flake.lock index 675f3ed..dd0d514 100644 --- a/flake.lock +++ b/flake.lock @@ -17,17 +17,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1598251641, - "narHash": "sha256-5XRLDKBbFEyVdwbI+pXAkLFgM03wAEZCvH1sr4uSFKI=", + "lastModified": 1599246614, + "narHash": "sha256-l2QyMGtf8H4jbgbAPefbevMeYOufTzbDAdj35gaaCoY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a332da8588aeea4feb9359d23f58d95520899e3c", + "rev": "e3e39aa84e9d8c381d9f420f08a57eccb6e0a285", "type": "github" }, "original": { "owner": "NixOS", "repo": "nixpkgs", - "rev": "a332da8588aeea4feb9359d23f58d95520899e3c", + "rev": "e3e39aa84e9d8c381d9f420f08a57eccb6e0a285", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 4d89519..466f1cb 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { -inputs.nixpkgs.url = "github:NixOS/nixpkgs/a332da8588aeea4feb9359d23f58d95520899e3c"; +inputs.nixpkgs.url = "github:NixOS/nixpkgs/e3e39aa84e9d8c381d9f420f08a57eccb6e0a285"; inputs.flake-utils.url = "github:numtide/flake-utils"; inputs.shell = { type = "path"; path = "./shell"; flake = false; }; inputs.secrets = { type = "path"; path = "./sec"; flake = false; }; @@ -25,7 +25,7 @@ outputs = inputs: let } { meta.description = "apparmor: fix and improve the service"; url = "https://github.com/NixOS/nixpkgs/pull/93457.diff"; - sha256 = "8QNOKDWNJiZujAvmDtZPZI5VRc+oh40IqjTYn/RCUi4="; + sha256 = "sha256-GxTZvaQrUxxV8vd7DT42k0xEXMQt2mAgEdiY3fsA8Gs="; } { meta.description = "nixos/security.gnupg: provisioning GnuPG-protected secrets through the Nix store"; url = "https://github.com/NixOS/nixpkgs/pull/93659.diff"; @@ -33,11 +33,7 @@ outputs = inputs: let } { meta.description = "nixos/croc: init"; url = "https://github.com/NixOS/nixpkgs/pull/93629.diff"; - sha256 = "0fv3lpj244hvxyixxv4akrr70jv5wwbhb3kmbmd2yskx59a71rch"; - } - { meta.description = "nixos/biboumi: init"; - url = "https://github.com/NixOS/nixpkgs/pull/94917.diff"; - sha256 = "sha256-kUYk6Lr31rXUkbGnnIfpls6v1Jw/EVF4giByoH4MfEk="; + sha256 = "sha256-hzs5Z9cYCo6aNFfylB37W+1neejV4/kVyM1QmqVhVww="; } { meta.description = "dovecot_fts_xapian: 1.3.1 -> 1.3.3"; url = "https://github.com/NixOS/nixpkgs/pull/94938.diff"; @@ -45,7 +41,7 @@ outputs = inputs: let } { meta.description = "nixos-install: add support for flakes"; url = "https://github.com/NixOS/nixpkgs/pull/95194.diff"; - sha256 = "sha256-Y0KE9i+NFa3xLDdXXcVEAbpm//W7tCeOtKArgf2Dw2M="; + sha256 = "sha256-7EsqWguUWC4CQCMV0ZKQmjlsuLnQuR2/gI7Z/8sM8ww="; } { meta.description = "transmission: use freeformType on settings"; url = "https://github.com/NixOS/nixpkgs/pull/96655.diff"; @@ -53,10 +49,8 @@ outputs = inputs: let } ]; localNixpkgsPatches = [ - #nixpkgs/patches/security.apparmor.diff #nixpkgs/patches/fix-ld-nix.diff #nixpkgs/patches/fix-ld-nix-apparmor.diff - #nixpkgs/patches/nixos-install.diff ]; originPkgs = inputs.nixpkgs.legacyPackages."x86_64-linux"; nixpkgs = originPkgs.applyPatches { diff --git a/machines/losurdo.nix b/machines/losurdo.nix index 5f1f9ef..8984cb7 100644 --- a/machines/losurdo.nix +++ b/machines/losurdo.nix @@ -30,7 +30,7 @@ modules = [ losurdo/hardware.nix losurdo/networking.nix losurdo/nginx.nix - losurdo/postgresql.nix + #losurdo/postgresql.nix losurdo/prosody.nix (inputs.secrets + "/machines/losurdo/prosody.nix") losurdo/sanoid.nix diff --git a/machines/losurdo/fail2ban.nix b/machines/losurdo/fail2ban.nix index 79ae851..e1b2794 100644 --- a/machines/losurdo/fail2ban.nix +++ b/machines/losurdo/fail2ban.nix @@ -1,7 +1,7 @@ { pkgs, lib, config, machines, ... }: { services.openssh.logLevel = "VERBOSE"; -services.postgresql.extraConfig = "log_line_prefix = '%h '"; +services.postgresql.settings.log_line_prefix = "%h "; /* systemd.services.nftables.postStart = '' systemctl reload fail2ban ''; */ diff --git a/machines/losurdo/networking.nix b/machines/losurdo/networking.nix index b6c3420..6f7ade2 100644 --- a/machines/losurdo/networking.nix +++ b/machines/losurdo/networking.nix @@ -1,6 +1,7 @@ { pkgs, lib, config, machineName, machines, wireguard, ... }: with builtins; let + inherit (config) networking; #lanIPv4 = "192.168.1.215"; lanNet = "192.168.1.0/24"; #lanIPv4Gateway = "192.168.1.1"; @@ -10,6 +11,7 @@ imports = [ networking/nftables.nix networking/ssh.nix networking/wireguard.nix + networking/tor.nix ]; boot.initrd.network = { @@ -89,8 +91,9 @@ boot.kernel.sysctl = { networking = { hostName = machineName; domain = "sourcephile.fr"; - + useDHCP = false; + enableIPv6 = true; /* defaultGateway = { address = lanIPv4Gateway; diff --git a/machines/losurdo/networking/nftables.nix b/machines/losurdo/networking/nftables.nix index dc4a1c2..1e21912 100644 --- a/machines/losurdo/networking/nftables.nix +++ b/machines/losurdo/networking/nftables.nix @@ -2,6 +2,7 @@ let inherit (builtins) hasAttr readFile; inherit (pkgs.lib) unlinesAttrs; + inherit (config) networking; inherit (config.users) users groups; in { @@ -15,25 +16,21 @@ networking.nftables = { table inet filter { set lograte4 { type ipv4_addr; size 65535; flags dynamic; } set lograte6 { type ipv6_addr; size 65535; flags dynamic; } + chain block { + add @lograte4 { ip saddr limit rate 1/minute } log level warn prefix "block: " + add @lograte6 { ip6 saddr limit rate 1/minute } log level warn prefix "block: " + counter drop + } chain ping-flood { add @lograte4 { ip saddr limit rate 1/minute } log level warn prefix "ping-flood: " add @lograte6 { ip6 saddr limit rate 1/minute } log level warn prefix "ping-flood: " counter drop } - chain check-ping { - ip protocol icmp icmp type echo-request limit rate over 10/second burst 20 packets goto ping-flood - ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 10/second burst 20 packets goto ping-flood - } chain smurf { add @lograte4 { ip saddr limit rate 1/minute } log level warn prefix "smurf: " add @lograte6 { ip6 saddr limit rate 1/minute } log level warn prefix "smurf: " counter drop } - chain check-broadcast { - ip saddr 0.0.0.0/32 counter accept comment "DHCP broadcast" - fib saddr type broadcast counter goto smurf - ip saddr 224.0.0.0/4 counter goto smurf - } chain bogus-tcp { add @lograte4 { ip saddr limit rate 1/minute } log level warn prefix "bogus-tcp: " add @lograte6 { ip6 saddr limit rate 1/minute } log level warn prefix "bogus-tcp: " @@ -70,15 +67,14 @@ networking.nftables = { #jump non-internet #ct state new add @connlimit { ip saddr ct count over 20 } counter tcp reject with tcp reset - + # Some .nix append rules here with: add rule inet filter net2fw ... } chain fw2net { - ip daddr 224.0.0.0/4 udp dport 1900 counter accept comment "UPnP" tcp dport { 80, 443 } counter accept comment "HTTP" udp dport 123 skuid ${users.systemd-timesync.name} counter accept comment "NTP" tcp dport 9418 counter accept comment "Git" - + # Some .nix append rules here with: add rule inet filter fw2net ... } chain intra2fw { @@ -90,53 +86,171 @@ networking.nftables = { chain fwd-intra { # Some .nix append rules here with: add rule inet filter fwd-intra ... } + chain icmpv6 { + # Traffic That Must Not Be Dropped + # https://tools.ietf.org/html/rfc4890#section-4.4.1 + ip6 nexthdr ipv6-icmp icmpv6 type destination-unreachable counter accept + ip6 nexthdr ipv6-icmp icmpv6 type packet-too-big counter accept + ip6 nexthdr ipv6-icmp icmpv6 type time-exceeded counter accept + ip6 nexthdr ipv6-icmp icmpv6 type parameter-problem counter accept + + # Address Configuration and Router Selection messages + # (must be received with hop limit = 255) + ip6 nexthdr ipv6-icmp icmpv6 type nd-router-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-router-advert ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-advert ip6 hoplimit 255 counter accept + # redirect messages provide a significant security risk, + # and administrators should take a case-by-case approach + # to whether firewalls, routers in general, + # and other nodes should accept these messages + #ip6 nexthdr ipv6-icmp icmpv6 type redirect ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-advert ip6 hoplimit 255 counter accept + + # Link-local multicast receiver notification messages + # (must have link-local source address) + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-query ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-report ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-done ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld2-listener-report ip6 saddr fe80::/10 counter accept + + # SEND Certificate Path notification messages + # (must be received with hop limit = 255) + ip6 nexthdr ipv6-icmp icmpv6 type 148 ip6 hoplimit 255 counter accept comment "certificate-path-solicitation" + ip6 nexthdr ipv6-icmp icmpv6 type 149 ip6 hoplimit 255 counter accept comment "certificate-path-advertisement" + + # Multicast Router Discovery messages + # (must have link-local source address and hop limit = 1) + ip6 nexthdr ipv6-icmp icmpv6 type 151 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-advertisement" + ip6 nexthdr ipv6-icmp icmpv6 type 152 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-solicitation" + ip6 nexthdr ipv6-icmp icmpv6 type 153 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-termination" + } chain input { type filter hook input priority 0 policy drop - + iifname lo accept - + jump check-tcp - jump check-ping - jump check-broadcast - + ct state { established, related } accept + + # (multicast) ping + ip protocol icmp icmp type echo-reply counter accept + + ${lib.optionalString networking.enableIPv6 '' + # drop packets with rh0 headers + rt type 0 jump block + rt type 0 jump block + rt type 0 jump block + + # (multicast) ping + ip6 nexthdr ipv6-icmp icmpv6 type echo-reply counter accept + ''} + ct state invalid counter drop - + + ip protocol icmp icmp type destination-unreachable counter accept + ip protocol icmp icmp type time-exceeded counter accept + ip protocol icmp icmp type parameter-problem counter accept + ip protocol icmp icmp type echo-request limit rate over 10/second burst 20 packets goto ping-flood + ip protocol icmp icmp type echo-request counter accept + # echo-reply is handled before invalid packets to allow multicast ping + # which do not have an associated connection. + + #ip daddr 224.0.0.251 udp dport 5353 counter accept comment "mDNS" + #ip daddr 239.255.255.250 udp dport 1900 counter accept comment "UPnP" + #ip saddr 0.0.0.0/32 counter accept comment "DHCP" + #ip udp sport 67 udp dport 68 counter accept comment "DHCP" + + ${lib.optionalString networking.enableIPv6 '' + # Traffic That Must Not Be Dropped + # https://tools.ietf.org/html/rfc4890#section-4.4.1 + ip6 nexthdr ipv6-icmp icmpv6 type destination-unreachable counter accept + ip6 nexthdr ipv6-icmp icmpv6 type packet-too-big counter accept + ip6 nexthdr ipv6-icmp icmpv6 type time-exceeded counter accept + ip6 nexthdr ipv6-icmp icmpv6 type parameter-problem counter accept + + # Connectivity checking messages + ip6 nexthdr ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 20 packets goto ping-flood + ip6 nexthdr ipv6-icmp icmpv6 type echo-request counter accept + # echo-reply is handled before invalid packets to allow multicast ping + # which do not have an associated connection. + + # Address Configuration and Router Selection messages + # (must be received with hop limit = 255) + ip6 nexthdr ipv6-icmp icmpv6 type nd-router-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-router-advert ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-advert ip6 hoplimit 255 counter accept + # redirect messages provide a significant security risk, + # and administrators should take a case-by-case approach + # to whether firewalls, routers in general, + # and other nodes should accept these messages + #ip6 nexthdr ipv6-icmp icmpv6 type redirect ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-solicit ip6 hoplimit 255 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-advert ip6 hoplimit 255 counter accept + + # Link-local multicast receiver notification messages + # (must have link-local source address) + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-query ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-report ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-done ip6 saddr fe80::/10 counter accept + ip6 nexthdr ipv6-icmp icmpv6 type mld2-listener-report ip6 saddr fe80::/10 counter accept + + # SEND Certificate Path notification messages + # (must be received with hop limit = 255) + ip6 nexthdr ipv6-icmp icmpv6 type 148 ip6 hoplimit 255 counter accept comment "certificate-path-solicitation" + ip6 nexthdr ipv6-icmp icmpv6 type 149 ip6 hoplimit 255 counter accept comment "certificate-path-advertisement" + + # Multicast Router Discovery messages + # (must have link-local source address and hop limit = 1) + ip6 nexthdr ipv6-icmp icmpv6 type 151 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-advertisement" + ip6 nexthdr ipv6-icmp icmpv6 type 152 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-solicitation" + ip6 nexthdr ipv6-icmp icmpv6 type 153 ip6 saddr fe80::/10 ip6 hoplimit 1 counter accept comment "multicast-router-termination" + + ip6 daddr ff02::fb udp dport 5353 counter accept comment "mDNS" + ip6 daddr ff02::f udp dport 1900 counter accept comment "UPnP" + ''} + + ip saddr 224.0.0.0/4 counter goto smurf + fib saddr type broadcast counter goto smurf + # admin services tcp dport 22 counter accept comment "SSH" udp dport 60000-61000 counter accept comment "Mosh" - - # ICMP - ip protocol icmp icmp type echo-request counter accept + + # Some .nix append gotos here with: add rule inet filter input iffname ... goto ... + } + chain forward { + type filter hook forward priority 0 + policy drop + ip protocol icmp icmp type destination-unreachable counter accept - ip protocol icmp icmp type router-solicitation counter accept - ip protocol icmp icmp type router-advertisement counter accept ip protocol icmp icmp type time-exceeded counter accept ip protocol icmp icmp type parameter-problem counter accept - ip protocol icmp log level warn prefix "net2fw: icmpv: " counter accept - #ip protocol icmp icmp type { echo-request, destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } counter accept - - ip6 nexthdr icmpv6 icmpv6 type echo-request counter accept - ip6 nexthdr icmpv6 icmpv6 type nd-neighbor-solicit counter accept - ip6 nexthdr icmpv6 icmpv6 type nd-neighbor-advert counter accept - ip6 nexthdr icmpv6 icmpv6 type nd-router-solicit counter accept - ip6 nexthdr icmpv6 icmpv6 type nd-router-advert counter accept - ip6 nexthdr icmpv6 icmpv6 type mld-listener-query counter accept - ip6 nexthdr icmpv6 icmpv6 type mld-listener-report counter accept - ip6 nexthdr icmpv6 icmpv6 type mld-listener-reduction counter accept - ip6 nexthdr icmpv6 icmpv6 type destination-unreachable counter accept - ip6 nexthdr icmpv6 icmpv6 type packet-too-big counter accept - ip6 nexthdr icmpv6 icmpv6 type time-exceeded counter accept - ip6 nexthdr icmpv6 icmpv6 type parameter-problem counter accept - ip6 nexthdr icmpv6 icmpv6 type ind-neighbor-solicit counter accept - ip6 nexthdr icmpv6 icmpv6 type ind-neighbor-advert counter accept - ip6 nexthdr icmpv6 icmpv6 type mld2-listener-report counter accept - ip6 nexthdr icmpv6 log level warn prefix "net2fw: icmpv6: " counter accept - #ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, mld-listener-report, mld-listener-reduction, destination-unreachable, packet-too-big, time-exceeded, parameter-problem, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } counter accept + ip protocol icmp icmp type echo-request counter accept - # Some .nix append gotos here with: add rule inet filter input iffname ... goto ... + ${lib.optionalString networking.enableIPv6 '' + # Traffic That Must Not Be Dropped + # https://tools.ietf.org/html/rfc4890#section-4.3.1 + ip6 nexthdr ipv6-icmp icmpv6 type destination-unreachable counter accept + ip6 nexthdr ipv6-icmp icmpv6 type packet-too-big counter accept + ip6 nexthdr ipv6-icmp icmpv6 type time-exceeded counter accept + ip6 nexthdr ipv6-icmp icmpv6 type parameter-problem counter accept + + ip6 nexthdr ipv6-icmp icmpv6 type echo-request counter accept + ip6 nexthdr ipv6-icmp icmpv6 type echo-reply counter accept + + # Traffic That Normally Should Not Be Dropped + # https://tools.ietf.org/html/rfc4890#section-4.3.2 + ip6 nexthdr ipv6-icmp icmpv6 type 144 counter accept comment "home-agent-address-discovery-request" + ip6 nexthdr ipv6-icmp icmpv6 type 145 counter accept comment "home-agent-address-discovery-reply" + ip6 nexthdr ipv6-icmp icmpv6 type 146 counter accept comment "mobile-prefix-solicitation" + ip6 nexthdr ipv6-icmp icmpv6 type 147 counter accept comment "mobile-prefix-advertisement" + ''} } chain output { type filter hook output priority 0 @@ -147,18 +261,23 @@ networking.nftables = { ct state { related, established } accept ct state invalid counter drop - # ICMP ip protocol icmp counter accept - ip6 nexthdr icmpv6 counter accept + ip daddr 224.0.0.0/4 udp dport 1900 counter accept comment "UPnP" + + ${lib.optionalString networking.enableIPv6 '' + # Connectivity checking messages + ip6 nexthdr ipv6-icmp icmpv6 type echo-request counter accept + ip6 nexthdr ipv6-icmp icmpv6 type echo-reply counter accept + jump icmpv6 + + + ip6 nexthdr udp ip6 saddr fe80::/10 udp sport 547 ip6 daddr fe80::/10 udp dport 546 counter accept comment "DHCPv6" + ''} tcp dport 22 counter accept comment "SSH" # Some .nix append gotos here with: add rule inet filter output oifname ... goto ... } - chain forward { - type filter hook forward priority 0 - policy drop - } } ''; }; diff --git a/machines/losurdo/networking/tor.nix b/machines/losurdo/networking/tor.nix new file mode 100644 index 0000000..21bbc8a --- /dev/null +++ b/machines/losurdo/networking/tor.nix @@ -0,0 +1,62 @@ +{ pkgs, lib, config, ... }: +let inherit (config) networking; in +{ +environment.systemPackages = [ + pkgs.tor +]; + +systemd.services.tor.serviceConfig.StateDirectory = [ + "tor" + "tor/onion" + "tor/onion/${networking.domain}" +]; +systemd.services.tor.serviceConfig.StateDirectoryMode = "0700"; +services.tor = { + enable = true; + enableGeoIP = false; + hiddenServices = { + "${networking.domain}/${networking.hostName}".map = [ + { port = 22; } + ]; + }; + extraConfig = '' + ClientUseIPv4 1 + ClientUseIPv6 1 + ClientPreferIPv6ORPort 0 + ''; +}; +/* +# copy your onion folder +boot.initrd.secrets = { + "/etc/tor/onion/bootup" = /home/tony/tor/onion; # maybe find a better spot to store this. +}; + +# copy tor to you initrd +boot.initrd.extraUtilsCommands = '' + copy_bin_and_libs ${pkgs.tor}/bin/tor +''; + +# start tor during boot process +boot.initrd.network.postCommands = let + torRc = (pkgs.writeText "tor.rc" '' + DataDirectory /etc/tor + SOCKSPort 127.0.0.1:9050 IsolateDestAddr + SOCKSPort 127.0.0.1:9063 + HiddenServiceDir /etc/tor/onion/bootup + HiddenServicePort 22 127.0.0.1:22 + ''); +in '' + echo "tor: preparing onion folder" + # have to do this otherwise tor does not want to start + chmod -R 700 /etc/tor + + echo "make sure localhost is up" + ip a a 127.0.0.1/8 dev lo + ip link set lo up + + echo "tor: starting tor" + tor -f ${torRc} --verify-config + tor -f ${torRc} & +''; +*/ +} diff --git a/machines/losurdo/nginx/sourcephile.fr/losurdo.nix b/machines/losurdo/nginx/sourcephile.fr/losurdo.nix index 6b76546..a4d1579 100644 --- a/machines/losurdo/nginx/sourcephile.fr/losurdo.nix +++ b/machines/losurdo/nginx/sourcephile.fr/losurdo.nix @@ -7,6 +7,9 @@ let srv = "losurdo"; in { +services.tor.hiddenServices."${domain}/${srv}".map = [ + { port = 443; toPort = 8443; } +]; services.nginx = { virtualHosts."${srv}" = { serverName = "${srv}.${domain}"; diff --git a/machines/losurdo/postgresql.nix b/machines/losurdo/postgresql.nix index 3f89026..99a4ac4 100644 --- a/machines/losurdo/postgresql.nix +++ b/machines/losurdo/postgresql.nix @@ -27,22 +27,22 @@ services.postgresql = { enable = true; package = pkgs.postgresql_9_6; enableTCPIP = true; - extraConfig = '' + settings = { # ZFS is Copy on Write (CoW). As a result, itâs not possible # to have a torn page because a page canât be partially written # without reverting to the previous copy. - full_page_writes = off - log_connections = true - log_disconnections = true - log_hostname = false - max_connections = 25 - max_locks_per_transaction = 1024 - password_encryption = on # FIXME: replace md5 by scram-sha-256, which requires postfix >= 11 - ssl = on - ssl_cert_file = '/var/lib/acme/${networking.domain}/fullchain.pem' - ssl_key_file = '/var/lib/acme/${networking.domain}/key.pem' - unix_socket_permissions = 0770 - ''; + full_page_writes = false; + log_connections = true; + log_disconnections = true; + log_hostname = false; + max_connections = 25; + max_locks_per_transaction = 1024; + password_encryption = "on"; # FIXME: replace md5 by scram-sha-256, which requires postfix >= 11 + ssl = true; + ssl_cert_file = '/var/lib/acme/${networking.domain}/fullchain.pem'; + ssl_key_file = '/var/lib/acme/${networking.domain}/key.pem'; + unix_socket_permissions = "0770"; + }; authentication = lib.mkForce '' # CONNECTION DATABASE USER AUTH OPTIONS local all postgres peer map=admin @@ -84,7 +84,7 @@ systemd.services.postgresql = { REVOKE ALL ON pg_catalog.pg_database FROM public; REVOKE ALL ON pg_catalog.pg_tablespace FROM public; EOF - + pg_createdb () { local db=$1 local owner=''${owner:-$db} diff --git a/machines/losurdo/prosody.nix b/machines/losurdo/prosody.nix index 1159d7e..d40640a 100644 --- a/machines/losurdo/prosody.nix +++ b/machines/losurdo/prosody.nix @@ -15,6 +15,11 @@ networking.nftables.ruleset = '' add rule inet filter net2fw tcp dport {${lib.concatMapStringsSep "," toString prosody.httpsPorts}} counter accept comment "XMPP HTTPS" add rule inet filter fw2net meta skuid ${prosody.user} counter accept comment "Prosody" ''; +services.tor.hiddenServices."${networking.domain}/xmpp".map = [ + { port = 5222; } + { port = 5269; } + { port = 5000; } +] ++ map (port: {inherit port;}) prosody.httpsPorts; users.groups.acme.members = [ prosody.user ]; security.acme.certs."${networking.domain}" = { postRun = "systemctl reload prosody"; @@ -61,7 +66,7 @@ services.prosody = { turncredentials_host = "turn.${networking.domain}" turncredentials_port = 3478 - + --http_files_dir = "/var/lib/prosody/files" --http_external_url = "https://tmp.${networking.domain}:5281" --https_certificate = "/var/lib/acme/${networking.domain}/fullchain.pem" @@ -72,7 +77,7 @@ services.prosody = { Component "proxy65.${networking.domain}" "proxy65" proxy65_address = "proxy65.${networking.domain}" proxy65_acl = { "${networking.domain}" } - + Component "biboumi.${networking.domain}" component_secret = "useless-secret-on-loopback" ''; diff --git a/machines/losurdo/users.nix b/machines/losurdo/users.nix index 7ae3eb9..6104bd5 100644 --- a/machines/losurdo/users.nix +++ b/machines/losurdo/users.nix @@ -20,6 +20,7 @@ networking.nftables.ruleset = lib.concatMapStringsSep "\n" ''tcp dport 5222 counter accept comment "XMPP"'' ''tcp dport 11371 counter accept comment "HKP"'' ''tcp dport {9009,9010,9011,9012,9013} counter accept comment "croc"'' + #''ip protocol tcp counter accept comment "all"'' ]; users = { diff --git a/machines/mermet/networking/nftables.nix b/machines/mermet/networking/nftables.nix index fc03156..b0b2cb2 100644 --- a/machines/mermet/networking/nftables.nix +++ b/machines/mermet/networking/nftables.nix @@ -23,7 +23,7 @@ networking.nftables = { } chain check-ping { ip protocol icmp icmp type echo-request limit rate over 10/second burst 20 packets goto ping-flood - #ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 10/second burst 20 packets goto ping-flood + #ip6 nexthdr ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 20 packets goto ping-flood } chain smurf { add @lograte4 { ip saddr limit rate 1/minute } log level warn prefix "smurf: " @@ -134,27 +134,27 @@ networking.nftables = { ip protocol icmp log level warn prefix "net2fw: icmpv: " counter accept #ip protocol icmp icmp type { echo-request, destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } counter accept - #ip6 nexthdr icmpv6 icmpv6 type echo-request counter accept - #ip6 nexthdr icmpv6 icmpv6 type nd-neighbor-solicit counter accept - #ip6 nexthdr icmpv6 icmpv6 type nd-neighbor-advert counter accept - #ip6 nexthdr icmpv6 icmpv6 type nd-router-solicit counter accept - #ip6 nexthdr icmpv6 icmpv6 type nd-router-advert counter accept - #ip6 nexthdr icmpv6 icmpv6 type mld-listener-query counter accept - #ip6 nexthdr icmpv6 icmpv6 type mld-listener-report counter accept - #ip6 nexthdr icmpv6 icmpv6 type mld-listener-reduction counter accept - #ip6 nexthdr icmpv6 icmpv6 type destination-unreachable counter accept - #ip6 nexthdr icmpv6 icmpv6 type packet-too-big counter accept - #ip6 nexthdr icmpv6 icmpv6 type time-exceeded counter accept - #ip6 nexthdr icmpv6 icmpv6 type parameter-problem counter accept - #ip6 nexthdr icmpv6 icmpv6 type ind-neighbor-solicit counter accept - #ip6 nexthdr icmpv6 icmpv6 type ind-neighbor-advert counter accept - #ip6 nexthdr icmpv6 icmpv6 type mld2-listener-report counter accept - #ip6 nexthdr icmpv6 log level warn prefix "net2fw: icmpv6: " counter accept - #ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, mld-listener-report, mld-listener-reduction, destination-unreachable, packet-too-big, time-exceeded, parameter-problem, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type echo-request counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-solicit counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type nd-neighbor-advert counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type nd-router-solicit counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type nd-router-advert counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-query counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-report counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type mld-listener-reduction counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type destination-unreachable counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type packet-too-big counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type time-exceeded counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type parameter-problem counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-solicit counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type ind-neighbor-advert counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type mld2-listener-report counter accept + #ip6 nexthdr ipv6-icmp log level warn prefix "net2fw: icmpv6: " counter accept + #ip6 nexthdr ipv6-icmp icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, mld-listener-report, mld-listener-reduction, destination-unreachable, packet-too-big, time-exceeded, parameter-problem, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } counter accept # ICMP ip protocol icmp icmp type echo-request accept - #ip6 nexthdr icmpv6 icmpv6 type echo-request accept + #ip6 nexthdr ipv6-icmp icmpv6 type echo-request accept # Some .nix append gotos here with: add rule inet filter input iffname ... goto ... } diff --git a/nixos/modules.nix b/nixos/modules.nix index 28fae0a..1ccdf06 100644 --- a/nixos/modules.nix +++ b/nixos/modules.nix @@ -5,9 +5,11 @@ imports = [ modules/services/databases/openldap.nix modules/services/mail/public-inbox.nix + modules/services/security/tor.nix #modules/services/torrent/transmission.nix #modules/security/gnupg.nix #modules/services/networking/biboumi.nix + #modules/services/networking/croc.nix #/home/julm/src/nix/nixpkgs/.git-worktree/transmission/nixos/modules/services/torrent/transmission.nix #/home/julm/src/nix/nixpkgs/nixos/modules/services/torrent/transmission.nix #modules/services/mail/mlmmj.nix @@ -15,8 +17,10 @@ imports = [ disabledModules = [ "services/mail/mlmmj.nix" "services/mail/public-inbox.nix" + "services/security/tor.nix" #"security/gnupg.nix" #"services/networking/biboumi.nix" + #"services/networking/croc.nix" #"services/torrent/transmission.nix" ]; } diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix new file mode 100644 index 0000000..b4bc2f6 --- /dev/null +++ b/nixos/modules/services/security/tor.nix @@ -0,0 +1,799 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.tor; + torDirectory = "/var/lib/tor"; + torRunDirectory = "/run/tor"; + + opt = name: value: optionalString (value != null) "${name} ${value}"; + optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}"; + + isolationOptions = { + type = types.listOf (types.enum [ + "IsolateClientAddr" + "IsolateSOCKSAuth" + "IsolateClientProtocol" + "IsolateDestPort" + "IsolateDestAddr" + ]); + default = []; + example = [ + "IsolateClientAddr" + "IsolateSOCKSAuth" + "IsolateClientProtocol" + "IsolateDestPort" + "IsolateDestAddr" + ]; + description = "Tor isolation options"; + }; + + + torRc = '' + User tor + DataDirectory ${torDirectory} + ${optionalString cfg.enableGeoIP '' + GeoIPFile ${cfg.package.geoip}/share/tor/geoip + GeoIPv6File ${cfg.package.geoip}/share/tor/geoip6 + ''} + + ${optint "ControlPort" cfg.controlPort} + ${optionalString cfg.controlSocket.enable "ControlPort unix:${torRunDirectory}/control GroupWritable RelaxDirModeCheck"} + '' + # Client connection config + + optionalString cfg.client.enable '' + SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions} + SOCKSPort ${cfg.client.socksListenAddressFaster} + ${opt "SocksPolicy" cfg.client.socksPolicy} + + ${optionalString cfg.client.transparentProxy.enable '' + TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions} + ''} + + ${optionalString cfg.client.dns.enable '' + DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions} + AutomapHostsOnResolve 1 + AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes} + ''} + '' + # Explicitly disable the SOCKS server if the client is disabled. In + # particular, this makes non-anonymous hidden services possible. + + optionalString (! cfg.client.enable) '' + SOCKSPort 0 + '' + # Relay config + + optionalString cfg.relay.enable '' + ORPort ${toString cfg.relay.port} + ${opt "Address" cfg.relay.address} + ${opt "Nickname" cfg.relay.nickname} + ${opt "ContactInfo" cfg.relay.contactInfo} + + ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate} + ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst} + ${opt "AccountingMax" cfg.relay.accountingMax} + ${opt "AccountingStart" cfg.relay.accountingStart} + + ${if (cfg.relay.role == "exit") then + opt "ExitPolicy" cfg.relay.exitPolicy + else + "ExitPolicy reject *:*"} + + ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) '' + BridgeRelay 1 + ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed + ExtORPort auto + ${optionalString (cfg.relay.role == "private-bridge") '' + ExtraInfoStatistics 0 + PublishServerDescriptor 0 + ''} + ''} + '' + # Hidden services + + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: '' + HiddenServiceDir ${torDirectory}/onion/${v.name} + ${optionalString (v.version != null) "HiddenServiceVersion ${toString v.version}"} + ${flip concatMapStrings v.map (p: '' + HiddenServicePort ${toString p.port} ${p.destination} + '')} + ${optionalString (v.authorizeClient != null) '' + HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames} + ''} + '')) + + cfg.extraConfig; + + torRcFile = pkgs.writeText "torrc" torRc; + +in +{ + imports = [ + (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ]) + (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.") + (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.") + ]; + + options = { + services.tor = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the Tor daemon. By default, the daemon is run without + relay, exit, bridge or client connectivity. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.tor; + defaultText = "pkgs.tor"; + example = literalExample "pkgs.tor"; + description = '' + Tor package to use + ''; + }; + + enableGeoIP = mkOption { + type = types.bool; + default = true; + description = '' + Whenever to configure Tor daemon to use GeoIP databases. + + Disabling this will disable by-country statistics for + bridges and relays and some client and third-party software + functionality. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration. Contents will be added verbatim to the + configuration file at the end. + ''; + }; + + controlPort = mkOption { + type = types.nullOr (types.either types.int types.str); + default = null; + example = 9051; + description = '' + If set, Tor will accept connections on the specified port + and allow them to control the tor process. + ''; + }; + + controlSocket = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable Tor control socket. Control socket is created + in <literal>${torRunDirectory}/control</literal> + ''; + }; + }; + + client = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable Tor daemon to route application + connections. You might want to disable this if you plan + running a dedicated Tor relay. + ''; + }; + + socksListenAddress = mkOption { + type = types.str; + default = "127.0.0.1:9050"; + example = "192.168.0.1:9100"; + description = '' + Bind to this address to listen for connections from + Socks-speaking applications. Provides strong circuit + isolation, separate circuit per IP address. + ''; + }; + + socksListenAddressFaster = mkOption { + type = types.str; + default = "127.0.0.1:9063"; + example = "192.168.0.1:9101"; + description = '' + Bind to this address to listen for connections from + Socks-speaking applications. Same as + <option>socksListenAddress</option> but uses weaker + circuit isolation to provide performance suitable for a + web browser. + ''; + }; + + socksPolicy = mkOption { + type = types.nullOr types.str; + default = null; + example = "accept 192.168.0.0/16, reject *"; + description = '' + Entry policies to allow/deny SOCKS requests based on IP + address. First entry that matches wins. If no SocksPolicy + is set, we accept all (and only) requests from + <option>socksListenAddress</option>. + ''; + }; + + socksIsolationOptions = mkOption (isolationOptions // { + default = ["IsolateDestAddr"]; + }); + + transparentProxy = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable tor transparent proxy"; + }; + + listenAddress = mkOption { + type = types.str; + default = "127.0.0.1:9040"; + example = "192.168.0.1:9040"; + description = '' + Bind transparent proxy to this address. + ''; + }; + + isolationOptions = mkOption isolationOptions; + }; + + dns = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable tor dns resolver"; + }; + + listenAddress = mkOption { + type = types.str; + default = "127.0.0.1:9053"; + example = "192.168.0.1:9053"; + description = '' + Bind tor dns to this address. + ''; + }; + + isolationOptions = mkOption isolationOptions; + + automapHostsSuffixes = mkOption { + type = types.listOf types.str; + default = [".onion" ".exit"]; + example = [".onion"]; + description = "List of suffixes to use with automapHostsOnResolve"; + }; + }; + + privoxy.enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable and configure the system Privoxy to use Tor's + faster port, suitable for HTTP. + + To have anonymity, protocols need to be scrubbed of identifying + information, and this can be accomplished for HTTP by Privoxy. + + Privoxy can also be useful for KDE torification. A good setup would be: + setting SOCKS proxy to the default Tor port, providing maximum + circuit isolation where possible; and setting HTTP proxy to Privoxy + to route HTTP traffic over faster, but less isolated port. + ''; + }; + }; + + relay = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable relaying TOR traffic for others. + + See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" /> + for details. + + Setting this to true requires setting + <option>services.tor.relay.role</option> + and + <option>services.tor.relay.port</option> + options. + ''; + }; + + role = mkOption { + type = types.enum [ "exit" "relay" "bridge" "private-bridge" ]; + description = '' + Your role in Tor network. There're several options: + + <variablelist> + <varlistentry> + <term><literal>exit</literal></term> + <listitem> + <para> + An exit relay. This allows Tor users to access regular + Internet services through your public IP. + </para> + + <important><para> + Running an exit relay may expose you to abuse + complaints. See + <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies" /> + for more info. + </para></important> + + <para> + You can specify which services Tor users may access via + your exit relay using <option>exitPolicy</option> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>relay</literal></term> + <listitem> + <para> + Regular relay. This allows Tor users to relay onion + traffic to other Tor nodes, but not to public + Internet. + </para> + + <important><para> + Note that some misconfigured and/or disrespectful + towards privacy sites will block you even if your + relay is not an exit relay. That is, just being listed + in a public relay directory can have unwanted + consequences. + + Which means you might not want to use + this role if you browse public Internet from the same + network as your relay, unless you want to write + e-mails to those sites (you should!). + </para></important> + + <para> + See + <link xlink:href="https://www.torproject.org/docs/tor-doc-relay.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bridge</literal></term> + <listitem> + <para> + Regular bridge. Works like a regular relay, but + doesn't list you in the public relay directory and + hides your Tor node behind obfs4proxy. + </para> + + <para> + Using this option will make Tor advertise your bridge + to users through various mechanisms like + <link xlink:href="https://bridges.torproject.org/" />, though. + </para> + + <important> + <para> + WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVICE. + Consult with your lawer when in doubt. + </para> + + <para> + This role should be safe to use in most situations + (unless the act of forwarding traffic for others is + a punishable offence under your local laws, which + would be pretty insane as it would make ISP + illegal). + </para> + </important> + + <para> + See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>private-bridge</literal></term> + <listitem> + <para> + Private bridge. Works like regular bridge, but does + not advertise your node in any way. + </para> + + <para> + Using this role means that you won't contribute to Tor + network in any way unless you advertise your node + yourself in some way. + </para> + + <para> + Use this if you want to run a private bridge, for + example because you'll give out your bridge address + manually to your friends. + </para> + + <para> + Switching to this role after measurable time in + "bridge" role is pretty useless as some Tor users + would have learned about your node already. In the + latter case you can still change + <option>port</option> option. + </para> + + <para> + See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + </variablelist> + ''; + }; + + bridgeTransports = mkOption { + type = types.listOf types.str; + default = ["obfs4"]; + example = ["obfs2" "obfs3" "obfs4" "scramblesuit"]; + description = "List of pluggable transports"; + }; + + nickname = mkOption { + type = types.str; + default = "anonymous"; + description = '' + A unique handle for your TOR relay. + ''; + }; + + contactInfo = mkOption { + type = types.nullOr types.str; + default = null; + example = "admin@relay.com"; + description = '' + Contact information for the relay owner (e.g. a mail + address and GPG key ID). + ''; + }; + + accountingMax = mkOption { + type = types.nullOr types.str; + default = null; + example = "450 GBytes"; + description = '' + Specify maximum bandwidth allowed during an accounting period. This + allows you to limit overall tor bandwidth over some time period. + See the <literal>AccountingMax</literal> option by looking at the + tor manual <citerefentry><refentrytitle>tor</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for more. + + Note this limit applies individually to upload and + download; if you specify <literal>"500 GBytes"</literal> + here, then you may transfer up to 1 TBytes of overall + bandwidth (500 GB upload, 500 GB download). + ''; + }; + + accountingStart = mkOption { + type = types.nullOr types.str; + default = null; + example = "month 1 1:00"; + description = '' + Specify length of an accounting period. This allows you to limit + overall tor bandwidth over some time period. See the + <literal>AccountingStart</literal> option by looking at the tor + manual <citerefentry><refentrytitle>tor</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for more. + ''; + }; + + bandwidthRate = mkOption { + type = types.nullOr types.int; + default = null; + example = 100; + description = '' + Specify this to limit the bandwidth usage of relayed (server) + traffic. Your own traffic is still unthrottled. Units: bytes/second. + ''; + }; + + bandwidthBurst = mkOption { + type = types.nullOr types.int; + default = cfg.relay.bandwidthRate; + example = 200; + description = '' + Specify this to allow bursts of the bandwidth usage of relayed (server) + traffic. The average usage will still be as specified in relayBandwidthRate. + Your own traffic is still unthrottled. Units: bytes/second. + ''; + }; + + address = mkOption { + type = types.nullOr types.str; + default = null; + example = "noname.example.com"; + description = '' + The IP address or full DNS name for advertised address of your relay. + Leave unset and Tor will guess. + ''; + }; + + port = mkOption { + type = types.either types.int types.str; + example = 143; + description = '' + What port to advertise for Tor connections. This corresponds to the + <literal>ORPort</literal> section in the Tor manual; see + <citerefentry><refentrytitle>tor</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for more details. + + At a minimum, you should just specify the port for the + relay to listen on; a common one like 143, 22, 80, or 443 + to help Tor users who may have very restrictive port-based + firewalls. + ''; + }; + + exitPolicy = mkOption { + type = types.nullOr types.str; + default = null; + example = "accept *:6660-6667,reject *:*"; + description = '' + A comma-separated list of exit policies. They're + considered first to last, and the first match wins. If you + want to _replace_ the default exit policy, end this with + either a reject *:* or an accept *:*. Otherwise, you're + _augmenting_ (prepending to) the default exit policy. + Leave commented to just use the default, which is + available in the man page or at + <link xlink:href="https://www.torproject.org/documentation.html" />. + + Look at + <link xlink:href="https://www.torproject.org/faq-abuse.html#TypicalAbuses" /> + for issues you might encounter if you use the default + exit policy. + + If certain IPs and ports are blocked externally, e.g. by + your firewall, you should update your exit policy to + reflect this -- otherwise Tor users will be told that + those destinations are down. + ''; + }; + }; + + hiddenServices = mkOption { + description = '' + A set of static hidden services that terminate their Tor + circuits at this node. + + Every element in this set declares a virtual onion host. + + You can specify your onion address by putting corresponding + private key to an appropriate place in ${torDirectory}. + + For services without private keys in ${torDirectory} Tor + daemon will generate random key pairs (which implies random + onion addresses) on restart. The latter could take a while, + please be patient. + + <note><para> + Hidden services can be useful even if you don't intend to + actually <emphasis>hide</emphasis> them, since they can + also be seen as a kind of NAT traversal mechanism. + + E.g. the example will make your sshd, whatever runs on + "8080" and your mail server available from anywhere where + the Tor network is available (which, with the help from + bridges, is pretty much everywhere), even if both client + and server machines are behind NAT you have no control + over. + </para></note> + ''; + default = {}; + example = literalExample '' + { "my-hidden-service-example".map = [ + { port = 22; } # map ssh port to this machine's ssh + { port = 80; toPort = 8080; } # map http port to whatever runs on 8080 + { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can + ]; + } + ''; + type = types.loaOf (types.submodule ({name, ...}: { + options = { + + name = mkOption { + type = types.str; + description = '' + Name of this tor hidden service. + + This is purely descriptive. + + After restarting Tor daemon you should be able to + find your .onion address in + <literal>${torDirectory}/onion/$name/hostname</literal>. + ''; + }; + + map = mkOption { + default = []; + description = "Port mapping for this hidden service."; + type = types.listOf (types.submodule ({config, ...}: { + options = { + + port = mkOption { + type = types.either types.int types.str; + example = 80; + description = '' + Hidden service port to "bind to". + ''; + }; + + destination = mkOption { + internal = true; + type = types.str; + description = "Forward these connections where?"; + }; + + toHost = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Mapping destination host."; + }; + + toPort = mkOption { + type = types.either types.int types.str; + example = 8080; + description = "Mapping destination port."; + }; + + }; + + config = { + toPort = mkDefault config.port; + destination = mkDefault "${config.toHost}:${toString config.toPort}"; + }; + })); + }; + + authorizeClient = mkOption { + default = null; + description = "If configured, the hidden service is accessible for authorized clients only."; + type = types.nullOr (types.submodule ({...}: { + + options = { + + authType = mkOption { + type = types.enum [ "basic" "stealth" ]; + description = '' + Either <literal>"basic"</literal> for a general-purpose authorization protocol + or <literal>"stealth"</literal> for a less scalable protocol + that also hides service activity from unauthorized clients. + ''; + }; + + clientNames = mkOption { + type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+"); + description = '' + Only clients that are listed here are authorized to access the hidden service. + Generated authorization data can be found in <filename>${torDirectory}/onion/$name/hostname</filename>. + Clients need to put this authorization data in their configuration file using <literal>HidServAuth</literal>. + ''; + }; + }; + })); + }; + + version = mkOption { + default = null; + description = "Rendezvous service descriptor version to publish for the hidden service. Currently, versions 2 and 3 are supported. (Default: 2)"; + type = types.nullOr (types.enum [ 2 3 ]); + }; + }; + + config = { + name = mkDefault name; + }; + })); + }; + }; + }; + + config = mkIf cfg.enable { + # Not sure if `cfg.relay.role == "private-bridge"` helps as tor + # sends a lot of stats + warnings = optional (cfg.relay.enable && cfg.hiddenServices != {}) + '' + Running Tor hidden services on a public relay makes the + presence of hidden services visible through simple statistical + analysis of publicly available data. + + You can safely ignore this warning if you don't intend to + actually hide your hidden services. In either case, you can + always create a container/VM with a separate Tor daemon instance. + ''; + + users.groups.tor.gid = config.ids.gids.tor; + users.users.tor = + { description = "Tor Daemon User"; + createHome = true; + home = torDirectory; + group = "tor"; + uid = config.ids.uids.tor; + }; + + # We have to do this instead of using RuntimeDirectory option in + # the service below because systemd has no way to set owners of + # RuntimeDirectory and putting this into the service below + # requires that service to relax it's sandbox since this needs + # writable /run + systemd.services.tor-init = + { description = "Tor Daemon Init"; + wantedBy = [ "tor.service" ]; + script = '' + install -m 0700 -o tor -g tor -d ${torDirectory} ${torDirectory}/onion + install -m 0750 -o tor -g tor -d ${torRunDirectory} + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + + systemd.services.tor = + { description = "Tor Daemon"; + path = [ pkgs.tor ]; + + wantedBy = [ "multi-user.target" ]; + after = [ "tor-init.service" "network.target" ]; + restartTriggers = [ torRcFile ]; + + serviceConfig = + { Type = "simple"; + # Translated from the upstream contrib/dist/tor.service.in + ExecStartPre = "${cfg.package}/bin/tor -f ${torRcFile} --verify-config"; + ExecStart = "${cfg.package}/bin/tor -f ${torRcFile}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + KillSignal = "SIGINT"; + TimeoutSec = 30; + Restart = "on-failure"; + LimitNOFILE = 32768; + + # Hardening + # this seems to unshare /run despite what systemd.exec(5) says + PrivateTmp = mkIf (!cfg.controlSocket.enable) "yes"; + PrivateDevices = "yes"; + ProtectHome = "yes"; + ProtectSystem = "strict"; + InaccessiblePaths = "/home"; + ReadOnlyPaths = "/"; + ReadWritePaths = [ torDirectory torRunDirectory ]; + NoNewPrivileges = "yes"; + + # tor.service.in has this in, but this line it fails to spawn a namespace when using hidden services + #CapabilityBoundingSet = "CAP_SETUID CAP_SETGID CAP_NET_BIND_SERVICE"; + }; + }; + + environment.systemPackages = [ cfg.package ]; + + services.privoxy = mkIf (cfg.client.enable && cfg.client.privoxy.enable) { + enable = true; + extraConfig = '' + forward-socks4a / ${cfg.client.socksListenAddressFaster} . + toggle 1 + enable-remote-toggle 0 + enable-edit-actions 0 + enable-remote-http-toggle 0 + ''; + }; + }; +} diff --git a/nixos/profiles/hardware/dl10j.nix b/nixos/profiles/hardware/dl10j.nix index a66f8ce..0801457 100644 --- a/nixos/profiles/hardware/dl10j.nix +++ b/nixos/profiles/hardware/dl10j.nix @@ -8,6 +8,11 @@ nix = { }; powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; +# https://insanity.industries/post/sata-power-consumption/ +services.udev.extraRules = '' + SUBSYSTEM=="scsi_host", KERNEL=="host*", ATTR{link_power_management_policy}="med_power_with_dipm" +''; + boot.loader = { grub = { enable = true; @@ -71,7 +76,6 @@ boot.kernelParams = [ environment.systemPackages = with pkgs; [ pciutils - #flashrom nvme-cli ]; } diff --git a/nixpkgs/patches/fix-ld-nix-apparmor.diff b/nixpkgs/patches/fix-ld-nix-apparmor.diff deleted file mode 100644 index 7b756a1..0000000 --- a/nixpkgs/patches/fix-ld-nix-apparmor.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/nixos/modules/config/malloc.nix b/nixos/modules/config/malloc.nix -index 5c5752ef515..54ba3048fdb 100644 ---- a/nixos/modules/config/malloc.nix -+++ b/nixos/modules/config/malloc.nix -@@ -90,7 +90,7 @@ in - security.apparmor.includes = { - "abstractions/base" = '' - r /etc/ld-nix.so.preload, -- r ${config.environment.etc."ld-nix.so.preload".source}, -+ r ${config.environment.etc."ld-nix.${pkgs.glibc.src.outputHash}.so.preload".source}, - mr ${providerLibPath}, - ''; - }; diff --git a/nixpkgs/patches/fix-ld-nix.diff b/nixpkgs/patches/fix-ld-nix.diff deleted file mode 100644 index 0743c37..0000000 --- a/nixpkgs/patches/fix-ld-nix.diff +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/nixos/modules/config/malloc.nix b/nixos/modules/config/malloc.nix -index 31a659ee83f..93089c220a2 100644 ---- a/nixos/modules/config/malloc.nix -+++ b/nixos/modules/config/malloc.nix -@@ -84,7 +84,9 @@ in - }; - - config = mkIf (cfg.provider != "libc") { -- environment.etc."ld-nix.so.preload".text = '' -+ # See comment in pkgs/development/libraries/glibc/common.nix -+ # for an explanation about the name of this file. -+ environment.etc."ld-nix.${pkgs.glibc.src.outputHash}.so.preload".text = '' - ${providerLibPath} - ''; - }; -diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix -index 0b2f34c7b76..e1349c0076b 100644 ---- a/pkgs/development/libraries/glibc/common.nix -+++ b/pkgs/development/libraries/glibc/common.nix -@@ -68,9 +68,6 @@ stdenv.mkDerivation ({ - /* Don't use /etc/ld.so.cache, for non-NixOS systems. */ - ./dont-use-system-ld-so-cache.patch - -- /* Don't use /etc/ld.so.preload, but /etc/ld-nix.so.preload. */ -- ./dont-use-system-ld-so-preload.patch -- - /* The command "getconf CS_PATH" returns the default search path - "/bin:/usr/bin", which is inappropriate on NixOS machines. This - patch extends the search path by "/run/current-system/sw/bin". */ -@@ -128,6 +125,18 @@ stdenv.mkDerivation ({ - # nscd needs libgcc, and we don't want it dynamically linked - # because we don't want it to depend on bootstrap-tools libs. - echo "LDFLAGS-nscd += -static-libgcc" >> nscd/Makefile -+ -+ # Don't use /etc/ld.so.preload, but /etc/ld-nix.${sha256}.so.preload. -+ # ${sha256} is included in the name -+ # in order to only share a same .so.preload between the programs -+ # built with that version of glibc, -+ # otherwise it could break programs -+ # requiring symbols from a more recent glibc -+ # than the one loaded by shared libraries in that file. -+ # This file may later be generated by a NixOS module, -+ # using pkgs.glibc.src.outputHash instead of sha256 -+ substituteInPlace elf/rtld.c \ -+ --replace /etc/ld.so.preload /etc/ld-nix.${sha256}.so.preload - '' - # FIXME: find a solution for infinite recursion in cross builds. - # For now it's hopefully acceptable that IDN from libc doesn't reliably work. -diff --git a/pkgs/development/libraries/glibc/dont-use-system-ld-so-preload.patch b/pkgs/development/libraries/glibc/dont-use-system-ld-so-preload.patch -deleted file mode 100644 -index 894e2a11cf8..00000000000 ---- a/pkgs/development/libraries/glibc/dont-use-system-ld-so-preload.patch -+++ /dev/null -@@ -1,12 +0,0 @@ --diff -ru glibc-2.20-orig/elf/rtld.c glibc-2.20/elf/rtld.c ----- glibc-2.20-orig/elf/rtld.c 2014-09-07 10:09:09.000000000 +0200 --+++ glibc-2.20/elf/rtld.c 2014-10-27 11:32:25.203043157 +0100 --@@ -1513,7 +1513,7 @@ -- open(). So we do this first. If it succeeds we do almost twice -- the work but this does not matter, since it is not for production -- use. */ --- static const char preload_file[] = "/etc/ld.so.preload"; --+ static const char preload_file[] = "/etc/ld-nix.so.preload"; -- if (__glibc_unlikely (__access (preload_file, R_OK) == 0)) -- { -- /* Read the contents of the file. */ -- 2.47.2