parent
2ec9a72b80
commit
be6463cd9d
@ -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 ]; |
||||
} |
@ -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") |
||||
''; |
||||
}) |
Loading…
Reference in new issue