Mon 20 February 2017
| tags: nest ntp openwrt iot
The issue
Some time ago I received a smart Nest thermostat as part of a promotional offer.
I wasn't very keen on the idea of having something like a thermostat phoning
home to a centralised server in the "cloud", but it was a good deal and the Nest
does still offer some benefits over a traditional dumb thermostat even when it
has no access to the internet. I have a good number of reasons for wanting to
keep the thermostat disconnected from the internet and I will not go into them
here as that is not the point of this article.
There is one downside to keeping the Nest disconnected though; it's not very
good at keeping track of the date and time. In fact, it's quite bad at it
actually, I'd see it reset to January the 1st 1970 every few days or weeks. As
a result, this messes up your heating schedule and you might find yourself
being in a cold house when you'd expect it to be warm, or the thermostat might
instruct your heating to turn on in the middle of the night wasting unnecessary
energy and money.
Looking into Nest traffic
The behaviour as described above indicates that the Nest lacks a proper RTC,
or realtime clock. Searching on the internet on several occasions did not
yield me many useful results, it appears that most users of the thermostat do
not suffer from this problem. This led me to believe that the thermostat relies
on some sort of network service to periodically query the time and adjust
itself. I suspected it was using the well-established NTP protocol for this,
and set out investigate.
As I have OpenWRT running on my router, I added a firewall rule to block all
traffic going from the LAN to the WAN for the MAC address of the Nest. I used
LuCI for doing this but you can also use uci
over ssh if you prefer. You can
find out the MAC address of your Nest before connecting it to a network by
going into Settings > Technical Info and scrolling all the way down until you
see it listed.
After this, I felt comfortable configuring the thermostat to connect to my WiFi
AP and to inspect the traffic it would generate. For this I am using tcpdump
on the router and examining the capture files with Wireshark on my desktop.
When I did this I noticed I made a small mistake, I blocked the wrong MAC
address from accessing the internet and my Nest did in fact phone home. While
being connected for less than 5 minutes, it submitted some sort of statistical
data to the Nest servers and pulled in a firmware update. I had no way of
preventing this update after it was pulled in, though I don't mind that as much
as the statistics it managed to send off. So, make sure you block the right MAC
address or just even pull the cable to your modem entirely if you want to be on
the safe side.
After quickly correcting my firewall rule, I noticed the Nest was not too happy
with the connection. It'd try to connect and upon finding that the internet
wasn't accessible it'd disassociate from the AP again. The new firmware it
pulled in is more tolerant of the restricted network capabilities, it stays
connected to the WiFi AP without much complaining. Looks like my little mistake
did end up benefitting me after all.
On to addressing the issue at hand, which is timekeeping. I noticed some very
convenient behaviour in the traffic I analysed. The Nest does indeed rely on
NTP for keeping time, and it actually tries to query your network's gateway
for it first! In my case that meant it was trying to connect to an NTP server
on my router which I did not have running. After a few failed attempts, it
resolves time.nest.com
and queries that instead.
The solution
At this point there are three possible approaches I can think of to give the
Nest the time information it seeks:
Host an NTP daemon on the router
Redirect DNS queries for time.nest.com
to a machine within my LAN that has an NTP daemon running
Explicitely allow NTP requests to access the internet
I decided to go for option 1 as it seemed the simplest and most direct way of
remedying the timekeeping issues whilst keeping all control.
For OpenWRT there are various ways to host an NTP daemon, but the quickest way
to accomplish this without pulling in any extra packages is to use the ntpd
that is compiled into busybox
. Instructions on how to do this may be a little
unclear online as it seems to be a recent inclusion into OpenWRT, but it is in
fact very simple.
Connect to your OpenWRT/LEDE router over ssh and open up /etc/config/system
in your favourite editor. There will be a section describing the NTP
configuration:
config timeserver ' ntp '
list server ' 0. openwrt . pool . ntp . org '
list server ' 1. openwrt . pool . ntp . org '
list server ' 2. openwrt . pool . ntp . org '
list server ' 3. openwrt . pool . ntp . org '
option enabled '1'
After these existing options defining the nameservers and enabling the client,
add the following line:
Save the file, exit, and run /etc/init.d/sysntpd reload
. You're done! At this
point you can verify that the ntp daemon is up and running by issuing
netstat -l
; it should now show that there's a service listening to the NTP
port. Further traffic analysis of the Nest shows me that the Nest is indeed
getting an NTP response from my router and that it doesn't bother to query
time.nest.com
after that.