wg-home: derive wireguard key from ssh privkey

This commit is contained in:
colin 2023-01-20 06:57:49 +00:00
parent 7c18d77046
commit 7c2ab92302
6 changed files with 64 additions and 10 deletions

View File

@ -67,9 +67,6 @@
sops.secrets."wg_ovpnd_ukr_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_home_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."snippets" = {
sopsFile = ../../secrets/universal/snippets.bin;

View File

@ -2,6 +2,7 @@
{
imports = [
./derived-secrets.nix
./hardware
./hosts.nix
./roles

View File

@ -0,0 +1,47 @@
{ config, lib, ... }:
let
inherit (builtins) toString;
inherit (lib) mapAttrs mkOption types;
cfg = config.sane.derived-secrets;
secret = types.submodule {
options = {
len = mkOption {
type = types.int;
};
encoding = mkOption {
type = types.enum [ "base64" ];
};
};
};
in
{
options = {
sane.derived-secrets = mkOption {
type = types.attrsOf secret;
default = {};
description = ''
fs path => secret options.
for each entry, we create an item at the given path whose value is deterministic,
but also pseudo-random and not predictable by anyone without root access to the machine.
as PRNG source we use the host ssh key, and derived secrets are salted based on the destination path.
'';
};
};
config = {
sane.fs = mapAttrs (path: c: {
generated.script.script = ''
echo "$1" | cat /dev/stdin /etc/ssh/host_keys/ssh_host_ed25519_key \
| sha512sum \
| cut -c 1-${toString (c.len * 2)} \
| tr a-z A-Z \
| basenc -d --base16 \
| basenc --${c.encoding} \
> "$1"
'';
generated.script.scriptArgs = [ path ];
generated.acl.mode = "0600";
}) cfg;
};
}

View File

@ -52,7 +52,7 @@ in
sane.hosts.by-name."lappy" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
wg-home.pubkey = "pWtnKW7f7sNIZQ2M83uJ7cHg3IL1tebE3IoVkCgjkXM=";
wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
};
sane.hosts.by-name."moby" = {

View File

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkMerge mkOption optionalAttrs types;
@ -17,6 +17,12 @@ in
config = mkIf cfg.enable (mkMerge [
{
# generate a (deterministic) wireguard private key
sane.derived-secrets."/run/wg-home.priv" = {
len = 32;
encoding = "base64";
};
# wireguard VPN which allows everything on my domain to speak to each other even when
# not behind a shared LAN.
# this config defines both the endpoint (server) and client configs
@ -25,12 +31,17 @@ in
networking.firewall.allowedUDPPorts = [ 51820 ];
networking.wireguard.interfaces.wg-home = {
listenPort = 51820;
privateKeyFile = "/run/wg-home.priv";
preSetup =
let
gen-key = config.sane.fs."/run/wg-home.priv".unit;
in
"${pkgs.systemd}/bin/systemctl start '${gen-key}'";
};
}
{
networking.wireguard.interfaces.wg-home = lib.mkIf (cfg.role == "client") {
privateKeyFile = config.sops.secrets.wg_home_privkey.path;
# client IP (TODO: make host-specific)
ips = [ "10.0.10.20/24" ];
@ -54,7 +65,6 @@ in
}
{
networking.wireguard.interfaces.wg-home = lib.mkIf (cfg.role == "server") {
privateKeyFile = config.sops.secrets.wg_home_server_privkey.path;
ips = [
"10.0.10.5/24"
];

View File

@ -9,7 +9,6 @@ wg_ovpnd_us_privkey: ENC[AES256_GCM,data:5YkQ4r7HNWiRr/5pa1XfexxtJAz6kDjX+hNiZch
wg_ovpnd_us-atl_privkey: ENC[AES256_GCM,data:NMguzx35VvOAo37U9pGD5bYa/ghWeSK5tVh2XRNsfKjMPhMa44lm3pTscdU=,iv:f9hBhMksL0VGT8k2RsztU9AjR2AIIL+Z2Ls24UOPeNA=,tag:C46xDGb2d32mmHWl7WQb2g==,type:str]
wg_ovpnd_us-mi_privkey: ENC[AES256_GCM,data:uEC3UOOqn1l7KwGmOxKvXccPR9Gu8/BNTlpXxXlNWf19/pIX1CLPORUWme0=,iv:cnPGghGBAsIsR86F1hPZawLWlY/pLCNF/1cg6gjrIKE=,tag:LqMbpGklQH0GX7dNNV3/8Q==,type:str]
wg_ovpnd_ukr_privkey: ENC[AES256_GCM,data:5zfhsZnBk0Kb9Nb/3igsV/fN0ZDjwTAGTKyMLMly/l7MlJe6MEmd5Lv+JT8=,iv:Mov9eUP8WfvzfZ6NljgLolJ49GSqR7eSV+k0dgE1+1I=,tag:O9UtGX2qt+qEvabcsA0vIA==,type:str]
wg_home_privkey: ENC[AES256_GCM,data:c8wabBMlip3QlJ6P0ZMU/Y1Sp5V9NjVRB0sQGr9BGm1LFoSs9pkS+Su+SD8=,iv:hnIjd15g+zWqPnXu4puLrKSn2N4zVrXp32xnb315VQk=,tag:hFKSV6qb5ns9CvvuXBWLLg==,type:str]
#ENC[AES256_GCM,data:qlF8rpSMUv6Z/YrOTp7WYs0lcpmSIi/r+gCuiw==,iv:cneNp/0av/ttQvnW4JVX9mj3261QFAzkLIzEMwiKwE8=,tag:FFsPUQBsSeImtymawY4eSg==,type:comment]
router_passwd: ENC[AES256_GCM,data:Tya3Pd75Yu4=,iv:lqi7SavFnymL+uOQXDEzGxgikB6/ckNOBifjhyjXn1Q=,tag:HG3kf6e2g53uNUGI9FXyqQ==,type:str]
jackett_apikey: ENC[AES256_GCM,data:2oGczau3f/w/5iCx3aft0V/t0tO5zsr5Xi/HQ1koTTo=,iv:33VPT8GYCPPJ2RUBP6yuLep9YX/VMW9Kt3MyQPmZuO0=,tag:TUIbutJKV5e3Kc9INk5VUA==,type:str]
@ -91,8 +90,8 @@ sops:
YmhsY0FaSW5oWVNJMlhUSDRCeWQ4KzAKaQp321XYtAZ98f4QMl5PxivAYm6VMF43
wCThiQgvYAP59jvVDTZngvfWAD5PyWVVvMNbjHGvAzK5WnsTPmxlsg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-01-19T09:45:50Z"
mac: ENC[AES256_GCM,data:v+gQu9PFcLXxatllrlMX67ZaIr4MIn7v0YuQEfw2ZnIgcxlukW/wInCf8aOt+172Yme1e/YVf4X8KePUNQlFwPdfw4S+NDUSC92Kuu3/ZD3tYk46VGNPGfhiz9APeCej6oBebo4RBrIhFq5HUJe5pm2W5So/YAldUnCmfgSNyBs=,iv:plMcyLC3fj7KpOBbYcSDmY7vZpV/klHre12jbTKUhVw=,tag:yiJR3HmVYApF9CXruGGq4g==,type:str]
lastmodified: "2023-01-20T06:57:29Z"
mac: ENC[AES256_GCM,data:J/yLlcmlX6st/d6c8eL/6DKZiHAELb0/zj+5qOjoE2uAgTTFnojaP4ssrmt7BaLQF1MQNnvkchvuwRv+dAVTXkuYPuDWS3YriAKQIXUx9sHIEoY6Aqa37eBwUNUBuxoR6FvfOGtXrIZuS0f7hZr+ddBZgCSBBE54yeH68Va1tZk=,iv:Y/T8qykrqRVQ8eMkNH2DZa6XoGd5nL18h/2SJucVAD8=,tag:OwZfOyLc29c1bJJIA9IW3Q==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3