vpn-module #44

Merged
kalipso merged 11 commits from vpn-module into master 2024-12-17 11:30:36 +01:00
14 changed files with 296 additions and 7 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ result
*.qcow2
.direnv/
book/
fanny-efi-vars.fd

View File

@@ -14,6 +14,7 @@
- [How-to]()
- [Create New Host](./anleitung/create.md)
- [Sops](./anleitung/sops.md)
- [Wireguard](./anleitung/wireguard.md)
- [Updates](./anleitung/updates.md)
- [Rollbacks](./anleitung/rollback.md)
- [MicroVM](./anleitung/microvm.md)

View File

@@ -23,18 +23,21 @@ In order to test persistent microvms locally we need to create them using the ``
This is necessary to be able to mount persistent /etc and /var volumes on those hosts.
Do the following:
Prepare your host by including `microvm.nixosModules.host` in your `flake.nix` [Microvm Docs](https://astro.github.io/microvm.nix/host.html)
```bash
# go into our repo and start the default dev shell (or us direnv)
# go into our repo and start the default dev shell (or use direnv)
nix develop .#
# create a microvm on your host (on the example of durruti)
sudo microvm -c durruti -f git+file:///home/username/path/to/infrastructure/repo
# start the vm
sudo systemctl start microvm@durruti.serivce
sudo systemctl start microvm@durruti.service
# this may fail, if so we most probably need to create /var /etc manually, then restart
sudo mkdir /var/lib/microvms/durruti/{var, etc}
sudo mkdir -p /var/lib/microvms/durruti/{var,etc}
# now you can for example get the rsa host key from /var/lib/microvms/durruti/etc/ssh/

View File

@@ -0,0 +1,11 @@
# Wireguard
Running on the raspberry pi
- Create new keys
- Enter nix shell for wg commands `nix-shell -p wireguard-tools`
- New private key `wg genkey > secrets/keys/wireguard/example.key`
- Encrypt with `sops -e -i secrets/keys/wireguard/example.key`
- commit keys only after encrypting
- Decrypt to stdout `sops -d secrets/keys/wireguard/example.key`
- Decrypt for use on a client `sops -d secrets/keys/wireguard/private.key > /tmp/private.key`
- Display public key `sops -d secrets/keys/wireguard/example.key | wg pubkey`

View File

@@ -34,3 +34,10 @@ creation_rules:
- *machine_durruti
age:
- *admin_atlan
- path_regex: secrets/keys/wireguard/.*
key_groups:
- pgp:
- *admin_kalipso
- *admin_kalipso_dsktp
age:
- *admin_atlan

View File

@@ -123,7 +123,6 @@ in
];
};
durruti = nixosSystem {
system = "x86_64-linux";
specialArgs.inputs = inputs;
@@ -133,6 +132,16 @@ in
];
};
vpn = nixosSystem {
system = "x86_64-linux";
specialArgs.inputs = inputs;
specialArgs.self = self;
modules = makeMicroVM "vpn" "10.0.0.10" [
self.nixosModules.malobeo
./vpn/configuration.nix
];
};
lucia = nixosSystem {
system = "aarch64-linux";
specialArgs.inputs = inputs;

View File

@@ -1,5 +1,6 @@
hello: ENC[AES256_GCM,data:3VuyuX7MaLSmor4W22F3FUCGp8SUq4pE6z5nuiZenH07+zEeMAllVCP6g/j1fQ==,iv:A3Oh99AchsmrkMEb4ZRSIigb8Cr+3WlQtsgyZJGpLY8=,tag:TOHF9BaydkRD6cJAndryTg==,type:str]
njala_api_key: ENC[AES256_GCM,data:qXGngMJaAOk2Gb8B4nwMTht9Vp/OEhGmKS5vh1kpi0MyqcsmwuwpWuUz+RWD6NDFn2w/35M=,iv:lsZyCrmcT1xJcLjzK4zkcRYmbKUeLUFYZ7oDfCVJV8c=,tag:WK+aF3XGBRDQuvL87Qdusw==,type:str]
wireguard_private: ENC[AES256_GCM,data:ZxGbYLQKvrPibLpId+xbvqphlcgm/U5Se9XMS4FogmY4HfJnh9Y4Ja/x20I=,iv:PnZjiyKk1XuIq5/NLtOdWh20ytDEMYM7LJqmCoSrD0s=,tag:CZErG28Lo3aiQGovxEeZtA==,type:str]
sops:
kms: []
gcp_kms: []
@@ -15,8 +16,8 @@ sops:
aVFGZjk4UjVJa3FoMDJiaXR2MmdiQ2cKSVgIdxPBNTbNFQbdI5ECNGQrDUK9dQI3
f3mHj+XAPmEtjUXLyxUI1gQ+8toctnU6cgJ+HdGLX01lgTHwz7uieQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-10-24T15:09:51Z"
mac: ENC[AES256_GCM,data:f/wf0EuNmy+ic/k+fHg3IJ8p4I8BftFn6QwGJsXJgTBDspe7Plnwh+kGEqdPg8OEbWy/1niRfCXJa/vKoquWsxL7LUP2lGYT7lj7QYuj2F8fo2WIe2qhCikuxO6Q1asKyBcebYv5KAY/yQlVBYs9X9tcU6Fu4IU2AmJhjYB6m3s=,iv:K3DCEV4/FocdnEulNM9snH4uym8pAZRSmsYbM+rghe4=,tag:429oJE1du0IRl4aDuLzoZA==,type:str]
lastmodified: "2024-11-14T18:10:54Z"
mac: ENC[AES256_GCM,data:DPQsRraMAvoezHsA7uM8q8sEevnZRnpU1vydEL72r6KJj12dT58KXCTuUeNgD+320LE1i83k6HLdM9C/+uniu73Ba5JSwglLLDBkZpfsdCde0aqkGjQd/RF/0Vb8ZbE/KCCCMVOjT6hX6RSDSEujoRMY26n1CWYtPeivqpWb5NY=,iv:TarRTCyPRoyQEb3qoXAJcOYtrTtftyZO4ahkyTZT8qU=,tag:A0kqa1szfk6Z5etivjB/lA==,type:str]
pgp:
- created_at: "2024-11-14T13:02:46Z"
enc: |-
@@ -77,4 +78,4 @@ sops:
-----END PGP MESSAGE-----
fp: 3474196f3adf27cfb70f8f56bcd52d1ed55033db
unencrypted_suffix: _unencrypted
version: 3.7.3
version: 3.8.1

View File

@@ -17,6 +17,13 @@
mountOptions = [ "umask=0077" ];
};
};
encryptedSwap = {
size = "8G"; #set to 100M for testing
content = {
type = "swap";
randomEncryption = true;
};
};
zfs = {
size = "100%";
content = {
@@ -70,6 +77,7 @@
# Workaround: cannot import 'zroot': I/O error in disko tests
options.cachefile = "none";
rootFsOptions = {
mountpoint = "none";
compression = "zstd";
"com.sun:auto-snapshot" = "false";
};
@@ -114,6 +122,7 @@
storage = {
type = "zpool";
mode = "mirror";
rootFsOptions = { mountpoint = "none"; };
datasets = {
encrypted = {

View File

@@ -0,0 +1,24 @@
{
"vpn" = {
role = "server";
publicIp = "5.9.153.217";
ips = [ "10.100.0.1/24" ];
allowedIPs = [ "10.100.0.0/24" ];
listenPort = 51821;
publicKey = "";
};
"fanny" = {
role = "client";
ips = [ "10.100.0.2/24" ];
allowedIPs = [ "10.100.0.0/24" ];
publicKey = "";
};
"test" = {
role = "client";
ips = [ "10.100.0.3/24" ];
allowedIPs = [ "10.100.0.0/24" ];
publicKey = "";
};
}

View File

@@ -0,0 +1,90 @@
{ config, self, lib, inputs, options, pkgs, ... }:
with lib;
let
cfg = config.services.malobeo.vpn;
peers = import ./peers.nix;
myPeer = if cfg.name == "" then peers.${config.networking.hostName} else peers.${cfg.name};
peerList = builtins.filter (peer: peer.role != myPeer.role) (builtins.attrValues peers);
peerListWithEndpoint = map (host:
if host.role == "server" then
host // { endpoint = "${host.publicIp}:${builtins.toString host.listenPort}"; }
else
host
) peerList;
filteredPeerlist = map (host: builtins.removeAttrs host [
"role"
"ips"
"listenPort"
"publicIp"
] ) peerListWithEndpoint;
in
{
options = {
services.malobeo.vpn = {
enable = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc "Setup wireguard to access malobeo maintainance vpn";
};
name = mkOption {
default = "";
type = types.str;
description = ''
Name of the host in peers.nix, if empty uses hostname
'';
};
privateKey = mkOption {
default = "";
type = types.str;
description = ''
Path to private key
'';
};
};
};
imports = [
inputs.microvm.nixosModules.host
];
config = mkIf cfg.enable {
assertions = [
#{
# assertion = !(myPeer != "client" && cfg.role != "server");
# message = ''
# VPN Role must be either client or server, nothing else!
# '';
#}
];
networking.wireguard = {
enable = true;
interfaces = {
wg0 = {
ips = myPeer.ips;
listenPort = mkIf (myPeer.role == "server") myPeer.listenPort;
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN
# For this to work you have to set the dnsserver IP of your router (or dnsserver of choice) in your clients
postSetup = mkIf (myPeer.role == "server") ''
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# This undoes the above command
postShutdown = mkIf (myPeer.role == "server") ''
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
privateKey = cfg.privateKey;
peers = filteredPeerlist;
};
};
};
};
}

View File

@@ -0,0 +1,31 @@
{
"data": "ENC[AES256_GCM,data:MJnybSouJW9QcWks/6fBgYXhM1zREa76FDVh0vGF9LwffY4ceLMQpOsFXEN7,iv:z0H0r6VSXy92uiS9bGXL5KxqiA3jqAiAgAH5KMxppsE=,tag:RKwFFHgv+tnIlKRTyV68Ww==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1ljpdczmg5ctqyeezn739hv589fwhssjjnuqf7276fqun6kc62v3qmhkd0c",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjRlRzcldvSVkxV3VSeDBF\nRG9KK2NzYmtPWXE3a1JPN3NMRlJtbnJML0hzCmNTT0JFMTR6SDl0WVNBNk50VmdZ\nYi9pQU9FQW9qQ3NZdTM5T3FDcjNUQXMKLS0tIEpBcFhtbFMrbWlRYVdPSXpYM0xp\neW5MZ3dOYmphYXk2Tjh2Rk8xOGRkSGMKOLVuj75jqZeZ0SS1iHDRLONLbJ/UQXfO\nEN1ZhYXq7u5s+wKidmGoFVHWFAxM0O3kXaAQAHws4ttP0v6YqeSuBg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-11-14T18:24:30Z",
"mac": "ENC[AES256_GCM,data:1sVhca19IbHJUv+qfkn+cJXjYIaXLX12S9N3QvDUoeUSTT4m2GxArKjvKJSpmc3KZCbOwpF1TObHjDs88pqsCxkzl7J9TSu4EgESRfSUy0lRhIveN/38wvEGI/0yNZXwFisB0nNpPbwAUp4JUZnfcqihlDINbVCw7mzVShHlnvU=,iv:J7/9uhlisRJUkqEFeO9aBRX5rgv0392DCuF5Yu1a5gI=,tag:sd0eoBkxns2pitnMZWvPzQ==,type:str]",
"pgp": [
{
"created_at": "2024-11-14T18:24:30Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQGMA5HdvEwzh/H7AQv/cFzlEwHCdmrKutzeJHOVANtF93aunkV89avpcjNtxjKJ\nzWeDrxZPIhApRsS0Q5kvuYbplwJbDPDbQlDeRsAzZbGVzXisDEYVSLbSEDX253fV\npDoD3MdBU/syMus0x7gSulT288Ije5lY76kBoqrzzsDG1RbHHeQMBP4hrLrFdQhh\nlCtjXJHMPlxR+bsTLhmKFUl6UWA22QeevhIU2VSTU7ROgcE6qRAknJLVVhTBhHmB\nkm2JpTQuM6Vhq+zIYDgLegV2fOiOW9O6ONsUt5N/jQYFSj2T4WL5Wnix/bxVg6vL\nkAto2cO1GsRBRH994AUWq4h5dwYWUCafYkXMILCQmMy81YftAPiAoCTUBsc6DSJ1\nV+gr4G3wLetwY2DdM8HN2Cru49PI923aOtKztjX8+r/w22RZl99INY5F/RP6NAYA\nLCEdw9LlW6Ctct1B6JU+JlCdJ/FW2Q9RMazw9wF4ZCg0AfqC/tLW9ETZF0cRYmA5\nH9LJJIxjNyizlGoJ7p780lgBDNBJD2v3ST5ESJ9TctQLS2XBWHtgskW1rPaCxrVX\nrgE/0PUnqxofOLofu4ktKOxtutYOqyVeP6Tvr0TLLEjwikgZ92LxqMx5dW6h46rL\nUjGuKKBz7FyA\n=UMiq\n-----END PGP MESSAGE-----",
"fp": "c4639370c41133a738f643a591ddbc4c3387f1fb"
},
{
"created_at": "2024-11-14T18:24:30Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMA98TrrsQEbXUAQ//eu/1ioAXlJ2Po2xQ8xQ4HYTQqsMF0lWijN3kv4cH1w+W\nvnQRjB86do4L4DnZz66DDbjHClauLNeuDkYL1ejvetMtENp7KKT8LRJCH4X53eko\ngw6xAYXA8X6e3shM6eFOYIW97pbGQSlfzuh7IbAPZjEuV2ov67sxmWkd9ZJPxw+E\nn2dd/mxw96NM76o8WclwL/W1qrrIqydCJiBtqL09I2z9j9bJ4AxMWTB0kjpJZK4U\nNo5Hk6OwL3C6a3q0xfO0DIb3fy5O7VSwl7AuiRjGxclqy4mH+L9DBS0ONMjguTlo\n+yGZoJi7vaWNvVVW0U9RBEJyCjX6iYje5/gWlWXaMlyIubuOGFy5iXQOSMXk6589\niNcz+ouGAvK6Jy19zo+SQtvmUki+SSRGEzUbx85R13Hz3E5TTlq7wONsgZE4EqqM\ny/6OMCGOvHOzJyWMdKCJ+7DzWzKyQNGWco57hczX74iPGhlH7XfNa3Q0292qziT5\nVFnONWGgN7PLa6rJXOAsxPNlgH5Qbdi2XBgBso8rlAYUXTmKtK/5cDN3rDtRbzgX\nVDu64snQJvGOEKwgv/UXybMRe8OocuCW6zFQDjJMaRtEsg2LP2FjVaYzLhDyuDJ6\ntAIoxWMaMSxgGJkd/E45dOQq/oWBVTFKD8ECGORNOy4RCUMs2LHDbhesvo/PzvbS\nWAFsQZCvjXPe+YZmIuMt7MfgX8d/NhGTtGOaNfX3D+orBuhzWmIAAvlAwMrxorFb\ngayWLO7mYRDUw45uudFzJYql+QLGuvcrFP5BYjY5wk17u6cYYQzlNxs=\n=Qlcg\n-----END PGP MESSAGE-----",
"fp": "aef8d6c7e4761fc297cda833df13aebb1011b5d4"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.8.1"
}
}

View File

@@ -0,0 +1,28 @@
{ config, lib, pkgs, inputs, ... }:
with lib;
{
#sops.defaultSopsFile = ./secrets.yaml;
networking = {
hostName = mkDefault "vpn";
useDHCP = false;
nameservers = [ "1.1.1.1" ];
};
imports = [
../modules/malobeo_user.nix
../modules/sshd.nix
../modules/minimal_tools.nix
];
services.malobeo.vpn = {
enable = true;
name = "vpn";
privateKey = "somepath";
};
system.stateVersion = "22.11"; # Did you read the comment?
}

View File

@@ -0,0 +1,73 @@
{config, pkgs, ...}:
{
sops.secrets.wireguard_private = {};
# enable NAT
networking.nat.enable = true;
networking.nat.externalInterface = "eth0";
networking.nat.internalInterfaces = [ "wg0" ];
networking.firewall = {
allowedUDPPorts = [ 51820 ];
};
networking.wireguard.enable = true;
networking.wireguard.interfaces = {
# "wg0" is the network interface name. You can name the interface arbitrarily.
wg0 = {
# Determines the IP address and subnet of the server's end of the tunnel interface.
ips = [ "10.100.0.1/24" ];
# The port that WireGuard listens to. Must be accessible by the client.
listenPort = 51820;
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN
# For this to work you have to set the dnsserver IP of your router (or dnsserver of choice) in your clients
postSetup = ''
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# This undoes the above command
postShutdown = ''
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# Path to the private key file.
#
# Note: The private key can also be included inline via the privateKey option,
# but this makes the private key world-readable; thus, using privateKeyFile is
# recommended.
privateKey = config.sops.secrets.wireguard_private.path;
peers = [
# List of allowed peers.
{ # Feel free to give a meaningfull name
# Public key of the peer (not a file path).
publicKey = "SfokXbgmvSmodgPFoVHjwmHE3nriQ3OTQ+hISU/3eW4=";
# List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.
allowedIPs = [ "10.100.0.2/32" ];
}
];
};
};
#sops.secrets.wireguard_host = {};
#sops.secrets.mullvad_secret = {};
#networking.wg-quick.interfaces = {
# wg0 = {
# address = [ "50.100.0.2/24" ];
# privateKeyFile = "/home/kalipso/.config/wireguard-keys/private";
# peers = [
# {
# publicKey = "Anme1N482rGSZ14wqtZQbzUHvX4oFhoVct0d187H0iM=";
# allowedIPs = [ "50.100.0.0/24" ];
# endpoint = "5.9.153.217:51820";
# }
# ];
# };
}

View File

@@ -115,6 +115,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems
nixosModules.malobeo.imports = [
./machines/durruti/host_config.nix
./machines/modules/malobeo/microvm_host.nix
./machines/modules/malobeo/wireguard.nix
];
hydraJobs = nixpkgs.lib.mapAttrs (_: nixpkgs.lib.hydraJob) (