ZTXBAS 本番導入のセキュリティ強化ガイド
本番環境で重要となる ZTXBAS 固有のセキュリティ設定を説明します。Linux カーネルや SSH、ホストファイアウォール等の一般的な保護は対象外です。必要に応じて CIS Benchmarks と Ubuntu Server のセキュリティガイドを参照してください。
初期評価中であれば、まず 導入ガイド の docker run による動作確認を完了してください。
1. 脅威モデル
ZTXBAS は次の攻撃への対抗を目的としています。
- フィッシング: オリジンバインディングと端末上の表示によって、別オリジンへの承認転用を防ぎます。
- 通信上のリプレイ: API リクエストは HMAC-SHA256、時刻制限、ノンスで保護し、TLS で通信路を暗号化します。
- RP のなりすまし: アプリごとに HMAC シークレットを分離し、漏えい時の影響を当該アプリに限定します。
- 承認トークンの窃取: JWT は短寿命で ES256 署名され、
sub、aud、originに結び付いています。
保護対象外: 侵害された管理者端末・管理者認証情報、悪意ある RP、攻撃者が使用できるロック解除済みの登録端末、コンテナーの下位レイヤー(ホストカーネル、ハイパーバイザー、物理ディスク)です。管理コンソールへのアクセスは root 権限相当として扱ってください。
2. 実行前のコンテナーイメージ検証
各リリースイメージは cosign で署名されています。本番配備の前に署名を検証し、デプロイ定義では変更可能なタグよりもイミュータブルなダイジェストを指定してください。以下に公開鍵取得・検証・ダイジェスト指定例を示します。
署名鍵のローテーション: 鍵が変更される場合は旧鍵と新鍵を 1 リリースサイクル併記し、リリースページと SECURITY.md で通知する方針です。OIDC による keyless 署名は GitHub Actions 対応後の計画であり、現行の署名処理はリリース担当者の端末から実行されます。
# Get the public key once (pin both URLs; either is fine).
curl -sO https://corezt.com/ztxbas/cosign.pub
# Verify the tag you're about to run.
cosign verify --key cosign.pub ghcr.io/corezt/ztxbas:1.0.0
docker pull ghcr.io/corezt/ztxbas:1.0.0
docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/corezt/ztxbas:1.0.0
# ghcr.io/corezt/ztxbas@sha256:...
3. コンテナー実行環境の設定
配布の docker-compose.yml に含まれる制限を、他のオーケストレーターへ移す場合も維持してください。
cap_drop: ALL: 権限を付与しません。1024 番未満の特権ポートを直接使用せず、8443/8080/9443 等とリバースプロキシを使います。no-new-privileges: setuid 等を使う権限昇格を防ぎます。read_only: trueと/tmp用 tmpfs: 書き込み先をデータボリューム/var/lib/ztxbasと一時領域に限定します。- 非 root ユーザー: コンテナーは uid/gid 10001 で実行されます。データディレクトリは初期起動で
0700となります。アクセスエラーの対処として安易に root 所有へ変更しないでください。
リソース上限も設定してください。単一インスタンスで数百の同時チャレンジを扱える設計ですが、制限は異常動作時の被害抑止が目的であり、実運用のサイジングとは別です。
cap_drop: [ALL]
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:size=16m
user: "10001:10001" # non-root in the image
deploy:
resources:
limits:
memory: 512M
pids: 200
4. ネットワークの公開範囲
公開すべきポートは用途に応じて異なります。
| ポート | プロトコル | 内容 | インターネット公開 |
|---|---|---|---|
| 8443/tcp | HTTPS | RP 向け HMAC 認証 API | TLS 終端して公開 |
| 8080/tcp | HTTP(S) | 管理コンソール | 直接公開しない |
| 9443/udp | AES-GCM | モバイルアプリの通信 | ホストから直接公開 |
モバイル向け UDP 9443 は AES-256-GCM と端末に結び付いた ECDSA アテステーションを利用する独自プロトコルで、一般的な HTTP リバースプロキシを通りません。ホスト側に直接公開し、ファイアウォールで許可します。下記は ufw の設定例です。
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp comment 'ssh'
ufw allow 443/tcp comment 'caddy → ZTXBAS 8443'
ufw allow 9443/udp comment 'ZTXBAS mobile transport'
# 8080 is NOT opened — see section 6.
ufw enable
5. TLS
次の 3 方式から選択します。
- 推奨:Caddy リバースプロキシで TLS を終端。 ACME による証明書の取得・更新を自動化します。
docker-compose.caddy.ymlを利用できます。 - 直接 TLS 終端:
ZTXBAS_TLS_CERTとZTXBAS_TLS_KEYに PEM ファイルを指定します。ZTXBAS 自身に ACME や証明書のホットリロードはありません。証明書更新時はコンテナーの再起動が必要です。 - クラウドロードバランサーで TLS を終端: ロードバランサーが証明書を管理します。
X-Forwarded-ForおよびX-Forwarded-Protoの扱いはセクション 7 を確認してください。
TLS 1.2 以上を必須とし、TLS 1.3 を推奨します。ロードバランサーでは TLS 1.2 未満を明示的に無効化します。
6. 管理コンソールを安全に公開する
管理コンソールのポート 8080 は最も機密性の高い攻撃面です。安全性の高い順に以下を推奨します。
A. ループバック + SSH トンネル(最も安全): 既定の ZTXBAS_CONSOLE_LISTEN_ADDR=127.0.0.1:8080 を維持し、ローカルに SSH ポート転送します。
B. リバースプロキシ + Basic 認証 + IP 許可リスト: console.ztxbas.example.com などのホスト名を Caddy の背後で公開し、Basic 認証と社内/VPN の IP 制限を併用します。Basic 認証だけに依存しないでください。
C. リバースプロキシで mTLS: クライアント証明書と IP 許可リストを組み合わせます。
起動時の安全装置: TLS なしでループバック以外に管理コンソールをバインドすると、ZTXBAS は起動を拒否します。ZTXBAS_ALLOW_INSECURE_CONSOLE=1 を使えるのは、ホスト側の公開をループバック・プライベートアドレスに制限した場合、または認証ヘッダーや Cookie の扱いを確認した TLS 終端リバースプロキシの背後だけです。保護なしで 0.0.0.0 に公開する構成には使用しないでください。
ssh -L 8080:127.0.0.1:8080 ztxbas.example.com
# then open http://127.0.0.1:8080 in your browser
7. リバースプロキシの安全な設定
Caddy、nginx、ロードバランサーの背後に配置する場合は、信頼するプロキシの CIDR を明示的に設定します。
これにより管理者ログインに対する送信元 IP 単位の制限や監査ログに実クライアント IP を利用できます。信頼していない送信元からの X-Forwarded-For は無視されます。
さらにプロキシ側では外部から受け取った X-Forwarded-* を削除してから、自ら正しい値を設定してください。そうしないと外部クライアントによる IP 偽装を引き継ぐ可能性があります。Caddy 設定例を以下に示します。
ZTXBAS_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12
reverse_proxy ztxbas:8443 {
header_up -X-Forwarded-For
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
8. SMTP
ZTXBAS は SMTP が未設定の場合、起動しません。登録用 QR コードのメール送信がユーザーの初期設定に必須だからです。
必要な設定:ZTXBAS_SMTP_HOST、ZTXBAS_SMTP_PORT、ZTXBAS_SMTP_USER、ZTXBAS_SMTP_PASS、ZTXBAS_SMTP_FROM。
- SPF、DKIM、DMARC を構成した専用送信ドメインを推奨します。
- 取引メール向け SMTP リレー、または適切に構成した内部 Postfix 等を利用してください。
- 設定変更後はテスト登録メールの配送結果を受信トレイ、迷惑メール、メールログで確認します。
- 認証情報は Git に入る平文の compose ファイルではなく、Docker/Kubernetes の secrets に保存してください。
9. ディスク上の秘密情報
データボリュームには次の機密ファイルがあります。
| ファイル | 用途 | 権限 |
|---|---|---|
ztxbas.db(-wal / -shm を含む) | アプリ、ユーザー、オリジン、監査を格納する SQLite | 0600 |
jwt-signing.key | ES256 JWT の秘密署名鍵 | 0600 |
breakglass.txt(初回起動のみ) | 初期管理者パスワード | 0600、初回使用後は不要 |
権限エラーを回避するためにアクセス権を緩めないでください。バックアップでは SQLite 状態と JWT 鍵を一組として保護し、復元時に食い違いを生じさせないようにします。
初期の breakglass パスワードは初回管理者ログイン後に失効する使い捨ての認証情報です。アプリごとの HMAC シークレットも作成時に 1 回だけ表示されるため、RP 側のシークレットマネージャーへ保存し、ソース管理には含めません。
CLI でシークレットをローテーションできます。ただし現行版の切り替えは原子的で、旧シークレットを同時に受け入れる猶予期間はありません。並行して 2 つのシークレットを受け付けるローテーションは v1.1 の計画です。
docker exec ztxbas ztxbas app rotate <app-id>
10. 永続化とバックアップ
SQLite は WAL モードで動作し、アプリ、オリジン、ユーザー、監査、管理者、セッションの状態を保持します。
オンラインバックアップ: sqlite3 .backup でコンテナーを停止せず DB を保存します。JWT 署名鍵も一緒にバックアップしてください。
オフラインスナップショット: コンテナーを停止し、ボリュームをアーカイブして再起動します。簡単ですが数秒程度の停止が生じます。
バックアップは暗号化し、少なくとも四半期に 1 回は復元テストを行ってください。テスト環境で管理コンソールの起動、アプリ一覧、復元済み鍵による新しい JWT の検証まで確認します。
docker exec ztxbas sqlite3 /var/lib/ztxbas/ztxbas.db \
".backup /var/lib/ztxbas/backup.db"
docker cp ztxbas:/var/lib/ztxbas/backup.db ./ztxbas-$(date +%F).db
# Also grab the JWT signing key — see section 9.
docker cp ztxbas:/var/lib/ztxbas/jwt-signing.key ./jwt-$(date +%F).key
docker stop ztxbas
docker run --rm -v ztxbas-data:/data -v $PWD:/backup alpine \
tar czf /backup/ztxbas-$(date +%F).tgz -C /data .
docker start ztxbas
11. ログと監視
ZTXBAS は stdout に JSON 形式の構造化ログを出力します。journald、docker logs、Loki、SIEM 収集ツールで扱えます。
監視したい代表的なイベント:
hmac.verify.failの多発:時刻ずれ、漏えいやローテーション後のシークレット不一致。admin.login.failの多発:管理コンソールへの総当たり攻撃。challenge.expiredの多発:プッシュ通知の配送問題や UDP 9443 番への到達性問題。smtp.send.fail:登録メールの送信失敗。
GET /health は生存状態とバージョンのみを返し、SMTP 等の下流サービスは調べません。部分障害時に正常なインスタンスを誤って除外しないためです。外部連携の問題はログ監視で検出します。
{"time":"2026-01-15T10:04:11.812Z","level":"WARN","msg":"hmac.verify.fail",
"app_id":"app_a1b2c3d4e5","reason":"timestamp_skew","skew_sec":312}
12. レート制限
管理者ログインを含む公開 API へのアクセスは、可能な限りリバースプロキシや WAF で制限してください。元の運用ガイドでは、公開エンドポイントをアプリごとにバースト許容付きで、管理者エンドポイントをクライアント IP およびユーザー名単位で厳しく制限する設計が説明されています。
バージョンに関する注意: API 概要では v1 の組み込みレート制限は強制されないと説明されています。実際の配布バージョンでの実装状況を確認し、組み込み制限があるものと想定せず、エッジのリバースプロキシや WAF で必要な制限を適用してください。
13. アップグレード
- リリースノートを確認してください。DB マイグレーションは追加型で、古いバイナリへの単純なダウングレードはサポートされません。
- 信頼済みの
cosign.pubで新リリースの署名を検証します。 - 新しいダイジェストを pull し、データボリュームをバックアップします。
docker compose up -dで起動します。起動時に必要なマイグレーションが適用されます。- ログと
/healthの新しいversionを確認します。
ロールバックが必要な場合は停止してアップグレード前のバックアップに復元したうえで以前のイメージを実行します。新 DB のまま古いバイナリを実行しないでください。
14. インシデント対応
アプリの HMAC シークレット漏えい: シークレットをローテーションし、RP 側に新しい値を展開します。旧シークレットで作られた進行中のチャレンジは継続しますが、新しい API 呼び出しは旧シークレットで失敗します。
JWT 署名鍵漏えい: v1 では手動で鍵をローテーションし、新しい鍵が起動時に生成されます。JWKS は新しい kid の鍵を配布します。旧鍵で署名された JWT は検証できなくなるため、直近 5 分のユーザー認証に失敗が発生する可能性があります。RP 側で既存セッションを無効化するなど、漏えいを前提とした対応が必要です。鍵を重複公開する猶予期間は v1.1 の計画です。
breakglass パスワード漏えい: 初回使用前なら ztxbas admin reset-password --user admin で再発行し、既存セッションを失効させます。
管理者セッション侵害の疑い: コンソールの Account → Sessions → Revoke all other sessions で他のセッションを無効化し、管理者パスワードを変更します。監査ログでセッション ID と送信元 IP を確認します。
スマートフォンの紛失・侵害: ユーザー登録を解除して端末鍵を無効にし、アカウント回復手順に従って新しい端末で再登録させます。
docker exec ztxbas ztxbas app rotate <app-id>
docker stop ztxbas
docker exec -u root ztxbas rm /var/lib/ztxbas/jwt-signing.key # or delete via the host mount
docker start ztxbas
# From the RP side, using an SDK — or from the console under Users.
curl -X DELETE https://ztxbas.example.com/v1/users/<user-id> ...
15. エアギャップ環境
ZTXBAS は外部クラウドへのコールバック、ライセンスサーバー、強制テレメトリー、強制更新がないため、分離環境でも運用できます。次の準備が必要です。
- イメージ配布: cosign で検証した
ghcr.io/corezt/ztxbasを内部レジストリへミラーします。 - TLS: インターネット上の ACME は利用できません。内部 CA の証明書を
ZTXBAS_TLS_CERT/ZTXBAS_TLS_KEYに設定します。 - SMTP: 内部 Postfix/Exchange 等を使用します。
- 時刻: 内部 NTP を参照する chrony 等で同期します。HMAC の時刻ずれ制限があるため重要です。
- SDK: Go の GOPROXY や Node・Python の依存パッケージを内部配布できるようミラー・ベンダリングします。
16. 意図的に対象外としている機能
以下は独立型 ZTXBAS ではなく、より広いアクセス基盤である ZTXGate が対象とする機能です。両製品でモバイル認証アプリは共通で、ZTXGate 内のライセンスされた ZTXBAS 機能は別サーバーではなくライブラリとして統合されます。
- 管理者向けの SSO/SAML/OIDC
- 単一管理者を超える管理 RBAC
- SCIM ユーザープロビジョニング
- MDM による端末状態の評価
- stdout ログ転送以上の SIEM 連携
- マルチテナント分離
- ZTXGate の WireGuard ベースのクライアントアクセスによる SSH/RDP 等を含むネットワークアクセス制御、および対応 Web アプリへのクライアントレス HTTP/HTTPS アクセス
これらを独立型 ZTXBAS に継ぎ足すより、必要に応じて ZTXGate を採用することを推奨します。