c684398c6a
nixos/tests/initrd-openvpn: Add test for openvpn in the initramfs The module in this commit adds new options that allows the integration of an OpenVPN client into the initrd. This can be used e.g. to remotely unlock LUKS devices. This commit also adds two tests for `boot.initrd.network.openvpn`. The first one is a basic test to validate that a failing connection does not prevent the machine from booting. The second test validates that this module actually creates a valid openvpn connection. For this, it spawns three nodes: - The client that uses boot.initrd.network.openvpn - An OpenVPN server that acts as gateway and forwards a port to the client - A node that is external to the OpenVPN network The client connects to the OpenVPN server and spawns a netcat instance that echos a value to every client. Afterwards, the external node checks if it receives this value over the forwarded port on the OpenVPN gateway.
146 lines
4.1 KiB
Nix
146 lines
4.1 KiB
Nix
import ../make-test-python.nix ({ lib, ...}:
|
|
|
|
{
|
|
name = "initrd-network-openvpn";
|
|
|
|
nodes =
|
|
let
|
|
|
|
# Inlining of the shared secret for the
|
|
# OpenVPN server and client
|
|
secretblock = ''
|
|
secret [inline]
|
|
<secret>
|
|
${lib.readFile ./shared.key}
|
|
</secret>
|
|
'';
|
|
|
|
in
|
|
{
|
|
|
|
# Minimal test case to check a successful boot, even with invalid config
|
|
minimalboot =
|
|
{ ... }:
|
|
{
|
|
boot.initrd.network = {
|
|
enable = true;
|
|
openvpn = {
|
|
enable = true;
|
|
configuration = "/dev/null";
|
|
};
|
|
};
|
|
};
|
|
|
|
# initrd VPN client
|
|
ovpnclient =
|
|
{ ... }:
|
|
{
|
|
virtualisation.useBootLoader = true;
|
|
virtualisation.vlans = [ 1 ];
|
|
|
|
boot.initrd = {
|
|
# This command does not fork to keep the VM in the state where
|
|
# only the initramfs is loaded
|
|
preLVMCommands =
|
|
''
|
|
/bin/nc -p 1234 -lke /bin/echo TESTVALUE
|
|
'';
|
|
|
|
network = {
|
|
enable = true;
|
|
|
|
# Work around udhcpc only getting a lease on eth0
|
|
postCommands = ''
|
|
/bin/ip addr add 192.168.1.2/24 dev eth1
|
|
'';
|
|
|
|
# Example configuration for OpenVPN
|
|
# This is the main reason for this test
|
|
openvpn = {
|
|
enable = true;
|
|
configuration = "${./initrd.ovpn}";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# VPN server and gateway for ovpnclient between vlan 1 and 2
|
|
ovpnserver =
|
|
{ ... }:
|
|
{
|
|
virtualisation.vlans = [ 1 2 ];
|
|
|
|
# Enable NAT and forward port 12345 to port 1234
|
|
networking.nat = {
|
|
enable = true;
|
|
internalInterfaces = [ "tun0" ];
|
|
externalInterface = "eth2";
|
|
forwardPorts = [ { destination = "10.8.0.2:1234";
|
|
sourcePort = 12345; } ];
|
|
};
|
|
|
|
# Trust tun0 and allow the VPN Server to be reached
|
|
networking.firewall = {
|
|
trustedInterfaces = [ "tun0" ];
|
|
allowedUDPPorts = [ 1194 ];
|
|
};
|
|
|
|
# Minimal OpenVPN server configuration
|
|
services.openvpn.servers.testserver =
|
|
{
|
|
config = ''
|
|
dev tun0
|
|
ifconfig 10.8.0.1 10.8.0.2
|
|
${secretblock}
|
|
'';
|
|
};
|
|
};
|
|
|
|
# Client that resides in the "external" VLAN
|
|
testclient =
|
|
{ ... }:
|
|
{
|
|
virtualisation.vlans = [ 2 ];
|
|
};
|
|
};
|
|
|
|
|
|
testScript =
|
|
''
|
|
# Minimal test case, checks whether enabling (with invalid config) harms
|
|
# the boot process
|
|
with subtest("Check for successful boot with broken openvpn config"):
|
|
minimalboot.start()
|
|
# If we get to multi-user.target, we booted successfully
|
|
minimalboot.wait_for_unit("multi-user.target")
|
|
minimalboot.shutdown()
|
|
|
|
# Elaborated test case where the ovpnclient (where this module is used)
|
|
# can be reached by testclient only over ovpnserver.
|
|
# This is an indirect test for success.
|
|
with subtest("Check for connection from initrd VPN client, config as file"):
|
|
ovpnserver.start()
|
|
testclient.start()
|
|
ovpnclient.start()
|
|
|
|
# Wait until the OpenVPN Server is available
|
|
ovpnserver.wait_for_unit("openvpn-testserver.service")
|
|
ovpnserver.succeed("ping -c 1 10.8.0.1")
|
|
|
|
# Wait for the client to connect
|
|
ovpnserver.wait_until_succeeds("ping -c 1 10.8.0.2")
|
|
|
|
# Wait until the testclient has network
|
|
testclient.wait_for_unit("network.target")
|
|
|
|
# Check that ovpnclient is reachable over vlan 1
|
|
ovpnserver.succeed("nc -w 2 192.168.1.2 1234 | grep -q TESTVALUE")
|
|
|
|
# Check that ovpnclient is reachable over tun0
|
|
ovpnserver.succeed("nc -w 2 10.8.0.2 1234 | grep -q TESTVALUE")
|
|
|
|
# Check that ovpnclient is reachable from testclient over the gateway
|
|
testclient.succeed("nc -w 2 192.168.2.3 12345 | grep -q TESTVALUE")
|
|
'';
|
|
})
|