1 { config, lib, pkgs, ... }:
4 cfg = config.services._3proxy;
5 optionalList = list: if list == [ ] then "*" else lib.concatMapStringsSep "," toString list;
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";
13 Ignore all other 3proxy options and load configuration from this file.
16 usersFile = lib.mkOption {
17 type = lib.types.nullOr lib.types.path;
19 example = "/var/lib/3proxy/3proxy.passwd";
21 Load users and passwords from this file.
23 Example users file with plain-text passwords:
30 Example users file with md5-crypted passwords:
33 test1:CR:$1$tFkisVd2$1GA8JXkRmTXdLDytM/i3a1
34 test2:CR:$1$rkpibm5J$Aq1.9VtYAn0JrqZ8M.1ME.
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.
42 services = lib.mkOption {
43 type = lib.types.listOf (lib.types.submodule {
46 type = lib.types.enum [
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.
70 bindAddress = lib.mkOption {
73 example = "127.0.0.1";
75 Address used for service.
78 bindPort = lib.mkOption {
79 type = lib.types.nullOr lib.types.int;
83 Override default port used for service.
86 maxConnections = lib.mkOption {
91 Maximum number of simulationeous connections to this service.
95 type = lib.types.listOf (lib.types.enum [ "none" "iponly" "strong" ]);
96 example = [ "iponly" "strong" ];
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.
108 auth = [ "iponly" "strong" ];
112 targets = [ "192.168.0.0/16" ];
116 users = [ "user1" "user2" ];
121 In this example strong username authentication is not required to access 192.168.0.0/16.
125 type = lib.types.listOf (lib.types.submodule {
127 rule = lib.mkOption {
128 type = lib.types.enum [ "allow" "deny" ];
131 ACL rule. The following values are valid:
133 - `"allow"`: connections allowed.
134 - `"deny"`: connections not allowed.
137 users = lib.mkOption {
138 type = lib.types.listOf lib.types.str;
140 example = [ "user1" "user2" "user3" ];
142 List of users, use empty list for any.
145 sources = lib.mkOption {
146 type = lib.types.listOf lib.types.str;
148 example = [ "127.0.0.1" "192.168.1.0/24" ];
150 List of source IP range, use empty list for any.
153 targets = lib.mkOption {
154 type = lib.types.listOf lib.types.str;
156 example = [ "127.0.0.1" "192.168.1.0/24" ];
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.
164 targetPorts = lib.mkOption {
165 type = lib.types.listOf lib.types.int;
167 example = [ 80 443 ];
169 List of target ports, use empty list for any.
175 example = lib.literalExpression ''
183 sources = [ "192.168.1.0/24" ];
191 Use this option to limit user access to resources.
194 extraArguments = lib.mkOption {
195 type = lib.types.nullOr lib.types.str;
199 Extra arguments for service.
200 Consult "Options" section in [documentation](https://github.com/z3APA3A/3proxy/wiki/3proxy.cfg) for available arguments.
203 extraConfig = lib.mkOption {
204 type = lib.types.nullOr lib.types.lines;
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.
214 example = lib.literalExpression ''
218 bindAddress = "192.168.1.24";
224 bindAddress = "10.10.1.20";
230 bindAddress = "172.17.0.1";
237 Use this option to define 3proxy services.
240 denyPrivate = lib.mkOption {
241 type = lib.types.bool;
244 Whether to deny access to private IP ranges including loopback.
247 privateRanges = lib.mkOption {
248 type = lib.types.listOf lib.types.str;
261 What IP ranges to deny access when denyPrivate is set tu true.
264 resolution = lib.mkOption {
265 type = lib.types.submodule {
267 nserver = lib.mkOption {
268 type = lib.types.listOf lib.types.str;
270 example = [ "127.0.0.53" "192.168.1.3:5353/tcp" ];
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.
278 nscache = lib.mkOption {
279 type = lib.types.int;
281 description = "Set name cache size for IPv4.";
283 nscache6 = lib.mkOption {
284 type = lib.types.int;
286 description = "Set name cache size for IPv6.";
288 nsrecord = lib.mkOption {
289 type = lib.types.attrsOf lib.types.str;
291 example = lib.literalExpression ''
293 "files.local" = "192.168.1.12";
294 "site.local" = "192.168.1.43";
297 description = "Adds static nsrecords.";
303 Use this option to configure name resolution and DNS caching.
306 extraConfig = lib.mkOption {
307 type = lib.types.nullOr lib.types.lines;
310 Extra configuration, appended to the 3proxy configuration file.
311 Consult [documentation](https://github.com/z3APA3A/3proxy/wiki/3proxy.cfg) for available options.
316 config = lib.mkIf cfg.enable {
317 services._3proxy.confFile = lib.mkDefault (pkgs.writeText "3proxy.conf" ''
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}"''
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:
342 lib.concatMapStringsSep " " optionalList [
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}"
358 lib.optionalString (service.extraArguments != null) service.extraArguments
363 ${lib.optionalString (cfg.extraConfig != null) cfg.extraConfig}
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" ];
372 StateDirectory = "3proxy";
373 ExecStart = "${pkg}/bin/3proxy ${cfg.confFile}";
374 Restart = "on-failure";
379 meta.maintainers = with lib.maintainers; [ misuzu ];