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.
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.
Installation on Linux is straightforward; it's simply a matter of doing
./configure make make installonce 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.
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.
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.)
Among other things, this automatically writes /etc/ntp.conf, which can be edited by hand later to resolve problems.
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:
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.
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 --systohcThe 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.]
As root, do
crontab -u root -eThis 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.
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"
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.
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:
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:
Continuous clock adjustment with ntpd
server server1
server server2
. . .
There are many other ntpd configuration options, but
this is all that is necessary to get started.
# systemctl start ntpd
# systemctl enable ntpd
to start it now and set it up for starting on boot,
respectively.
# /etc/init.d/ntpd start
# chkconfig --add ntpd
to start it now and set it up for starting on boot,
respectively. If /etc/init.d/ntpd does not
exist, see the next step.
Running an NTP server
Random tricks
ntpdate `perl -ane 'print "$F[1] " if $F[0] eq "server";' /etc/ntp.conf`
This only works if ntpd isn't running.
Opening up a firewall for an NTP client
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>