diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix index b41a2fd27be..1b61a3ee599 100644 --- a/nixos/modules/services/networking/mosquitto.nix +++ b/nixos/modules/services/networking/mosquitto.nix @@ -199,6 +199,7 @@ let allow_anonymous = 1; allow_zero_length_clientid = 1; auto_id_prefix = 1; + bind_interface = 1; cafile = 1; capath = 1; certfile = 1; @@ -629,9 +630,10 @@ in ])); RemoveIPC = true; RestrictAddressFamilies = [ - "AF_UNIX" # for sd_notify() call + "AF_UNIX" "AF_INET" "AF_INET6" + "AF_NETLINK" ]; RestrictNamespaces = true; RestrictRealtime = true; diff --git a/nixos/tests/mosquitto.nix b/nixos/tests/mosquitto.nix index 36cc8e3e3d9..d516d3373d9 100644 --- a/nixos/tests/mosquitto.nix +++ b/nixos/tests/mosquitto.nix @@ -4,6 +4,7 @@ let port = 1888; tlsPort = 1889; anonPort = 1890; + bindTestPort = 1891; password = "VERY_secret"; hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw=="; topic = "test/foo"; @@ -125,6 +126,10 @@ in { }; }; } + { + settings.bind_interface = "eth0"; + port = bindTestPort; + } ]; }; }; @@ -134,6 +139,8 @@ in { }; testScript = '' + import json + def mosquitto_cmd(binary, user, topic, port): return ( "mosquitto_{} " @@ -162,6 +169,27 @@ in { start_all() server.wait_for_unit("mosquitto.service") + with subtest("bind_interface"): + addrs = dict() + for iface in json.loads(server.succeed("ip -json address show")): + for addr in iface['addr_info']: + # don't want to deal with multihoming here + assert addr['local'] not in addrs + addrs[addr['local']] = (iface['ifname'], addr['family']) + + # mosquitto grabs *one* random address per type for bind_interface + (has4, has6) = (False, False) + for line in server.succeed("ss -HlptnO sport = ${toString bindTestPort}").splitlines(): + items = line.split() + if "mosquitto" not in items[5]: continue + listener = items[3].rsplit(':', maxsplit=1)[0].strip('[]') + assert listener in addrs + assert addrs[listener][0] == "eth0" + has4 |= addrs[listener][1] == 'inet' + has6 |= addrs[listener][1] == 'inet6' + assert has4 + assert has6 + with subtest("check passwords"): client1.succeed(publish("-m test", "password_store")) client1.succeed(publish("-m test", "password_file"))