2023-09-12 16:13:15 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.services.frp;
|
2023-12-15 10:13:45 +00:00
|
|
|
settingsFormat = pkgs.formats.toml { };
|
|
|
|
configFile = settingsFormat.generate "frp.toml" cfg.settings;
|
2023-09-12 16:13:15 +00:00
|
|
|
isClient = (cfg.role == "client");
|
|
|
|
isServer = (cfg.role == "server");
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
services.frp = {
|
|
|
|
enable = mkEnableOption "frp";
|
|
|
|
|
2023-11-30 18:03:14 +00:00
|
|
|
package = mkPackageOption pkgs "frp" { };
|
2023-09-12 16:13:15 +00:00
|
|
|
|
|
|
|
role = mkOption {
|
|
|
|
type = types.enum [ "server" "client" ];
|
|
|
|
description = ''
|
|
|
|
The frp consists of `client` and `server`. The server is usually
|
|
|
|
deployed on the machine with a public IP address, and
|
|
|
|
the client is usually deployed on the machine
|
|
|
|
where the Intranet service to be penetrated resides.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
settings = mkOption {
|
|
|
|
type = settingsFormat.type;
|
|
|
|
default = { };
|
|
|
|
description = ''
|
|
|
|
Frp configuration, for configuration options
|
2023-12-15 10:13:45 +00:00
|
|
|
see the example of [client](https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml)
|
|
|
|
or [server](https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml) on github.
|
2023-09-12 16:13:15 +00:00
|
|
|
'';
|
2023-12-15 10:13:45 +00:00
|
|
|
example = {
|
|
|
|
serverAddr = "x.x.x.x";
|
|
|
|
serverPort = 7000;
|
|
|
|
};
|
2023-09-12 16:13:15 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config =
|
|
|
|
let
|
|
|
|
serviceCapability = optionals isServer [ "CAP_NET_BIND_SERVICE" ];
|
|
|
|
executableFile = if isClient then "frpc" else "frps";
|
|
|
|
in
|
|
|
|
mkIf cfg.enable {
|
|
|
|
systemd.services = {
|
|
|
|
frp = {
|
|
|
|
wants = optionals isClient [ "network-online.target" ];
|
|
|
|
after = if isClient then [ "network-online.target" ] else [ "network.target" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
description = "A fast reverse proxy frp ${cfg.role}";
|
|
|
|
serviceConfig = {
|
|
|
|
Type = "simple";
|
|
|
|
Restart = "on-failure";
|
|
|
|
RestartSec = 15;
|
2023-12-15 10:13:45 +00:00
|
|
|
ExecStart = "${cfg.package}/bin/${executableFile} --strict_config -c ${configFile}";
|
2023-09-12 16:13:15 +00:00
|
|
|
StateDirectoryMode = optionalString isServer "0700";
|
|
|
|
DynamicUser = true;
|
|
|
|
# Hardening
|
|
|
|
UMask = optionalString isServer "0007";
|
|
|
|
CapabilityBoundingSet = serviceCapability;
|
|
|
|
AmbientCapabilities = serviceCapability;
|
|
|
|
PrivateDevices = true;
|
|
|
|
ProtectHostname = true;
|
|
|
|
ProtectClock = true;
|
|
|
|
ProtectKernelTunables = true;
|
|
|
|
ProtectKernelModules = true;
|
|
|
|
ProtectKernelLogs = true;
|
|
|
|
ProtectControlGroups = true;
|
|
|
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ] ++ optionals isClient [ "AF_UNIX" ];
|
|
|
|
LockPersonality = true;
|
|
|
|
MemoryDenyWriteExecute = true;
|
|
|
|
RestrictRealtime = true;
|
|
|
|
RestrictSUIDSGID = true;
|
|
|
|
PrivateMounts = true;
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
SystemCallFilter = [ "@system-service" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
meta.maintainers = with maintainers; [ zaldnoay ];
|
|
|
|
}
|