I have a lot of devices connected to my home network, and like most modern computers, they automatically keep their system clocks correct by use of the Network Time Protocol (ntp), to connect, over the internet, to a very accurate central time server.

Many of the devices on my network phoned home to pre-set servers operated by their manufacturers – Ubuntu machines phoned Canonical servers, Macs and iOS devices phoned Apple, Windows phoned Microsoft. Since, in this post Snowden era we live in, we know for a fact that if something can be used to track you it will, and since I’ve been working to make my network as non-leaky as possible, by stopping all but authorised outgoing network connections, this seemed like something I should change.

My home server itself provides NTP, so there was no need for any other clients to talk to NTP servers elsewhere on the internet. Great, although it presents us with a number of problems:

  1. There are a lot of devices, and I’m lazy, so I don’t want to go around reconfiguring each device.
  2. While some devices allow you to easily change the timeserver, there are a bunch that don’t.
  3. I also want devices to be able to continue syncing themselves when connected to other networks.
  4. It would be nice if visitors to my network were afforded the same protection!

Remapping using Shorewall

Thankfully, I have shorewall running on a Linux box between my network and the wider internet, and also thankfully, NTP is fairly identifiable as a protocol, as it operates over UDP port 123.

So, using DNAT, I was able to remap any request to an outgoing NTP server on UDP port 123 from the network to my local server, using this line towards the end of my /etc/shorewall/rules file.

...

DNAT            loc:!192.168.1.1         loc:192.168.1.1 udp     123

...

This has the effect of redirecting all NTP requests from the network, transparently, to my server, regardless of what servers the client believes it is talking to.

To verify, we can use the tool ntpdate -d to connect to a time server on a bogus, but still technically valid, IP address, e.g. 1.2.3.4 (the -d puts it in debug mode, so we won’t reset any clocks). The bogus IP will be transparently remapped, and we should get a lock.

Before remapping…

24 Mar 16:22:30 ntpdate[13715]: ntpdate 4.2.6p3@1.2290-o Tue Jun  5 20:12:09 UTC 2012 (1)
Looking for host 1.2.3.4 and service ntp
host found : 1.2.3.4
transmit(1.2.3.4)
transmit(1.2.3.4)
transmit(1.2.3.4)
transmit(1.2.3.4)
transmit(1.2.3.4)
1.2.3.4: Server dropped: no data
server 1.2.3.4, port 123
stratum 0, precision 0, leap 00, trust 000
refid [1.2.3.4], delay 0.00000, dispersion 64.00000
transmitted 4, in filter 4
reference time:    00000000.00000000  Mon, Jan  1 1900  0:00:00.000
originate timestamp: 00000000.00000000  Mon, Jan  1 1900  0:00:00.000
transmit timestamp:  d6dada51.643e780f  Mon, Mar 24 2014 16:22:41.391
filter delay:  0.00000  0.00000  0.00000  0.00000 
         0.00000  0.00000  0.00000  0.00000 
filter offset: 0.000000 0.000000 0.000000 0.000000
         0.000000 0.000000 0.000000 0.000000
delay 0.00000, dispersion 64.00000
offset 0.000000

24 Mar 16:22:43 ntpdate[13715]: no server suitable for synchronization found

After remapping…

24 Mar 16:24:17 ntpdate[13736]: ntpdate 4.2.6p3@1.2290-o Tue Jun  5 20:12:09 UTC 2012 (1)
Looking for host 1.2.3.4 and service ntp
host found : 1.2.3.4
transmit(1.2.3.4)
receive(1.2.3.4)
transmit(1.2.3.4)
receive(1.2.3.4)
transmit(1.2.3.4)
receive(1.2.3.4)
transmit(1.2.3.4)
receive(1.2.3.4)
transmit(1.2.3.4)
server 1.2.3.4, port 123
stratum 3, precision -20, leap 00, trust 000
refid [1.2.3.4], delay 0.02592, dispersion 0.00000
transmitted 4, in filter 4
reference time:    d6dad7fc.de9a7567  Mon, Mar 24 2014 16:12:44.869
originate timestamp: d6dadabd.0543d5bb  Mon, Mar 24 2014 16:24:29.020
transmit timestamp:  d6dadabd.054a4033  Mon, Mar 24 2014 16:24:29.020
filter delay:  0.02597  0.02596  0.02594  0.02592 
         0.00000  0.00000  0.00000  0.00000 
filter offset: -0.00033 -0.00033 -0.00036 -0.00036
         0.000000 0.000000 0.000000 0.000000
delay 0.02592, dispersion 0.00000
offset -0.000361

24 Mar 16:24:31 ntpdate[13736]: adjust time server 1.2.3.4 offset -0.000361 sec

So, we can see that all network requests for ntp are now mapped to the local server on the quiet. A handy technique, and one I think I’ll start applying to some other protocols (I wonder if anyone has managed to reverse engineer icloud yet?).