# RPKI RTR Server 默认运行平台:Ubuntu/Linux。 ## RTR Server RTR Server 运行时从 `CCR` 目录中扫描最新的 `.ccr` 文件作为输入源。当前 `main` 路径不再读取 `vrps.txt` / `aspas.txt` / `router-keys.txt`,而是统一从 CCR 快照加载: - `VRP` - `VAP / ASPA` 相关实现位置: - [`src/main.rs`](src/main.rs) - [`src/rtr/ccr.rs`](src/rtr/ccr.rs) ### 环境变量 | 变量名 | 说明 | 示例 | | --- | --- | --- | | `RPKI_RTR_ENABLE_TLS` | 是否额外启用 TLS 监听。支持 `true/false`、`1/0`、`yes/no`、`on/off`。 | `true` | | `RPKI_RTR_TCP_ADDR` | TCP 监听地址。 | `0.0.0.0:323` | | `RPKI_RTR_TLS_ADDR` | TLS 监听地址。 | `0.0.0.0:324` | | `RPKI_RTR_DB_PATH` | RocksDB 路径。 | `./rtr-db` | | `RPKI_RTR_CCR_DIR` | CCR 目录路径;程序会扫描其中最新的 `.ccr` 文件。 | `./data` | | `RPKI_RTR_TLS_CERT_PATH` | TLS 服务端证书路径。 | `./certs/server-dns.crt` | | `RPKI_RTR_TLS_KEY_PATH` | TLS 服务端私钥路径。 | `./certs/server-dns.key` | | `RPKI_RTR_TLS_CLIENT_CA_PATH` | 用于校验 router 客户端证书的 CA 证书路径。 | `./certs/client-ca.crt` | | `RPKI_RTR_MAX_DELTA` | 最多保留多少条 delta。 | `100` | | `RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE` | 是否启用“累计 delta 估算 wire size 不小于 snapshot 时,继续裁剪最老 delta”的策略。 | `false` | | `RPKI_RTR_STRICT_CCR_VALIDATION` | 是否对 CCR 中的非法 VRP / VAP 采用严格模式;`true` 表示整份 CCR 拒绝,`false` 表示跳过非法项并告警。 | `false` | | `RPKI_RTR_REFRESH_INTERVAL_SECS` | 刷新 CCR 目录并重新加载最新 `.ccr` 的间隔,单位秒。 | `300` | | `RPKI_RTR_MAX_CONNECTIONS` | 最大并发 RTR 客户端连接数。 | `512` | | `RPKI_RTR_NOTIFY_QUEUE_SIZE` | Serial Notify 广播队列大小。 | `1024` | | `RPKI_RTR_TCP_KEEPALIVE_SECS` | TCP keepalive 时间,单位秒;设为 `0` 表示禁用。 | `60` | | `RPKI_RTR_WARN_INSECURE_TCP` | 纯 TCP 模式下是否输出不安全警告。 | `true` | | `RPKI_RTR_REQUIRE_TLS_SERVER_DNS_NAME_SAN` | 严格模式:TLS 服务端证书不包含 `subjectAltName dNSName` 时拒绝启动。 | `false` | ### 说明 - 纯 TCP 模式只应部署在受信任、可控网络中。 - TLS 模式要求客户端证书认证。 - 当前输入源是 `CCR` 目录,不再是单独的文本 VRP / ASPA / Router Key 文件。 - 刷新时会重新扫描 `RPKI_RTR_CCR_DIR`,并选取文件名排序最新的 `.ccr` 文件。 - `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。 ## 启动示例 ### Bash 纯 TCP 模式: ```sh sh ./scripts/start-rtr-server-tcp.sh ``` TLS / mutual TLS 模式: ```sh sh ./scripts/start-rtr-server-tls.sh ``` ### 手动启动 #### 纯 TCP ```sh export RPKI_RTR_ENABLE_TLS=false export RPKI_RTR_TCP_ADDR=0.0.0.0:323 export RPKI_RTR_DB_PATH=./rtr-db export RPKI_RTR_CCR_DIR=./data export RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE=false export RPKI_RTR_STRICT_CCR_VALIDATION=false export RPKI_RTR_TCP_KEEPALIVE_SECS=60 export RPKI_RTR_WARN_INSECURE_TCP=true cargo run --bin rpki ``` #### TLS / mutual TLS ```sh export RPKI_RTR_ENABLE_TLS=true export RPKI_RTR_TCP_ADDR=0.0.0.0:323 export RPKI_RTR_TLS_ADDR=0.0.0.0:324 export RPKI_RTR_DB_PATH=./rtr-db export RPKI_RTR_CCR_DIR=./data export RPKI_RTR_PRUNE_DELTA_BY_SNAPSHOT_SIZE=false export RPKI_RTR_STRICT_CCR_VALIDATION=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 export RPKI_RTR_TCP_KEEPALIVE_SECS=60 export RPKI_RTR_WARN_INSECURE_TCP=true export RPKI_RTR_REQUIRE_TLS_SERVER_DNS_NAME_SAN=true cargo run --bin rpki ``` 示例脚本: - [`scripts/start-rtr-server-tcp.sh`](scripts/start-rtr-server-tcp.sh) - [`scripts/start-rtr-server-tls.sh`](scripts/start-rtr-server-tls.sh) - [`scripts/start-rtr-server.sh`](scripts/start-rtr-server.sh) ## CCR 输入说明 当前会从 `RPKI_RTR_CCR_DIR` 指向的目录中扫描最新 `.ccr` 文件,并从中提取: - `VRP` - `VAP / ASPA` 测试样例可参考: - [`data/20260324T000037Z-sng1.ccr`](data/20260324T000037Z-sng1.ccr) - [`data/20260324T000138Z-zur1.ccr`](data/20260324T000138Z-zur1.ccr) ## 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 ```