Unverified Commit 5d87a1b9 authored by Ryan Lahfa's avatar Ryan Lahfa Committed by GitHub
Browse files

Merge pull request #195735 from hax404/tayga_init

nixos/tayga: init
parents 831b9b4c 3e534cfd
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1809,6 +1809,13 @@ services.github-runner.serviceOverrides.SupplementaryGroups = [
          <link xlink:href="options.html#opt-services.tandoor-recipes.enable">services.tandoor-recipes</link>.
        </para>
      </listitem>
      <listitem>
        <para>
          <link xlink:href="http://www.litech.org/tayga/">TAYGA</link>,
          an out-of-kernel stateless NAT64 implementation. Available as
          <link linkend="opt-services.tayga.enable">services.tayga</link>.
        </para>
      </listitem>
      <listitem>
        <para>
          <link xlink:href="https://github.com/tmate-io/tmate-ssh-server">tmate-ssh-server</link>,
+2 −0
Original line number Diff line number Diff line
@@ -526,6 +526,8 @@ In addition to numerous new and upgraded packages, this release includes the fol

- [Tandoor Recipes](https://tandoor.dev), a self-hosted multi-tenant recipe collection. Available as [services.tandoor-recipes](options.html#opt-services.tandoor-recipes.enable).

- [TAYGA](http://www.litech.org/tayga/), an out-of-kernel stateless NAT64 implementation. Available as [services.tayga](#opt-services.tayga.enable).

- [tmate-ssh-server](https://github.com/tmate-io/tmate-ssh-server), server side part of [tmate](https://tmate.io/). Available as [services.tmate-ssh-server](#opt-services.tmate-ssh-server.enable).

- [Uptime Kuma](https://uptime.kuma.pet/), a fancy self-hosted monitoring tool. Available as [services.uptime-kuma](#opt-services.uptime-kuma.enable).
+1 −0
Original line number Diff line number Diff line
@@ -967,6 +967,7 @@
  ./services/networking/syncthing-relay.nix
  ./services/networking/syncplay.nix
  ./services/networking/tailscale.nix
  ./services/networking/tayga.nix
  ./services/networking/tcpcrypt.nix
  ./services/networking/teamspeak3.nix
  ./services/networking/tedicross.nix
+195 −0
Original line number Diff line number Diff line
{ config, lib, pkgs, ... }:

with lib;
let
  cfg = config.services.tayga;

  # Converts an address set to a string
  strAddr = addr: "${addr.address}/${toString addr.prefixLength}";

  configFile = pkgs.writeText "tayga.conf" ''
    tun-device ${cfg.tunDevice}

    ipv4-addr ${cfg.ipv4.address}
    ${optionalString (cfg.ipv6.address != null) "ipv6-addr ${cfg.ipv6.address}"}

    prefix ${strAddr cfg.ipv6.pool}
    dynamic-pool ${strAddr cfg.ipv4.pool}
    data-dir ${cfg.dataDir}
  '';

  addrOpts = v:
    assert v == 4 || v == 6;
    {
      options = {
        address = mkOption {
          type = types.str;
          description = lib.mdDoc "IPv${toString v} address.";
        };

        prefixLength = mkOption {
          type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
          description = lib.mdDoc ''
            Subnet mask of the interface, specified as the number of
            bits in the prefix ("${if v == 4 then "24" else "64"}").
          '';
        };
      };
    };

  versionOpts = v: {
    options = {
      router = {
        address = mkOption {
          type = types.str;
          description = lib.mdDoc "The IPv${toString v} address of the router.";
        };
      };

      address = mkOption {
        type = types.nullOr types.str;
        default = null;
        description = lib.mdDoc "The source IPv${toString v} address of the TAYGA server.";
      };

      pool = mkOption {
        type = with types; nullOr (submodule (addrOpts v));
        description = lib.mdDoc "The pool of IPv${toString v} addresses which are used for translation.";
      };
    };
  };
in
{
  options = {
    services.tayga = {
      enable = mkEnableOption (lib.mdDoc "Tayga");

      package = mkOption {
        type = types.package;
        default = pkgs.tayga;
        defaultText = lib.literalMD "pkgs.tayga";
        description = lib.mdDoc "This option specifies the TAYGA package to use.";
      };

      ipv4 = mkOption {
        type = types.submodule (versionOpts 4);
        description = lib.mdDoc "IPv4-specific configuration.";
        example = literalExpression ''
          {
            address = "192.0.2.0";
            router = {
              address = "192.0.2.1";
            };
            pool = {
              address = "192.0.2.1";
              prefixLength = 24;
            };
          }
        '';
      };

      ipv6 = mkOption {
        type = types.submodule (versionOpts 6);
        description = lib.mdDoc "IPv6-specific configuration.";
        example = literalExpression ''
          {
            address = "2001:db8::1";
            router = {
              address = "64:ff9b::1";
            };
            pool = {
              address = "64:ff9b::";
              prefixLength = 96;
            };
          }
        '';
      };

      dataDir = mkOption {
        type = types.path;
        default = "/var/lib/tayga";
        description = lib.mdDoc "Directory for persistent data";
      };

      tunDevice = mkOption {
        type = types.str;
        default = "nat64";
        description = lib.mdDoc "Name of the nat64 tun device";
      };
    };
  };

  config = mkIf cfg.enable {
    networking.interfaces."${cfg.tunDevice}" = {
      virtual = true;
      virtualType = "tun";
      virtualOwner = mkIf config.networking.useNetworkd "";
      ipv4 = {
        addresses = [
          { address = cfg.ipv4.router.address; prefixLength = 32; }
        ];
        routes = [
          cfg.ipv4.pool
        ];
      };
      ipv6 = {
        addresses = [
          { address = cfg.ipv6.router.address; prefixLength = 128; }
        ];
        routes = [
          cfg.ipv6.pool
        ];
      };
    };

    systemd.services.tayga = {
      description = "Stateless NAT64 implementation";
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];

      serviceConfig = {
        ExecStart = "${cfg.package}/bin/tayga -d --nodetach --config ${configFile}";
        ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
        Restart = "always";

        # Hardening Score:
        #  - nixos-scripts: 2.1
        #  - systemd-networkd: 1.6
        ProtectHome = true;
        SystemCallFilter = [
          "@network-io"
          "@system-service"
          "~@privileged"
          "~@resources"
        ];
        ProtectKernelLogs = true;
        AmbientCapabilities = [
          "CAP_NET_ADMIN"
        ];
        CapabilityBoundingSet = "";
        RestrictAddressFamilies = [
          "AF_INET"
          "AF_INET6"
          "AF_NETLINK"
        ];
        StateDirectory = "tayga";
        DynamicUser = mkIf config.networking.useNetworkd true;
        MemoryDenyWriteExecute = true;
        RestrictRealtime = true;
        RestrictSUIDSGID = true;
        ProtectHostname = true;
        ProtectKernelModules = true;
        ProtectKernelTunables = true;
        RestrictNamespaces = true;
        NoNewPrivileges = true;
        ProtectControlGroups = true;
        SystemCallArchitectures = "native";
        PrivateTmp = true;
        LockPersonality = true;
        ProtectSystem = true;
        PrivateUsers = true;
        ProtectProc = "invisible";
      };
    };
  };
}
+1 −0
Original line number Diff line number Diff line
@@ -638,6 +638,7 @@ in {
  systemd-misc = handleTest ./systemd-misc.nix {};
  tandoor-recipes = handleTest ./tandoor-recipes.nix {};
  taskserver = handleTest ./taskserver.nix {};
  tayga = handleTest ./tayga.nix {};
  teeworlds = handleTest ./teeworlds.nix {};
  telegraf = handleTest ./telegraf.nix {};
  teleport = handleTest ./teleport.nix {};
Loading