aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
blob: bb4c41e6d70950b922202512058df24b1f1f6200 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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")
    '';
})