166 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| with lib;
 | |
| let
 | |
| 
 | |
|   cfg = config.programs.proxychains;
 | |
| 
 | |
|   configFile = ''
 | |
|     ${cfg.chain.type}_chain
 | |
|     ${optionalString (cfg.chain.type == "random")
 | |
|     "chain_len = ${builtins.toString cfg.chain.length}"}
 | |
|     ${optionalString cfg.proxyDNS "proxy_dns"}
 | |
|     ${optionalString cfg.quietMode "quiet_mode"}
 | |
|     remote_dns_subnet ${builtins.toString cfg.remoteDNSSubnet}
 | |
|     tcp_read_time_out ${builtins.toString cfg.tcpReadTimeOut}
 | |
|     tcp_connect_time_out ${builtins.toString cfg.tcpConnectTimeOut}
 | |
|     localnet ${cfg.localnet}
 | |
|     [ProxyList]
 | |
|     ${builtins.concatStringsSep "\n"
 | |
|       (lib.mapAttrsToList (k: v: "${v.type} ${v.host} ${builtins.toString v.port}")
 | |
|         (lib.filterAttrs (k: v: v.enable) cfg.proxies))}
 | |
|   '';
 | |
| 
 | |
|   proxyOptions = {
 | |
|     options = {
 | |
|       enable = mkEnableOption "this proxy";
 | |
| 
 | |
|       type = mkOption {
 | |
|         type = types.enum [ "http" "socks4" "socks5" ];
 | |
|         description = "Proxy type.";
 | |
|       };
 | |
| 
 | |
|       host = mkOption {
 | |
|         type = types.str;
 | |
|         description = "Proxy host or IP address.";
 | |
|       };
 | |
| 
 | |
|       port = mkOption {
 | |
|         type = types.port;
 | |
|         description = "Proxy port";
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| 
 | |
| in {
 | |
| 
 | |
|   ###### interface
 | |
| 
 | |
|   options = {
 | |
| 
 | |
|     programs.proxychains = {
 | |
| 
 | |
|       enable = mkEnableOption "installing proxychains configuration";
 | |
| 
 | |
|       chain = {
 | |
|         type = mkOption {
 | |
|           type = types.enum [ "dynamic" "strict" "random" ];
 | |
|           default = "strict";
 | |
|           description = ''
 | |
|             <literal>dynamic</literal> - Each connection will be done via chained proxies
 | |
|             all proxies chained in the order as they appear in the list
 | |
|             at least one proxy must be online to play in chain
 | |
|             (dead proxies are skipped)
 | |
|             otherwise <literal>EINTR</literal> is returned to the app.
 | |
| 
 | |
|             <literal>strict</literal> - Each connection will be done via chained proxies
 | |
|             all proxies chained in the order as they appear in the list
 | |
|             all proxies must be online to play in chain
 | |
|             otherwise <literal>EINTR</literal> is returned to the app.
 | |
| 
 | |
|             <literal>random</literal> - Each connection will be done via random proxy
 | |
|             (or proxy chain, see <option>programs.proxychains.chain.length</option>) from the list.
 | |
|           '';
 | |
|         };
 | |
|         length = mkOption {
 | |
|           type = types.nullOr types.int;
 | |
|           default = null;
 | |
|           description = ''
 | |
|             Chain length for random chain.
 | |
|           '';
 | |
|         };
 | |
|       };
 | |
| 
 | |
|       proxyDNS = mkOption {
 | |
|         type = types.bool;
 | |
|         default = true;
 | |
|         description = "Proxy DNS requests - no leak for DNS data.";
 | |
|       };
 | |
| 
 | |
|       quietMode = mkEnableOption "Quiet mode (no output from the library).";
 | |
| 
 | |
|       remoteDNSSubnet = mkOption {
 | |
|         type = types.enum [ 10 127 224 ];
 | |
|         default = 224;
 | |
|         description = ''
 | |
|           Set the class A subnet number to use for the internal remote DNS mapping, uses the reserved 224.x.x.x range by default.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       tcpReadTimeOut = mkOption {
 | |
|         type = types.int;
 | |
|         default = 15000;
 | |
|         description = "Connection read time-out in milliseconds.";
 | |
|       };
 | |
| 
 | |
|       tcpConnectTimeOut = mkOption {
 | |
|         type = types.int;
 | |
|         default = 8000;
 | |
|         description = "Connection time-out in milliseconds.";
 | |
|       };
 | |
| 
 | |
|       localnet = mkOption {
 | |
|         type = types.str;
 | |
|         default = "127.0.0.0/255.0.0.0";
 | |
|         description = "By default enable localnet for loopback address ranges.";
 | |
|       };
 | |
| 
 | |
|       proxies = mkOption {
 | |
|         type = types.attrsOf (types.submodule proxyOptions);
 | |
|         description = ''
 | |
|           Proxies to be used by proxychains.
 | |
|         '';
 | |
| 
 | |
|         example = literalExample ''
 | |
|           { myproxy =
 | |
|             { type = "socks4";
 | |
|               host = "127.0.0.1";
 | |
|               port = 1337;
 | |
|             };
 | |
|           }
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|     };
 | |
| 
 | |
|   };
 | |
| 
 | |
|   ###### implementation
 | |
| 
 | |
|   meta.maintainers = with maintainers; [ sorki ];
 | |
| 
 | |
|   config = mkIf cfg.enable {
 | |
| 
 | |
|     assertions = singleton {
 | |
|       assertion = cfg.chain.type != "random" && cfg.chain.length == null;
 | |
|       message = ''
 | |
|         Option `programs.proxychains.chain.length`
 | |
|         only makes sense with `programs.proxychains.chain.type` = "random".
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     programs.proxychains.proxies = mkIf config.services.tor.client.enable
 | |
|       {
 | |
|         torproxy = mkDefault {
 | |
|           enable = true;
 | |
|           type = "socks4";
 | |
|           host = "127.0.0.1";
 | |
|           port = 9050;
 | |
|         };
 | |
|       };
 | |
| 
 | |
|     environment.etc."proxychains.conf".text = configFile;
 | |
|     environment.systemPackages = [ pkgs.proxychains ];
 | |
|   };
 | |
| 
 | |
| }
 | 
