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 ];
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |