2020-04-28 18:32:22 +02:00
|
|
|
{ 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 = {
|
2022-08-28 21:18:44 +02:00
|
|
|
enable = mkEnableOption (lib.mdDoc "this proxy");
|
2020-04-28 18:32:22 +02:00
|
|
|
|
|
|
|
type = mkOption {
|
|
|
|
type = types.enum [ "http" "socks4" "socks5" ];
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Proxy type.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
host = mkOption {
|
|
|
|
type = types.str;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Proxy host or IP address.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
port = mkOption {
|
|
|
|
type = types.port;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Proxy port";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
in {
|
|
|
|
|
|
|
|
###### interface
|
|
|
|
|
|
|
|
options = {
|
|
|
|
|
|
|
|
programs.proxychains = {
|
|
|
|
|
2022-08-28 21:18:44 +02:00
|
|
|
enable = mkEnableOption (lib.mdDoc "installing proxychains configuration");
|
2020-04-28 18:32:22 +02:00
|
|
|
|
|
|
|
chain = {
|
|
|
|
type = mkOption {
|
|
|
|
type = types.enum [ "dynamic" "strict" "random" ];
|
|
|
|
default = "strict";
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc ''
|
|
|
|
`dynamic` - Each connection will be done via chained proxies
|
2020-04-28 18:32:22 +02:00
|
|
|
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)
|
2022-07-20 12:32:04 +02:00
|
|
|
otherwise `EINTR` is returned to the app.
|
2020-04-28 18:32:22 +02:00
|
|
|
|
2022-07-20 12:32:04 +02:00
|
|
|
`strict` - Each connection will be done via chained proxies
|
2020-04-28 18:32:22 +02:00
|
|
|
all proxies chained in the order as they appear in the list
|
|
|
|
all proxies must be online to play in chain
|
2022-07-20 12:32:04 +02:00
|
|
|
otherwise `EINTR` is returned to the app.
|
2020-04-28 18:32:22 +02:00
|
|
|
|
2022-07-20 12:32:04 +02:00
|
|
|
`random` - Each connection will be done via random proxy
|
|
|
|
(or proxy chain, see {option}`programs.proxychains.chain.length`) from the list.
|
2020-04-28 18:32:22 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
length = mkOption {
|
|
|
|
type = types.nullOr types.int;
|
|
|
|
default = null;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-04-28 18:32:22 +02:00
|
|
|
Chain length for random chain.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
proxyDNS = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Proxy DNS requests - no leak for DNS data.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
2022-08-28 21:18:44 +02:00
|
|
|
quietMode = mkEnableOption (lib.mdDoc "Quiet mode (no output from the library).");
|
2020-04-28 18:32:22 +02:00
|
|
|
|
|
|
|
remoteDNSSubnet = mkOption {
|
|
|
|
type = types.enum [ 10 127 224 ];
|
|
|
|
default = 224;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-04-28 18:32:22 +02:00
|
|
|
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;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Connection read time-out in milliseconds.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
tcpConnectTimeOut = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = 8000;
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "Connection time-out in milliseconds.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
localnet = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "127.0.0.0/255.0.0.0";
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc "By default enable localnet for loopback address ranges.";
|
2020-04-28 18:32:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
proxies = mkOption {
|
|
|
|
type = types.attrsOf (types.submodule proxyOptions);
|
2022-07-20 12:32:04 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-04-28 18:32:22 +02:00
|
|
|
Proxies to be used by proxychains.
|
|
|
|
'';
|
|
|
|
|
2021-10-03 18:06:03 +02:00
|
|
|
example = literalExpression ''
|
2020-04-28 18:32:22 +02:00
|
|
|
{ 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 ];
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|