unmask

docs

JA4 取得, LB 設定, 対応 distro, よくある質問.

FAQ

JA4 ってどの構成で取れるの? forward-auth だと取れない?
JA4 を取得できるかどうかは TLS 終端の位置で決まります。nginx + unmask-plugin-nginx (native mode) なら取得でき、plugin 無し (forward-auth mode) では取得できません。前段に LB / CDN がある場合は header forward で取得できます。構成ごとの図解は JA4 取得方法 をご覧ください。
forward-auth で daemon が落ちたときの挙動は? fail-closed にできる?
forward-auth は daemon が落ちると既定で完全に fail-open します。保護パスはゲート (auth_request) が素通しし、challenge 途中の訪問者も / へ 302 で戻ってそのままバックエンドへ流れます (native mode が元リクエストを replay するのと同じ結果)。サイトは落ちません。

逆に fail-closed にしたい場合 — daemon down 時に 503 を返して上位 LB の health check に落とし、その node を drain させる、または元リクエストを自前のバックエンドへ流す — は、@unmask_admin_downinclude より前に定義します (nginx は named location の先に定義された方を採用するため、include の後に書くと黙って無視されます):
# (a) 503 で上位 LB に drain させる:
location @unmask_admin_down { add_header Retry-After "10" always; return 503; }
# (b) 元リクエストを自前バックエンドへ流す:
location @unmask_admin_down {
    proxy_pass http://your-upstream;          # static 配信なら: try_files $uri $uri/index.html =404;
    proxy_set_header Host $host;
}
include /etc/unmask/forward-auth/server.inc;
JA4 verdict が空 ("-") のイベントがあるけど大丈夫?
問題ありません。これは upstream (nginx native module / GCP LB など) が JA4 を取得できなかったリクエスト (TLS resumption や一部の特殊な handshake) で発生します。unmask 側が原因ではありません。
stealth 列が赤く表示される。問題ない?
「JS 検出 (flags) はすべてクリアなのに JA4 では bot 判定」というのは、最新のヘッドレス bot が来ている兆候です。ただしブロック判定では challenge が強制されるので、ダッシュボードの「JA4 bot/suspect 判定 × CAPTCHA 通過」カードが 0 のままであれば、実際には何も通過していません。
既定ではどの訪問者が challenge 対象になる?
既定では、bypass IP / bypass path / 検索 bot のいずれにも該当しない訪問者は全て challenge 対象です (no-match 経路の KnownBrowserAction / UnknownUAAction は、未設定時はいずれも pow_only に解決されます)。PoW は自動で実行され操作も不要なため、通常の利用者が感じる負荷はごくわずかです。検索 bot は UA preset と公式 IP range の bypass list が OR 条件で適用されて素通しするので、SEO 事故は起きません。「普通のブラウザはそのまま通し、curl / scraper だけ challenge する」といった軽めの運用にしたい場合は、settings → 動作モード tab で KnownBrowserActionpass に設定します。
前段に CDN / リバースプロキシがある。正しいクライアント IP で判定される?
IP ベースの判定 (BAN / rate limit / 国別フィルタ / ホワイトリスト IP) は nginx が見ているクライアント IP を使います。前段に CDN / proxy / LB があると既定ではその前段の IP になるため、nginx 側で set_real_ip_from (信頼する前段の範囲) と real_ip_header (CDN なら CF-Connecting-IP、一般には X-Forwarded-For など) を設定し、転送ヘッダから実 IP を復元してください。これは unmask 固有ではなく nginx 標準の real_ip 機能です。

復元しないと、すべてのアクセスが前段の同一 IP に見えて rate limit や国別判定が意図どおり効きません。JA4 の取得可否はこれとは別で TLS 終端の位置で決まります (前段で TLS を終端する構成では header forward が必要)。詳しくは JA4 取得方法ロードバランサ構成 を参照してください。
正規のユーザーが誤って challenge / ブロックされた。どう対処する?
まず既定の動作は即ブロックではなく PoW / CAPTCHA なので、本物のユーザーは challenge を解けばそのまま通れます (PoW は自動、CAPTCHA も 1 回)。特定の相手や経路を確実に素通しさせたい場合は、狙い撃ちで緩めるのが安全です:
・信頼できる IP (社内 / 監視 / LB の出口) → settings → ホワイトリスト IP
・特定のパス (公開 API など) → settings → ホワイトパス
・特定の JA4 を bot と誤判定している → settings → JA4 verdict tab でその verdict の action を observe / allow に
・全体的に厳しすぎる → 動作モード tab で KnownBrowserActionpass に (普通のブラウザは素通し、curl / scraper だけ challenge)
どのアクセスが何で止まったかは hunt 画面で JA4 / fingerprint / 理由を確認できます。原因を見てから、該当する分だけ緩めてください。
unmask は WAF ですか? 脆弱性スキャンや攻撃を防げますか?
unmask は WAF ではなく bot management ゲートウェイです。WAF が「リクエストの中身 (SQLi / XSS などの payload)」を検査するのに対し、unmask は「誰がアクセスしてきたか」を JA4 / PoW / CAPTCHA / 行動分析で判定し、自動化されたクライアントを入口で止めます。

セキュリティ上の効果は副次的だが実在します。wp-login.php.env、既知の CVE path を機械的に探る脆弱性スキャナや、総当たり・credential stuffing の大半は JS を実行しない非ブラウザのクライアントなので、PoW / CAPTCHA を課す入口で弾かれ、攻撃の試行回数そのものが減ります (その結果、突破や情報漏えいのリスクが下がります)。AI によって脆弱性の探索や攻撃が自動化・高速化していく時代でも、「自動化された大量アクセス」にコストを課し続けられるのが強みです。

ただし unmask は脆弱性そのものを塞ぐものではありません。payload の検査も行いません。チャレンジを突破した本物のブラウザからの単発の攻撃や、既知 CVE のパッチ適用は、別のレイヤーの責務です。unmask は多層防御 (defense in depth) の一層として、WAF やパッチ運用と併用する位置づけです。
PoW のアルゴリズムは?
SHA-256 hashcash です (challenge.js に内蔵した pure-JS の SHA-256 実装で、先頭 N bit がゼロになる nonce を探します)。難易度は settings → Challenge tab で leading-zero の bit 数を調整できます (既定 18 bit、通常 1 秒前後)。
SQLite から MariaDB へ (またはその逆へ) 移行したい (DB 接続先を変えたい)
管理画面の再設定ウィザード、または config.yml の直接編集で切り替えられます。どちらの方向 (SQLite → MariaDB でも、MariaDB → SQLite でも) も手順は同じです。ただし過去の event / ban / user などの履歴は切り替え先の DB に引き継がれません (元の DB はそのまま残ります。切り替え先に既存の unmask データがあればそれを利用し、空なら新しいスキーマを作成します)。

方法 A — 再設定ウィザード (簡単): superadmin でログインして /admin/setup/ を開くと再設定モードになります。DB ステップで切り替え先の driver (SQLite / MariaDB) を選び、接続情報 (MariaDB は host・DB・user、SQLite はファイルパス) を入力 → 接続先が空なら最初の管理者を作成 (既に管理者がいれば「スキップ」で流用) → 確認 → 適用。DB を切り替えると background worker を新しい DB に張り直すため daemon が自動で再起動します (手動操作は不要)。

方法 B — CLI で手動: (1) admin 停止 (2) config.ymldb.driver を切り替え先 (mariadb / sqlite) に変更して接続情報を記入 (MariaDB は事前に DB と接続用ユーザーを作成、SQLite は sqlite_path を指定) (3) unmask doctor で接続を検証 (不足テーブルも報告) (4) unmask migrate で schema 投入 (5) unmask user create admin -role superadmin で管理者作成 (6) admin 起動。
統計タブの「強制 CAPTCHA 判定 (理由別)」カードの reason の意味は?
none=通常の PoW (強制なし) / ja4_bot=JA4 verdict が bot / honeypot=罠を踏んだ / banned=BAN list にヒット (共有バン・手動・honeypot 由来を含む。source 別の内訳は Community Bans / BAN 管理ページで確認できます) / protected=保護パス mode / rate_limit=rate limit 超過 / test=debug 経路。特定の reason に偏っていれば、その原因を狙い撃ちで設定を見直せます。
「(SSE 接続エラー)」が頻発する
多くは、前段の LB / proxy が idle connection を切ることで起こります (例:GCP LB の backend timeout は既定で 30 秒)。heartbeat は 20 秒間隔で送っています。「(再接続中)」と表示されている間は、EventSource が自動でリトライしています。完全に closed になったときだけ「接続エラー」と表示します。
Prometheus メトリクスは出せる?
はい — admin daemon が /unmask/metrics で Prometheus 形式の endpoint を出します。phase / verdict 別の challenge 量、behavioral score の histogram、DB latency など。既定は loopback のみで、リモートから取るなら scraper の IP / CIDR を metrics_allow_from(設定 → Network)に足します。死活監視用に、認証なしで ok を返す /unmask/healthz もあります。詳しくは 監視
admin_allow_from を空にすると?
「allow all」 (全 IP を許可) として扱われ、認証のみで防御します。空でなければ、handler 層と nginx render の両方で IP 制限が効きます。
サードパーティ CAPTCHA に変えたら管理画面に入れなくなった
保護パスのプリセット unmask itself が有効だと /unmask/admin/ は CAPTCHA で覆われます。Turnstile / hCaptcha / reCAPTCHA はいずれも許可ドメインの登録が必須なので、管理画面にアクセスしているホスト名をその CAPTCHA の許可ドメインに登録していないと CAPTCHA ボタンが表示されず入室できなくなります (特にサーバ名で直接 admin を開く運用や multi-host 構成)。復旧は /etc/unmask/config.ymlchallenge.default.captcha.providerbuiltin に変更して unmask を再起動してください。unmask 標準 CAPTCHA は全 host で動くので管理画面に入れます。multi-host 環境では builtin が安全な既定です。
IP 位置情報 DB (mmdb) を入れたい / 最新化したい
一番簡単なのは sudo unmask install-ipgeo です。登録不要の DB-IP Lite (CC BY 4.0) を自動でダウンロードし、/var/lib/unmask/ipgeo/ に配置します。cron に登録しておけば月次更新も自動で行えます。手動で行いたい場合は、settings → 国別フィルタ tab の「📥 dl / 更新」ボタンからでも取得できます。mmdb は hot-reload されるので、admin の再起動は不要です。
install 後にユーザーを作成し忘れた
sudo unmask user create <username> -role superadmin -password <pw> で作成できます。または /admin/setup/ のウィザードからでも作成できます。
パスワードを忘れた
sudo unmask user reset-password <username> -password <new> で再設定できます。
CentOS 6 / 7 で feed 同期が certificate signed by unknown authority で失敗する
EOL distro の CA bundle が古く、unmask の feed 同期 / auto-update の TLS 検証で Let's Encrypt の現行 root を持っていないために起こります (unmask のバグではなく、host 側の信頼ストアが原因です。unmask は system の信頼ストアに従う方針です)。sudo yum update ca-certificates を実行するか、ISRG Root X1 / X2 を信頼ストアに追加して unmask を再起動してください。同期できない間も、同梱の snapshot で検索 bot の救済は継続します。