166 lines
4.8 KiB
Nix
166 lines
4.8 KiB
Nix
|
{ system ? builtins.currentSystem
|
||
|
, config ? {}
|
||
|
, pkgs ? import ../.. { inherit system config; }
|
||
|
, systemdStage1 ? false
|
||
|
}:
|
||
|
|
||
|
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.systemd.enable = systemdStage1;
|
||
|
boot.initrd.network = {
|
||
|
enable = true;
|
||
|
openvpn = {
|
||
|
enable = true;
|
||
|
configuration = builtins.toFile "initrd.ovpn" "";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
# initrd VPN client
|
||
|
ovpnclient =
|
||
|
{ ... }:
|
||
|
{
|
||
|
virtualisation.useBootLoader = true;
|
||
|
virtualisation.vlans = [ 1 ];
|
||
|
|
||
|
boot.initrd = {
|
||
|
systemd.enable = systemdStage1;
|
||
|
systemd.extraBin.nc = "${pkgs.busybox}/bin/nc";
|
||
|
systemd.services.nc = {
|
||
|
requiredBy = ["initrd.target"];
|
||
|
after = ["network.target"];
|
||
|
serviceConfig = {
|
||
|
ExecStart = "/bin/nc -p 1234 -lke /bin/echo TESTVALUE";
|
||
|
Type = "oneshot";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
# This command does not fork to keep the VM in the state where
|
||
|
# only the initramfs is loaded
|
||
|
preLVMCommands = lib.mkIf (!systemdStage1)
|
||
|
''
|
||
|
/bin/nc -p 1234 -lke /bin/echo TESTVALUE
|
||
|
'';
|
||
|
|
||
|
network = {
|
||
|
enable = true;
|
||
|
|
||
|
# Work around udhcpc only getting a lease on eth0
|
||
|
postCommands = lib.mkIf (!systemdStage1)
|
||
|
''
|
||
|
/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
|
||
|
cipher AES-256-CBC
|
||
|
${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")
|
||
|
'';
|
||
|
})
|