iptablesntp

What's the right way to allow systemd-timesyncd through iptables firewall?


First, I set up my firewall like this to allow everything:

sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables --flush

Then, I check if NTP is working:

sudo systemctl daemon-reload
sudo systemctl restart systemd-timesyncd
timedatectl

and I can see that it says System clock synchronized: yes.

But then if I reboot and set up my firewall like this (reject everything except for NTP):

sudo iptables -P INPUT REJECT
sudo iptables -P OUTPUT REJECT
sudo iptables -P FORWARD REJECT
sudo iptables -A INPUT -p udp --dport 123 -j ACCEPT
sudo iptables -A OUTPUT -p udp --sport 123 -j ACCEPT

then I get System clock synchronized: no and the clock won't sync.

Based on the above steps, I'm convinced it's the firewall that's blocking timesyncd. I have read (for example, here) that perhaps it has to do with extra ports being opened by the service or the fact that is uses SNTP instead of NTP. I have tried different combinations of rules, but with no success yet as I am not an expert with iptables.

But there must be a way to set it up such that it works without altogether disabling the firewall.


Solution

  • Summary

    --dport and --sport are switched.

    Explanation

    For the other services that I am allowing through the firewall, my machine is the server. For NTP, my machine is the client. Because the rest of my original configuration actually looked more like this:

    ...
    sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
    sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    sudo iptables -A INPUT -p udp --dport 5353 -j ACCEPT
    ...
    sudo iptables -A OUTPUT -p tcp --sport 443 -j ACCEPT
    sudo iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
    sudo iptables -A OUTPUT -p udp --sport 5353 -j ACCEPT
    ...
    

    I assumed that --dport was meant to be used with INPUT and --sport was used with OUTPUT. However, you have to think about what it means. To use NTP as a client, I need to allow INPUT packets that are coming from a source port of 123, not input packets that are coming to a destination port of 123. Likewise, I need to allow OUTPUT packets with destination port 123, not output with source 123.

    So the answer to my question is to use this:

    sudo iptables -P INPUT REJECT
    sudo iptables -P OUTPUT REJECT
    sudo iptables -P FORWARD REJECT
    sudo iptables -A INPUT -p udp --sport 123 -j ACCEPT
    sudo iptables -A OUTPUT -p udp --dport 123 -j ACCEPT