3

I have this nftables rule:

ip daddr { "0.nixos.pool.ntp.org", "1.nixos.pool.ntp.org", "2.nixos.pool.ntp.org", "3.nixos.pool.ntp.org" } udp dport ntp accept comment "Allow NTP traffic for system time"

The goal is to allow NTP traffic from a host that otherwise denies most traffic (default reject policy). The hostnames in the rule come from the system's default NTP configuration (so they're the same hostnames the NTP daemon is configured with).

It fails to load, however, because 0.nixos.pool.ntp.org (and the others) have multiple addresses:

$ host 0.nixos.pool.ntp.org
0.nixos.pool.ntp.org has address 66.228.42.59
0.nixos.pool.ntp.org has address 216.229.4.66
0.nixos.pool.ntp.org has address 216.229.0.50
0.nixos.pool.ntp.org has address 69.10.161.7

So nftables complains and refuses to load the ruleset:

# nft -f ...-nftables-rules
...-nftables-rules:37:16-37: Error: Hostname resolves to multiple addresses
    ip daddr { "0.nixos.pool.ntp.org", ... } udp dport ntp accept comment "..."
               ^^^^^^^^^^^^^^^^^^^^^^

These domain names are outside of my control. Thus, I can't stop them from resolving to multiple addresses. I also don't know when the address records associated with them might change.

How should I write my nftables ruleset to deal with this case?

Jean-Paul Calderone
  • 352
  • 1
  • 4
  • 14
  • 2
    AFAIK you can't. Either you get all IPs and whitelist them one by one (failure-prone), or allow outbound 123 udp and restrict access in your NTP client / service. – Lenniey Apr 18 '19 at 13:35

1 Answers1

2

To clarify up front: this isn't an answer to your question about nftables. It's to offer some other options.

  1. If you fully control the machine in question (i.e. there are no untrusted users who might produce malicious NTP queries), then there's no substantive difference to security by allowing outbound NTP to any server versus allowing access to only the servers returned by the DNS query, because the NTP pool is guaranteed to change those hostnames based on the weights of the servers in the pool. So the simple solution is just to allow all outbound NTP.

  2. If you have untrusted users and want to lock down your rules to allow only the IPs that are returned by the NTP pool DNS server for those specific names and you use dnsmasq as your resolver (or are willing to switch to it), then one option might be to use dnsmasq to populate an ipset, and then refer to that ipset in your nftables rule (assuming that nftables supports ipsets). I use this with iptables to limit certain outbound traffic (e.g. HTTPS) to only those domains I know I want to use, without needing to know the IP addresses in advance.

If you follow the latter approach, use ipset definitions something like this:

ipset create ntp       hash:ip family inet  counters  # IPv4
ipset create ntp-inet6 hash:ip family inet6 counters  # IPv6

along with a dnsmasq option like this:

ipset=/nixos.pool.ntp.org/ntp,ntp-inet6

With the above configuration, dnsmasq will add IPv4 addresses for names it resolves to the ntp ipset, and IPv6 addresses to the ntp-inet6 ipset. Then you can refer to those ipsets in your rules. You can also configure a timeout on the ipsets, but that's probably inadvisable in this case, because NTP will keep using pool servers for long periods of time after querying DNS, if the source is found to be stable.

Paul Gear
  • 3,938
  • 15
  • 36