路由与策略
规格文件是 Server Core 的唯一输入方式:绝对路径、常规文件、非符号链接、0600 权限。绝不要把 URL、密码或 Key 放进命令行参数。
01 HTTP 路由规格 releases.json ⧉ {
"name": "Release mirror",
"alias": "releases",
"base_url": "https://upstream.example/releases/",
"authorization": "Bearer upstream-secret",
"methods": ["GET", "HEAD"],
"query_keys": ["version", "platform"],
"egress": "Auto"
}methods:允许的 HTTP 方法白名单。query_keys:允许透传的查询参数;未列出的一律拒绝。egress:Direct / Proxy / Auto。
02 SSH 路由规格 build.json ⧉ {
"name": "Build server",
"alias": "build",
"local_username": "build",
"upstream": "build.example:22",
"username": "deploy",
"password": "upstream-password",
"host_key": "ssh-ed25519 AAAA...",
"allowed_command": "deploy --release",
"allow_all_commands": false,
"allow_interactive_shell": false,
"allow_sftp": false,
"record_commands": true,
"keyword_replacements": [
{ "from": "%%TOKEN%%", "to": "protected-value", "enabled": true }
],
"egress": "Auto"
}allowed_command:完整字符串精确匹配(默认模式)。allow_all_commands:需要 CLI 的 --allow-all-confirmed 或桌面高风险确认。allow_interactive_shell:要求同时开启 all-commands;开启后转发 PTY。allow_sftp:为现代 scp/SFTP 客户端启用(高风险)。keyword_replacements:命令策略通过后才应用替换,防止把敏感值写死在命令里。
03 LLM 路由规格 coding.json ⧉ {
"name": "Coding",
"alias": "coding",
"base_url": "https://api.example.com/v1",
"authorization": "upstream-key",
"provider": "openai",
"models": ["model-a"],
"max_output_tokens": 4096,
"requests_per_minute": 60,
"max_concurrent": 4,
"track_usage": true,
"keyword_replacements": [
{"from": "mypasswd123", "to": "user.passwd.feishu", "enabled": true}
]
}provider:openai(/v1/responses、/v1/chat/completions)或 anthropic(/v1/messages)。models:白名单,请求中模型必须匹配。max_output_tokens:请求不能超过该上限,缺失时自动填充。requests_per_minute / max_concurrent:频率与并发上限。track_usage:只记录数字统计。keyword_replacements:双向内容映射;请求时真实值替换为字段键,响应(含流式)再替换回来,字段键与真实值必须 JSON 安全。
04 创建与启用流程 SSH 路由创建后默认处于停用状态,必须:探测 Host Key → 写入规格 → 创建 → 健康检查 → 启用。HTTP 与 LLM 路由同样建议按此顺序验证。
标准流程 ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes create <http|ssh|llm> --file /path/route.json
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes health <alias>
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes enable <alias>
05 Host Key 探测 探测(不执行认证) ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
ssh probe --address ssh.example:22 --egress Auto探测只读取 Host Key 并在认证前停止。请通过独立渠道(如服务器控制台)核对指纹后再写入规格。
Routes and policies
Spec files are the only input path for Server Core: absolute path, regular file, non-symlink, 0600. Never put URLs, passwords, or keys in command arguments.
01 HTTP route spec releases.json ⧉ {
"name": "Release mirror",
"alias": "releases",
"base_url": "https://upstream.example/releases/",
"authorization": "Bearer upstream-secret",
"methods": ["GET", "HEAD"],
"query_keys": ["version", "platform"],
"egress": "Auto"
}methods: allowed HTTP method allowlist.query_keys: query parameters allowed to pass through; anything else is rejected.egress: Direct / Proxy / Auto.
02 SSH route spec build.json ⧉ {
"name": "Build server",
"alias": "build",
"local_username": "build",
"upstream": "build.example:22",
"username": "deploy",
"password": "upstream-password",
"host_key": "ssh-ed25519 AAAA...",
"allowed_command": "deploy --release",
"allow_all_commands": false,
"allow_interactive_shell": false,
"allow_sftp": false,
"record_commands": true,
"keyword_replacements": [
{ "from": "%%TOKEN%%", "to": "protected-value", "enabled": true }
],
"egress": "Auto"
}allowed_command: exact full-string match (default mode).allow_all_commands: requires CLI --allow-all-confirmed or an in-app high-risk acknowledgement.allow_interactive_shell: requires all-commands; forwards PTY when enabled.allow_sftp: enables modern scp/SFTP clients (high risk).keyword_replacements: applied only after the command policy passes.
03 LLM route spec coding.json ⧉ {
"name": "Coding",
"alias": "coding",
"base_url": "https://api.example.com/v1",
"authorization": "upstream-key",
"provider": "openai",
"models": ["model-a"],
"max_output_tokens": 4096,
"requests_per_minute": 60,
"max_concurrent": 4,
"track_usage": true,
"keyword_replacements": [
{"from": "mypasswd123", "to": "user.passwd.feishu", "enabled": true}
]
}provider: openai (/v1/responses, /v1/chat/completions) or anthropic (/v1/messages).models: allowlist; the request model must match.max_output_tokens: requests cannot exceed it; defaults are injected when absent.requests_per_minute / max_concurrent: rate and concurrency caps.track_usage: numbers only.keyword_replacements: bidirectional content mapping; real values are masked to field keys on requests and restored on responses, including streaming. Keys and values must be JSON-safe.
04 Create and enable flow SSH routes are created disabled by default and must follow: probe host key → write spec → create → health check → enable. HTTP and LLM routes should be verified in the same order.
Standard flow ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes create <http|ssh|llm> --file /path/route.json
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes health <alias>
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes enable <alias>
05 Host-key probing Probe (stops before authentication) ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
ssh probe --address ssh.example:22 --egress AutoThe probe reads only the host key and stops before authentication. Confirm the fingerprint over an independent channel before writing the spec.
ルートとポリシー
仕様ファイルは Server Core の唯一の入力経路です:絶対パス、通常ファイル、シンボリックリンク禁止、0600。URL・パスワード・キーをコマンドライン引数に入れないでください。
01 HTTP ルート仕様 releases.json ⧉ {
"name": "Release mirror",
"alias": "releases",
"base_url": "https://upstream.example/releases/",
"authorization": "Bearer upstream-secret",
"methods": ["GET", "HEAD"],
"query_keys": ["version", "platform"],
"egress": "Auto"
}methods:許可する HTTP メソッドの許可リスト。query_keys:透過を許可するクエリパラメータ。それ以外は拒否。egress:Direct / Proxy / Auto。
02 SSH ルート仕様 build.json ⧉ {
"name": "Build server",
"alias": "build",
"local_username": "build",
"upstream": "build.example:22",
"username": "deploy",
"password": "upstream-password",
"host_key": "ssh-ed25519 AAAA...",
"allowed_command": "deploy --release",
"allow_all_commands": false,
"allow_interactive_shell": false,
"allow_sftp": false,
"record_commands": true,
"keyword_replacements": [
{ "from": "%%TOKEN%%", "to": "protected-value", "enabled": true }
],
"egress": "Auto"
}allowed_command:完全一致(既定モード)。allow_all_commands:CLI の --allow-all-confirmed またはアプリ内の高リスク確認が必要。allow_interactive_shell:all-commands と併用が必須。有効時のみ PTY 転送。allow_sftp:最新 scp/SFTP 向け(高リスク)。keyword_replacements:コマンドポリシー通過後にのみ適用。
03 LLM ルート仕様 coding.json ⧉ {
"name": "Coding",
"alias": "coding",
"base_url": "https://api.example.com/v1",
"authorization": "upstream-key",
"provider": "openai",
"models": ["model-a"],
"max_output_tokens": 4096,
"requests_per_minute": 60,
"max_concurrent": 4,
"track_usage": true,
"keyword_replacements": [
{"from": "mypasswd123", "to": "user.passwd.feishu", "enabled": true}
]
}provider:openai(/v1/responses、/v1/chat/completions)または anthropic(/v1/messages)。models:許可リスト。リクエストのモデルは一致必須。max_output_tokens:上限を超えるリクエストは拒否。未指定時は自動で補完。requests_per_minute / max_concurrent:レート・並列上限。track_usage:数値のみ記録。keyword_replacements:双方向コンテンツマッピング。リクエストでは実値をフィールドキーへ、レスポンス(ストリーミング含む)ではフィールドキーを実値へ戻します。キーと値は JSON セーフである必要があります。
04 作成と有効化の流れ SSH ルートは既定で無効状態で作成されます。Host Key プローブ → 仕様作成 → create → health → enable の順で進めてください。
標準フロー ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes create <http|ssh|llm> --file /path/route.json
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes health <alias>
airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
routes enable <alias>
05 Host Key プローブ プローブ(認証前に停止) ⧉ airlock --data-dir /var/lib/airlock --token-file /etc/airlock/control.token \
ssh probe --address ssh.example:22 --egress Autoプローブは Host Key を読み取るだけで認証前に停止します。独立した経路でフィンガープリントを確認してから仕様に書き込みます。