python312Packages.aiohomeconnect: 0.10.0 -> 0.11.0 (#374011)
[NixPkgs.git] / nixos / modules / services / networking / zapret.nix
blobee41777364966caa7333d2b37c3ec87cd96ceb43
2   lib,
3   config,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.zapret;
10   whitelist = lib.optionalString (
11     (builtins.length cfg.whitelist) != 0
12   ) "--hostlist ${pkgs.writeText "zapret-whitelist" (lib.concatStringsSep "\n" cfg.whitelist)}";
14   blacklist =
15     lib.optionalString ((builtins.length cfg.blacklist) != 0)
16       "--hostlist-exclude ${pkgs.writeText "zapret-blacklist" (lib.concatStringsSep "\n" cfg.blacklist)}";
18   params = lib.concatStringsSep " " cfg.params;
20   qnum = toString cfg.qnum;
23   options.services.zapret = {
24     enable = lib.mkEnableOption "the Zapret DPI bypass service.";
25     package = lib.mkPackageOption pkgs "zapret" { };
26     params = lib.mkOption {
27       default = [ ];
28       type = with lib.types; listOf str;
29       example = ''
30         [
31           "--dpi-desync=fake,disorder2"
32           "--dpi-desync-ttl=1"
33           "--dpi-desync-autottl=2"
34         ]
35       '';
36       description = ''
37         Specify the bypass parameters for Zapret binary.
38         There are no universal parameters as they vary between different networks, so you'll have to find them yourself.
40         This can be done by running the `blockcheck` binary from zapret package, i.e. `nix-shell -p zapret --command blockcheck`.
41         It'll try different params and then tell you which params are working for your network.
42       '';
43     };
44     whitelist = lib.mkOption {
45       default = [ ];
46       type = with lib.types; listOf str;
47       example = ''
48         [
49           "youtube.com"
50           "googlevideo.com"
51           "ytimg.com"
52           "youtu.be"
53         ]
54       '';
55       description = ''
56         Specify a list of domains to bypass. All other domains will be ignored.
57         You can specify either whitelist or blacklist, but not both.
58         If neither are specified, then bypass all domains.
60         It is recommended to specify the whitelist. This will make sure that other resources won't be affected by this service.
61       '';
62     };
63     blacklist = lib.mkOption {
64       default = [ ];
65       type = with lib.types; listOf str;
66       example = ''
67         [
68           "example.com"
69         ]
70       '';
71       description = ''
72         Specify a list of domains NOT to bypass. All other domains will be bypassed.
73         You can specify either whitelist or blacklist, but not both.
74         If neither are specified, then bypass all domains.
75       '';
76     };
77     qnum = lib.mkOption {
78       default = 200;
79       type = lib.types.int;
80       description = ''
81         Routing queue number.
82         Only change this if you already use the default queue number somewhere else.
83       '';
84     };
85     configureFirewall = lib.mkOption {
86       default = true;
87       type = lib.types.bool;
88       description = ''
89         Whether to setup firewall routing so that system http(s) traffic is forwarded via this service.
90         Disable if you want to set it up manually.
91       '';
92     };
93     httpSupport = lib.mkOption {
94       default = true;
95       type = lib.types.bool;
96       description = ''
97         Whether to route http traffic on port 80.
98         Http bypass rarely works and you might want to disable it if you don't utilise http connections.
99       '';
100     };
101     httpMode = lib.mkOption {
102       default = "first";
103       type = lib.types.enum [
104         "first"
105         "full"
106       ];
107       example = "full";
108       description = ''
109         By default this service only changes the first packet sent, which is enough in most cases.
110         But there are DPIs that monitor the whole traffic within a session.
111         That requires full processing of every packet, which increases the CPU usage.
113         Set the mode to `full` if http doesn't work.
114       '';
115     };
116     udpSupport = lib.mkOption {
117       default = false;
118       type = lib.types.bool;
119       description = ''
120         Enable UDP routing.
121         This requires you to specify `udpPorts` and `--dpi-desync-any-protocol` parameter.
122       '';
123     };
124     udpPorts = lib.mkOption {
125       default = [ ];
126       type = with lib.types; listOf str;
127       example = ''
128         [
129           "50000:50099"
130           "1234"
131         ]
132       '';
133       description = ''
134         List of UDP ports to route.
135         Port ranges are delimited with a colon like this "50000:50099".
136       '';
137     };
138   };
140   config = lib.mkIf cfg.enable (
141     lib.mkMerge [
142       {
143         assertions = [
144           {
145             assertion = (builtins.length cfg.whitelist) == 0 || (builtins.length cfg.blacklist) == 0;
146             message = "Can't specify both whitelist and blacklist.";
147           }
148           {
149             assertion = (builtins.length cfg.params) != 0;
150             message = "You have to specify zapret parameters. See the params option's description.";
151           }
152           {
153             assertion = cfg.udpSupport -> (builtins.length cfg.udpPorts) != 0;
154             message = "You have to specify UDP ports or disable UDP support.";
155           }
156           {
157             assertion = !cfg.configureFirewall || !config.networking.nftables.enable;
158             message = "You need to manually configure you firewall for Zapret service when using nftables.";
159           }
160         ];
162         systemd.services.zapret = {
163           description = "DPI bypass service";
164           wantedBy = [ "multi-user.target" ];
165           after = [ "network.target" ];
166           serviceConfig = {
167             ExecStart = "${cfg.package}/bin/nfqws --pidfile=/run/nfqws.pid ${params} ${whitelist} ${blacklist} --qnum=${qnum}";
168             Type = "simple";
169             PIDFile = "/run/nfqws.pid";
170             Restart = "always";
171             RuntimeMaxSec = "1h"; # This service loves to crash silently or cause network slowdowns. It also restarts instantly. Restarting it at least hourly provided the best experience.
173             # Hardening.
174             DevicePolicy = "closed";
175             KeyringMode = "private";
176             PrivateTmp = true;
177             PrivateMounts = true;
178             ProtectHome = true;
179             ProtectHostname = true;
180             ProtectKernelModules = true;
181             ProtectKernelTunables = true;
182             ProtectSystem = "strict";
183             ProtectProc = "invisible";
184             RemoveIPC = true;
185             RestrictNamespaces = true;
186             RestrictRealtime = true;
187             RestrictSUIDSGID = true;
188             SystemCallArchitectures = "native";
189           };
190         };
191       }
193       # Route system traffic via service for specified ports.
194       (lib.mkIf cfg.configureFirewall {
195         networking.firewall.extraCommands =
196           let
197             httpParams = lib.optionalString (
198               cfg.httpMode == "first"
199             ) "-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6";
201             udpPorts = lib.concatStringsSep "," cfg.udpPorts;
202           in
203           ''
204             ip46tables -t mangle -I POSTROUTING -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num ${qnum} --queue-bypass
205           ''
206           + lib.optionalString (cfg.httpSupport) ''
207             ip46tables -t mangle -I POSTROUTING -p tcp --dport 80 ${httpParams} -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num ${qnum} --queue-bypass
208           ''
209           + lib.optionalString (cfg.udpSupport) ''
210             ip46tables -t mangle -A POSTROUTING -p udp -m multiport --dports ${udpPorts} -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num ${qnum} --queue-bypass
211           '';
212       })
213     ]
214   );
216   meta.maintainers = with lib.maintainers; [
217     nishimara
218   ];