vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / 3proxy.nix
blob03c67ed2f6f8f020ee4bdd13559a6e1368c48371
1 { config, lib, pkgs, ... }:
2 let
3   pkg = pkgs._3proxy;
4   cfg = config.services._3proxy;
5   optionalList = list: if list == [ ] then "*" else lib.concatMapStringsSep "," toString list;
6 in {
7   options.services._3proxy = {
8     enable = lib.mkEnableOption "3proxy";
9     confFile = lib.mkOption {
10       type = lib.types.path;
11       example = "/var/lib/3proxy/3proxy.conf";
12       description = ''
13         Ignore all other 3proxy options and load configuration from this file.
14       '';
15     };
16     usersFile = lib.mkOption {
17       type = lib.types.nullOr lib.types.path;
18       default = null;
19       example = "/var/lib/3proxy/3proxy.passwd";
20       description = ''
21         Load users and passwords from this file.
23         Example users file with plain-text passwords:
25         ```
26           test1:CL:password1
27           test2:CL:password2
28         ```
30         Example users file with md5-crypted passwords:
32         ```
33           test1:CR:$1$tFkisVd2$1GA8JXkRmTXdLDytM/i3a1
34           test2:CR:$1$rkpibm5J$Aq1.9VtYAn0JrqZ8M.1ME.
35         ```
37         You can generate md5-crypted passwords via https://unix4lyfe.org/crypt/
38         Note that htpasswd tool generates incompatible md5-crypted passwords.
39         Consult [documentation](https://github.com/z3APA3A/3proxy/wiki/How-To-%28incomplete%29#USERS) for more information.
40       '';
41     };
42     services = lib.mkOption {
43       type = lib.types.listOf (lib.types.submodule {
44         options = {
45           type = lib.mkOption {
46             type = lib.types.enum [
47               "proxy"
48               "socks"
49               "pop3p"
50               "ftppr"
51               "admin"
52               "dnspr"
53               "tcppm"
54               "udppm"
55             ];
56             example = "proxy";
57             description = ''
58               Service type. The following values are valid:
60               - `"proxy"`: HTTP/HTTPS proxy (default port 3128).
61               - `"socks"`: SOCKS 4/4.5/5 proxy (default port 1080).
62               - `"pop3p"`: POP3 proxy (default port 110).
63               - `"ftppr"`: FTP proxy (default port 21).
64               - `"admin"`: Web interface (default port 80).
65               - `"dnspr"`: Caching DNS proxy (default port 53).
66               - `"tcppm"`: TCP portmapper.
67               - `"udppm"`: UDP portmapper.
68             '';
69           };
70           bindAddress = lib.mkOption {
71             type = lib.types.str;
72             default = "[::]";
73             example = "127.0.0.1";
74             description = ''
75               Address used for service.
76             '';
77           };
78           bindPort = lib.mkOption {
79             type = lib.types.nullOr lib.types.int;
80             default = null;
81             example = 3128;
82             description = ''
83               Override default port used for service.
84             '';
85           };
86           maxConnections = lib.mkOption {
87             type = lib.types.int;
88             default = 100;
89             example = 1000;
90             description = ''
91               Maximum number of simulationeous connections to this service.
92             '';
93           };
94           auth = lib.mkOption {
95             type = lib.types.listOf (lib.types.enum [ "none" "iponly" "strong" ]);
96             example = [ "iponly" "strong" ];
97             description = ''
98               Authentication type. The following values are valid:
100               - `"none"`: disables both authentication and authorization. You can not use ACLs.
101               - `"iponly"`: specifies no authentication. ACLs authorization is used.
102               - `"strong"`: authentication by username/password. If user is not registered their access is denied regardless of ACLs.
104               Double authentication is possible, e.g.
106               ```
107                 {
108                   auth = [ "iponly" "strong" ];
109                   acl = [
110                     {
111                       rule = "allow";
112                       targets = [ "192.168.0.0/16" ];
113                     }
114                     {
115                       rule = "allow"
116                       users = [ "user1" "user2" ];
117                     }
118                   ];
119                 }
120               ```
121               In this example strong username authentication is not required to access 192.168.0.0/16.
122             '';
123           };
124           acl = lib.mkOption {
125             type = lib.types.listOf (lib.types.submodule {
126               options = {
127                 rule = lib.mkOption {
128                   type = lib.types.enum [ "allow" "deny" ];
129                   example = "allow";
130                   description = ''
131                     ACL rule. The following values are valid:
133                     - `"allow"`: connections allowed.
134                     - `"deny"`: connections not allowed.
135                   '';
136                 };
137                 users = lib.mkOption {
138                   type = lib.types.listOf lib.types.str;
139                   default = [ ];
140                   example = [ "user1" "user2" "user3" ];
141                   description = ''
142                     List of users, use empty list for any.
143                   '';
144                 };
145                 sources = lib.mkOption {
146                   type = lib.types.listOf lib.types.str;
147                   default = [ ];
148                   example = [ "127.0.0.1" "192.168.1.0/24" ];
149                   description = ''
150                     List of source IP range, use empty list for any.
151                   '';
152                 };
153                 targets = lib.mkOption {
154                   type = lib.types.listOf lib.types.str;
155                   default = [ ];
156                   example = [ "127.0.0.1" "192.168.1.0/24" ];
157                   description = ''
158                     List of target IP ranges, use empty list for any.
159                     May also contain host names instead of addresses.
160                     It's possible to use wildmask in the beginning and in the the end of hostname, e.g. `*badsite.com` or `*badcontent*`.
161                     Hostname is only checked if hostname presents in request.
162                   '';
163                 };
164                 targetPorts = lib.mkOption {
165                   type = lib.types.listOf lib.types.int;
166                   default = [ ];
167                   example = [ 80 443 ];
168                   description = ''
169                     List of target ports, use empty list for any.
170                   '';
171                 };
172               };
173             });
174             default = [ ];
175             example = lib.literalExpression ''
176               [
177                 {
178                   rule = "allow";
179                   users = [ "user1" ];
180                 }
181                 {
182                   rule = "allow";
183                   sources = [ "192.168.1.0/24" ];
184                 }
185                 {
186                   rule = "deny";
187                 }
188               ]
189             '';
190             description = ''
191               Use this option to limit user access to resources.
192             '';
193           };
194           extraArguments = lib.mkOption {
195             type = lib.types.nullOr lib.types.str;
196             default = null;
197             example = "-46";
198             description = ''
199               Extra arguments for service.
200               Consult "Options" section in [documentation](https://github.com/z3APA3A/3proxy/wiki/3proxy.cfg) for available arguments.
201             '';
202           };
203           extraConfig = lib.mkOption {
204             type = lib.types.nullOr lib.types.lines;
205             default = null;
206             description = ''
207               Extra configuration for service. Use this to configure things like bandwidth limiter or ACL-based redirection.
208               Consult [documentation](https://github.com/z3APA3A/3proxy/wiki/3proxy.cfg) for available options.
209             '';
210           };
211         };
212       });
213       default = [ ];
214       example = lib.literalExpression ''
215         [
216           {
217             type = "proxy";
218             bindAddress = "192.168.1.24";
219             bindPort = 3128;
220             auth = [ "none" ];
221           }
222           {
223             type = "proxy";
224             bindAddress = "10.10.1.20";
225             bindPort = 3128;
226             auth = [ "iponly" ];
227           }
228           {
229             type = "socks";
230             bindAddress = "172.17.0.1";
231             bindPort = 1080;
232             auth = [ "strong" ];
233           }
234         ]
235       '';
236       description = ''
237         Use this option to define 3proxy services.
238       '';
239     };
240     denyPrivate = lib.mkOption {
241       type = lib.types.bool;
242       default = true;
243       description = ''
244         Whether to deny access to private IP ranges including loopback.
245       '';
246     };
247     privateRanges = lib.mkOption {
248       type = lib.types.listOf lib.types.str;
249       default = [
250         "0.0.0.0/8"
251         "127.0.0.0/8"
252         "10.0.0.0/8"
253         "100.64.0.0/10"
254         "172.16.0.0/12"
255         "192.168.0.0/16"
256         "::"
257         "::1"
258         "fc00::/7"
259       ];
260       description = ''
261         What IP ranges to deny access when denyPrivate is set tu true.
262       '';
263     };
264     resolution = lib.mkOption {
265       type = lib.types.submodule {
266         options = {
267           nserver = lib.mkOption {
268             type = lib.types.listOf lib.types.str;
269             default = [ ];
270             example = [ "127.0.0.53" "192.168.1.3:5353/tcp" ];
271             description = ''
272               List of nameservers to use.
274               Up to 5 nservers may be specified. If no nserver is configured,
275               default system name resolution functions are used.
276             '';
277           };
278           nscache = lib.mkOption {
279             type = lib.types.int;
280             default = 65535;
281             description = "Set name cache size for IPv4.";
282           };
283           nscache6 = lib.mkOption {
284             type = lib.types.int;
285             default = 65535;
286             description = "Set name cache size for IPv6.";
287           };
288           nsrecord = lib.mkOption {
289             type = lib.types.attrsOf lib.types.str;
290             default = { };
291             example = lib.literalExpression ''
292               {
293                 "files.local" = "192.168.1.12";
294                 "site.local" = "192.168.1.43";
295               }
296             '';
297             description = "Adds static nsrecords.";
298           };
299         };
300       };
301       default = { };
302       description = ''
303         Use this option to configure name resolution and DNS caching.
304       '';
305     };
306     extraConfig = lib.mkOption {
307       type = lib.types.nullOr lib.types.lines;
308       default = null;
309       description = ''
310         Extra configuration, appended to the 3proxy configuration file.
311         Consult [documentation](https://github.com/z3APA3A/3proxy/wiki/3proxy.cfg) for available options.
312       '';
313     };
314   };
316   config = lib.mkIf cfg.enable {
317     services._3proxy.confFile = lib.mkDefault (pkgs.writeText "3proxy.conf" ''
318       # log to stdout
319       log
321       ${lib.concatMapStringsSep "\n" (x: "nserver " + x) cfg.resolution.nserver}
323       nscache ${toString cfg.resolution.nscache}
324       nscache6 ${toString cfg.resolution.nscache6}
326       ${lib.concatMapStringsSep "\n" (x: "nsrecord " + x)
327       (lib.mapAttrsToList (name: value: "${name} ${value}")
328         cfg.resolution.nsrecord)}
330       ${lib.optionalString (cfg.usersFile != null)
331         ''users $"${cfg.usersFile}"''
332       }
334       ${lib.concatMapStringsSep "\n" (service: ''
335         auth ${lib.concatStringsSep " " service.auth}
337         ${lib.optionalString (cfg.denyPrivate)
338         "deny * * ${optionalList cfg.privateRanges}"}
340         ${lib.concatMapStringsSep "\n" (acl:
341           "${acl.rule} ${
342             lib.concatMapStringsSep " " optionalList [
343               acl.users
344               acl.sources
345               acl.targets
346               acl.targetPorts
347             ]
348           }") service.acl}
350         maxconn ${toString service.maxConnections}
352         ${lib.optionalString (service.extraConfig != null) service.extraConfig}
354         ${service.type} -i${toString service.bindAddress} ${
355           lib.optionalString (service.bindPort != null)
356           "-p${toString service.bindPort}"
357         } ${
358           lib.optionalString (service.extraArguments != null) service.extraArguments
359         }
361         flush
362       '') cfg.services}
363       ${lib.optionalString (cfg.extraConfig != null) cfg.extraConfig}
364     '');
365     systemd.services."3proxy" = {
366       description = "Tiny free proxy server";
367       documentation = [ "https://github.com/z3APA3A/3proxy/wiki" ];
368       after = [ "network.target" ];
369       wantedBy = [ "multi-user.target" ];
370       serviceConfig = {
371         DynamicUser = true;
372         StateDirectory = "3proxy";
373         ExecStart = "${pkg}/bin/3proxy ${cfg.confFile}";
374         Restart = "on-failure";
375       };
376     };
377   };
379   meta.maintainers = with lib.maintainers; [ misuzu ];