1 { config, lib, pkgs, ... }:
4 cfg = config.programs.proxychains;
7 ${cfg.chain.type}_chain
8 ${lib.optionalString (cfg.chain.type == "random")
9 "chain_len = ${builtins.toString cfg.chain.length}"}
10 ${lib.optionalString cfg.proxyDNS "proxy_dns"}
11 ${lib.optionalString cfg.quietMode "quiet_mode"}
12 remote_dns_subnet ${builtins.toString cfg.remoteDNSSubnet}
13 tcp_read_time_out ${builtins.toString cfg.tcpReadTimeOut}
14 tcp_connect_time_out ${builtins.toString cfg.tcpConnectTimeOut}
15 localnet ${cfg.localnet}
17 ${builtins.concatStringsSep "\n"
18 (lib.mapAttrsToList (k: v: "${v.type} ${v.host} ${builtins.toString v.port}")
19 (lib.filterAttrs (k: v: v.enable) cfg.proxies))}
24 enable = lib.mkEnableOption "this proxy";
27 type = lib.types.enum [ "http" "socks4" "socks5" ];
28 description = "Proxy type.";
33 description = "Proxy host or IP address.";
37 type = lib.types.port;
38 description = "Proxy port";
49 programs.proxychains = {
51 enable = lib.mkEnableOption "proxychains configuration";
53 package = lib.mkPackageOption pkgs "proxychains" {
54 example = "proxychains-ng";
59 type = lib.types.enum [ "dynamic" "strict" "random" ];
62 `dynamic` - Each connection will be done via chained proxies
63 all proxies chained in the order as they appear in the list
64 at least one proxy must be online to play in chain
65 (dead proxies are skipped)
66 otherwise `EINTR` is returned to the app.
68 `strict` - Each connection will be done via chained proxies
69 all proxies chained in the order as they appear in the list
70 all proxies must be online to play in chain
71 otherwise `EINTR` is returned to the app.
73 `random` - Each connection will be done via random proxy
74 (or proxy chain, see {option}`programs.proxychains.chain.length`) from the list.
77 length = lib.mkOption {
78 type = lib.types.nullOr lib.types.int;
81 Chain length for random chain.
86 proxyDNS = lib.mkOption {
87 type = lib.types.bool;
89 description = "Proxy DNS requests - no leak for DNS data.";
92 quietMode = lib.mkEnableOption "Quiet mode (no output from the library)";
94 remoteDNSSubnet = lib.mkOption {
95 type = lib.types.enum [ 10 127 224 ];
98 Set the class A subnet number to use for the internal remote DNS mapping, uses the reserved 224.x.x.x range by default.
102 tcpReadTimeOut = lib.mkOption {
103 type = lib.types.int;
105 description = "Connection read time-out in milliseconds.";
108 tcpConnectTimeOut = lib.mkOption {
109 type = lib.types.int;
111 description = "Connection time-out in milliseconds.";
114 localnet = lib.mkOption {
115 type = lib.types.str;
116 default = "127.0.0.0/255.0.0.0";
117 description = "By default enable localnet for loopback address ranges.";
120 proxies = lib.mkOption {
121 type = lib.types.attrsOf (lib.types.submodule proxyOptions);
123 Proxies to be used by proxychains.
126 example = lib.literalExpression ''
140 ###### implementation
142 meta.maintainers = with lib.maintainers; [ sorki ];
144 config = lib.mkIf cfg.enable {
146 assertions = lib.singleton {
147 assertion = cfg.chain.type != "random" && cfg.chain.length == null;
149 Option `programs.proxychains.chain.length`
150 only makes sense with `programs.proxychains.chain.type` = "random".
154 programs.proxychains.proxies = lib.mkIf config.services.tor.client.enable
156 torproxy = lib.mkDefault {
164 environment.etc."proxychains.conf".text = configFile;
165 environment.systemPackages = [ cfg.package ];