Automatic system clock setting with NTP

Home : Linux resources : Automatic clock setting


It didn't take me long to get tired of resetting the system clock on my cheapo PC. Not only did it drift pretty badly, needing resetting every three or four weeks in order to keep halfway decent time, but every time I booted (at least during Daylight Savings Time), the clock would be off by nearly an hour. So, in November of 2000, I learned how to run an NTP time server under Linux. Since I figured I was not the only one with this problem, I then sat down and wrote this page.

Table of contents

  1. Automatic system clock setting with NTP
    1. Table of contents
    2. About NTP and time service in general
    3. Installing NTP software
      1. Installing NTP on Unix
    4. Synchronizing the clock with NTP
      1. Adjusting the clock with a built-in NTP daemon
      2. Resetting the clock periodically with ntpdate
        1. Resetting the clock at boot time with ntpdate
        2. Resetting the clock periodically via cron
      3. Continuous clock adjustment with ntpd
      4. Running an NTP server
    5. Random tricks
      1. Opening up a firewall for an NTP client

About NTP and time service in general

NTP stands for "Network Time Protocol," and is a UDP-based (i.e. connectionless) protocol for synchronizing system clocks over the Internet. With sufficient care and the right hardware (I am told), it is possible to synchronize the machines on a local-area network within tens of microseconds of Universal Time Coordinated (UTC), the official time kept by standards agencies using atomic clocks. (For the truly hard core, version 3 of the NTP protocol itself is described in
RFC1305.)

With the rather minimal effort I have expended, it is possible to keep the system clock on my very basic AMD K6 within a second of UTC (worst case), which is far more accuracy than I'll ever need for any practical reason. More important, it makes damn sure I'll never ever have to reset the stupid system clock by hand. Throughout this document, I assume that you have similar interests and accuracy requirements. If you require greater accuracy, e.g. on the order of milliseconds, or if you wish to synchronize a subnet of machines, then you'll probably need to study the NTP configuration notes in some detail.

Systems with the most accurate time have at least one interface to a radio clock that receives timebase signals from a transmitter operated by one of the aforementioned agencies. These systems are called "stratum 1," and any computer that synchronizes itself to one or more stratum 1 servers is said to operate at stratum 2, and so on for stratum 3 and higher. Since NTP is a very lightweight protocol, a server at any level can easily support thousands of simultaneous clients (in other words, the "fanout" is high), so it is rarely necessary to go higher than stratum 4. Stratum 1 servers are not usually available for service to the casual home computer user, but there are a number of stratum 2 and 3 servers that are open to the public.

I had originally set my computer up to provide stratum 3 service to anyone that requests it when it was my home network's interface firewall/router system, but it's now itself behind a firewall. In principle, I could tell the cable modem to route the necessary packets to my server, but that would usurp the cable modem's ability to do NTP, and I haven't tried that. On top of that, I would have to secure my NTP server to prevent it from being abused for DDOS attacks, which is difficult.

Installing NTP software

For quite a while now, Unix and GNU/Linux systems have come with some version of the NTP software installed, so the rest of this section is for people with older systems; most users can
skip to the next section.

Installing NTP on Unix

If you are not fortunate enough to have NTP included as part of your system, you will need to download the tarball and compile it yourself, but fortunately this is not hard. Get the latest version from the download area on the Time Server site at
http://www.ntp.org/.

Installation on Linux is straightforward; it's simply a matter of doing

    ./configure
    make
    make install
once you've unpacked the tarball and changed to that directory. This installs the following binaries into the /usr/local/bin directory. The links will take you to the HTML equivalent of man pages for each program; these are also included on the tarball.

Synchronizing the clock with NTP

This section addresses NTP configuration, assuming that you have already downloaded and installed the requisite software. There are two approaches:
  1. Create a cron job that resets the clock periodically from a set of external servers.
  2. Run a daemon process that adjusts the clock continuously, querying servers as needed to stay on track.
The second choice is more accurate, but both are adequate for maintaining one-second clock accuracy. Since setup is simpler if the NTP software comes pre-installed with the distro, it is well worth checking this first:
    rogers@orion> rpm -qa | grep -i ntp
    ntp-4.2.8p13-31.9.1.x86_64
    yast2-ntp-client-3.2.18-6.1.noarch
    rogers@orion>  

On a recent GNU/Linux distro, you should see a package named "ntp" or "xntp" with a version of 4 or greater. ("yast2-ntp-client" is a client configuration interface for the GUI control panel; it's an openSUSE thing.) If not, you may still be able to install this from distribution media, or from the vendor's Web site.

In any case, before taking either route, you must pick a set of NTP servers that are willing to provide time service. Using more than one server is desirable for the sake of redundancy, in case of host downtime or network outages. (Using more than two improves accuracy -- the more the better, up to a point -- but two servers are quite adequate for one-second accuracy.) See the public NTP time server lists at http://support.ntp.org/bin/view/Servers/WebHome. Other resources are listed on the Network Time Protocol (NTP) project site.

Note that it is best to refer to time servers by domain name, rather than IP address, since IP addresses are often reassigned. In fact, a large site may even use an alias (CNAME record) such as "time.bu.edu" to point to a designated time server host; the server can then be moved to a different host with minimal disruption simply by reassigning the alias.

Adjusting the clock with a built-in NTP daemon

The following instructions work for recent OpenSUSE releases under KDE. Something similar is probably provided in other recent GNU/Linux distros; poking around in the KDE or Gnome menus is probably a good bet.

If you can't find a way to do this via your graphical interface, the Continuous clock adjustment with ntpd section below tells how to do this from the command-line. But if NTP came pre-installed, it's a good bet there's a GUI for it and you just haven't found it yet. (Maybe you should look at the documentation.)

  1. Invoke "System" => "YaST" from the "K menu."
  2. Select "Network Services" => "NTP Configuration". This will required you to supply the root password (assuming you are not already logged in as root).
  3. Tick the selection to start the NTP daemon "Now and on Boot."
  4. Click "Add" to add servers one by one. Note that for a pre-installed ntpd, the distro/vendor may already have servers preconfigured.
  5. Click "OK" to start.

Among other things, this automatically writes /etc/ntp.conf, which can be edited by hand later to resolve problems.

Resetting the clock periodically with ntpdate

If you have decided to set via ntpdate, then it is best to do this in two places: In the startup scripts, so that the clock gets started right when you boot up, and in a cron job, so that it stays right if you keep the machine up for more than a few days. You can also run it manually from the command line (as root) to set the clock immediately.

In both places, the command you need is the same:

    ntpdate -s server1 [server2 ...]

This simply tells ntpdate to set the system clock using time information from the various servers supplied by name on the command line. The -s option causes ntpdate to direct its output to the system logging facility; if you do not specify this in a command run by cron, the output will be emailed to you, which is likely to become annoying after a few occurrences. Of course, you need to run this as root to actually set the clock, though for testing purposes you can use the -q option to ntpdate to query the server(s) as an ordinary user without attempting to set the time.

The setup procedure is as follows:

  1. Once you have chosen time servers, try "ntpdate server1 [server2 ...]" on the command line to verify that the packets can get through in both directions. If ntpdate seems to hang, complaining that no servers are usable, but the servers all respond to ping, then you should read the "Opening up a firewall for an NTP client" section below.
  2. As root, add the following crontab line:
           30 4 * * *    ntpdate -s server1 [server2 ...]
    
    This schedules the update for every night at 04:30 local time, when the network should be about as quiet as it gets. See the "Resetting the clock periodically via cron" section for further details.
  3. Also as root, add ntpdate to the correct (system-dependent) boot script. See the "Using ntpdate at boot time" section for further details.
  4. Periodically, you should inspect the system log for messages from ntpdate. If ntpdate has to change the clock in large jumps too frequently (where "large" probably means more than a minute), then you might consider increasing the frequencing of the cron job. For instance, replacing the "4" in the crontab line above with "4,10,16,22" would cause the update to happen four times per day at half past the stated hours.

Resetting the clock at boot time with ntpdate

The system clock is initialized from the hardware clock by the /etc/init.d/boot.clock script. (At least this is true in SuSE 8.1 and later; when booting Red Hat Linux 6.x, the system clock is initialized by /etc/rc.d/rc.sysinit instead.) Unfortunately, when this runs, the network has not yet been fully initialized, so it is not possible to query servers. Instead, it is better to run ntpdate from the /etc/init.d/boot.local script (called /etc/rc.d/rc.local in older versions), which is run as the very last thing when booting up (in run levels 2, 3, and 5, which is appropriate). Setting the system clock twice like this may leave it off by a bit during boot, but the amount by which it is off can be limited for the next boot by resetting the hardware clock after initializing the system clock from the NTP servers. You can do all of this by adding the following two lines to the end of your /etc/init.d/boot.local script (after replacing the server names):

    ntpdate -sb server1 [server2 ...]
    hwclock --systohc
The next time you boot, the hardware clock will only be off by the amount of drift between boots. (You should first check to see that you have hwclock on your system.)

The "-b" option forces the system clock to be set in one jump, rather than attempting to slew it gradually, and is recommended by the ntpdate documentation page when booting.

Note that this double clock setting procedure is essentially equivalent to what the standard boot-time startup scripts for ntpd do, so making the clock jump back and forth at boot time can't be all that bad. (It can make the log files harder to decipher, though.)

Unfortunately, the system boot scripts are very vendor-dependent, so this recipe may not work for your configuration. If there is an /etc/init.d/rc.local or /etc/init.d/boot.local script, it probably works the same way; otherwise, you will need to figure out something different for your flavor of Linux/*BSD/etc.

[Further disclaimer: Since I need a different setup in order to run a server, I haven't ever actually tried this startup scheme myself. If you find a bug in this "recipe," please let me know. -- rgr, 24-Nov-00.]

Resetting the clock periodically via cron

"cron" is the name of the Unix facility for running periodic jobs. The "cron daemon" is started at boot time, and looks in "crontab files" for instructions. These files can be examined and modified via the crontab program. (For more information on their format, do "man 5 crontab".)

As root, do

    crontab -u root -e
This will fire up an editor with a copy of root's existing crontab file; you must then add a line for ntpdate that describes when and how to run it. For example, to run ntpdate daily at 1:23 AM (local time), add the following lines (after replacing the server names):
    # Daily time update at 1:23AM
    23 1 * * *    ntpdate -s server1 [server2 ...]
The "*"'s in the day-of-month, month, and day-of-week fields indicate that those time periods should not be consulted when deciding when to run ntpdate. The "-s" option tells ntpdate to use the system logging facilities for messages instead of the standard output, and is suggested by the
ntpdate documentation page when running ntpdate as a cron job. (Otherwise, the cron daemon will send you the output in what would become a tedious daily email message.)

Hint: For best results, you should pick a random time that no one else is likely to have chosen. If everybody chose 1:23AM, then once all clients were synchronized, the servers would suffer a flood of NTP packets every day at that time, and accuracy would suffer.

Don't forget to save the edited crontab file before exiting the editor. The next morning, you should examine the logs to ensure that ntpdate ran successfully.

For more information, see the crontab(1) man page, and for instructions on how to select a different editor. See the crontab(8) page for more information on the crontab file format.

Continuous clock adjustment with ntpd

Running an ntpd process will make your clock even more accurate, compared to calling ntpdate as a cron job. That is because ntpd effectively adjusts the clock continuously, as opposed to just at the cron intervals. And ntpd adjustments are more stable (in the control systems theory sense) because it is in charge of the adjustment intervals, and can also collect a clock drift history to use in deciding when and how much to adjust.

This is the command-line version of the "Adjusting the clock with a built-in NTP daemon"

  1. Create an /etc/ntp.conf file that names your servers. Each server should appear on a "server" line by itself, like this:
           server server1
           server server2
           . . .
    
    There are many other ntpd configuration options, but this is all that is necessary to get started.
  2. Start the daemon. There are a few possibilities.
  3. Check the logs for messages confirming that ntpd started without error.
  4. You can also do ntptime to find out what the kernel knows about the current time, but be aware that ntptime will report an error until the clock is "synchronized," which takes about half an hour after the daemon starts.

Running an NTP server

This is discouraged, since it is necessary to prevent it from being abused for DDOS attacks, which is difficult. I have not tried to do this myself, so I can't say much about it.

Random tricks

Manual reset:
To reset the time manually from the NTP servers mentioned in the /etc/ntp.conf file:
       ntpdate `perl -ane 'print "$F[1] " if $F[0] eq "server";' /etc/ntp.conf`
       
This only works if ntpd isn't running.
Find out what time it really is:
Just run ntptime from the command line. If you are running an NTP server, it will tell you the time down to microsecond precision, along with an estimate of maximum error and estimated (most likely) error.
Loss of synchronization while burning CDs.
For what it's worth, ntpd on my wimpy 300MHz system reported "synchronisation lost" and steps the clock by up to 20 or 30 seconds after I burn 50MB or more to CD. The time steps are always positive when this happens, so I imagine this just means that the kernel has lost some timer interrupts while it's dealing with the CD hardware, and needs to catch up, so the time while it's out of synch should be brief. (And I've never seen this problem since I bought a new desktop system in 2004.)

Opening up a firewall for an NTP client

If your NTP client machine is behind a firewall, you need to be sure that packets to and from remote NTP servers can get through. When ntpdate queries a server, it sends a series of UDP packets (the default is four), each of which is addressed to UDP port 123 on the remote machine and bears a quasi-random source port, call it X, as the return address on the local machine. Responses are returned with a destination port of X on the local machine and a source port of 123 on the remote machine. In order for the query to succeed, both packets must be able to traverse the firewall. If there is outbound package filtering, it simply needs to let out all UDP packets destined for port 123 on any machine. I don't use outbound filtering (except to block X11 connections).

Inbound filtering is trickier. If you let through any UDP packet with a source port of 123, then a cracker could potentially abuse this by sending UDP packets with a source port of 123 to an arbitrary target port on your machine. There are two ways to deal with this:

  1. Restrict incoming IP addresses to just those servers of interest. This certainly narrows the opportunity for abuse considerably, but is inconvenient to implement if server addresses might change arbitrarily. And it still allows unrestricted access to your UDP ports for users on those machines.

  2. Restrict the destination to a non-priviledged port, and use the "-u" option to ntpdate to tell it to use only non-priviledged source ports when it sends out queries. By long-standing Unix convention, priviledged ports are those below 1024, so this means refusing UDP packets addressed to a port below 1024 even if the source port is 123. But this notion of "priviledge" is only a convention and is somewhat meaningless for single-user machines, except that it does mean that security-critical services such as file service (NFS) and remote configuration (BOOTP, SNMP) tend to be implemented on the low-numbered ports, especially in the Unix world.

Either way, I believe this is not a serious threat. Most threats to computer security come in through the TCP ports -- it's hard (but not impossible!) to craft a useful buffer overflow exploit that fits into a UDP packet. However, I still think the issue is worth paying attention to, since if a UDP-based vulnerability is discovered, it is certain that many crackers will learn about it before I do.

In order to implement the second option, I have the following line in my firewall setup script:

    iptables -A INPUT -p UDP -s 0.0.0.0/0 --source-port ntp \
                      -d `hostname -i` --destination-port 1025: -j ACCEPT
This is just an example; it will not work as described above without the rest of the setup script as well. And if you choose this route, you will then need to be careful what services you make available on the high ports. Despite the drawback, I prefer this option.


Bob Rogers <rogers@rgrjr.com>