From c5c5baf5afbdc648bdf5beb67ec9acb5fcf9068b Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 14 Oct 2019 01:59:38 -0700 Subject: [PATCH 1/3] maintainers: add danderson --- maintainers/maintainer-list.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 3dbd6282df4..428c3d1ee62 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -1439,6 +1439,12 @@ githubId = 245394; name = "Hannu Hartikainen"; }; + danderson = { + email = "dave@natulte.net"; + github = "danderson"; + githubId = 1918; + name = "David Anderson"; + }; danharaj = { email = "dan@obsidian.systems"; github = "danharaj"; From 997a6f6f1eee4f2191bbb73fab08a5765014cd1e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 14 Oct 2019 01:59:50 -0700 Subject: [PATCH 2/3] nixos/pppd: init --- nixos/modules/module-list.nix | 1 + nixos/modules/services/networking/pppd.nix | 133 +++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 nixos/modules/services/networking/pppd.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4d177ae9699..5214126ff7e 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -666,6 +666,7 @@ ./services/networking/polipo.nix ./services/networking/powerdns.nix ./services/networking/pdns-recursor.nix + ./services/networking/pppd.nix ./services/networking/pptpd.nix ./services/networking/prayer.nix ./services/networking/privoxy.nix diff --git a/nixos/modules/services/networking/pppd.nix b/nixos/modules/services/networking/pppd.nix new file mode 100644 index 00000000000..db135911764 --- /dev/null +++ b/nixos/modules/services/networking/pppd.nix @@ -0,0 +1,133 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.pppd; +in +{ + meta = { + maintainers = with maintainers; [ danderson ]; + }; + + options = { + services.pppd = { + enable = mkEnableOption "pppd"; + + package = mkOption { + default = pkgs.ppp; + defaultText = "pkgs.ppp"; + type = types.package; + description = "pppd package to use."; + }; + + peers = mkOption { + default = {}; + type = types.attrsOf (types.submodule ( + { name, ... }: + { + options = { + name = mkOption { + type = types.str; + default = name; + example = "dialup"; + description = "Name of the PPP peer."; + }; + + enable = mkOption { + type = types.bool; + default = true; + example = false; + description = "Whether to enable this PPP peer."; + }; + + autostart = mkOption { + type = types.bool; + default = true; + example = false; + description = "Whether the PPP session is automatically started at boot time."; + }; + + config = mkOption { + type = types.lines; + default = ""; + description = "pppd configuration for this peer, see the pppd(8) man page."; + }; + }; + })); + }; + }; + }; + + config = let + enabledConfigs = filter (f: f.enable) (attrValues cfg.peers); + + mkEtc = peerCfg: { + "ppp/peers/${peerCfg.name}".text = peerCfg.config; + }; + + mkSystemd = peerCfg: { + "pppd-${peerCfg.name}" = { + restartTriggers = [ config.environment.etc."ppp/peers/${peerCfg.name}".source ]; + before = [ "network.target" ]; + wants = [ "network.target" ]; + after = [ "network-pre.target" ]; + environment = { + # pppd likes to write directly into /var/run. This is rude + # on a modern system, so we use libredirect to transparently + # move those files into /run/pppd. + LD_PRELOAD = "${pkgs.libredirect}/lib/libredirect.so"; + NIX_REDIRECTS = "/var/run=/run/pppd"; + }; + serviceConfig = { + ExecStart = "${getBin cfg.package}/sbin/pppd call ${peerCfg.name} nodetach nolog"; + Restart = "always"; + RestartSec = 5; + + AmbientCapabilities = "CAP_SYS_TTY_CONFIG CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_ADMIN"; + CapabilityBoundingSet = "CAP_SYS_TTY_CONFIG CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_ADMIN"; + KeyringMode = "private"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateMounts = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelModules = true; + # pppd can be configured to tweak kernel settings. + ProtectKernelTunables = false; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = "AF_PACKET AF_UNIX AF_PPPOX AF_ATMPVC AF_ATMSVC AF_INET AF_INET6 AF_IPX"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SecureBits = "no-setuid-fixup-locked noroot-locked"; + SystemCallFilter = "@system-service"; + SystemCallArchitectures = "native"; + + # All pppd instances on a system must share a runtime + # directory in order for PPP multilink to work correctly. So + # we give all instances the same /run/pppd directory to store + # things in. + # + # For the same reason, we can't set PrivateUsers=true, because + # all instances need to run as the same user to access the + # multilink database. + RuntimeDirectory = "pppd"; + RuntimeDirectoryPreserve = true; + }; + wantedBy = mkIf peerCfg.autostart [ "multi-user.target" ]; + }; + }; + + etcFiles = map mkEtc enabledConfigs; + systemdConfigs = map mkSystemd enabledConfigs; + + in mkIf cfg.enable { + environment.etc = mkMerge etcFiles; + systemd.services = mkMerge systemdConfigs; + }; +} From ae02b3dd1f450b51ef69bb13e4c7728106009936 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 14 Oct 2019 21:26:54 -0700 Subject: [PATCH 3/3] nixos/tests/pppd: init This test creates a PPPoE link between two machines, and verifies that the machines can ping each other. --- nixos/tests/all-tests.nix | 1 + nixos/tests/pppd.nix | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 nixos/tests/pppd.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 914b32f97c3..e94c9712cbf 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -227,6 +227,7 @@ in postgresql = handleTest ./postgresql.nix {}; postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {}; powerdns = handleTest ./powerdns.nix {}; + pppd = handleTest ./pppd.nix {}; predictable-interface-names = handleTest ./predictable-interface-names.nix {}; printing = handleTest ./printing.nix {}; prometheus = handleTest ./prometheus.nix {}; diff --git a/nixos/tests/pppd.nix b/nixos/tests/pppd.nix new file mode 100644 index 00000000000..91f81185909 --- /dev/null +++ b/nixos/tests/pppd.nix @@ -0,0 +1,62 @@ +import ./make-test.nix ( + let + chap-secrets = { + text = ''"flynn" * "reindeerflotilla" *''; + mode = "0640"; + }; + in { + nodes = { + server = {config, pkgs, ...}: { + config = { + # Run a PPPoE access concentrator server. It will spawn an + # appropriate PPP server process when a PPPoE client sets up a + # PPPoE session. + systemd.services.pppoe-server = { + restartTriggers = [ + config.environment.etc."ppp/pppoe-server-options".source + config.environment.etc."ppp/chap-secrets".source + ]; + after = ["network.target"]; + serviceConfig = { + ExecStart = "${pkgs.rpPPPoE}/sbin/pppoe-server -F -O /etc/ppp/pppoe-server-options -q ${pkgs.ppp}/sbin/pppd -I eth1 -L 192.0.2.1 -R 192.0.2.2"; + }; + wantedBy = ["multi-user.target"]; + }; + environment.etc = { + "ppp/pppoe-server-options".text = '' + lcp-echo-interval 10 + lcp-echo-failure 2 + plugin rp-pppoe.so + require-chap + nobsdcomp + noccp + novj + ''; + "ppp/chap-secrets" = chap-secrets; + }; + }; + }; + client = {config, pkgs, ...}: { + services.pppd = { + enable = true; + peers.test = { + config = '' + plugin rp-pppoe.so eth1 + name "flynn" + noipdefault + persist + noauth + debug + ''; + }; + }; + environment.etc."ppp/chap-secrets" = chap-secrets; + }; + }; + + testScript = '' + startAll; + $client->waitUntilSucceeds("ping -c1 -W1 192.0.2.1"); + $server->waitUntilSucceeds("ping -c1 -W1 192.0.2.2"); + ''; + })