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 have set my computer up to provide
stratum 3 service to anyone that requests it.
Installing NTP software
For several years now, most 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/. As
of June 2004, the latest production version was 4.2.0, dated
15-Oct-2003.
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.
Note, however, that MacOS 8.5 or later (Classic at any rate) already has a built-in NTP client. Just go to the "Date & Time" control panel, and enable it. They already have the addresses of three Apple servers built in. Unfortunately, it only allows you to specify one server. And it seems to require numeric IP addresses, which makes it difficult to use servers such as mine that get their addresses reassigned periodically. (The OSX implementation and interface are probably completely different; I'd bet OSX uses the standard free Unix NTP software.)
There may be other clients out there as well; you can do a search for "macintosh ntp client" or "windows ntp client", if you're feeling adventurous.
In any case, caveat emptor (if that can be said to apply to
downloaders of free software).
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 Servers page
(http://www.eecis.udel.edu/~mills/ntp/servers.html). Other
resources are listed on the Network Time
Protocol (NTP) project site. You are welcome to use
rgrjr.dyndns.org as one of the NTP servers with which you
synchronize, and you might want to pick another stratum 2 or 3 machine
from the
Public NTP Time Servers page
(http://www.eecis.udel.edu/~mills/ntp/servers.html). Be
sure to read the ground rules first before picking a server, and notify
the contact person if requested. And if you do use my
machine, please send me an
email to let me know.
Note that it is best to refer to time servers by domain name
(e.g. rgrjr.dyndns.org), rather than IP address
(e.g. 192.168.3.5), 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. Other hosts, such as mine, have
dynamically-assigned IP addresses that may change on short notice (which
is why I use the free
dyndns.org dynamic DNS service to give myself a portable
DNS name).
Under KDE:
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:
The setup procedure is as follows:
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):
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 2or /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
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 log file (probably
/var/log/messages) 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.
In iptables, this is a piece of cake:
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:
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:
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@alp> rpm -qa | grep -i ntp
yast2-ntp-client-2.8.10-26
xntp-4.1.1-286
rogers@alp>
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 a SuSE thing.)
If not, you may still be able to install this from distribution media,
or from the vendor's Web site.
Adjusting the clock with a built-in NTP daemon
The following instructions work for YAST2 under SuSE 9.0 and subsequent releases.
Something similar is probably provided in other recent GNU/Linux distros;
poking around in the KDE "Control Center" (or the Gnome equivalent) is
probably a good bet.
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
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.
30 4 * * * ntpdate -s server1 [server2 ...]
This schedules the update for every night at 04:30, at which time
the network should be about as quiet as it gets. See the "Resetting the clock periodically via
cron" section for further details.
Resetting the clock at boot time with ntpdate
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.)
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".)
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 setting
the time. 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.)
Continuous clock adjustment with ntpd
Even if you never offer the service to anyone else, running
ntpd 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.
server server1
server server2
. . .
There are many other ntpd configuration options, but
this is all that is necessary to get started.
Running an NTP server
Fortunately, this is no harder than using ntpd
to maintain your clock, with the possible exception of punching a hole of the right shape through the
firewall. Once you have it running, here are some things you can do
to verify that clients can access it:
nmap -sU -p123 server1
If this reports that UDP port 123 is open, then you have a client
problem.
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 server
Fortunately, the NTP server always uses UDP port 123, so it is only
necessary to accept input packets destined from that port, and to permit
outgoing packages coming from that port.
iptables -A OUTPUT -p UDP -s `hostname -i` --source-port ntp -j ACCEPT
iptables -A INPUT -p UDP -d `hostname -i` --destination-port ntp -j ACCEPT
However, if you experience startup problems, you should check to see
whether your /etc/init.d/ntpd startup script (or
/etc/init.d/xntpd) uses the -u option to select an
unprivileged port when initializing the system time, which makes it look
like a client. If so, you must either follow the client instructions
below, or change the startup script to drop the -u option.
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.dyndns.org>
$Id: ntp.html 103 2005-01-10 02:58:14Z rogers $