nixpkgs/nixos/tests/libreswan.nix
Silvan Mosberger 4f0dadbf38 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:26:33 +01:00

165 lines
4.1 KiB
Nix

# This test sets up a host-to-host IPsec VPN between Alice and Bob, each on its
# own network and with Eve as the only route between each other. We check that
# Eve can eavesdrop the plaintext traffic between Alice and Bob, but once they
# enable the secure tunnel Eve's spying becomes ineffective.
{ lib, pkgs, ... }:
let
# IPsec tunnel between Alice and Bob
tunnelConfig = {
services.libreswan.enable = true;
services.libreswan.connections.tunnel = ''
leftid=@alice
left=fd::a
rightid=@bob
right=fd::b
authby=secret
auto=add
'';
environment.etc."ipsec.d/tunnel.secrets" = {
text = ''@alice @bob : PSK "j1JbIi9WY07rxwcNQ6nbyThKCf9DGxWOyokXIQcAQUnafsNTUJxfsxwk9WYK8fHj"'';
mode = "600";
};
};
# Common network setup
baseNetwork = {
# shared hosts file
extraHosts = lib.mkVMOverride ''
fd::a alice
fd::b bob
fd::e eve
'';
# remove all automatic addresses
useDHCP = false;
interfaces.eth1.ipv4.addresses = lib.mkVMOverride [ ];
interfaces.eth2.ipv4.addresses = lib.mkVMOverride [ ];
interfaces.eth1.ipv6.addresses = lib.mkVMOverride [ ];
interfaces.eth2.ipv6.addresses = lib.mkVMOverride [ ];
# open a port for testing
firewall.allowedUDPPorts = [ 1234 ];
};
# Adds an address and route from a to b via Eve
addRoute = a: b: {
interfaces.eth1.ipv6.addresses = [
{
address = a;
prefixLength = 64;
}
];
interfaces.eth1.ipv6.routes = [
{
address = b;
prefixLength = 128;
via = "fd::e";
}
];
};
in
{
name = "libreswan";
meta = with lib.maintainers; {
maintainers = [ rnhmjoj ];
};
# Our protagonist
nodes.alice =
{ ... }:
{
virtualisation.vlans = [ 1 ];
networking = baseNetwork // addRoute "fd::a" "fd::b";
}
// tunnelConfig;
# Her best friend
nodes.bob =
{ ... }:
{
virtualisation.vlans = [ 2 ];
networking = baseNetwork // addRoute "fd::b" "fd::a";
}
// tunnelConfig;
# The malicious network operator
nodes.eve =
{ ... }:
{
virtualisation.vlans = [
1
2
];
networking = lib.mkMerge [
baseNetwork
{
interfaces.br0.ipv6.addresses = [
{
address = "fd::e";
prefixLength = 64;
}
];
bridges.br0.interfaces = [
"eth1"
"eth2"
];
}
];
environment.systemPackages = [ pkgs.tcpdump ];
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
};
testScript = ''
def alice_to_bob(msg: str):
"""
Sends a message as Alice to Bob
"""
bob.execute("nc -lu ::0 1234 >/tmp/msg &")
alice.sleep(1)
alice.succeed(f"echo '{msg}' | nc -uw 0 bob 1234")
bob.succeed(f"grep '{msg}' /tmp/msg")
def eavesdrop():
"""
Starts eavesdropping on Alice and Bob
"""
match = "src host alice and dst host bob"
eve.execute(f"tcpdump -i br0 -c 1 -Avv {match} >/tmp/log &")
start_all()
with subtest("Network is up"):
alice.wait_until_succeeds("ping -c1 bob")
alice.succeed("systemctl restart ipsec")
bob.succeed("systemctl restart ipsec")
with subtest("Eve can eavesdrop cleartext traffic"):
eavesdrop()
alice_to_bob("I secretly love turnip")
eve.sleep(1)
eve.succeed("grep turnip /tmp/log")
with subtest("Libreswan is ready"):
alice.wait_for_unit("ipsec")
bob.wait_for_unit("ipsec")
alice.succeed("ipsec checkconfig")
with subtest("Alice and Bob can start the tunnel"):
alice.execute("ipsec start tunnel >&2 &")
bob.succeed("ipsec start tunnel")
# apparently this is needed to "wake" the tunnel
bob.execute("ping -c1 alice")
with subtest("Eve no longer can eavesdrop"):
eavesdrop()
alice_to_bob("Just kidding, I actually like rhubarb")
eve.sleep(1)
eve.fail("grep rhubarb /tmp/log")
'';
}