at master 4.9 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 9 cfg = config.programs.proxychains; 10 11 configFile = '' 12 ${cfg.chain.type}_chain 13 ${lib.optionalString ( 14 cfg.chain.type == "random" 15 ) "chain_len = ${builtins.toString cfg.chain.length}"} 16 ${lib.optionalString cfg.proxyDNS "proxy_dns"} 17 ${lib.optionalString cfg.quietMode "quiet_mode"} 18 remote_dns_subnet ${builtins.toString cfg.remoteDNSSubnet} 19 tcp_read_time_out ${builtins.toString cfg.tcpReadTimeOut} 20 tcp_connect_time_out ${builtins.toString cfg.tcpConnectTimeOut} 21 localnet ${cfg.localnet} 22 [ProxyList] 23 ${builtins.concatStringsSep "\n" ( 24 lib.mapAttrsToList (k: v: "${v.type} ${v.host} ${builtins.toString v.port}") ( 25 lib.filterAttrs (k: v: v.enable) cfg.proxies 26 ) 27 )} 28 ''; 29 30 proxyOptions = { 31 options = { 32 enable = lib.mkEnableOption "this proxy"; 33 34 type = lib.mkOption { 35 type = lib.types.enum [ 36 "http" 37 "socks4" 38 "socks5" 39 ]; 40 description = "Proxy type."; 41 }; 42 43 host = lib.mkOption { 44 type = lib.types.str; 45 description = "Proxy host or IP address."; 46 }; 47 48 port = lib.mkOption { 49 type = lib.types.port; 50 description = "Proxy port"; 51 }; 52 }; 53 }; 54 55in 56{ 57 58 ###### interface 59 60 options = { 61 62 programs.proxychains = { 63 64 enable = lib.mkEnableOption "proxychains configuration"; 65 66 package = lib.mkPackageOption pkgs "proxychains" { 67 example = "proxychains-ng"; 68 }; 69 70 chain = { 71 type = lib.mkOption { 72 type = lib.types.enum [ 73 "dynamic" 74 "strict" 75 "random" 76 ]; 77 default = "strict"; 78 description = '' 79 `dynamic` - Each connection will be done via chained proxies 80 all proxies chained in the order as they appear in the list 81 at least one proxy must be online to play in chain 82 (dead proxies are skipped) 83 otherwise `EINTR` is returned to the app. 84 85 `strict` - Each connection will be done via chained proxies 86 all proxies chained in the order as they appear in the list 87 all proxies must be online to play in chain 88 otherwise `EINTR` is returned to the app. 89 90 `random` - Each connection will be done via random proxy 91 (or proxy chain, see {option}`programs.proxychains.chain.length`) from the list. 92 ''; 93 }; 94 length = lib.mkOption { 95 type = lib.types.nullOr lib.types.int; 96 default = null; 97 description = '' 98 Chain length for random chain. 99 ''; 100 }; 101 }; 102 103 proxyDNS = lib.mkOption { 104 type = lib.types.bool; 105 default = true; 106 description = "Proxy DNS requests - no leak for DNS data."; 107 }; 108 109 quietMode = lib.mkEnableOption "Quiet mode (no output from the library)"; 110 111 remoteDNSSubnet = lib.mkOption { 112 type = lib.types.enum [ 113 10 114 127 115 224 116 ]; 117 default = 224; 118 description = '' 119 Set the class A subnet number to use for the internal remote DNS mapping, uses the reserved 224.x.x.x range by default. 120 ''; 121 }; 122 123 tcpReadTimeOut = lib.mkOption { 124 type = lib.types.int; 125 default = 15000; 126 description = "Connection read time-out in milliseconds."; 127 }; 128 129 tcpConnectTimeOut = lib.mkOption { 130 type = lib.types.int; 131 default = 8000; 132 description = "Connection time-out in milliseconds."; 133 }; 134 135 localnet = lib.mkOption { 136 type = lib.types.str; 137 default = "127.0.0.0/255.0.0.0"; 138 description = "By default enable localnet for loopback address ranges."; 139 }; 140 141 proxies = lib.mkOption { 142 type = lib.types.attrsOf (lib.types.submodule proxyOptions); 143 description = '' 144 Proxies to be used by proxychains. 145 ''; 146 147 example = lib.literalExpression '' 148 { myproxy = 149 { type = "socks4"; 150 host = "127.0.0.1"; 151 port = 1337; 152 }; 153 } 154 ''; 155 }; 156 157 }; 158 159 }; 160 161 ###### implementation 162 163 meta.maintainers = with lib.maintainers; [ sorki ]; 164 165 config = lib.mkIf cfg.enable { 166 167 assertions = lib.singleton { 168 assertion = cfg.chain.type != "random" && cfg.chain.length == null; 169 message = '' 170 Option `programs.proxychains.chain.length` 171 only makes sense with `programs.proxychains.chain.type` = "random". 172 ''; 173 }; 174 175 programs.proxychains.proxies = lib.mkIf config.services.tor.client.enable { 176 torproxy = lib.mkDefault { 177 enable = true; 178 type = "socks4"; 179 host = "127.0.0.1"; 180 port = 9050; 181 }; 182 }; 183 184 environment.etc."proxychains.conf".text = configFile; 185 environment.systemPackages = [ cfg.package ]; 186 }; 187 188}