# 32.12.用 NTP 进行时钟同步

## 32.12.1. NTP 配置

在 FreeBSD 中，可以使用内置的 ntpd 来同步系统时钟。ntpd 通过 [rc.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=rc.conf\&sektion=5\&format=html) 变量和 **/etc/ntp.conf** 配置文件进行配置，具体说明如下。

ntpd 与其网络对等方通过 UDP 数据包进行通信。在计算机与 NTP 对等方之间的任何防火墙必须配置为允许端口 123 上的 UDP 数据包进出。

### 32.12.1.1. **/etc/ntp.conf** 文件

ntpd 读取 **/etc/ntp.conf** 来确定要查询的 NTP 服务器。建议选择多个 NTP 服务器，以防其中一个服务器无法访问或其时钟不可靠。ntpd 会根据接收到的响应，优先选择可靠的服务器，而将不可靠的服务器排除。查询的服务器可以是本地网络中的服务器，ISP 提供的服务器，或者从 [公开可访问的 NTP 服务器列表](http://support.ntp.org/bin/view/Servers/WebHome) 中选择。选择公共 NTP 服务器时，应选择一个地理位置接近的服务器，并查看其使用政策。`pool` 配置关键字从服务器池中选择一个或多个服务器。可以参考 [公开的 NTP 服务器池列表](http://support.ntp.org/bin/view/Servers/NTPPoolServers)，按地理区域组织。此外，FreeBSD 提供了一个由项目支持的池，`0.freebsd.pool.ntp.org`。

**示例 3. 示例 `/etc/ntp.conf`**

这是一个简单的 **ntp.conf** 文件示例。可以安全地按原样使用；它包含了在公开可访问的网络连接上操作时推荐的 `restrict` 选项。

```ini
# 禁止 ntpq 控制/查询访问。仅允许根据此文件中的 pool 和 server 语句添加对等方。
restrict default limited kod nomodify notrap noquery nopeer
restrict source  limited kod nomodify notrap noquery

# 允许来自本地主机的查询和控制访问。
restrict 127.0.0.1
restrict ::1

# 添加特定的服务器。
server ntplocal.example.com iburst

# 添加 FreeBSD 池服务器，直到有 3 到 6 个有效的服务器。
tos minclock 3 maxclock 6
pool 0.freebsd.pool.ntp.org iburst

# 使用本地的闰秒文件。
leapfile "/var/db/ntpd.leap-seconds.list"
```

该文件的格式在 [ntp.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=ntp.conf\&sektion=5\&format=html) 中有详细说明。以下是对示例中使用的关键字的简要概述。

默认情况下，NTP 服务器对任何网络主机都可访问。`restrict` 关键字控制哪些系统可以访问服务器。支持多个 `restrict` 条目，每个条目都会根据前面的声明细化访问限制。示例中的值授予本地系统完全的查询和控制访问权限，同时允许远程系统仅能够查询时间。有关更多详细信息，请参阅 [ntp.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=ntp.conf\&sektion=5\&format=html) 中的 `Access Control Support` 子部分。

`server` 关键字指定一个服务器进行查询。该文件可以包含多个 `server` 关键字，每行列出一个服务器。`pool` 关键字指定一个服务器池。ntpd 会根据需要从该池中添加一个或多个服务器，以达到 `tos minclock` 值所指定的对等方数量。`iburst` 关键字指示 ntpd 在首次建立联系时与服务器进行八次快速数据包交换，以帮助快速同步系统时间。

`leapfile` 关键字指定一个文件的位置，该文件包含关于闰秒的信息。该文件会通过 [periodic(8)](https://man.freebsd.org/cgi/man.cgi?query=periodic\&sektion=8\&format=html) 自动更新。此关键字指定的文件位置必须与 **/etc/rc.conf** 中的 `ntp_db_leapfile` 变量所设置的路径匹配。

### 32.12.1.2. **/etc/rc.conf** 中的 NTP 条目

设置 `ntpd_enable=YES` 以在启动时启动 ntpd。将 `ntpd_enable=YES` 添加到 **/etc/rc.conf** 后，可以通过以下命令立即启动 ntpd，而无需重启系统：

```sh
# service ntpd start
```

只需设置 `ntpd_enable` 即可使用 ntpd。下面列出了一些可选的 **rc.conf** 变量，可以根据需要进行配置。

设置 `ntpd_sync_on_start=YES` 以允许 ntpd 在启动时一次性调整时钟的任何偏差。通常，如果时钟偏差超过 1000 秒，ntpd 会记录错误信息并退出。此选项在没有电池支持的实时时钟的系统中尤其有用。

设置 `ntpd_oomprotect=YES` 以保护 ntpd 守护进程不被系统因内存不足 (OOM) 情况下而终止。

设置 `ntpd_config=` 为备用 **ntp.conf** 文件的位置。

设置 `ntpd_flags=` 以包含其他 ntpd 所需的标志，但避免使用以下由 **/etc/rc.d/ntpd** 内部管理的标志：

* `-p`（pid 文件位置）
* `-c`（使用 `ntpd_config=` 代替）

### 32.12.1.3. ntpd 和非特权用户 `ntpd`

在 FreeBSD 上，ntpd 可以作为一个非特权用户启动并运行。这需要 [mac\_ntpd(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_ntpd\&sektion=4\&format=html) 策略模块。**/etc/rc.d/ntpd** 启动脚本首先检查 NTP 配置。如果可能，它会加载 `mac_ntpd` 模块，然后以非特权用户 `ntpd`（用户 ID 123）启动 ntpd。为了避免文件和目录访问问题，当配置包含任何与文件相关的选项时，启动脚本不会自动以 `ntpd` 用户身份启动 ntpd。

在 `ntpd_flags` 中出现以下任何选项时，需要按照下面的描述手动配置以便作为 `ntpd` 用户运行：

* -f 或 --driftfile
* -i 或 --jaildir
* -k 或 --keyfile
* -l 或 --logfile
* -s 或 --statsdir

在 **ntp.conf** 中出现以下任何关键字时，需要按照下面的描述手动配置以便作为 `ntpd` 用户运行：

* crypto
* driftfile
* key
* logdir
* statsdir

要手动配置 ntpd 作为 `ntpd` 用户运行，必须：

* 确保 `ntpd` 用户对配置中指定的所有文件和目录具有访问权限。
* 安排加载或将 `mac_ntpd` 模块编译到内核中。有关详细信息，请参见 [mac\_ntpd(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_ntpd\&sektion=4\&format=html)。
* 在 **/etc/rc.conf** 中设置 `ntpd_user="ntpd"`。

## 32.12.2. 使用 PPP 连接与 NTP

ntpd 不需要与互联网的永久连接即可正常运行。然而，如果 PPP 连接配置为按需拨号，则应防止 NTP 流量触发拨号或保持连接处于活动状态。可以通过在 **/etc/ppp/ppp.conf** 中配置 `filter` 指令来实现。例如：

```ini
set filter dial 0 deny udp src eq 123
# 防止 NTP 流量触发拨号
set filter dial 1 permit 0 0
set filter alive 0 deny udp src eq 123
# 防止传入的 NTP 流量保持连接打开
set filter alive 1 deny udp dst eq 123
# 防止传出的 NTP 流量保持连接打开
set filter alive 2 permit 0/0 0/0
```

更多细节，请参考 [ppp(8)](https://man.freebsd.org/cgi/man.cgi?query=ppp\&sektion=8\&format=html) 中的 `PACKET FILTERING` 部分以及 **/usr/share/examples/ppp/** 中的示例。

> **注意**
>
> 一些互联网接入提供商会阻止较低端口，从而导致 NTP 无法正常工作，因为回复无法到达机器。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/hanbook/di-32-zhang-wang-luo-fu-wu-qi/32.12.-yong-ntp-jin-hang-shi-zhong-tong-bu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
