# 为 NPC 连接 NPS 配置证书

> 选择服务端证书，配置 NPC 的验证方式，并检查连接是否正常

---

LLMS 索引： [llms.txt](/llms.txt)

---

本页介绍如何为 NPC（客户端）与 NPS（服务端）之间的连接配置证书（用于证明服务端身份的电子文件）。这些设置用于桥接连接（NPC 与 NPS 之间传送连接管理信息和转发数据的连接）。

开启 TLS（保护网络通信的加密协议）后，NPC 默认会验证服务端身份，也就是确认连到的是你信任的 NPS。这里最低支持 TLS 1.2；NPC 和 NPS 都支持 TLS 1.3 时，会使用 TLS 1.3。

如果还没开启加密连接，请先看[加密 NPC 与 NPS 之间的连接](/extend/feature/encrypted-transport.html)。本页配置的是 TLS 桥接端口（NPS 专门接收 NPC 加密连接的入口，通常为 `8025`）使用的证书。网页管理页面的 `web_cert_file`、`web_key_file`，以及按域名转发的网站所用的证书，需要在各自的设置中配置。

## 先选择适合你的方式

公钥（证书中可以公开的密钥）与私钥（需要由服务端保密的配套密钥）配合使用，让服务端证明自己的身份。公钥指纹（根据公钥计算出的一串识别码）用于核对服务端出示的公钥是否与你预先保存的一致。

| 你的情况                                                  | NPS 使用什么证书                                      | NPC 如何确认服务端身份                                                |
| --------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------- |
| 已有公共 CA（通常被操作系统信任的证书签发机构）签发的证书 | 填写已有证书和对应私钥的文件路径                      | 使用操作系统信任的 CA 验证证书，并检查域名是否匹配                    |
| 使用私有 CA（自己或组织内部管理的证书签发机构）签发的证书 | 填写已有证书和对应私钥的文件路径                      | 用 `tls_ca_file` 指定信任的 CA 证书文件，并检查域名或 IP 地址是否匹配 |
| 没有准备证书，使用 NPS 自动生成的证书                     | 让 NPS 生成自签名证书（由服务端自己签发的证书）并保存 | 从 NPS 启动日志复制公钥指纹，填入 `tls_server_fingerprint`            |

没有准备证书时，可以按“[让 NPS 自动生成并保存证书](#让-nps-自动生成并保存证书)”和“[使用公钥指纹确认服务端](#使用公钥指纹确认服务端)”两节配置。相关名词也可查阅[术语表](/extend/glossary.html#连接证书与身份验证)。

## 在 NPS 中配置证书

### 使用已有证书

在服务端的 `nps.conf` 中填写证书文件和私钥文件的路径。下面使用 TCP（按顺序可靠传送数据的网络协议）连接，路径仅为示例，请替换为实际文件的位置：

```ini
bridge_type=tcp
tls_enable=true
tls_bridge_port=8025
tls_cert_file=/etc/letsencrypt/live/nps.example.com/fullchain.pem
tls_key_file=/etc/letsencrypt/live/nps.example.com/privkey.pem
```

文件需要使用 PEM（用文本保存证书或密钥的格式）。证书文件应包含证书链（一组前后关联、用于证明证书来源的证书）：第一张是签发给 NPS 的证书，后面依次放中间证书（连接服务端证书与受信任 CA 的证书）。证书提供方通常会给出合并好的文件，例如 `fullchain.pem`。

证书的 SAN（记录证书适用于哪些域名或 IP 地址的字段）应包含 NPC 要验证的地址。例如，用 `nps.example.com` 验证时，证书需要包含这个域名（便于记忆的网络名称）；用 `203.0.113.10` 验证时，则需要包含这个 IP 地址（设备在网络上的地址）。

填写路径时，建议使用绝对路径（完整写出文件位置的路径），例如上面的 `/etc/letsencrypt/...`。如果使用相对路径（从某个目录开始查找文件的路径），例如 `conf/tls/bridge.pem`，NPS 会从它的运行目录（存放 `conf` 文件夹的目录）开始查找。启动日志中 `the config path is:` 后面的路径就是这个目录，详情见[配置文件位置](/server/nps_use.html#工作目录与配置文件位置)。

`tls_cert_file` 和 `tls_key_file` 必须一起填写。如果文件找不到、内容无法读取为证书或私钥、证书与私钥不配套，NPS 会报错并退出。服务端证书尚未生效、已经过期，或证书限定的用途不允许用于证明服务端身份时，也会报错退出。

**NPS 在启动时读取证书。** 更新或替换证书文件后，需要重启 NPS。读取失败时，NPS 会保留文件供你检查，不会改用临时生成的证书。

### 让 NPS 自动生成并保存证书

在 `nps.conf` 中开启 TLS，并让 `tls_cert_file` 和 `tls_key_file` 都留空：

```ini
bridge_type=tcp
tls_enable=true
tls_bridge_port=8025
tls_cert_file=
tls_key_file=
```

首次启动时，NPS 会在运行目录中创建这两个文件：

```text
conf/tls/bridge.pem
conf/tls/bridge.key
```

`bridge.pem` 保存证书，`bridge.key` 保存私钥。以后重启时会继续使用这两个文件，公钥指纹也保持不变。请备份这两个文件，并妥善保管私钥。

如果使用 Docker（将应用放在称为“容器”的独立环境中运行的工具），需要为整个 `conf` 目录设置挂载（把容器中的目录对应到容器外的存储位置）。这样替换容器后，原来的证书和私钥仍然可用。

自动生成的证书有以下设置：

- 使用 RSA（一种生成和使用公钥、私钥的算法），密钥长度为 2048 位，证书有效期为 365 天。
- CN（证书中的通用名称）填写 `localhost`（表示本机的名称）；O（组织名称）和 C（国家）留空。
- SAN 包含 `localhost`、`127.0.0.1` 和 `::1`。这些名称和地址都表示本机，不包含你实际使用的远程服务端地址，因此建议按下文的公钥指纹方式验证。
- 文件权限为 `0600`（普通账号中只有文件所有者可以读写），新建目录权限为 `0700`（普通账号中只有目录所有者可以进入、读取和修改）。Windows 上需要另行检查文件和目录的访问权限。

如果文件损坏，或两个文件只剩下一个，NPS 会报错并保留现有文件，等待你处理。证书到期后，也需要你更新或替换证书；NPS 不会自动更换密钥，以免 NPC 中保存的指纹突然失效。

## 可选：更改自动生成证书中的名称

这个设置决定新生成的自签名证书填写什么名称。通常保持默认值即可。在 `nps.conf` 中设置：

```ini
# 默认设置：通用名称 CN 填写 localhost，组织名称 O 留空
tls_self_signed_name_mode=standard
```

如果希望 CN 和 O 使用随机名称，可以改为：

```ini
tls_self_signed_name_mode=random
```

`random` 会用适合安全用途的随机数，分别生成 CN 和 O。两个名称各有 32 个十六进制字符（由数字 `0–9` 和字母 `a–f` 组成），各自独立生成。两种设置都不会填写 `NPS Org` 或 `My Company Name LTD.`。如果你使用的是已有证书，NPS 会保留证书原有的名称和其他内容。

此设置只在**生成新证书**时生效。如果证书已经存在，只修改设置并重启，名称不会改变。要更改已有自签名证书中的名称，请按顺序操作：

1. 选择允许暂时断开连接的时间，停止 NPS。
2. 备份 `conf/tls/bridge.pem` 和 `conf/tls/bridge.key`，再把原文件移到其他目录。
3. 在 `nps.conf` 中填写需要的名称设置，然后启动 NPS。
4. 从 NPS 启动日志获取新指纹，并更新使用指纹验证的 NPC。

重新生成时会同时更换公钥和私钥，原来的指纹将失效。更改名称只能去掉证书中的默认产品名称，不能保证别人认不出这是 NPS。任何能连接这个 TLS 端口的人，都可以在建立连接时取得服务端证书；使用 TLS 1.3 也一样。

## 在 NPC 中选择验证方式

下列设置可以写在 `npc.conf` 的 `[common]` 下方，也可以作为命令行参数（启动程序时附加的设置）使用。命令行写法需要在名称前加 `-`，例如 `-tls_enable=true`。`true` 表示开启，`false` 表示关闭。

| 配置项                     | 默认值  | 填写方法和作用                                                                                                                         |
| -------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `tls_enable`               | `false` | 填 `true` 开启加密连接，同时将服务端地址中的端口改为 TLS 桥接端口，通常是 `8025`                                                       |
| `tls_ca_file`              | 空      | 填写你信任的 CA 证书文件路径，文件需为 PEM 格式。使用 CA 验证时，留空表示使用操作系统信任的 CA；填写后只使用该文件中的证书作为信任依据 |
| `tls_server_name`          | 空      | 填写证书应当包含的域名或 IP 地址，不带端口。使用 CA 验证时，留空会检查连接地址中的域名或 IP；使用指纹验证时，填写此项才会额外检查名称  |
| `tls_server_fingerprint`   | 空      | 填写从服务端获取的公钥指纹，共 64 个十六进制字符。与 `tls_ca_file` 只能选一个填写                                                      |
| `tls_insecure_skip_verify` | `false` | 填 `true` 会关闭服务端身份验证，仅供升级旧版本时临时使用                                                                               |

请留意以下填写规则：

- 使用这些验证设置前，需要先设置 `tls_enable=true`。
- `tls_ca_file` 和 `tls_server_fingerprint` 不能同时填写。
- 设置 `tls_insecure_skip_verify=true` 时，`tls_ca_file`、`tls_server_name` 和 `tls_server_fingerprint` 都必须留空。

指纹格式错误、CA 文件无法读取或不含可用证书、同时填写了不能一起使用的选项，都会报错。开关值填写错误也会报错，请按示例使用 `true` 或 `false`。遇到这些错误时，NPC 会停止连接，等待你修正设置。

下面示例中的域名、IP 地址和文件路径都需要换成你自己的值。`vkey` 填客户端验证密钥（NPC 接入 NPS 时使用的连接凭据，可在网页管理的客户端列表中查看）。

### 使用公共 CA 证书

如果 NPS 使用的证书由操作系统信任的公共 CA 签发，并且证书包含 `nps.example.com`，可直接使用该域名连接：

```shell
./npc -server=nps.example.com:8025 -vkey=客户端验证密钥 -tls_enable=true
```

如果通过 IP 地址连接，而证书只包含域名，则用 `tls_server_name` 填写证书上的域名：

```shell
./npc -server=203.0.113.10:8025 -vkey=客户端验证密钥 \
  -tls_enable=true -tls_server_name=nps.example.com
```

上面的命令仍然连接 `203.0.113.10:8025`，只是检查证书是否适用于 `nps.example.com`。

验证名称是域名时，NPC 还会发送 SNI（建立加密连接时，告诉服务端自己要访问哪个域名的信息），方便服务端选择对应证书。名称是 IP 地址时，不发送 SNI。如果没有填写 `tls_server_name`，就使用连接地址中的域名或 IP 地址。

### 使用私有 CA 证书

如果证书由你自己或组织内部的 CA 签发，需要把该 CA 的证书文件放到 NPC 所在设备上，再填写 `tls_ca_file`。例如，在 `npc.conf` 中配置：

```ini
[common]
server_addr=203.0.113.10:8025
conn_type=tcp
vkey=客户端验证密钥
tls_enable=true
tls_ca_file=certs/root-ca.pem
tls_server_name=nps.example.com
```

这里的 `certs/root-ca.pem` 是 CA 证书文件的相对路径。NPC 会从 `npc.conf` 所在目录开始查找。例如，配置文件在 `/etc/nps/npc.conf` 时，就会读取 `/etc/nps/certs/root-ca.pem`。

如果从命令行或 GUI（通过窗口和按钮操作的图形客户端）填写路径，则从程序的当前工作目录（程序查找相对路径时使用的目录）开始查找。建议填写完整的绝对路径，避免因启动方式不同而找不到文件。

NPC 会检查证书是否由所信任的 CA 签发、是否在有效期内、是否允许用于证明服务端身份，以及 SAN 是否包含需要验证的域名或 IP 地址。

### 使用公钥指纹确认服务端

使用 NPS 自动生成的自签名证书时，建议选择这种方式。NPC 会计算收到的证书的公钥指纹，并与事先保存的指纹比较。

先登录你自己的 NPS 服务器，查看启动日志，找到下面这一行：

```text
bridge TLS public-key SHA-256 fingerprint: <64个十六进制字符组成的指纹>
```

复制冒号后面的完整指纹，填入 NPC 配置。也可以从你确认可信的 NPS 管理页面获取。指纹必须来自你自己的服务端或管理员，否则就失去了核对身份的意义。

```ini
[common]
server_addr=nps.example.com:8025
conn_type=tcp
vkey=客户端验证密钥
tls_enable=true
tls_server_fingerprint=替换为服务端实际输出的64个字符的指纹
```

使用指纹验证时，可以通过域名或 IP 地址连接，也可以使用自签名证书。NPC 仍会检查证书有效期，以及证书是否允许用于证明服务端身份。

默认只核对公钥和上述证书条件。如果还希望检查证书适用的域名或 IP 地址，可以再填写 `tls_server_name`；此时 SAN 中必须包含填写的名称或地址。指纹不匹配时，NPC 会拒绝连接。

证书到期后，如果用原来的公钥重新签发，指纹保持不变；如果更换了公钥和私钥，就需要更新 NPC 中保存的指纹。

如果前置代理（放在 NPS 前面、代为接收连接的服务器）负责与 NPC 建立 TLS 加密连接，那么 NPC 收到的是代理提供的证书。此时应填写代理证书的公钥指纹。

#### 可选：从证书文件计算指纹

通常直接复制 NPS 启动日志中的指纹即可。如果需要自己计算，可以使用 OpenSSL（处理证书和加密连接的命令行工具），在服务端执行：

```shell
openssl x509 -in conf/tls/bridge.pem -pubkey -noout \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256
```

请把命令中的路径替换为实际证书路径。三行命令需要一起执行：先提取公钥，再转换格式，最后计算指纹。取最后输出中的 64 个十六进制字符，填入 `tls_server_fingerprint`。

这里的计算方式写作 `SHA-256(DER SubjectPublicKeyInfo)`：SHA-256（将数据计算成固定长度识别值的算法）处理的是 DER（二进制数据编码格式）保存的 SubjectPublicKeyInfo（证书中记录公钥及其算法的部分）。**需要计算的是这部分公钥信息的指纹，不是整张证书的指纹。**

## 使用快捷连接码或图形客户端

在网页管理的客户端列表中，可以复制 TLS 连接命令或快捷连接码（将地址、验证密钥等设置打包成一段文字，供 NPC 导入）。新生成的命令和连接码都包含当前桥接证书的公钥指纹。

直接复制管理页面提供的完整连接码即可。它使用 Base64（把数据转换成一段便于复制的文字的编码方式）保存以下内容，各项用 `|` 分隔：

```text
nps:<备注>|<地址:端口>|<vkey>|true|<公钥指纹>
```

其中 `vkey` 是客户端验证密钥，`true` 表示开启 TLS。Base64 不会对这些内容加密，连接码中包含验证密钥，请妥善保管。

新版命令行客户端、通过交互菜单注册的系统服务（由操作系统管理、在后台运行的程序），以及图形客户端，都会保留导入的指纹。

旧连接码只有备注、地址、验证密钥和 TLS 开关四项，没有公钥指纹。新版 NPC 仍能读取，但使用自签名证书时需要补充验证设置。最方便的做法是从自己的管理页面重新复制 TLS 连接码。如果使用公共 CA 证书，也可以按前面的命令行示例连接，无需填写指纹。

在图形客户端中手工添加连接时，先启用 TLS，再根据所选方式填写公钥指纹或 CA 文件，需要时填写证书域名。每个连接分别保存自己的验证设置。已有连接需要更换指纹或 CA 文件时，可以删除该连接，再用新的连接码或设置重新添加。

## 通过代理连接及其他连接方式

使用出站代理（NPC 借助另一台服务器连接 NPS）时，可以选择 HTTP CONNECT（让 HTTP 代理建立到目标地址的转发连接）或 SOCKS5（通过代理转发网络连接的协议）。代理连通目标后，NPC 仍会与 NPS 进行 TLS 握手（建立加密连接前，交换证书并确定加密方式的过程），并按你配置的方式验证证书。SNI 中填写的域名也仍然是 NPS 的域名。具体设置见[让 NPC 通过代理连接 NPS](/extend/feature/outbound-proxy.html)。

本页的 TLS 加密连接只支持 TCP。KCP（另一种网络传输协议，NPS 可用它连接客户端和服务端）不支持这种连接方式。NPC 同时启用 KCP 和这里的 TLS 设置时，会报错。

`crypt=true` 是隧道（把外部访问转发到目标服务的规则）原有的数据加密选项，它不会单独验证 NPS 身份。要确认连到的是自己的 NPS，需要开启本页介绍的 TLS 桥接。

## 从旧版本升级

旧版 NPC 默认不检查服务端证书，新版默认会检查。如果之前使用的是 NPS 临时生成的自签名证书，建议按顺序操作：

1. 升级 NPS，启动后确认 `conf/tls/` 下已经生成证书和私钥，并备份这两个文件。
2. 从 NPS 启动日志获取公钥指纹。
3. 升级 NPC，填写 `tls_enable=true` 和 `tls_server_fingerprint`，重新连接。

旧版 NPC 可以连接新版 NPS，但只升级 NPS 不会让旧版 NPC 开始验证证书。

升级过程中，如果确实需要暂时沿用旧版的连接方式，可以设置 `tls_insecure_skip_verify=true`，并将 CA 文件、证书名称和指纹三项留空。此时连接仍然加密，但 NPC 无法确认对方是不是你的 NPS。完成升级后，应改回 `false`，再按所选方式配置 CA 验证或指纹验证。

## 检查是否配置成功

先使用正确的配置连接，在网页管理的客户端列表中确认 NPC 在线。再根据所选验证方式检查以下情况；需要更换证书的测试，请在测试环境中进行：

| 检查内容                                                  | 应看到的结果                                                 |
| --------------------------------------------------------- | ------------------------------------------------------------ |
| 使用正确的 CA 证书和匹配的域名，或正确的公钥指纹          | NPC 可以连接                                                 |
| 检查证书名称时，将 `tls_server_name` 改为证书中没有的名称 | NPC 拒绝连接                                                 |
| 将公钥指纹中的一个字符改成其他十六进制字符                | NPC 拒绝连接                                                 |
| 使用过期证书                                              | NPS 启动时拒绝加载；如果连接时收到过期证书，NPC 也会拒绝连接 |
| 重启 NPS 后继续使用原指纹                                 | NPC 仍然可以连接                                             |
| 通过 HTTP CONNECT 或 SOCKS5 代理连接，并填写错误指纹      | NPC 仍然拒绝连接                                             |

如果需要查看服务端实际发来了什么证书，可以使用 OpenSSL：

```shell
openssl s_client -connect nps.example.com:8025 -servername nps.example.com -showcerts
```

把命令中的地址、端口和域名换成实际值。这个命令用于查看建立 TLS 连接时收到的证书，不会提交 NPS 要求的客户端验证密钥，因此不能用它判断 NPC 是否能完整登录。

---

反链：

- [使用说明](/client/use.html)
- [更多功能](/extend/feature/index.html)
- [TLS 加密 NPC 连接](/extend/feature/encrypted-transport.html)
- [NPC 通过代理连接 NPS](/extend/feature/outbound-proxy.html)
- [术语表](/extend/glossary.html)
- [服务端配置](/server/configuration.html)
- [增强功能](/server/nps_extend.html)
