mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-10 19:55:41 +03:00

Format all Nix files using the officially approved formatter,
making the CI check introduced in the previous commit succeed:
nix-build ci -A fmt.check
This is the next step of the of the [implementation](https://github.com/NixOS/nixfmt/issues/153)
of the accepted [RFC 166](https://github.com/NixOS/rfcs/pull/166).
This commit will lead to merge conflicts for a number of PRs,
up to an estimated ~1100 (~33%) among the PRs with activity in the past 2
months, but that should be lower than what it would be without the previous
[partial treewide format](https://github.com/NixOS/nixpkgs/pull/322537).
Merge conflicts caused by this commit can now automatically be resolved while rebasing using the
[auto-rebase script](8616af08d9/maintainers/scripts/auto-rebase
).
If you run into any problems regarding any of this, please reach out to the
[formatting team](https://nixos.org/community/teams/formatting/) by
pinging @NixOS/nix-formatting.
327 lines
10 KiB
Nix
327 lines
10 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.sslh;
|
|
user = "sslh";
|
|
|
|
configFormat = pkgs.formats.libconfig { };
|
|
configFile = configFormat.generate "sslh.conf" cfg.settings;
|
|
in
|
|
|
|
{
|
|
imports = [
|
|
(mkRenamedOptionModule
|
|
[ "services" "sslh" "listenAddress" ]
|
|
[ "services" "sslh" "listenAddresses" ]
|
|
)
|
|
(mkRenamedOptionModule [ "services" "sslh" "timeout" ] [ "services" "sslh" "settings" "timeout" ])
|
|
(mkRenamedOptionModule
|
|
[ "services" "sslh" "transparent" ]
|
|
[ "services" "sslh" "settings" "transparent" ]
|
|
)
|
|
(mkRemovedOptionModule [ "services" "sslh" "appendConfig" ] "Use services.sslh.settings instead")
|
|
(mkChangedOptionModule
|
|
[ "services" "sslh" "verbose" ]
|
|
[ "services" "sslh" "settings" "verbose-connections" ]
|
|
(config: if config.services.sslh.verbose then 1 else 0)
|
|
)
|
|
];
|
|
|
|
meta.buildDocsInSandbox = false;
|
|
|
|
options.services.sslh = {
|
|
enable = mkEnableOption "sslh, protocol demultiplexer";
|
|
|
|
method = mkOption {
|
|
type = types.enum [
|
|
"fork"
|
|
"select"
|
|
"ev"
|
|
];
|
|
default = "fork";
|
|
description = ''
|
|
The method to use for handling connections:
|
|
|
|
- `fork` forks a new process for each incoming connection. It is
|
|
well-tested and very reliable, but incurs the overhead of many
|
|
processes.
|
|
|
|
- `select` uses only one thread, which monitors all connections at once.
|
|
It has lower overhead per connection, but if it stops, you'll lose all
|
|
connections.
|
|
|
|
- `ev` is implemented using libev, it's similar to `select` but
|
|
scales better to a large number of connections.
|
|
'';
|
|
};
|
|
|
|
listenAddresses = mkOption {
|
|
type = with types; coercedTo str singleton (listOf str);
|
|
default = [
|
|
"0.0.0.0"
|
|
"[::]"
|
|
];
|
|
description = "Listening addresses or hostnames.";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 443;
|
|
description = "Listening port.";
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = types.submodule {
|
|
freeformType = configFormat.type;
|
|
|
|
options.timeout = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 2;
|
|
description = "Timeout in seconds.";
|
|
};
|
|
|
|
options.transparent = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether the services behind sslh (Apache, sshd and so on) will see the
|
|
external IP and ports as if the external world connected directly to
|
|
them.
|
|
'';
|
|
};
|
|
|
|
options.verbose-connections = mkOption {
|
|
type = types.ints.between 0 4;
|
|
default = 0;
|
|
description = ''
|
|
Where to log connections information. Possible values are:
|
|
|
|
0. don't log anything
|
|
1. write log to stdout
|
|
2. write log to syslog
|
|
3. write log to both stdout and syslog
|
|
4. write to a log file ({option}`sslh.settings.logfile`)
|
|
'';
|
|
};
|
|
|
|
options.numeric = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to disable reverse DNS lookups, thus keeping IP
|
|
address literals in the log.
|
|
'';
|
|
};
|
|
|
|
options.protocols = mkOption {
|
|
type = types.listOf configFormat.type;
|
|
default = [
|
|
{
|
|
name = "ssh";
|
|
host = "localhost";
|
|
port = "22";
|
|
service = "ssh";
|
|
}
|
|
{
|
|
name = "openvpn";
|
|
host = "localhost";
|
|
port = "1194";
|
|
}
|
|
{
|
|
name = "xmpp";
|
|
host = "localhost";
|
|
port = "5222";
|
|
}
|
|
{
|
|
name = "http";
|
|
host = "localhost";
|
|
port = "80";
|
|
}
|
|
{
|
|
name = "tls";
|
|
host = "localhost";
|
|
port = "443";
|
|
}
|
|
{
|
|
name = "anyprot";
|
|
host = "localhost";
|
|
port = "443";
|
|
}
|
|
];
|
|
description = ''
|
|
List of protocols sslh will probe for and redirect.
|
|
Each protocol entry consists of:
|
|
|
|
- `name`: name of the probe.
|
|
|
|
- `service`: libwrap service name (see {manpage}`hosts_access(5)`),
|
|
|
|
- `host`, `port`: where to connect when this probe succeeds,
|
|
|
|
- `log_level`: to log incoming connections,
|
|
|
|
- `transparent`: proxy this protocol transparently,
|
|
|
|
- etc.
|
|
|
|
See the documentation for all options, including probe-specific ones.
|
|
'';
|
|
};
|
|
};
|
|
description = "sslh configuration. See {manpage}`sslh(8)` for available settings.";
|
|
};
|
|
};
|
|
|
|
config = mkMerge [
|
|
(mkIf cfg.enable {
|
|
systemd.services.sslh = {
|
|
description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
serviceConfig = {
|
|
DynamicUser = true;
|
|
User = "sslh";
|
|
PermissionsStartOnly = true;
|
|
Restart = "always";
|
|
RestartSec = "1s";
|
|
ExecStart = "${pkgs.sslh}/bin/sslh-${cfg.method} -F${configFile}";
|
|
KillMode = "process";
|
|
AmbientCapabilities = [
|
|
"CAP_NET_BIND_SERVICE"
|
|
"CAP_NET_ADMIN"
|
|
"CAP_SETGID"
|
|
"CAP_SETUID"
|
|
];
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
ProtectSystem = "full";
|
|
ProtectHome = true;
|
|
};
|
|
};
|
|
|
|
services.sslh.settings = {
|
|
# Settings defined here are not supposed to be changed: doing so will
|
|
# break the module, as such you need `lib.mkForce` to override them.
|
|
foreground = true;
|
|
inetd = false;
|
|
listen = map (addr: {
|
|
host = addr;
|
|
port = toString cfg.port;
|
|
}) cfg.listenAddresses;
|
|
};
|
|
|
|
})
|
|
|
|
# code from https://github.com/yrutschle/sslh#transparent-proxy-support
|
|
# the only difference is using iptables mark 0x2 instead of 0x1 to avoid conflicts with nixos/nat module
|
|
(mkIf (cfg.enable && cfg.settings.transparent) {
|
|
# Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination
|
|
boot.kernel.sysctl."net.ipv4.conf.default.route_localnet" = 1;
|
|
boot.kernel.sysctl."net.ipv4.conf.all.route_localnet" = 1;
|
|
|
|
systemd.services.sslh =
|
|
let
|
|
iptablesCommands = [
|
|
# DROP martian packets as they would have been if route_localnet was zero
|
|
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
|
|
{
|
|
table = "raw";
|
|
command = "PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP";
|
|
}
|
|
{
|
|
table = "mangle";
|
|
command = "POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP";
|
|
}
|
|
# Mark all connections made by ssl for special treatment (here sslh is run as user ${user})
|
|
{
|
|
table = "nat";
|
|
command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f";
|
|
}
|
|
# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
|
|
{
|
|
table = "mangle";
|
|
command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f";
|
|
}
|
|
];
|
|
ip6tablesCommands = [
|
|
{
|
|
table = "raw";
|
|
command = "PREROUTING ! -i lo -d ::1/128 -j DROP";
|
|
}
|
|
{
|
|
table = "mangle";
|
|
command = "POSTROUTING ! -o lo -s ::1/128 -j DROP";
|
|
}
|
|
{
|
|
table = "nat";
|
|
command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f";
|
|
}
|
|
{
|
|
table = "mangle";
|
|
command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f";
|
|
}
|
|
];
|
|
in
|
|
{
|
|
path = [
|
|
pkgs.iptables
|
|
pkgs.iproute2
|
|
pkgs.procps
|
|
];
|
|
|
|
preStart =
|
|
''
|
|
# Cleanup old iptables entries which might be still there
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "while iptables -w -t ${table} -D ${command} 2>/dev/null; do echo; done"
|
|
) iptablesCommands}
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "iptables -w -t ${table} -A ${command}"
|
|
) iptablesCommands}
|
|
|
|
# Configure routing for those marked packets
|
|
ip rule add fwmark 0x2 lookup 100
|
|
ip route add local 0.0.0.0/0 dev lo table 100
|
|
|
|
''
|
|
+ optionalString config.networking.enableIPv6 ''
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "while ip6tables -w -t ${table} -D ${command} 2>/dev/null; do echo; done"
|
|
) ip6tablesCommands}
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "ip6tables -w -t ${table} -A ${command}"
|
|
) ip6tablesCommands}
|
|
|
|
ip -6 rule add fwmark 0x2 lookup 100
|
|
ip -6 route add local ::/0 dev lo table 100
|
|
'';
|
|
|
|
postStop =
|
|
''
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "iptables -w -t ${table} -D ${command}"
|
|
) iptablesCommands}
|
|
|
|
ip rule del fwmark 0x2 lookup 100
|
|
ip route del local 0.0.0.0/0 dev lo table 100
|
|
''
|
|
+ optionalString config.networking.enableIPv6 ''
|
|
${concatMapStringsSep "\n" (
|
|
{ table, command }: "ip6tables -w -t ${table} -D ${command}"
|
|
) ip6tablesCommands}
|
|
|
|
ip -6 rule del fwmark 0x2 lookup 100
|
|
ip -6 route del local ::/0 dev lo table 100
|
|
'';
|
|
};
|
|
})
|
|
];
|
|
}
|