nixos/croc: init

This commit is contained in:
Julien Moutinho 2020-07-22 10:34:57 +02:00
parent 2ec9a72b80
commit be6463cd9d
4 changed files with 141 additions and 0 deletions

View File

@ -632,6 +632,7 @@
./services/networking/coredns.nix
./services/networking/corerad.nix
./services/networking/coturn.nix
./services/networking/croc.nix
./services/networking/dante.nix
./services/networking/ddclient.nix
./services/networking/dhcpcd.nix

View File

@ -0,0 +1,88 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) types;
cfg = config.services.croc;
rootDir = "/run/croc";
in
{
options.services.croc = {
enable = lib.mkEnableOption "croc relay";
ports = lib.mkOption {
type = with types; listOf port;
default = [9009 9010 9011 9012 9013];
description = "Ports of the relay.";
};
pass = lib.mkOption {
type = with types; either path str;
default = "pass123";
description = "Password or passwordfile for the relay.";
};
openFirewall = lib.mkEnableOption "opening of the peer port(s) in the firewall";
debug = lib.mkEnableOption "debug logs";
};
config = lib.mkIf cfg.enable {
systemd.services.croc = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.croc}/bin/croc --pass '${cfg.pass}' ${lib.optionalString cfg.debug "--debug"} relay --ports ${lib.concatMapStringsSep "," toString cfg.ports}";
# The following options are only for optimizing:
# systemd-analyze security croc
AmbientCapabilities = "";
CapabilityBoundingSet = "";
DynamicUser = true;
# ProtectClock= adds DeviceAllow=char-rtc r
DeviceAllow = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
MountAPIVFS = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateNetwork = lib.mkDefault false;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "noaccess";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RootDirectory = rootDir;
# Avoid mounting rootDir in the own rootDir of ExecStart='s mount namespace.
InaccessiblePaths = [ "-+${rootDir}" ];
BindReadOnlyPaths = [
builtins.storeDir
] ++ lib.optional (types.path.check cfg.pass) cfg.pass;
# This is for BindReadOnlyPaths=
# to allow traversal of directories they create in RootDirectory=.
UMask = "0066";
# Create rootDir in the host's mount namespace.
RuntimeDirectory = [(baseNameOf rootDir)];
RuntimeDirectoryMode = "700";
SystemCallFilter = [
"@system-service"
"~@aio" "~@chown" "~@keyring" "~@memlock"
"~@privileged" "~@resources" "~@setuid"
"~@sync" "~@timer"
];
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
};
};
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall cfg.ports;
};
meta.maintainers = with lib.maintainers; [ hax404 julm ];
}

View File

@ -82,6 +82,7 @@ in
couchdb = handleTest ./couchdb.nix {};
cri-o = handleTestOn ["x86_64-linux"] ./cri-o.nix {};
custom-ca = handleTest ./custom-ca.nix {};
croc = handleTest ./croc.nix {};
deluge = handleTest ./deluge.nix {};
dhparams = handleTest ./dhparams.nix {};
dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};

51
nixos/tests/croc.nix Normal file
View File

@ -0,0 +1,51 @@
import ./make-test-python.nix ({ pkgs, ... }:
let
client = { pkgs, ... }: {
environment.systemPackages = [ pkgs.croc ];
};
pass = pkgs.writeText "pass" "PassRelay";
in {
name = "croc";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ hax404 julm ];
};
nodes = {
relay = {
services.croc = {
enable = true;
pass = pass;
openFirewall = true;
};
};
sender = client;
receiver = client;
};
testScript = ''
start_all()
# wait until relay is up
relay.wait_for_unit("croc")
relay.wait_for_open_port(9009)
relay.wait_for_open_port(9010)
relay.wait_for_open_port(9011)
relay.wait_for_open_port(9012)
relay.wait_for_open_port(9013)
# generate testfiles and send them
sender.wait_for_unit("multi-user.target")
sender.execute("echo Hello World > testfile01.txt")
sender.execute("echo Hello Earth > testfile02.txt")
sender.execute(
"croc --pass ${pass} --relay relay send --code topSecret testfile01.txt testfile02.txt &"
)
# receive the testfiles and check them
receiver.succeed(
"croc --pass ${pass} --yes --relay relay topSecret"
)
assert "Hello World" in receiver.succeed("cat testfile01.txt")
assert "Hello Earth" in receiver.succeed("cat testfile02.txt")
'';
})