# RPKI RTR Server 这是一个用 Rust 实现的 RPKI-to-Router (RTR) cache server。服务端从 CCR 文件中读取 RPKI 数据,生成 RTR cache snapshot 和 delta,并通过 RTR 协议提供给路由器或调试客户端。 当前代码重点覆盖: - RTR server:TCP 默认启用,可选启用 TLS/mTLS 和进程内 SSH transport。 - 数据输入:从 CCR 目录选择最新 `.ccr` 文件,解析 VRP 和 VAP/ASPA。 - 本地策略:可选加载 SLURM 文件,对 CCR 解析出的 payload 做过滤和本地断言。 - 持久化:使用 RocksDB 保存 RTR cache 状态。 - 运行报告:输出 source、client、runtime 三类 JSON report。 - 运行期管理:可选启用 HTTP Admin API,修改部分 runtime config、触发 source reload、管理 SLURM 文件。 - 调试工具:`rtr_debug_client` 支持 TCP、TLS 和 SSH 连接 RTR server。 ## 目录 - [协议参考](#协议参考) - [项目结构](#项目结构) - [构建与测试](#构建与测试) - [数据输入](#数据输入) - [快速启动](#快速启动) - [前置数据生成](#前置数据生成) - [Docker 运行](#docker-运行) - [跨架构构建](#跨架构构建) - [传输模式](#传输模式) - [主要环境变量](#主要环境变量) - [运行报告](#运行报告) - [Admin API](#admin-api) - [调试客户端](#调试客户端) - [部署入口](#部署入口) - [开发说明](#开发说明) ## 协议参考 - RTR: [RFC 6810](https://www.rfc-editor.org/rfc/rfc6810.html), [RFC 8210](https://www.rfc-editor.org/rfc/rfc8210.html) - SLURM: [RFC 8416](https://www.rfc-editor.org/rfc/rfc8416.html) - CCR: [draft-ietf-sidrops-rpki-ccr](https://www.ietf.org/archive/id/draft-ietf-sidrops-rpki-ccr-02.html) ## 项目结构 | 路径 | 说明 | | --- | --- | | `src/main_rtr.rs` | RTR server 入口 | | `src/rtr/` | RTR 协议、cache、store、server transport、admin、report | | `src/source/` | CCR/SLURM source 加载流程 | | `src/slurm/` | SLURM 文件解析、合并和策略应用 | | `src/data_model/` | RPKI 相关数据结构 | | `src/bin/rtr_debug_client/` | RTR 调试客户端 | | `deploy/server/` | server Docker 镜像和 compose | | `deploy/client/` | debug client Docker 镜像和 compose | | `deploy/frr/`, `deploy/bird/` | FRR/BIRD 作为 RTR client 的测试部署 | | `tests/` | 单元和集成测试 | ## 构建与测试 ```bash cargo build --bin rpki_rtr cargo build --bin rtr_debug_client cargo test ``` 服务端 binary 名称是 `rpki_rtr`: ```bash cargo run --bin rpki_rtr ``` 默认配置会监听 `0.0.0.0:323`,从 `./data` 查找 CCR 文件,并使用 `./rtr-db` 保存 RocksDB 数据。启动前需要确保 CCR 目录里存在可解析的 `.ccr` 文件。 ## 数据输入 服务端启动和刷新时会读取 `RPKI_RTR_CCR_DIR` 指向的目录: 1. 如果该目录下存在包含 `.ccr` 文件的子目录,先按子目录名排序选择最新子目录。 2. 在选中的目录中按文件名排序选择最新 `.ccr` 文件。 3. 从 CCR 中解析 VRP 和 VAP/ASPA。 4. 如果配置了 `RPKI_RTR_SLURM_DIR`,加载其中启用的 `*.slurm` 文件并应用本地策略。 ## 快速启动 ### 前置数据生成 TLS/mTLS 或 SSH transport 需要本地证书和密钥。开发和 Docker 联调可用脚本生成 compose 默认引用的最小文件集: ```bash bash scripts/10_generate-certs.sh ``` 如需覆盖已有 `certs/` 内容: ```bash bash scripts/10_generate-certs.sh --force ``` `10_generate-certs.sh` 常用参数: | 参数 | 说明 | | --- | --- | | `--out-dir DIR` | 指定输出目录,默认生成到 `./certs`。 | | `--server-dns NAME` | 指定 TLS server 证书的 dNSName SAN,默认 `localhost`。 | | `--tls-only` | 只生成 `certs/tls` 下的 TLS 证书和私钥。 | | `--ssh-only` | 只生成 `certs/ssh` 下的 SSH host key、client key 和 `authorized_keys`。 | | `--force` | 覆盖已有文件。未指定时,如果目标文件已存在会直接报错退出。 | | `-h`, `--help` | 查看脚本帮助。 | TLS server name 默认是 `localhost`。如果需要其它 DNS 名称,需要同时设置 `scripts/10_generate-certs.sh --server-dns ` 和 client 的 `RPKI_RTR_TLS_SERVER_NAME=`。 ### Docker 运行 推荐使用 `deploy/server/build-run.sh` 和 `deploy/client/build-run.sh` 分别管理 server 与 debug client: 以下命令默认从仓库根目录执行。 ```bash chmod +x deploy/server/build-run.sh deploy/client/build-run.sh ./deploy/server/build-run.sh up --mode tcp ./deploy/client/build-run.sh up --mode tcp ./deploy/client/build-run.sh down ./deploy/server/build-run.sh down ``` 脚本常用参数: | 参数/变量 | server | client | 说明 | | --- | --- | --- | --- | | `--mode base|tcp|tls|ssh`, `MODE` | yes | yes | 选择 compose 模式,默认 `tcp`。 | | `--clients single|multi`, `CLIENTS` | no | yes | 单 client 或 5 client,默认 `single`。 | | `--no-build`, `BUILD=0` | yes | yes | 只运行已有镜像,不执行 compose build。 | | `--server-image TAG`, `SERVER_IMAGE` | yes | no | server 镜像名;会传给 compose 的 `RPKI_RTR_SERVER_IMAGE`。 | | `--client-image TAG`, `CLIENT_IMAGE` | no | yes | client 镜像名;会传给 compose 的 `RPKI_RTR_CLIENT_IMAGE`。 | | `--platform VALUE`, `TARGET_PLATFORM` | yes | yes | `buildx` 目标平台,默认 `linux/arm64`。 | | `--push`, `BUILDX_PUSH=1` | yes | yes | `buildx` 构建后推送到 registry;不设置时加载到本地 Docker。 | | `--skip-base-pull`, `SKIP_BASE_IMAGE_PULL=1` | yes | yes | 跳过 buildx 前的基础镜像预拉取。 | 支持的 action 包括 `up`、`build`、`buildx`、`rebuild`、`down`/`stop`、`restart`、`logs`、`ps`。完整帮助见: ```bash ./deploy/server/build-run.sh --help ./deploy/client/build-run.sh --help ``` ### 跨架构构建 示例:x86 开发机本地构建 ARM 镜像,打包后传到 ARM 部署机。 ```bash ./deploy/server/build-run.sh buildx \ --platform linux/arm64 \ --server-image rpki-rtr:arm64 ./deploy/client/build-run.sh buildx \ --platform linux/arm64 \ --client-image rpki-rtr-debug-client:arm64 mkdir -p dist/images docker save rpki-rtr:arm64 -o dist/images/rpki-rtr-arm64.tar docker save rpki-rtr-debug-client:arm64 -o dist/images/rpki-rtr-debug-client-arm64.tar scp dist/images/*.tar user@arm-host:/tmp/ ``` ARM 部署机加载镜像并运行: ```bash docker load -i /tmp/rpki-rtr-arm64.tar docker load -i /tmp/rpki-rtr-debug-client-arm64.tar SERVER_IMAGE=rpki-rtr:arm64 \ BUILD=0 ./deploy/server/build-run.sh up --mode tcp CLIENT_IMAGE=rpki-rtr-debug-client:arm64 \ BUILD=0 ./deploy/client/build-run.sh up --mode tcp ``` ```bash docker compose -f deploy/server/docker-compose.yml up -d --build docker compose -f deploy/server/docker-compose.yml down ``` TLS/mTLS 示例: ```bash docker compose -f deploy/server/docker-compose.tls.yml up -d --build docker compose -f deploy/server/docker-compose.tls.yml down ``` ## 传输模式 TCP 默认启用。TLS 和 SSH 是附加监听,不会替代 TCP。 | 模式 | 默认地址 | 启用方式 | | --- | --- | --- | | TCP | `0.0.0.0:323` | 默认启用 | | TLS/mTLS | `0.0.0.0:324` | `RPKI_RTR_ENABLE_TLS=true` | | SSH | `0.0.0.0:22` | `RPKI_RTR_ENABLE_SSH=true` | TLS server 会加载服务端证书、私钥和 client CA。SSH server 使用 OpenSSH host key 和 authorized_keys 文件;`RPKI_RTR_SSH_AUTH_MODE` 支持 `key`、`password`、`both`。 ## 主要环境变量 布尔值支持 `true/false`、`1/0`、`yes/no`、`on/off`。 | 变量 | 默认值 | 说明 | | --- | --- | --- | | `RPKI_RTR_ENABLE_TLS` | `false` | 是否启用 TLS/mTLS 监听 | | `RPKI_RTR_ENABLE_SSH` | `false` | 是否启用 SSH 监听 | | `RPKI_RTR_TCP_ADDR` | `0.0.0.0:323` | TCP 监听地址 | | `RPKI_RTR_TLS_ADDR` | `0.0.0.0:324` | TLS 监听地址 | | `RPKI_RTR_SSH_ADDR` | `0.0.0.0:22` | SSH 监听地址 | | `RPKI_RTR_SSH_PORT` | 未设置 | 仅覆盖 `RPKI_RTR_SSH_ADDR` 中的端口 | | `RPKI_RTR_DB_PATH` | `./rtr-db` | RocksDB 路径 | | `RPKI_RTR_CCR_DIR` | `./data` | CCR 输入目录 | | `RPKI_RTR_SLURM_DIR` | 未设置 | SLURM 目录;空值表示禁用 | | `RPKI_RTR_REPORT_DIR` | `./report` | JSON report 输出目录 | | `RPKI_RTR_MAX_DELTA` | `100` | 每个 RTR 版本保留的最大 delta 数,必须大于 0 | | `RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE` | `false` | 是否按 snapshot wire size 继续裁剪 delta window | | `RPKI_RTR_SOURCE_REFRESH_INTERVAL_SECS` | `300` | source 刷新间隔,单位秒 | | `RPKI_RTR_REFRESH_INTERVAL_SECS` | 未设置 | 旧变量名,仍兼容;建议使用 `RPKI_RTR_SOURCE_REFRESH_INTERVAL_SECS` | | `RPKI_RTR_TIMING_REFRESH_SECS` | `3600` | RTR EndOfData `refresh` 字段 | | `RPKI_RTR_TIMING_RETRY_SECS` | `600` | RTR EndOfData `retry` 字段 | | `RPKI_RTR_TIMING_EXPIRE_SECS` | `7200` | RTR EndOfData `expire` 字段,必须大于 refresh 和 retry | | `RPKI_RTR_MAX_CONNECTIONS` | `512` | 最大并发 RTR 连接数 | | `RPKI_RTR_MAX_CONCURRENT_HANDSHAKES` | `128` | 最大并发握手数,不能大于最大连接数 | | `RPKI_RTR_NOTIFY_QUEUE_SIZE` | `1024` | Serial Notify 广播队列大小 | | `RPKI_RTR_TCP_KEEPALIVE_SECS` | `60` | TCP keepalive;设为 `0` 表示禁用 | | `RPKI_RTR_WARN_INSECURE_TCP` | `true` | TCP 模式是否输出安全提示 | | `RPKI_RTR_REQUIRE_TLS_SERVER_DNS_NAME_SAN` | `false` | 是否要求 TLS 服务端证书包含 dNSName SAN | | `RPKI_RTR_ENFORCE_TLS_CLIENT_SAN_IP_MATCH` | `true` | 是否校验 TLS client 证书 SAN IP 与 peer IP 匹配 | | `RPKI_RTR_RUNTIME_REPORT_INTERVAL_SECS` | `300` | runtime report 周期 | | `RPKI_RTR_REPORT_HISTORY_LIMIT` | `10` | 每类 report 滚动保留数量 | | `RPKI_RTR_TIMEZONE` | `Asia/Shanghai` | 日志和 report 使用的时区 | | `RPKI_RTR_ADMIN_ADDR` | 未设置 | Admin API 监听地址;未设置时关闭 | | `RPKI_RTR_ADMIN_TOKEN` | 未设置 | Admin API Bearer token;非 loopback 监听时必须设置 | TLS 相关路径: | 变量 | 默认值 | | --- | --- | | `RPKI_RTR_TLS_CERT_PATH` | `./certs/tls/server-dns.crt` | | `RPKI_RTR_TLS_KEY_PATH` | `./certs/tls/server-dns.key` | | `RPKI_RTR_TLS_CLIENT_CA_PATH` | `./certs/tls/client-ca.crt` | SSH 相关配置: | 变量 | 默认值 | | --- | --- | | `RPKI_RTR_SSH_HOST_KEY_PATH` | `./certs/ssh/ssh_host_rsa_key` | | `RPKI_RTR_SSH_AUTHORIZED_KEYS_PATH` | `./certs/ssh/rtr-authorized_keys` | | `RPKI_RTR_SSH_USERNAME` | `rpki-rtr` | | `RPKI_RTR_SSH_SUBSYSTEM_NAME` | `rpki-rtr` | | `RPKI_RTR_SSH_AUTH_MODE` | `key` | | `RPKI_RTR_SSH_PASSWORD` | 未设置 | ## 运行报告 服务会在 `RPKI_RTR_REPORT_DIR` 下写入 JSON report,并按 `RPKI_RTR_REPORT_HISTORY_LIMIT` 滚动保留: - `rtr-source-*.json`:CCR/SLURM source、fingerprint、刷新状态、数据质量、cache 统计。 - `rtr-clients-*.json`:client 连接数和连接方式统计。 - `rtr-runtime-*.json`:进程状态、服务状态和当前生效的 runtime config。 ## Admin API Admin API 默认关闭。设置 `RPKI_RTR_ADMIN_ADDR` 后启用: ```bash export RPKI_RTR_ADMIN_ADDR=127.0.0.1:8323 export RPKI_RTR_ADMIN_TOKEN=change-me ``` 如果监听非 loopback 地址,例如 `0.0.0.0:8323`,必须设置 `RPKI_RTR_ADMIN_TOKEN`。设置 token 后,请求需要携带: ```http Authorization: Bearer change-me ``` 当前实现的主要接口: | 方法 | 路径 | 说明 | | --- | --- | --- | | `GET` | `/admin/rtr/health` | 健康检查和能力开关 | | `GET` | `/admin/rtr/config` | 查看 runtime config | | `POST` | `/admin/rtr/config` | 修改部分 runtime config | | `GET` | `/admin/rtr/logs/tail` | 读取 stdout/stderr 日志 tail | | `POST` | `/admin/rtr/slurm/reload` | 触发 source reload | | `GET` | `/admin/rtr/slurm/files` | 列出 SLURM 文件 | | `POST` | `/admin/rtr/slurm/files` | 新增或覆盖 SLURM 文件 | | `GET` | `/admin/rtr/slurm/files/{name}` | 读取 SLURM 文件 | | `PUT` | `/admin/rtr/slurm/files/{name}` | 新增或覆盖指定 SLURM 文件 | | `DELETE` | `/admin/rtr/slurm/files/{name}` | 删除 SLURM 文件 | | `POST` | `/admin/rtr/slurm/files/{name}/enable` | 启用 `.slurm.disabled` 文件 | | `POST` | `/admin/rtr/slurm/files/{name}/disable` | 禁用 `.slurm` 文件 | 示例: ```bash curl http://127.0.0.1:8323/admin/rtr/config \ -H "Authorization: Bearer change-me" curl -X POST http://127.0.0.1:8323/admin/rtr/config \ -H "Content-Type: application/json" \ -H "Authorization: Bearer change-me" \ -d '{"max_delta": 6, "source_refresh_interval_seconds": 60}' ``` ## 调试客户端 `rtr_debug_client` 用于手动发起 Reset Query 或 Serial Query,并观察服务端返回的 PDU。 RTR Client 的 Docker 调试、FRR/BIRD 互通验证和常用排障步骤见 `README.client.md`。 TCP: ```bash cargo run --bin rtr_debug_client -- 127.0.0.1:323 1 reset cargo run --bin rtr_debug_client -- 127.0.0.1:323 1 serial 42 100 ``` TLS: ```bash cargo run --bin rtr_debug_client -- \ 127.0.0.1:324 1 reset \ --tls \ --ca-cert certs/tls/client-ca.crt \ --server-name localhost \ --client-cert certs/tls/client-good.crt \ --client-key certs/tls/client-good.key ``` SSH: ```bash cargo run --bin rtr_debug_client -- \ 127.0.0.1:22 1 reset \ --ssh \ --ssh-user rpki-rtr \ --ssh-key certs/ssh/rtr-client.key \ --ssh-server-key certs/ssh/ssh_host_rsa_key.pub ``` SSH password auth 也已实现;SSH 模式下 `--ssh-key` 和 `--ssh-password` 二选一,同时必须通过 `--ssh-known-hosts` 或 `--ssh-server-key` 做 host key 校验。 更多参数见 `src/bin/rtr_debug_client/README.md`。 ## 部署入口 | 用途 | Compose 文件 | | --- | --- | | Server | `deploy/server/docker-compose.yml` | | Server TCP 示例 | `deploy/server/docker-compose.tcp.yml` | | Server TLS 示例 | `deploy/server/docker-compose.tls.yml` | | Server SSH 示例 | `deploy/server/docker-compose.ssh.yml` | | Debug client | `deploy/client/docker-compose.yml` | | Debug client 多实例 | `deploy/client/docker-compose.clients.yml` | | FRR client | `deploy/frr/docker-compose.yml` | | BIRD client | `deploy/bird/docker-compose.yml` | RTR Client 统一使用说明见 `README.client.md`。 通用操作: ```bash COMPOSE_FILE=deploy/server/docker-compose.yml docker compose -f "${COMPOSE_FILE}" up -d --build docker compose -f "${COMPOSE_FILE}" ps docker compose -f "${COMPOSE_FILE}" down ``` ## 开发说明 - 代码中的 RTR cache 按协议版本维护状态;v0 只包含 Route Origin,v1 包含 Route Origin 和 Router Key,v2 包含 Route Origin、Router Key 和 ASPA。 - 当前 source pipeline 从 CCR 生成 Route Origin 和 ASPA,再可选应用 SLURM。 - `RtrStore::save_cache_state_versioned(...)` 是 cache 状态写入 RocksDB 的核心入口,相关边界测试在 `tests/test_store_boundary.rs`。 - Admin API 的日志 tail 依赖部署入口写出的 stdout/stderr 日志文件;容器入口脚本会把日志写到 `/app/logs`。