···528 '';
529 };
530531+ virtualisation.restrictNetwork =
532+ mkOption {
533+ type = types.bool;
534+ default = false;
535+ example = true;
536+ description =
537+ lib.mdDoc ''
538+ If this option is enabled, the guest will be isolated, i.e. it will
539+ not be able to contact the host and no guest IP packets will be
540+ routed over the host to the outside. This option does not affect
541+ any explicitly set forwarding rules.
542+ '';
543+ };
544+545 virtualisation.vlans =
546 mkOption {
547 type = types.listOf types.ints.unsigned;
···950 else "'guestfwd=${proto}:${guest.address}:${toString guest.port}-" +
951 "cmd:${pkgs.netcat}/bin/nc ${host.address} ${toString host.port}',"
952 );
953+ restrictNetworkOption = lib.optionalString cfg.restrictNetwork "restrict=on,";
954 in
955 [
956 "-net nic,netdev=user.0,model=virtio"
957+ "-netdev user,id=user.0,${forwardingOptions}${restrictNetworkOption}\"$QEMU_NET_OPTS\""
958 ];
959960 # FIXME: Consolidate this one day.
···1+import ./make-test-python.nix ({
2+ name = "qemu-vm-restrictnetwork";
3+4+ nodes = {
5+ unrestricted = { config, pkgs, ... }: {
6+ virtualisation.restrictNetwork = false;
7+ };
8+9+ restricted = { config, pkgs, ... }: {
10+ virtualisation.restrictNetwork = true;
11+ };
12+ };
13+14+ testScript = ''
15+ import os
16+17+ if os.fork() == 0:
18+ # Start some HTTP server on the qemu host to test guest isolation.
19+ from http.server import HTTPServer, BaseHTTPRequestHandler
20+ HTTPServer(("", 8000), BaseHTTPRequestHandler).serve_forever()
21+22+ else:
23+ start_all()
24+ unrestricted.wait_for_unit("network-online.target")
25+ restricted.wait_for_unit("network-online.target")
26+27+ # Guests should be able to reach each other on the same VLAN.
28+ unrestricted.succeed("ping -c1 restricted")
29+ restricted.succeed("ping -c1 unrestricted")
30+31+ # Only the unrestricted guest should be able to reach host services.
32+ # 10.0.2.2 is the gateway mapping to the host's loopback interface.
33+ unrestricted.succeed("curl -s http://10.0.2.2:8000")
34+ restricted.fail("curl -s http://10.0.2.2:8000")
35+ '';
36+})