rpki/README.md
xiuting.xu b60d579a38 增加ssh
增加deploy下细分的tcp、tls、ssh
2026-04-22 16:02:42 +08:00

458 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# RPKI RTR Server
默认运行平台Ubuntu/Linux。
## 目录
- [协议与规范](#协议与规范)
- [RTR](#rtr)
- [SLURM](#slurm)
- [CCR](#ccr)
- [RTR Server](#rtr-server)
- [环境变量](#环境变量)
- [说明](#说明)
- [快速启动](#快速启动)
- [Docker 启动](#docker-启动)
- [本地运行(推荐先用脚本)](#本地运行推荐先用脚本)
- [本地手动运行(最小示例)](#本地手动运行最小示例)
- [CCR 输入说明](#ccr-输入说明)
- [Client 使用](#client-使用)
- [作用与选择](#作用与选择)
- [rtr_debug_client本地](#rtr_debug_client本地)
- [rtr_debug_clientDocker](#rtr_debug_clientdocker)
- [rpki-rs-test-clientDocker](#rpki-rs-test-clientdocker)
- [FRRDocker黑盒客户端](#frrdocker黑盒客户端)
- [RTR Debug Client](#rtr-debug-client)
- [Client 启动示例](#client-启动示例)
- [存储模型与边界约束(多视图)](#存储模型与边界约束多视图)
- [唯一写入口](#唯一写入口)
- [恢复约束](#恢复约束)
- [边界防回归测试](#边界防回归测试)
- [Deploy Layout](#deploy-layout)
- [Quick Start](#quick-start)
- [Compose 入口](#compose-入口)
- [角色附加命令](#角色附加命令)
## 协议与规范
### RTR
- [RFC 6810: The Resource Public Key Infrastructure (RPKI) to Router Protocol](https://www.rfc-editor.org/rfc/rfc6810.html)
- [RFC 8210: The Resource Public Key Infrastructure (RPKI) to Router Protocol, Version 1](https://www.rfc-editor.org/rfc/rfc8210.html)
- [Draft: The Resource Public Key Infrastructure (RPKI) to Router Protocol, Version 2](https://www.ietf.org/archive/id/draft-ietf-sidrops-8210bis-25.html)
### SLURM
- [RFC 8416: Simplified Local Internet Number Resource Management with the RPKI (SLURM)](https://www.rfc-editor.org/rfc/rfc8416.html)
- [Draft: ASPA extensions for SLURM](https://www.ietf.org/archive/id/draft-ietf-sidrops-aspa-slurm-04.html)
### CCR
- [Draft: A Concise Cryptographic Representation of RPKI Signed Objects (CCR)](https://www.ietf.org/archive/id/draft-ietf-sidrops-rpki-ccr-02.html)
## RTR Server
RTR Server 运行时从 `CCR` 目录中扫描最新的 `.ccr` 文件作为输入源:
- `VRP`
- `VAP (Validated ASPA Payload) / ASPA`
相关实现位置:
- [`src/main.rs`](src/main.rs)
- [`src/source/ccr.rs`](src/source/ccr.rs)
### 环境变量
| 变量名 | 说明 | 默认值 | 示例 |
| --- | --- | --- | --- |
| `RPKI_RTR_ENABLE_TLS` | 是否额外启用 TLS 监听。支持 `true/false``1/0``yes/no``on/off`。 | `false` | `true` |
| `RPKI_RTR_TCP_ADDR` | TCP 监听地址。 | `0.0.0.0:323` | `0.0.0.0:323` |
| `RPKI_RTR_TLS_ADDR` | TLS 监听地址。 | `0.0.0.0:324` | `0.0.0.0:324` |
| `RPKI_RTR_DB_PATH` | RocksDB 路径。 | `./rtr-db` | `./rtr-db` |
| `RPKI_RTR_CCR_DIR` | CCR 目录路径;程序会扫描其中最新的 `.ccr` 文件。 | `./data` | `./data` |
| `RPKI_RTR_SLURM_DIR` | SLURM 目录路径;为空或未设置表示禁用 SLURM。 | `未设置(禁用)` | `./slurm` |
| `RPKI_RTR_TLS_CERT_PATH` | TLS 服务端证书路径。 | `./certs/server.crt` | `./certs/server-dns.crt` |
| `RPKI_RTR_TLS_KEY_PATH` | TLS 服务端私钥路径。 | `./certs/server.key` | `./certs/server-dns.key` |
| `RPKI_RTR_TLS_CLIENT_CA_PATH` | 用于校验 router 客户端证书的 CA 证书路径。 | `./certs/client-ca.crt` | `./certs/client-ca.crt` |
| `RPKI_RTR_ENABLE_SSH` | 是否额外启用进程内原生 SSH 监听。支持 `true/false``1/0``yes/no``on/off`。 | `false` | `true` |
| `RPKI_RTR_SSH_ADDR` | SSH 监听地址。 | `0.0.0.0:22` | `0.0.0.0:22` |
| `RPKI_RTR_SSH_PORT` | SSH 监听端口(仅覆盖 `RPKI_RTR_SSH_ADDR` 中的端口)。 | `22` | `2022` |
| `RPKI_RTR_SSH_HOST_KEY_PATH` | OpenSSH host 私钥路径。 | `./certs/ssh_host_ed25519_key` | `./certs/ssh_host_ed25519_key` |
| `RPKI_RTR_SSH_AUTHORIZED_KEYS_PATH` | 允许接入的 router 公钥列表authorized_keys。 | `./certs/rtr-authorized_keys` | `./certs/rtr-authorized_keys` |
| `RPKI_RTR_SSH_USERNAME` | SSH 用户名白名单。 | `rpki-rtr` | `rpki-rtr` |
| `RPKI_RTR_SSH_SUBSYSTEM_NAME` | SSH 子系统名称。 | `rpki-rtr` | `rpki-rtr` |
| `RPKI_RTR_SSH_PASSWORD` | 可选的 SSH password 认证口令。未设置时仅允许 publickey设置后同时允许 publickey 与 password。 | `未设置` | `test-password` |
| `RPKI_RTR_MAX_DELTA` | 最多保留多少条 delta。 | `100` | `100` |
| `RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE` | 是否启用“累计 delta 估算 wire size 不小于 snapshot 时,继续裁剪最老 delta”的策略。 | `false` | `false` |
| `RPKI_RTR_STRICT_CCR_VALIDATION` | 是否对 CCR 中的非法 VRP / VAP 采用严格模式;`true` 表示整份 CCR 拒绝,`false` 表示跳过非法项并告警。 | `false` | `false` |
| `RPKI_RTR_SOURCE_REFRESH_INTERVAL_SECS` | 数据源刷新周期:扫描 CCR/SLURM 并尝试更新缓存的间隔,单位秒,必须 `>= 1`。 | `300` | `30` |
| `RPKI_RTR_REFRESH_INTERVAL_SECS` | 旧变量名(已兼容,建议迁移到 `RPKI_RTR_SOURCE_REFRESH_INTERVAL_SECS`)。 | `300` | `300` |
| `RPKI_RTR_TIMING_REFRESH_SECS` | RTR EndOfData timing 的 `refresh` 字段,单位秒。 | `3600` | `300` |
| `RPKI_RTR_TIMING_RETRY_SECS` | RTR EndOfData timing 的 `retry` 字段,单位秒。 | `600` | `60` |
| `RPKI_RTR_TIMING_EXPIRE_SECS` | RTR EndOfData timing 的 `expire` 字段,单位秒(需大于 refresh/retry。 | `7200` | `1800` |
| `RPKI_RTR_MAX_CONNECTIONS` | 最大并发 RTR 客户端连接数。 | `512` | `512` |
| `RPKI_RTR_NOTIFY_QUEUE_SIZE` | Serial Notify 广播队列大小。 | `1024` | `1024` |
| `RPKI_RTR_TCP_KEEPALIVE_SECS` | TCP keepalive 时间,单位秒;设为 `0` 表示禁用。 | `60` | `60` |
| `RPKI_RTR_WARN_INSECURE_TCP` | 纯 TCP 模式下是否输出不安全警告。 | `true` | `true` |
| `RPKI_RTR_REQUIRE_TLS_SERVER_DNS_NAME_SAN` | 严格模式TLS 服务端证书不包含 `subjectAltName dNSName` 时拒绝启动。 | `false` | `false` |
### 说明
- 纯 TCP 模式只应部署在受信任、可控网络中。
- TLS 模式要求客户端证书认证。
- 当前输入源是 `CCR` 目录,不再是单独的文本 VRP / ASPA / Router Key 文件。
- 刷新时会重新扫描 `RPKI_RTR_CCR_DIR`,并选取文件名排序最新的 `.ccr` 文件。
- `RPKI_RTR_SOURCE_REFRESH_INTERVAL_SECS`(旧名 `RPKI_RTR_REFRESH_INTERVAL_SECS`)控制的是“服务端多长时间扫描并更新数据源”,不是 RTR EndOfData 的 timing。
- RTR 客户端在 EndOfData 中看到的 `refresh/retry/expire``RPKI_RTR_TIMING_REFRESH_SECS``RPKI_RTR_TIMING_RETRY_SECS``RPKI_RTR_TIMING_EXPIRE_SECS` 控制。
- `RPKI_RTR_STRICT_CCR_VALIDATION=false`CCR 中的非法 VRP / VAP 会被跳过并输出 warning`true` 时整份 CCR 更新失败。
- `RPKI_RTR_TCP_KEEPALIVE_SECS=0` 表示关闭 keepalive非零值表示在整个连接生命周期内启用 keepalive。
- `RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE=true` 时,除了 `RPKI_RTR_MAX_DELTA` 的固定条数裁剪外,还会在累计 delta 估算 wire size 不小于 snapshot 时继续删除最老 delta。
## 快速启动
### Docker 启动
```bash
docker compose -f deploy/server/docker-compose.yml up -d --build
docker compose -f deploy/server/docker-compose.yml logs -f rpki-rtr
docker compose -f deploy/server/docker-compose.yml down
```
### 本地运行(推荐先用脚本)
```bash
docker compose -f deploy/server/docker-compose.yml up -d --build
docker compose -f deploy/server/docker-compose.yml logs -f rpki-rtr
docker compose -f deploy/server/docker-compose.yml down
```
### 本地手动运行(最小示例)
纯 TCP
```bash
docker compose -f deploy/server/docker-compose.yml up -d --build
```
TLS / mutual TLS
```bash
docker compose -f deploy/server/docker-compose.yml -f deploy/server/docker-compose.tls.yml up -d --build
```
## CCR 输入说明
当前会从 `RPKI_RTR_CCR_DIR` 指向的目录中扫描最新 `.ccr` 文件,并从中提取:
- `VRP`
- `VAP (Validated ASPA Payload) / ASPA`
测试样例可参考:
- [`data/20260324T000037Z-sng1.ccr`](data/20260324T000037Z-sng1.ccr)
## Client 使用
客户端的作用是从不同角度验证 RTR 服务端行为,覆盖“协议调试、自动化测试、黑盒互通”三类需求。
### 作用与选择
| Client | 主要作用 | 适用场景 |
| --- | --- | --- |
| `rtr_debug_client` | 面向协议交互调试,便于手动发起 `reset/serial` 并观察响应 | 开发联调、定位会话/报文问题、快速复现 |
| `rpki-rs-test-client` | 基于 `rpki-rs` 客户端 API 做自动化验证 | CI/CD、回归测试、批量步骤校验 |
| `FRR` | 真实路由软件黑盒接入,验证与生产侧客户端互通 | 互操作验证、运维演练、端到端验证 |
建议使用顺序:
1. 先用 `rtr_debug_client` 快速确认服务可连通、协议版本和基础响应正常。
2. 再用 `rpki-rs-test-client` 做可重复的自动化步骤校验。
3. 最后用 `FRR` 做黑盒互通验证,确认真实客户端接入行为。
### rtr_debug_clientDocker
```bash
docker compose -f deploy/client/docker-compose.yml up --build
docker compose -f deploy/client/docker-compose.yml logs -f rtr-debug-client
docker compose -f deploy/client/docker-compose.yml down
```
多实例压测/联调:
```bash
docker compose -f deploy/client/docker-compose.clients.yml up -d
docker compose -f deploy/client/docker-compose.clients.yml logs -f
docker compose -f deploy/client/docker-compose.clients.yml down
```
### rpki-rs-test-clientDocker
```bash
docker compose -f deploy/rpki-rs-client/docker-compose.yml up --build
docker compose -f deploy/rpki-rs-client/docker-compose.yml run --rm \
rpki-rs-test-client 127.0.0.1:323 2 reset --steps 1 --assert-min-records 1
docker compose -f deploy/rpki-rs-client/docker-compose.yml down
```
说明:
- 适合自动化场景:可作为流水线中的协议检查器。
- 适合回归校验:通过参数化步骤(`--steps`)和断言(如 `--assert-min-records`)稳定验证行为。
### FRRDocker黑盒客户端
```bash
docker compose -f deploy/frr/docker-compose.yml up -d
docker exec -it frr-rpki-client vtysh -c "show rpki cache-connection"
docker exec -it frr-rpki-client vtysh -c "show rpki prefix-table"
docker compose -f deploy/frr/docker-compose.yml down
```
说明:
- 适合真实互通验证FRR 更接近生产客户端行为。
- 适合观察业务结果:可直接查看缓存连接状态和前缀表结果。
## RTR Debug Client
调试用 RTR client 位于:
- [`src/bin/rtr_debug_client/main.rs`](src/bin/rtr_debug_client/main.rs)
说明文档位于:
- [`src/bin/rtr_debug_client/README.md`](src/bin/rtr_debug_client/README.md)
### Client 启动示例
连接纯 TCP RTR server
```sh
cargo run --bin rtr_debug_client -- 127.0.0.1:323 1 reset
```
连接 TLS RTR server
```sh
cargo run --bin rtr_debug_client -- \
127.0.0.1:324 1 reset \
--tls \
--ca-cert ./certs/client-ca.crt \
--server-name localhost \
--client-cert ./certs/client-good.crt \
--client-key ./certs/client-good.key
```
如果要在收到错误后继续自动轮询,可以加:
```sh
--keep-after-error
```
## 存储模型与边界约束(多视图)
当前 RTR cache 持久化采用三视图模型(按协议版本拆分):
- v0`RouteOrigin`
- v1`RouteOrigin + RouterKey`
- v2`RouteOrigin + RouterKey + Aspa`
RocksDB 中的核心状态按版本独立保存:
- `session_id_v0/v1/v2`
- `serial_v0/v1/v2`
- `current_v0/v1/v2`snapshot
- `delta_min_v0/v1/v2``delta_max_v0/v1/v2`
- delta key 采用 `D + version + serial_be`
### 唯一写入口
为保证 `session_id/serial/snapshot/delta_window` 的一致性,生产代码只允许通过:
- `RtrStore::save_cache_state_versioned(...)`
且该入口应仅由:
- `src/rtr/cache/store.rs`
发起调用(即由 cache 层统一批量原子写入)。
### 恢复约束
重启恢复时,按版本读取并校验:
- `availability`
- `snapshot_for_version(version)`
- `session_id_for_version(version)`
- `serial_for_version(version)`
- `delta_window_for_version(version)``load_delta_window_for_version(...)`
只有三视图状态完整且自洽时才走 store 恢复;否则回退到输入源加载流程。
### 边界防回归测试
新增边界测试用于限制写调用点,防止后续出现绕写路径:
- `tests/test_store_boundary.rs`
可单独执行:
```sh
cargo test --test test_store_boundary -- --nocapture
```
## Deploy Layout
`deploy/` 目录按角色拆分为四套部署与测试入口:
- `server/`: 本仓库 RTR Server`src/main.rs`)容器化部署
- `client/`: 本仓库 `rtr_debug_client` 容器化部署
- `rpki-rs-client/`: 基于外部 `rpki-rs` client API 的测试客户端容器化部署
- `frr/`: FRR 作为黑盒 RTR Client 的配置与 compose
### Quick Start
最短路径(本地容器环境):
```bash
docker compose -f deploy/server/docker-compose.yml up -d --build
docker compose -f deploy/server/docker-compose.yml logs -f rpki-rtr
docker compose -f deploy/server/docker-compose.yml down
```
### Compose 入口
| 角色 | Compose 文件 |
| --- | --- |
| Server | `deploy/server/docker-compose.yml` |
| Debug Client单实例 | `deploy/client/docker-compose.yml` |
| Debug Client多实例 | `deploy/client/docker-compose.clients.yml` |
| rpki-rs Client | `deploy/rpki-rs-client/docker-compose.yml` |
| FRR Client | `deploy/frr/docker-compose.yml` |
通用操作模板:
```bash
docker compose -f <compose-file> up -d --build
docker compose -f <compose-file> logs -f
docker compose -f <compose-file> down
```
### 角色附加命令
rpki-rs Client覆盖默认参数运行
```bash
docker compose -f deploy/rpki-rs-client/docker-compose.yml run --rm \
rpki-rs-test-client 127.0.0.1:323 2 reset --steps 1 --assert-min-records 1
```
FRR Client检查连接与前缀
```bash
docker exec -it frr-rpki-client vtysh -c "show rpki cache-connection"
docker exec -it frr-rpki-client vtysh -c "show rpki prefix-table"
```
更多部署细节:
- `deploy/server/DEPLOYMENT.md`
- `deploy/frr/README.md`
- `deploy/frr/README.zh.md`
## 传输模式说明TCP / TLS / 原生 SSH
当前 `rpki` 进程内支持三种传输:
- TCP默认开启
- TLS可选开启mTLS
- 原生 SSH可选开启进程内实现不再使用外部 `sshd Subsystem` 桥接)
### TCP 模式
默认监听:
- `RPKI_RTR_TCP_ADDR=0.0.0.0:323`
最小启动(仅 TCP
```sh
export RPKI_RTR_ENABLE_TLS=false
export RPKI_RTR_ENABLE_SSH=false
cargo run --bin rpki
```
说明:
- 仅建议部署在受信任、可控网络中。
### TLS 模式mTLS
相关环境变量:
- `RPKI_RTR_ENABLE_TLS=true`
- `RPKI_RTR_TLS_ADDR`(默认 `0.0.0.0:324`
- `RPKI_RTR_TLS_CERT_PATH`
- `RPKI_RTR_TLS_KEY_PATH`
- `RPKI_RTR_TLS_CLIENT_CA_PATH`
最小启动TCP + TLS
```sh
export RPKI_RTR_ENABLE_TLS=true
export RPKI_RTR_ENABLE_SSH=false
export RPKI_RTR_TLS_CERT_PATH=./certs/server-dns.crt
export RPKI_RTR_TLS_KEY_PATH=./certs/server-dns.key
export RPKI_RTR_TLS_CLIENT_CA_PATH=./certs/client-ca.crt
cargo run --bin rpki
```
### 原生 SSH 模式(进程内)
`draft-ietf-sidrops-8210bis-25` 对齐要点:
- 使用 SSHv2
- 使用 subsystem默认 `rpki-rtr`
- 使用 public key 认证
- 服务端拒绝 `none`
- 服务端默认不启用 `password`,配置 `RPKI_RTR_SSH_PASSWORD` 后可选启用draft 中为 MAY
相关环境变量:
- `RPKI_RTR_ENABLE_SSH=true`
- `RPKI_RTR_SSH_ADDR`(默认 `0.0.0.0:22`
- `RPKI_RTR_SSH_PORT`(默认 `22`,设置后会覆盖 `RPKI_RTR_SSH_ADDR` 的端口)
- `RPKI_RTR_SSH_HOST_KEY_PATH`OpenSSH host 私钥)
- `RPKI_RTR_SSH_AUTHORIZED_KEYS_PATH`(允许接入的 router 公钥列表)
- `RPKI_RTR_SSH_USERNAME`(默认 `rpki-rtr`
- `RPKI_RTR_SSH_SUBSYSTEM_NAME`(默认 `rpki-rtr`
- `RPKI_RTR_SSH_PASSWORD`(可选;设置后启用 password 认证)
密钥准备示例:
```sh
ssh-keygen -t ed25519 -N '' -f ./certs/ssh_host_ed25519_key
ssh-keygen -t ed25519 -N '' -f ./certs/rtr_client_ed25519_key
cp ./certs/rtr_client_ed25519_key.pub ./certs/rtr-authorized_keys
```
最小启动TCP + SSH
```sh
export RPKI_RTR_ENABLE_TLS=false
export RPKI_RTR_ENABLE_SSH=true
export RPKI_RTR_SSH_ADDR=0.0.0.0:22
# or only override the port:
# export RPKI_RTR_SSH_PORT=2022
export RPKI_RTR_SSH_HOST_KEY_PATH=./certs/ssh_host_ed25519_key
export RPKI_RTR_SSH_AUTHORIZED_KEYS_PATH=./certs/rtr-authorized_keys
export RPKI_RTR_SSH_USERNAME=rpki-rtr
export RPKI_RTR_SSH_SUBSYSTEM_NAME=rpki-rtr
# 可选:启用 password 认证(同时仍支持 publickey
# export RPKI_RTR_SSH_PASSWORD=test-password
cargo run --bin rpki
```
连通性检查OpenSSH
```sh
ssh -i ./certs/rtr_client_ed25519_key -p 22 -s rpki-rtr@127.0.0.1 rpki-rtr
```
说明:
- 该命令主要用于验证 SSH 子系统通道可建立,不等价于完整 RTR 协议回归测试。