FAQ

これは Arcivéo Monitor のインストール・設定・運用に関するガイドです。 各セクションは、全体概要、ダッシュボードの導入、セキュリティツールの接続、 組み込みモジュール、診断の順にまとめられています。コマンドは右側のボタンでコピーできます。

はじめに

01. パネルのインストール — 方法を選択

パネルのインストール手順は、ステップごとの個別ページにまとめています。方法を選択してください:

迷ったら自動を選んでください。このガイドはSSL、ツール、cron、診断に関する唯一の情報源であり続けます。インストールページは重複なくこのガイドの各セクションを参照します。

概要

02. Arcivéo Monitor とは

Arcivéo Monitor はサーバーセキュリティのダッシュボードです。導入済みのツール(Fail2ban、UFW、Lynis、ModSecurity、AIDE、ClamAV、Auditd、CrowdSec、Suricata、Falco など)からデータを収集し、ダッシュボード・攻撃マップ・各ツールの詳細ページを備えた統一インターフェースで表示します。

Monitor は能動的な防御手段ではなく、攻撃自体をブロックすることはありません。稼働中のツールから情報を集約し、見やすい形で提示することが役割です。

03. サーバー上でのモニターの動作

モニターはローカルでのみ動作します — 監視対象と同じサーバーにインストールする必要があります。SSH やリモート API は使用しません。

すべてのコマンド(fail2ban-clientufw statusipset list など)は、ダッシュボードが Web サーバーのユーザー(通常は www-data、ホスティングパネルではサイトのアカウント)として、限定された権限sudo で実行します — 特定のユーティリティのみに限られ、root 全体へのアクセスはありません。結果は解析されてブラウザーに表示されます。

複数のサーバーには、それぞれ固有のドメインで個別にモニターをインストールしてください。

04. セキュリティスコアの算出方法

スコアは満点から始まり、検出された問題ごとに減点されます:

  • UFWが無効 — −30
  • Fail2banが未起動(有効なjailなし) — −25
  • WebAuthnキーがない — −15
  • Lynis hardening index < 60 — −20;60〜79 — −10
  • IPset ipsumが未読み込み — −10
  • ClamAVが脅威を検出 — −20
  • AIDEがファイル変更を検出 — −15
  • SSL失効 — −30、期限まで14日未満 — −15、30日未満 — −5
  • CrowdSecがインストール済みだが未起動 — −5
  • Suricataがインストール済みだが未起動 — −5
  • DB/キャッシュ(MySQL、PostgreSQL、Redis…)が外部からアクセス可能 — −10
  • SSHでのrootログインが許可(PermitRootLogin yes) — −20
  • セキュリティ更新が未適用 — −5

結果: 80以上 = 保護済み、60〜79 = 要注意、<60 = 危険。

ClamAV、AIDE、CrowdSec、Suricataの減点はツールがインストールされている場合のみ適用されます。データベースが初期化されていないLynisとAIDEは「データなし」と表示され、スコアには影響しません。本日の攻撃件数はダッシュボードに表示されますが、セキュリティスコアには影響しません。

設定とライセンス

05. WebAuthn — 2要素認証

WebAuthn はハードウェアキーによるパスワード不要の認証規格です。YubiKey、Touch ID、Face ID、Windows Hello、Passkey に対応します。

パスワードでのログイン後、登録済みのキーによる確認が求められます。パスワードが漏洩しても、物理キーや生体認証がなければログインできません。

設定するには、サイドメニューの WebAuthn キー を開き、「キーを登録」をクリックします。キーは一度に2つ登録してください。唯一のキーを紛失または破損すると、そのキーでのパネルへのログインができなくなります。

WebAuthn は HTTPS 経由でのみ動作します。HTTP 接続ではキーの登録とログインは利用できません。

06. 通知: Telegram とメール

ダッシュボードはセキュリティレポートを Telegram とメールに送信できます(ボタン操作またはスケジュール実行)。設定は「設定」セクションで行います。

Telegram。ボットトークンchat id が必要です:

  1. Telegram で @BotFather/newbot に送信し、123456:ABC... の形式のトークンを取得します。
  2. 新しいボットに任意のメッセージを送ります(ボットが返信できるようにするため)。
  3. 自分の chat id を確認します: ボット @userinfobot にメッセージを送るか、https://api.telegram.org/bot<TOKEN>/getUpdates を開いて "chat":{"id":...} を探します。
  4. トークンと chat id を「設定」→ Telegram に入力し、「保存してテスト送信」をクリックします。

メール。「設定」→ メールで選べる方法は 2 つ:

  • SMTP — メールボックスのホスト、ポート(465/SSL または 587/TLS)、ログインとパスワード;
  • Resend — 最新の API: API キー(re_...)と確認済みの送信元ドメインを指定します。
「テスト送信」ボタンでチャンネルをすぐに確認できます。自動レポートのスケジュールは cron 経由です(「すべての cron ジョブ」セクション): cron が送信を呼び出し、チャンネルは設定から取得されます。

レポートのステータス:「注意」または「OK」。ヘッダーが「注意」になるのは、実際の問題または対応待ちがある場合のみです: ClamAV による脅威の検出、AIDE でのファイル変更、Falco の重大イベント(直近 24 時間の Emergency/Alert/Critical)、Monit で停止したサービス、再起動が必要、SSL の期限切れ間近(14 日以内)、またはセキュリティ更新の待機。バックグラウンドノイズ — ボットによる SSH の総当たり、fail2ban で BAN された IP、Suricata のアラート、Lynis の警告、すでに撃退済みの ModSecurity リクエスト — はステータスを上げません。したがってレポート内のこれらの数値だけで「注意」を意味することはありません。

07. ライセンス — 入力と有効化

詳細な監視モジュール(Lynis、UFW、ModSecurity、攻撃マップ、AIDE、ClamAV など)は、有効なライセンスがある場合に利用できます。ライセンスがなくてもダッシュボード、設定、アカウントは動作しますが、モジュールには「ライセンスが必要です」というカードが表示されます。

アカウントで購入すると、ARCIVEO-XXXX-XXXX-XXXX-XXXX の形式の有効化コードが発行されます。これをお使いのパネルのドメインに対して「有効化」する必要があります。これによりコードが署名済みのライセンスファイル([license] ブロック)に変換され、それをパネルに貼り付けます。

有効化の手順(3ステップ):

  1. 有効化コードを取得します。アカウント my.arciveo.com →「ライセンス」/「ライセンス有効化」セクションで ARCIVEO-… コードをコピーします。
  2. コードを自分のドメインで有効化します。同じくアカウント内で「ライセンス有効化」を開き、有効化コード、メールアドレス、パネルのドメイン(モニターが開くアドレス、例:monitor.example.com)を入力します。有効化を押すと、システムがそのドメインに紐付いたライセンスファイルを生成し、「コピー」ボタン付きのフィールドに表示します。
  3. キーをパネルに貼り付けます。ライセンスのテキスト全体をコピー →パネルで「設定」→「ライセンス」ブロックを開き、貼り付けて「保存」を押します。モジュールはすぐにロック解除されます。

パネルはキーを暗号的に検証します:署名、ドメインへの紐付け、有効期限を確認します。

有効化時のドメインは、パネルのアドレスと完全に一致している必要があります。config.phpAPP_URL 定数から取得し、ホスト名のみを入力してください。https://www プレフィックスは付けません。有効化は一度限りです:コードは入力したドメイン用のライセンスに変換され、再度有効化することはできません。ドメインを間違えるとキーがお使いのパネルに合わず、コードは消費されてしまいます。そのため、ドメインは慎重に入力してください。
有効期限が切れたりドメインが変わったりすると、パネルのヘッダーに警告が表示されます。ライセンスはドメインに永久に紐付けられ、別のドメインには移せません。新しい期間や新しいドメインには新しいキーが必要です(アカウントで購入し、一度限り有効化します)。

08. config.php ファイル — パネルの全設定

パネルの主要な設定はすべて、ルート(public/ フォルダと同じ階層)にある単一の config.php ファイルに、通常の define() 定数として記述されています。ファイルはインストール時に作成され、手動で編集する機会はまれです。主にドメイン変更、移行、別のデータベースへの接続時に限られます。編集後は必ず PHP-FPM を再起動してください(そうしないと OPcache により変更が反映されません)。

ハイライトされた箇所にご自身の値を入力し、それ以外はそのままにしてください。

// --- データベース --- define('DB_HOST', 'localhost'); // そのまま define('DB_NAME', 'db_name'); // DB作成時に指定した名前 define('DB_USER', 'user'); // DB作成時に指定したユーザー define('DB_PASS', 'db_password'); // DB作成時に指定したパスワード define('DB_CHARSET', 'utf8mb4'); // そのまま // --- アプリケーション --- define('APP_URL', 'https://monitor.example.com'); // パネルのアドレス、末尾のスラッシュなし define('TIMEZONE', 'Asia/Tokyo'); // タイムゾーン // --- セッション時間 --- define('SESSION_LIFETIME', 28800); // 再ログインまでのアイドル時間、秒(28800 = 8時間)

データベース。 MySQL/MariaDB への接続情報です。

  • DB_HOST — DBMS のホスト。ほぼ常に localhost
  • DB_NAME — パネルのデータベース名;
  • DB_USER — DB ユーザー(自分のデータベースにのみアクセス可);
  • DB_PASS — このユーザーのパスワード;
  • DB_CHARSET — 接続の文字コード。utf8mb4 のままにしてください。

アプリケーション。

  • APP_URL — パネルの完全なアドレス(例:https://monitor.example.com)。ライセンスを有効化したドメインと一致している必要があります。一致しない場合はキーが拒否されます(「ライセンス」の項を参照);
  • TIMEZONEPHP のタイムゾーン:パネルが日時を表示する方法にのみ影響します。cron ジョブの実行時刻には影響しません。そちらはシステムのタイムゾーンが適用されます(「すべての cron ジョブ」を参照)。

セッション時間。 SESSION_LIFETIME — セッションのアイドルタイムアウト(秒単位。スライド式:操作するたびに更新)。デフォルトは 28800 = 8時間で、この時間操作がないとパネルは再ログインを求めます。例:3600 = 1時間、86400 = 1日。

エラーのログ記録。 エラーが訪問者に表示されることはなく、logs/php_errors.log に記録されます。「アプリケーションログ」ページで確認できます。これらの行(display_errors=0log_errors=1error_log のパス)は通常変更する必要はありません。設定はファイル内に直接記述されており、php.ini に依存しません。

config.php は機密ファイルです。 DB のパスワードが含まれています。ファイルはパネルのルートpublic/ と同じ階層)にあり、このパネルの Web ルート(DocumentRoot)は public/ ではなくパネルのルートそのものです。ファイル自体が「漏洩」することはありません。ルートの .htaccess にこのファイルへの明示的な拒否設定(Require all denied)があり、サーバーは 403 を返します。このルールがなくてもソースは漏洩しません。これは PHP であり、サーバーはテキストとして返すのではなく実行するからです。念のため:公開リポジトリに置いたり、実際のパスワードを含めたままサポートに送ったりしないでください。ファイルの権限は 640 です。
移行やアクセス復旧の際、このファイルが接続情報の主要な取得元となります。DB 名、ユーザー、パスワードはここから取得されます(「パネルの更新と移行」および「アクセスの復旧」の項を参照)。

セキュリティツール

09. UFW ファイアウォール

UFW(Uncomplicated Firewall)は nftables/iptables への簡単なインターフェイスです。明示的に許可したポート以外の受信ポートをすべて閉じます。「UFW ファイアウォール」ページでは状態とルールを確認できます。

sudo apt install ufw # SSH(有効化する前に必ず!)とウェブを許可 sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # 外部からのDBアクセスを遮断(ローカルのみ許可) sudo ufw deny 3306 # 有効化して確認 sudo ufw enable sudo ufw status verbose
ufw enable の前に必ず SSH を許可してください(ufw allow OpenSSH)。さもないとサーバーへのアクセスを失います。
ダッシュボードの「外部への露出」は UFW を考慮します。deny ルールで閉じたポートは外部からアクセス可能とは見なされません。
Skipping adding existing rule はエラーではありません。 同一のルールがすでに存在するため重複して追加しないことを UFW が知らせているだけです。自動設定を再実行した場合(冪等です)、これは通常のメッセージなので対応は不要です。

10. Fail2ban のインストール

ログイン失敗の回数が上限を超えたIPを自動的にブロックします。SSH、nginx、Apache などのサービスのログを解析します。

sudo apt install fail2ban sudo systemctl enable --now fail2ban # ステータスを確認: sudo fail2ban-client status
実運用向けの設定(多数の jail と ipsum による自動バンを含む jail.local)は次のセクションで説明します。

11. Fail2ban + ipsum の実用構成

基本インストールは上記を参照。ここでは、数十のアクティブな jail と数千のブロックを実現する実用構成を紹介します。全体設定、主要な jail、そして ipsum リストによる悪質な IP の自動 ban です。

/etc/fail2ban/jail.local ファイル — 全体設定と重要な jail:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # 段階的 ban: 繰り返すほど期間が延びる bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # SSH ブルートフォースは永久 ban findtime = 3600 # 常習犯: 複数回 ban された相手は永久に ban [recidive] enabled = true logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = -1 findtime = 86400 maxretry = 2 [http-get-dos] enabled = true maxretry = 100 findtime = 300 bantime = 1w # Web サービス (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … 他のサービス別 jail (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) も enabled = true
ignoreip には必ず自分の IP と信頼するネットワークを記載してください。そうしないと自分自身を ban してしまう恐れがあります。編集後: sudo fail2ban-client reload

ipsum ブロックリストの自動読み込みは root の cron に設定します (sudo crontab -e): level 1 (10万以上の IP) が ipsum セットに読み込まれ、ファイアウォールで遮断されます (詳細は「IPset ブロックリスト」セクションを参照):

# 04:00 — ipset ipsum の更新 (level 1、最大カバレッジ): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
セット名は ipsum でなければなりません — ダッシュボード (「IPset ipsum」カード) が読み取るのはこの名前です。レベル: levels/1.txt は最大カバレッジ、levels/3.txt はより高精度 (3つ以上の情報源)。

「セキュリティモニター」が2つのゾーンに分かれている理由。 保護は2つのレベルで機能しており、ダッシュボードは両者を混同しません:

  • 実際の攻撃 (リアクティブ) — fail2ban が捕捉したすべて: 実際の侵入試行 (sshdapache-*nginx-* などの jail) と悪質な常習犯 (recidive jail — すでに複数回 ban された相手)。これらは実際にあなたのサーバーへ侵入を試みた IP で、攻撃マップや「タイムライン」に表示されます。
  • 予防的ブロック (プロアクティブ) — 既知の悪質 IP の公開ブロックリスト ipset ipsum で、ファイアウォールDROP ルールで遮断されます。これらのアドレスは大半があなたのサーバーに触れてすらいません — 事前に遮断されます。「IPset ipsum」カウンターは、予防的に遮断された数を表示します。

違いはシンプルです: リアクティブは「攻撃してきて ban された相手」、プロアクティブは「試行前にブロックされた相手」です。以前は recidive に ipsum の list-3 を人為的に流し込んでいました (これが旧来の「リスト型 recidive」区分の由来です)。現在の recidive は本物の常習犯のみで、予防的ブロックはすべてファイアウォール側にあります。

12. IPset ブロックリスト(ipsum)

ipsum は、毎日更新される公開の悪意あるIPリストです。モニターはダッシュボードと攻撃マップに読み込んだアドレス数を表示し、セキュリティ評価に反映します(セットが未読み込みの場合は −10)。

fail2ban を使わない最小構成では、専用セット ipsum を作り iptables でブロックします:

# セットを作成(一度だけ): sudo ipset create ipsum hash:ip # 更新スクリプト /usr/local/bin/update-ipsum.sh: #!/bin/bash ipset flush ipsum for ip in $(curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt); do ipset add ipsum "$ip" 2>/dev/null done iptables -C INPUT -m set --match-set ipsum src -j DROP 2>/dev/null \ || iptables -I INPUT -m set --match-set ipsum src -j DROP # Cron(sudo crontab -e、毎日 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
fail2ban-recidive を使う拡張構成は「Fail2ban + ipsum の実用構成」の項を参照してください。
ipset はメモリ上に存在し、再起動で失われます。 毎日のcronだけでは、再起動から次の実行までセットが空のままになります(ダッシュボードは0を表示)。起動時にもセットを読み込むよう、読み込み処理をスクリプトにまとめて @reboot に登録してください。同時に create … -exist コマンドで上限 maxelem 300000 を指定します(デフォルトの65536では level 1 が収まらず「Hash is full」になります):
# /usr/local/bin/load-ipsum.sh #!/bin/bash curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt \ | grep -v '^#' | sed 's/^/add ipsum /' \ | (echo "create ipsum hash:ip hashsize 131072 maxelem 300000 -exist"; echo "flush ipsum"; cat) \ | ipset restore -exist # sudo crontab -e — 毎日 04:00 と毎回の起動時: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
自動インストール時の仕組み。 スクリプトは level 1 の完全リスト(10万以上のIP)をセット ipsum に読み込み、ファイアウォールをインストーラーが管理している場合(新規VPS — プロファイル「フル」/「軽量」)は DROP ルールでセットを UFW に接続します — これらのIPからのトラフィックは実際にブロックされます。ルールは ESTABLISHED,RELATEDに置かれるため、現在の接続(SSHを含む)は切断されず、リスト上のIPからの新規接続のみが遮断されます。セットはサービス ipsum-load.service の起動時にファイアウォールよりに復元され(そうでないとUFWが起動できません)、cronで04:00に更新されます。すでに設定済みのサーバー(パネルや独自ファイアウォール)では、インストーラーはファイアウォールに手を加えません — そこでは ipsum はダッシュボードと攻撃マップ用のリストとして残り、必要なら DROP ルールを手動で追加します(iptables … --match-set ipsum … -j DROP による最小構成は上記)。自動インストールでは手動で行うことは何もありません。

13. CrowdSec のインストール

集合知による threat intelligence を備えた Fail2ban の最新の代替。コミュニティによるブロックに加え、独自ルールも利用できます。ブロックをファイアウォールに適用するには別途 bouncer が必要です。

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash sudo apt install crowdsec sudo systemctl enable --now crowdsec # iptables/nftables 用の bouncer: sudo apt install crowdsec-firewall-bouncer-iptables # ステータスを確認: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
パネル上の「未起動」ステータス = サービスはインストール済みだがデーモンが非アクティブ(モニターは systemctl is-active crowdsec で確認します)。起動するには sudo systemctl enable --now crowdsec。落ちる場合は sudo journalctl -u crowdsec -n 30 を確認。「未起動」ステータスのあらゆるサービス(Suricata、Falco、Monit、MySQL)にも同じ手順が当てはまります。
ダッシュボードの「シナリオ 0 件」または「bouncer 0 件」。 CrowdSec は初期状態ではほぼ空で、コレクションがなければ何も検知せず、bouncer が登録されていなければブロックがファイアウォールに適用されません。基本コレクションを導入し、bouncer が一覧にあることを確認してください:
# 基本コレクション(Linux + SSH + Web サーバー): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # bouncer が一覧にあり、接続がアクティブなステータスであること: sudo cscli bouncers list
bouncer のログに stream halted / ブロックが適用されない。 これは孤立した api キーです。bouncer は cscli bouncers list から削除されたのに、古いキーが /etc/crowdsec/bouncers/*.yaml に残っています。bouncer を再登録し、新しいキーを記入してください:
sudo cscli bouncers add fw-bouncer # 新しい api_key が出力される # このキーを /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml の api_key: に記入 sudo systemctl restart crowdsec-firewall-bouncer
自動インストール(「フル保護」プロファイル)はコレクションの導入と firewall-bouncer の登録を自動で行います。手動での作業が必要になるのは、手動インストール時や CrowdSec に手動で手を加えた後だけです。

14. AIDE のインストール

AIDE(Advanced Intrusion Detection Environment)はファイルシステムのスナップショットを取得し、チェックのたびに /etc/bin/usr の変更を報告します。インストール後はデータベースの初期化(aideinit)が必須です。

sudo apt install aide # データベースの初期化(5〜15分): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: /var/lib/aide ディレクトリは 700(所有者 _aide)で作成され、 # パネル(www-data)がデータベースを認識できず →「未初期化」と表示される。 # ディレクトリに通過権限を付与(データベースファイルは 600 のまま): sudo chmod 755 /var/lib/aide # モニターが読み取るログへ書き込む最初のチェック。 # Ubuntu/Debian では aide に明示的な --config が必要(ないと「missing configuration」; # 新バージョンでは aide.wrapper バイナリが同梱されない): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
aideinit の実行中、ターミナルは 5〜15分間 Running aide --init... の行で止まりますが、これは正常です(ファイルシステム全体のハッシュ化でディスク負荷がかかります)。Ctrl+C で中断しないでください。処理が「固まった」ように見えて何も出力されない場合、隠れた確認 Overwrite existing aide.db.new [Yn]? への応答を待っている可能性があります(Y を押してください)。別セッションから動作を確認: pgrep -af aide
aideinit のエラー:「21_aide_spamassassin … printf: invalid number」(return code 20) — Ubuntu 22.04 の AIDE 設定スニペットの既知のバグです。データベースが作成されません。壊れたスニペットを退避して再実行してください:
sudo mv /etc/aide/aide.conf.d/21_aide_spamassassin /etc/aide/21_aide_spamassassin.disabled sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
ダッシュボードのステータス。「未初期化」= パネルがデータベースファイルを認識できない状態: aideinit が実行されていないか、あるいは(Ubuntu 24.04)/var/lib/aide ディレクトリが 700 で作成され www-data からアクセスできない状態です — sudo chmod 755 /var/lib/aide で解決します(上のブロック参照)。「チェック未実施」= データベースはあるがチェックがまだ実行されていない状態で、エラーではありません。結果はモニターが /var/log/aide/aide.log から読み取ります。
定期チェック → パネル用ログ。 標準の /etc/cron.daily/aide は新しい Ubuntu/Debian では /var/log/aide/aide.log を必要な形式で書き込まないことがあります(それらには aide.wrapper も既にありません)。明示的な --config を指定した独自の cron を追加するほうが確実です — root がログを 644 で書き込むため、モニターは追加のグループなしで読み取れます:
# sudo crontab -e — 毎日 02:00 のチェック: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # スケジュールを待たずに今すぐ実行: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
自動インストールはこれらをすべて実行済みです: chmod 755 /var/lib/aide と 02:00 のチェック cron — 手動での作業は不要です。
最初の初期化はクリーンなサーバーで、Web アプリのインストール前に行ってください。正当な変更のあとはデータベースを再作成してください: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

15. ClamAV のインストール

Linux 向けのアンチウイルススキャナーです。/var/www を PHP シェルや悪意あるコードについて検査するのに特に役立ちます。

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # シグネチャデータベースを更新: sudo freshclam # フォルダーを手動でスキャン: sudo clamscan -r /var/www --infected
enable --now の後も clamd デーモンが「非アクティブ」と表示される? よくある原因は3つです:

1. 設定に Example 行が残っている — この行があるうちは clamd は起動を拒否します:

sudo sed -i '/^Example/d' /etc/clamav/clamd.conf sudo systemctl restart clamav-daemon

2. シグネチャデータベースがダウンロードされていない — これがないと clamd は起動しません:

sudo systemctl stop clamav-freshclam sudo freshclam sudo systemctl start clamav-freshclam sudo systemctl restart clamav-daemon

3. 単に読み込み中 — clamd は約800万件のシグネチャをメモリに30〜60秒かけて読み込みます。待ってから確認してください: systemctl is-active clamav-daemon(ステータスが activating → まだ読み込み中)。

診断: sudo journalctl -u clamav-daemon -n 30 --no-pager
ダッシュボードで「検査済みファイル: 0」/「最終スキャン: —」と表示される? clamd デーモンはシグネチャをメモリに保持するだけで、スケジュールに従って自らスキャンすることはありません。パネルは定期スキャンの結果を表示するため、スキャンしてログを書き込む cron が必要です。自動インストールではラッパー /usr/local/bin/clamav-scan.sh と01:30の cron を設定します — 初回実行後に「検査済みファイル」と「最終スキャン」が埋まります。スケジュールを待たずにすぐ実行するには: sudo /usr/local/bin/clamav-scan.sh

16. Linux Malware Detect (maldet) のインストール

Linux Malware Detect (LMD) — Web の脅威に対応したマルウェアスキャナーで、PHP シェル、Web バックドア、ダウンローダーを検出します。ClamAV エンジンを利用し、独自のシグネチャで補完します。

wget https://www.rfxn.com/downloads/maldetect-current.tar.gz tar -xzf maldetect-current.tar.gz dir=$(ls -d maldetect-*/ | head -1) && cd "$dir" && sudo bash install.sh && cd ~ rm -rf maldetect-* maldetect-current.tar.gz # シグネチャを更新: sudo maldet -u # /var/www をスキャン: sudo maldet -a /var/www
LMD と ClamAV は組み合わせて使うと効果的です。最新レポート: maldet --report
インストール時に update-rc.d: error: unable to read /etc/init.d/maldet という行が表示されることがありますが、問題ありません。maldet は init.d を使わず、シグネチャ更新とスキャンは /etc/cron.daily/maldet から実行されます。下に installation completed と表示されていれば、正常にインストールされています。
インストール済みなのにページには LMD が「未インストール」と表示される? maldet は apt ではなく /usr/local/maldetect にインストールされ、open_basedir が有効な場合は shell 経由で存在を確認します。「サーバーにデータがあるのにページが空」のセクションを参照してください。

17. Suricata のインストール

ネットワーク型侵入検知システム。トラフィックをパケットレベルで解析し、数千種類の攻撃シグネチャを認識します。ModSecurity を補完します(ModSecurity は HTTP レベル、Suricata は TCP/IP レベルで動作)。

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # 最新のルールをダウンロード: sudo suricata-update sudo systemctl enable --now suricata
Suricata は「稼働中」なのにダッシュボードにアラートが表示されない/イベント数が 0 ですか? Suricata は /var/log/suricata/eve.json を root 権限でディレクトリのパーミッション 750 で書き込むため、Web サーバー(www-data)が読み取れません。ディレクトリに通過権限を付与してください。内部のファイルは保護されたままです:
sudo chmod o+rx /var/log/suricata
自動インストールではこの処理も行われるため、手動での作業は不要です。

18. Falco のインストール

eBPF/カーネルモジュールを通じてシステムコールを捕捉し、異常をリアルタイムで検出します。nginx からの shell 起動、Web プロセスによる /etc/passwd の読み取り、/bin への書き込みなど。

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc > /tmp/falco.asc gpg --dearmor < /tmp/falco.asc | sudo tee /usr/share/keyrings/falco-archive-keyring.gpg > /dev/null sudo chmod 644 /usr/share/keyrings/falco-archive-keyring.gpg && rm /tmp/falco.asc echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" \ | sudo tee /etc/apt/sources.list.d/falcosecurity.list sudo apt update && sudo apt install falco sudo systemctl enable --now falco
モニターは journalctl -u falco を通じて Falco のイベントを読み取ります(sudo なし — systemd-journal グループ経由)。www-data がこのグループに属していることを確認してください。手動インストールページの「sudo の設定」(項目2)を参照してください。
「24時間で0件」は正常であり、エラーではありません。 Falco はイベント駆動型です。すべて正常な間は沈黙し、異常時のみイベントを記録します(Web プロセスからの shell 起動、/etc/passwd の読み取り、システムディレクトリへの書き込み)。平穏なサーバーで1日あたり重大イベントがゼロなのは健全な状態です。
パネルにはファイル出力の方が確実です。 journalctl 経由の読み取りにはジャーナルへの権限が必要です。パネルが安定してイベントを見られるよう、自動インストールでは Falco の file_output/var/log/falco/falco.log を有効化し、サービスに UMask=0022 を設定します(ログは Web サーバーから読み取れます)。新規インストールでは手動で設定する必要はありません。

19. ModSecurity(WAF)のインストール

ModSecurity は Apache または Nginx 向けの Web ファイアウォール(WAF)です。SQL インジェクション、XSS、パストラバーサル、スキャナーなど、アプリケーション層への攻撃をブロックします。

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # OWASP Core Rule Set ルールセット: sudo apt install modsecurity-crs # 必須: このファイルがないとルールエンジンは無効のまま sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf sudo apache2ctl configtest && sudo systemctl reload apache2 # 確認: 403 が返るはず curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
パッケージをインストールしただけでは何も保護されません。 Apache は IncludeOptional /etc/modsecurity/*.conf という行で設定を読み込みますが、パッケージが配置するのは modsecurity.conf-recommended だけで、*.conf のマスクには一致しません。これを modsecurity.conf にコピーしないと SecRuleEngineOff のまま。モジュールは読み込まれ、CRS ルールも読み込まれますが、トラフィックは検査されず監査ログも作成されません。中間モードの DetectionOnly はイベントをログに記録するだけでリクエストをブロックしないため、パネルでは黄色で表示されます。

パネルからの監査ログへのアクセス。 ログ /var/log/apache2/modsec_audit.log は root 所有(権限 640)で、Web ユーザーは読み取れません。パネルはラッパー経由でデータを取得します。次のように作成してください:

sudo tee /usr/local/bin/monitor-modsec >/dev/null <<'EOF' #!/bin/sh echo "ENGINE=$(grep -hE '^SecRuleEngine[[:space:]]+' /etc/modsecurity/*.conf 2>/dev/null | tail -1 | awk '{print $2}')" echo "---LOG---" tail -n 3000 /var/log/apache2/modsec_audit.log 2>/dev/null echo "---RULES---" for f in /etc/modsecurity/crs/rules/*.conf /usr/share/modsecurity-crs/rules/*.conf /etc/modsecurity/custom-rules.conf; do [ -f "$f" ] && { echo "===FILE:$(basename "$f")==="; cat "$f"; } done EOF sudo chown root:root /usr/local/bin/monitor-modsec sudo chmod 755 /usr/local/bin/monitor-modsec # /etc/sudoers.d/monitor に(ユーザー = PHP-FPM が動作しているユーザー): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
ラッパーはインデントのない最後の SecRuleEngine ディレクティブを取得します。インデントされた行は <LocationMatch><Directory> ブロック内(例えば phpMyAdmin での WAF 無効化)にあり、グローバルモードは決定しません。
sudoers のユーザーは FPM プールのユーザーと一致している必要があります。通常の Apache/Debian では www-data ですが、HestiaCP ではサイトのプールがサイト所有者(例えば admin)で動作します。grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf で確認してください。
サイトが Nginx プロキシ(HestiaCP)の背後にある場合、Apache にはクライアントとしてプロキシ自身が見えるため、パネルは攻撃者の実際の IP を X-Forwarded-For ヘッダーから取得します。統計にはルールが発動したトランザクションのみが含まれます。SecAuditLogRelevantStatus ディレクティブは 4xx/5xx のあらゆる応答を監査ログに記録するため、通常の 403/500 もそこに入りますが、パネルはそれらを WAF イベントとは見なしません。
---RULES--- ブロックは「すべての有効なルール」セクションに必要です。パネルは発動したものだけでなく、読み込まれたすべての CRS ルールとカスタムルールを表示します。ループ for f in … 内の 3 つのパスは、CRS ルールとローカルの追加分の典型的な配置先です。別の構成の場合(パッケージが独自のディレクトリにファイルを配置する、またはカスタムルールが /etc/modsecurity/custom-rules.conf 以外にある)は、sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null コマンドで実際のパスを見つけてリストに追加してください。ラッパーが古い場合(このセクションがない場合)は、セクションに「利用不可」という警告が表示されるだけで、ページの他の部分は従来どおり動作します。

20. Auditd のインストール

Auditd(Linux Audit Daemon)はカーネルレベルでシステムコールを記録します。ログインとログアウト、sudo コマンド、認証の失敗、ファイルの変更などです。モニターは当日のログイン、失敗した試行、sudo コマンドを表示します。

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # ステータスとイベントを確認: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
モニターは ausearch/usr/sbin/ausearch)でイベントを読み取り、必要に応じて tail コマンドで /var/log/audit/audit.log からも読み取ります。両方とも sudoers に登録されている必要があります。

21. Monit のインストール

サービス(nginx、php-fpm、mysql など)を監視し、ダウン時に再起動します。email でアラートを送信できます。

sudo apt install monit sudo systemctl enable --now monit # 設定ファイル: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
モニターは monit status でサービス一覧を取得します。/etc/monit/monitrc で HTTP インターフェース(allow localhost を含む set httpd ブロック)を有効にする必要があります。そうでないと monit status がエラーを返します。
ダッシュボードに「監視中のサービスが 0 件」と表示される? 原因は 2 つあります。(1) HTTP インターフェースが無効 — monitrcset httpd 行がコメントアウトされている(デフォルトでは # set httpd port 2812 … となっています)。ブロックのコメントを解除し、localhost を許可してください。(2) httpd を有効にしただけでは何も監視されません — Monit は check スタンザで記述したものだけをカウントするため、それがなければインターフェースが動作していても一覧は空です。最小限の動作設定:
# /etc/monit/conf.d/00-httpd — localhost 用の HTTP インターフェース: set httpd port 2812 use address localhost allow localhost # check スタンザの例(監視対象): check process sshd with pidfile /run/sshd.pid start program = "/usr/bin/systemctl start ssh" stop program = "/usr/bin/systemctl stop ssh" check filesystem rootfs with path / if space usage > 90% then alert
sudo monit -t # 構文チェック (Control file syntax OK) sudo systemctl reload monit sudo monit status
自動インストールでは、2812 ポートの httpd と一連のチェックを備えた conf.d が配置されます。新規インストールでは手動設定は不要です。
サービスのステータスが「エラーあり」? モニターは状態を表示するだけで、意図的にウェブパネルからサービスを再起動しません(セキュリティパネルでの root コマンドのリモート実行になってしまうため)。診断と再起動は SSH 経由で Monit を使って行います:
sudo monit status <service> # エラーの原因 sudo monit restart <service> # Monit 経由で再起動 # Monit がサービスを起動できない場合は、そのユニット自体を確認: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

22. PSAD のインストール(ポートスキャン検知)

PSAD は iptables のログを解析してポートスキャンやネットワーク攻撃を検出し、送信元ごとに脅威レベル(1〜5)を割り当てます。fail2ban と Suricata を補完します。

sudo apt install psad # PSAD は iptables のログを読み込むため、ロギングを有効にする必要があります(UFW は自動で行います)。 # 素の iptables では INPUT/FORWARD チェインに LOG ルールを追加してください。 sudo psad --sig-update sudo systemctl enable --now psad
モニターは psad --Status 経由でデータを読み込みます(sudoers への登録が必要)。iptables のロギングがない場合、ページは空になりますが、スキャンがまだ発生していないだけなので正常です。

23. AppArmor / SELinux(アクセス制御)

Mandatory Access Control は、プログラムが侵害された場合でも、そのプログラムがアクセスできるファイルやリソースを制限します。Ubuntu/Debian では標準で AppArmor が使われます(通常はすでにインストール・有効化済み)。

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # プロファイルを確認
モニターは aa-status でステータスを読み取ります(sudoers への登録が必要)。enforce/complain モードのプロファイル数と、プロファイルのないプロセスを表示します。

「読み込み済みプロファイル」が enforce + complain より多くても正常です。 AppArmor 4.x(Ubuntu 24.04 以降)では unconfined モードが導入されました。プロファイルはカーネルに読み込まれていますが、何も制限しません。Ubuntu は、user namespaces を使うプログラム(ブラウザ、torrent クライアントなど)のプロファイル数十個をこの状態にしています。こうしたプロファイルがあると、「読み込み済みプロファイル」カードは琥珀色になり、その数を表示します。例えば読み込み済み 120、enforce 26 に対して unconfined: 90 のように表示されます。実際に保護しているのは enforce のプロファイルだけです。Ubuntu 22.04(AppArmor 3.x)にはこのモードがなく、数値は常に一致します。

sudo aa-status | grep -E "profiles are" # モード別の内訳 sudo aa-enforce /etc/apparmor.d/profile-name # プロファイルを enforce に切り替え
Ubuntu が意図的に unconfined のままにしているプロファイルを enforce に切り替えるのは、十分に理解した上で行ってください。これらは誤って無効化されているのではなく、enforce にするとプログラム自体が動かなくなるためです。complain のプロファイルは別で、ルールはすでに書かれており、適用されていないだけです。

24. debsums のインストール(パッケージ整合性)

debsums は、インストール済みパッケージのファイルがリポジトリのチェックサムと一致するかを検証し、改ざんされたシステムバイナリを検出します(AIDE を補完)。完全スキャンには 1〜2 分かかるため cron で実行し、パネルは data/debsums/debsums.log から結果を読み取ってカテゴリ別に自動整理します(重要なのはバイナリとライブラリのみ)。

ジョブは root の cron(sudo crontab -e)に登録します。既製のラッパー debsums-scan.sh/usr/local/bin/ に配置し(chmod +x。cron ジョブ一覧を参照)、レポートはパネルの data/debsums/ へ自動的に書き込まれます。

sudo apt install debsums # Cron 行(毎日 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

ラッパー debsums-scan.sh はパネルの data/ を自動検出するため、パスを指定する必要はありません。

サーバー上の /etc/(設定ファイル)や /usr/share/(リソース)の変更は通常は問題なく、パネルは別の色で表示します。警戒すべきはバイナリやライブラリ(/bin/sbin/usr/lib など)の変更で、「バイナリ / ライブラリ」カードにはまさにそれらが表示されます。

25. Lynis レポートの設定

Lynis は手動または cron で実行します。レポートはプロジェクトの data/lynis/ フォルダに保存する必要があります。モニターは lynis-report.dat ファイルを読み取ります。

# 単発実行(パネルのルートへのパスを指定してください): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # 毎日の監査 — cron 行(すぐ使えるラッパー lynis-scan.sh は /usr/local/bin/ にあります。概要を参照): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
初回実行後、「Lynis 監査」ページに hardening index、警告、推奨事項がすぐに表示されます。
Lynis ページの「監査を実行」ボタン。 このボタンは(cron を待たずに)パネルから直接 lynis-scan.sh をバックグラウンドで実行します。「スキャン中…」と表示し、完了すると自動でレポートを更新します。そのためには、Web ユーザーがスクリプトを実行できる sudoers 行が必要です。インストーラーが /etc/sudoers.d/monitor に自動で追加します。パネルを手動で/以前にインストールした場合は、ファイルにすでに指定されているユーザーで同じ行を追記してください:
u=$(sudo awk '/NOPASSWD/ && !/lynis-scan/ {print $1; exit}' /etc/sudoers.d/monitor) [ -n "$u" ] && echo "$u ALL=(ALL) NOPASSWD: /usr/local/bin/lynis-scan.sh" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c && sudo chmod 440 /etc/sudoers.d/monitor

26. Logwatch レポートの設定

Logwatch は日次レポートをプロジェクトの data/logwatch/ フォルダに .txt 形式で保存する必要があります。モニターは最新レポートとアーカイブを表示します。

# 毎日(6:00)— cron 行(/usr/local/bin/ の logwatch_daily.sh ラッパーは準備済み。概要を参照): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

パネルモジュール

27. ネットワークモニター(組み込み)

ネットワークモニターはインストール不要で、ダッシュボードに組み込まれたページです。ローカルソースからサーバーのネットワーク状態を表示します:

  • インターフェースとトラフィック — /proc/net/dev から;
  • リンク状態(UP/DOWN)と IP — ip 経由;
  • 接続とリッスン中のポート — ss 経由;
  • 24時間分のカーネルネットワークイベント — journalctl -k 経由。

最初の3つのソースは sudo なしで動作するため、インターフェース、トラフィック、接続、ポートはすぐに表示されます。「カーネルイベント」ブロックは journalctl -k を使用し、systemd-journal グループ経由で読み取られるため(「sudo の設定」、項目2)、sudo は不要です。すべてが Web ユーザーからアクセス可能か確認するには:

# www-data として確認(PHP はこのユーザーで動作します): sudo -u www-data bash -c 'cat /proc/net/dev' sudo -u www-data bash -c 'ip -o link show' sudo -u www-data bash -c 'ss -s' sudo -u www-data journalctl -k --no-pager -n 5
「カーネルネットワークイベント」ブロックは、カーネルネットワークスタックのイベント(リンクの up/down 切り替え、キャリアエラー、「network unreachable」)を表示します。ファイアウォールの UFW BLOCK エントリはここには含まれません — それらは「ファイアウォール UFW」と「攻撃マップ」ページにあります。緑のチェックマーク付きの空ブロック = 24時間以内にネットワーク障害はありませんでした。

28. ディスクと SMART

組み込みのページには 3 つの情報が表示されます。

  • ファイルシステム — パーティションの使用状況(df)。90% 以上でゲージが赤くなります。
  • ストレージデバイス — ディスク一覧(lsblk)。実デバイスのみ(loop/snap は非表示)。
  • ヘルス(SMART) — ディスクの状態と属性(smartctl)。

空き容量とデバイス一覧は設定不要ですぐに動作します。SMART には smartmontools パッケージが必要です。Web プロセスはディスクデバイスへ直接アクセスできないため、SMART は cron 経由data/disk/smart.txt ファイルに取得され、ダッシュボードがそれを読み取ります。

ジョブは root の cron に登録します(sudo crontab -e)。既製のラッパー smart-scan.sh/usr/local/bin/ に配置し(chmod +x、cron ジョブ一覧を参照)、ラッパー自身がダッシュボードの data/disk/ に書き込みます。

sudo apt install smartmontools # Cron 行(30 分ごと): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

ラッパー smart-scan.sh はダッシュボードの data/ を自動で見つけるため、パスの指定は不要です。内部で lsblk -e7,11 により loop/cdrom を除外しています。

仮想ディスク(QEMU/KVM など)では通常、全体的な状態 「ヘルス: OK」のみが取得でき、温度・稼働時間・代替処理済みセクターは空になることがあります。これは正常です。物理サーバーではすべての属性が表示されます。

29. パフォーマンス(CPU/RAM/ネットワーク/ディスク)

このページは直近24時間のサーバー負荷履歴を表示します。Load Average、CPU使用率とI/O待ち、RAM/Swap、ネットワークトラフィック(受信/送信)、ディスクI/O(読み取り/書き込み)、ディスクとinodeの使用状況、開いているファイルディスクリプタとMySQL接続数、加えて現在のTCP接続数とプロセス数を確認できます。

データは cron/collect_metrics.php が収集します。5分ごとにカウンタの「生の」スナップショットを1件(/proc/loadavg/proc/meminfo/proc/stat/proc/net/dev/proc/diskstatsdf/df -i/proc/sys/fs/file-nrSHOW GLOBAL STATUS LIKE 'Threads_connected')データベースの system_metrics テーブルに書き込みます。パーセンテージと速度は、隣接するスナップショットの差分からページ自身が計算します(ディスク/inode/ディスクリプタ/MySQL接続の使用状況は瞬時値で、再計算は行いません)。root権限は不要で、ソースはroot権限なしで読み取れます。24時間より古いポイントは書き込みのたびに自動削除されます。

# Cron行(5分ごと): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

ラッパー collect-metrics-all.sh(cronタスク一覧を参照)は、サーバー上にインストールされたすべてのパネルインスタンスを自動検出し、各インスタンスの cron/collect_metrics.php をサイト所有者の権限で実行します。

コレクタが少なくとも2回実行されるまで(インストール後の最初の約10分間)、ページには「データを収集中」と表示されます。グラフは速度とパーセンテージを計算するために、隣接するポイントのペアが最低1組必要です。

負荷アラート(「設定」→「負荷アラート」)— CPU/RAM/ディスク/inodeがしきい値を超えると、パネルはTelegram/Emailに通知を送信し(日次レポートと同じチャネルで、アラート用に別途有効化する必要はありません)、メトリクスが正常に戻ったときにもう1件送信します。しきい値を超えている間の再送でスパムにはなりません。次の通知は「復旧→再度超過」のサイクル後にのみ届きます。

しきい値は同じ collect_metrics.php が実行ごと(5分ごと)にチェックするため、別途cronは不要です。「通知済み/未通知」の状態は data/alerts_state.json に、しきい値はパネルの設定に保存されます。

30. 攻撃マップ(GeoIP)

「攻撃マップ」ページは geoiplookup コマンドで IP から国を判定します。GeoIP パッケージがないと国は判定できず、マップ上に点は表示されません:

sudo apt install geoip-bin geoip-database # 確認: geoiplookup 8.8.8.8
sudo は不要です。データベース /usr/share/GeoIP/GeoIP.dat は全ユーザーが読み取り可能で、結果は tmp/geoip_cache.json にキャッシュされます。マップ本体(Leaflet + OpenStreetMap タイル)はブラウザで読み込まれるため、ダッシュボードを開くコンピューターにはインターネット接続が必要です。

31. 外部への露出、アップデートと自動アップデート

ダッシュボードに組み込まれた2枚のカードで、ツールの「オン/オフ」ではなく、サーバーの実際の防御状態を表示します。インストール不要、sudoなしでローカルに読み取ります。

外部への露出 — 全インターフェース(0.0.0.0/[::])で待ち受けし、外部からアクセス可能なサービスの数です。DBMSやキャッシュ(MySQL、PostgreSQL、Redis、MongoDB、Memcached、Elasticsearch)が外部に露出している場合は赤で強調表示されます — これは直接的な穴です(セキュリティ評価に−10)。ソース: ss -tuln

カードが赤い場合は、DBMSを外部に対して閉じてください: 127.0.0.1 にバインドするか(MySQL/PostgreSQL設定の bind-address、Redisの bind 127.0.0.1)、UFWでポートを閉じてください。
「開いているポート」≠「外部からアクセス可能」。 127.0.0.1(loopback)で待ち受けするサービスはサーバー自身にしか見えず、ポートが「開いて」いても外部からはアクセスできません。そのため、loopbackにバインドされたポート25のPostfixは安全です: 自動設定が inet_interfaces = loopback-only を設定します(加えて中立的な smtpd_banner により、バージョン漏洩に関するLynisの指摘 MAIL-8818 を解消します)。「外部への露出」カードは 0.0.0.0/[::] で待ち受けするものだけを外部としてカウントし、loopbackサービスは含まれません。
Lynis MAIL-8818を手動で(メールを自分で構築した場合): /etc/postfix/main.cfsmtpd_banner = $myhostname ESMTP(バージョンとOSなし)と inet_interfaces = loopback-only を設定し、その後 sudo systemctl restart postfix を実行します。

セキュリティアップデート — インストール待ちのセキュリティパッチの数と、カーネル更新後に再起動が必要かどうかを示します(パッチがある場合、セキュリティ評価に−5)。ソース: /usr/lib/update-notifier/apt-check、ファイル /var/run/reboot-required。詳細な一覧は「セキュリティアップデート」ページにあります。

# アップデートをインストール: sudo apt update && sudo apt upgrade # 外部に何が待ち受けているか確認: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
アップデートカードはUbuntu/Debianで動作します(update-notifier-common)。apt-check がない場合、モニターは apt-get -s upgrade でパッチを数えます。

セキュリティ自動アップデート(unattended-upgrades) — 「セキュリティアップデート」ページの専用カードで、セキュリティパッチの自動インストールが有効かどうか、最後に実行されたのがいつかを表示します。sudoは不要で、ステータスは apt-config dump で読み取ります。

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # 有効化 # 有効になっているか確認: apt-config dump | grep Unattended-Upgrade

メンテナンス

32. バックアップ

バックアップは最大の保険です。データの喪失はどんな侵入よりも深刻です。必要なものは2つ——サーバー/サイトのバックアップと、それとは別にパネルのDBのバックアップ(ユーザー、WebAuthnキー、設定、ライセンスが含まれます)です。

方法A — HestiaCP:ユーザーのBackupタブ → バックアップ作成ボタン(またはサーバー設定でスケジュール実行)。バックアップにはサイトとそのDBが含まれます。

方法B — 手動(cron):DBのダンプ+パネルのdata/ディレクトリのアーカイブ:

# root の cron(sudo crontab -e)— 毎日 2:30 にバックアップ(自分の名前/パスに置き換えてください): 30 2 * * * mysqldump -u root MY_DB | gzip > /var/backups/monitor-db-$(date +\%F).sql.gz 40 2 * * * tar czf /var/backups/monitor-data-$(date +\%F).tar.gz -C /path/to/monitor data # 14日より古いアーカイブを削除: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
同じサーバー上のバックアップはミスからは守れますが、サーバー自体の喪失には対応できません。アーカイブは外部ストレージ(別のサーバー、S3、rcloneでクラウドへ)にコピーしてください。復元が実際に機能することを確認してください。

33. パネルのアップデートと移行

新しいバージョンへのアップデート。 まずバックアップを取ってください。その後、データを保持したままコードファイルを上書きします。

  • 上書きする(コード): public/includes/assets/cron/database/、およびルートの .htaccess(フロントコントローラー — ルーティングを旧バージョンのまま残してはいけません)、manifest.jsonsw.js;
  • 触れないもの: config.php(DB情報)、data/(レポート)、logs/tmp/(セッションとキャッシュ)。
# アップロード後 — PHPキャッシュをクリア(opcache有効時): sudo systemctl reload php*-fpm
FileZilla が SSH_FX_PERMISSION_DENIEDPermission denied)と表示する場合。 パネルのファイルは www-data の所有です(インストール時にそう設定されています)が、SFTP クライアントは書き込み権限のないご自身のユーザーで接続しています。「動かすため」にパネル全体を www-data に渡すことこそ、まさにこのエラーを招く原因です。以下の 3 つの方法のいずれでも問題は解決します。
# 方法 A(推奨)— 所有者を分ける: コードは自分、作業用フォルダは Web サーバー。 # Web サーバーはパネルのコードへの書き込み権限をまったく得ません: sudo chown -R deploy:www-data /path/to/monitor sudo chown -R www-data:www-data /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo find /path/to/monitor -type d -exec chmod 755 {} \; sudo find /path/to/monitor -type f -exec chmod 644 {} \; sudo chmod 750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo chmod 640 /path/to/monitor/config.php # 方法 B — 現在の所有者はそのままに ACL を重ねる(何も移動しません): sudo apt install -y acl sudo setfacl -R -m u:deploy:rwX /path/to/monitor sudo setfacl -R -d -m u:deploy:rwX /path/to/monitor # 方法 C — www-data グループ経由。より簡単ですが、パネルのファイルへの # 書き込み権限は Web サーバーにも渡ります(PHP の脆弱性でコードを差し替えられます): sudo usermod -aG www-data deploy sudo find /path/to/monitor -type d -exec chmod 2775 {} \; sudo find /path/to/monitor -type f -exec chmod 664 {} \; sudo chmod 640 /path/to/monitor/config.php sudo chmod 2750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs
方法 A が安全な理由。 パネルが書き込むのは 3 つのディレクトリだけです — data/(レポート)、tmp/(セッションとキャッシュ)、logs/。これらは www-data の所有のまま残ります。残りはコードで、Web サーバーには読み取りだけが必要で、それは 644 の権限を持つ www-data グループが与えます。副次的な利点として、PHP に脆弱性があってもパネルのファイルはもう書き換えられません。ホスティングパネル(HestiaCP など)では方法 A は不要です。そこではサイトのファイルはもともと SFTP で接続するアカウントの所有であり、Web サーバーはグループ経由で読み取ります。
方法 B の落とし穴: その後にファイルへ chmod を実行すると ACL マスクがリセットされ、アクセスが黙って失われます。「権限を整理」した後にアップロードが再び Permission denied で止まる場合は、両方の setfacl コマンドを再実行してください。
方法 C の 2 が setgid です。SFTP でアップロードしたファイルは www-data グループに残り、そうでなければパネルは上書きできません。方法 C の後は FileZilla で接続し直してください — 新しいグループは新規ログイン時にしか反映されません。確認: id deploywww-data グループが表示されること)と ls -ld /path/to/monitordrwxrwsr-x — 文字 s は setgid が設定されていることを示します)。

別サーバーへの移行:

  1. 新しいサーバーでサイト + HTTPS を構築します(手動インストールのページを参照)。
  2. パネルの全ファイルを config.phpdata/ とともにコピーします。
  3. DBを移行: 旧サーバーで mysqldump → 新サーバーでインポート。config.php のDB情報を修正してください。
  4. 新しいサーバーで再設定: sudoers、adm グループへの所属、cronジョブ。
  5. ライセンスはドメインに紐づいています — ドメインが同じであれば、キーはそのまま機能し続けます。

34. アクセスの復旧(セキュリティキー・パスワード・IPブロックの喪失)

ログインできない場合は、サーバー上のデータベースで直接修復できます。データベースを開いてください(データベース名は config.php から):

sudo mysql MY_DB

WebAuthn のセキュリティキーを紛失した(第二要素が通らない)場合は、2FA を無効化し、パスワードでログインして新しいキーを登録してください:

UPDATE users SET webauthn_enabled = 0;

パスワードを忘れた場合は、新しいハッシュを設定してください(サーバー上で生成して置き換えます):

# 新しいパスワードのハッシュを生成: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # データベースへ(生成したハッシュを貼り付け): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

IPフィルターで自分を締め出した場合は、制限を無効化してください:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
データベースへはいつでもアクセスできます:サーバー上で sudo mysql、または phpMyAdmin / ホスティングパネルのデータベース欄から。復旧後は WebAuthn と IPフィルターを再度有効化してください。

35. すべての cron ジョブを一箇所で

ジョブの一覧はサーバーの root crontabに記述します(sudo crontab -e で追加)。使用するツールの行だけを残し、パスは自分のサーバーに合わせて調整してください。

# モニターのサーバー crontab(root)— 次で記述: sudo crontab -e # 01:30 — 危険なパス(web, home, temp)を対象とした ClamAV スキャン → カード「検査済みファイル数」「最終スキャン」 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — AIDE によるファイル整合性チェック(明示的な --config が必要) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # 起動時 — /var/lib/aide の権限を復元(パッケージの tmpfiles ファイル # aide-common.conf が 0700 にリセットし、パネルがデータベースを見られなくなる) @reboot chmod 755 /var/lib/aide # 03:00 — Lynis によるセキュリティ監査 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — ipsum ブロックリストの更新(level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # 起動時の ipsum セット読み込みは ipsum-load.service が担当(ファイアウォールより前、でないと # UFW が before.rules 内のセットを認識しない)— cron ではない。ここは上記の日次リフレッシュのみ。 # 06:00 — Logwatch レポート 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # 30 分ごと — SMART ディスクチェック */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — debsums によるパッケージ整合性 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — Email と Telegram へのスケジュールレポート 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # 1 時間ごと — パッケージ一覧の更新(「セキュリティアップデート」カード用) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # 5 分ごと — リソースのスナップショット(CPU/RAM/ネットワーク/ディスク)※「パフォーマンス」ページ用 */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1
各項目の詳細は該当セクションを参照してください。バックアップジョブ(前セクション)も同じ crontab に追加します。編集後は確認を: sudo crontab -l、そして cron サービスが有効であること。
cron の時刻はサーバーのタイムゾーンであり、config.phpTIMEZONE ではありません。 定数 TIMEZONE は PHP にのみ影響します(パネルが日付をどう表示するか)が、cron デーモンは OS のシステム時刻でジョブを実行します。サーバーのタイムゾーンが自分と異なると、「08:00」のレポートは違う時刻に届きます。例: サーバーが別のタイムゾーン(Asia/Shanghai, UTC+8)にあり、あなたは東京(UTC+9)にいる場合 →「08:00」のレポートはあなたの時刻で 09:00 に届きます。確認し、必要ならシステムのタイムゾーンを自分に合わせてください:
# サーバーの現在のタイムゾーンを確認: timedatectl # 自分のタイムゾーンを設定(例)して cron を再起動: sudo timedatectl set-timezone Asia/Tokyo sudo systemctl restart cron
これで 0 8 * * * の行は現地時間の 08:00 に実行されます。そうでなければ cron 自体をずらすことになりますが、冬時間/夏時間の切り替え時に再びずれてしまいます — そのためシステムのタイムゾーンを設定するのが正しいやり方です。
すぐ使えるラッパースクリプト。 その稼働用コピーと crontab のサンプル(crontab.txt)は、プロジェクトの隣、public_htmlにある system/ フォルダにあります。これはサイトの一部ではなく、web ルートにアップロードする必要はありません。サーバー上のシステムパスに配置してください(上記 crontab のとおり):
  • lynis-scan.sh/usr/local/bin/chmod +x)— lynis audit system を実行し、スキャン中はフラグ /tmp/lynis-running を立て、lynis-report.dat をパネルの data/lynis/ にコピーします。
  • logwatch_daily.sh/usr/local/bin/chmod +x)— 日次の Logwatch レポート(sshd, fail2ban, sudo, postfix)を data/logwatch/ に生成します。
  • smart-scan.sh/usr/local/bin/chmod +x)— ディスクの状態(smartctl)を data/disk/ に取得します。
  • debsums-scan.sh/usr/local/bin/chmod +x)— パッケージ整合性(debsums)を data/debsums/ でチェックします。
  • clamav-scan.sh/usr/local/bin/chmod +x)— 危険なパス(web, home, temp)を対象とした ClamAV アンチウイルススキャン。サマリを /var/log/clamav/scan.log に書き込み、そこから ClamAV ページが読み取ります(上記 crontab の 01:30 の行)。
  • load-ipsum.sh/usr/local/bin/chmod +x)— ipset の ipsum セット(level 1)をその場で更新し、有効なファイアウォール規則を壊さない(上記 crontab の 04:00 行)。
  • daily-report-all.sh/usr/local/bin/chmod +x)— パネルのレポート cron/daily_report.php を実行します(上記 crontab の 08:00 の行)。
  • daily_report.php — すでにパネルに含まれており(cron/daily_report.php)、daily-report-all.sh 経由で実行されます。個別に設置する必要はありません。
  • collect-metrics-all.sh/usr/local/bin/chmod +x)— パネルの cron/collect_metrics.php を実行します(「パフォーマンス」ページ、上記 crontab の */5 の行)。collect_metrics.php はすでにパネルに含まれており、個別に設置する必要はありません。
  • crontab.txt (system/cron/) — ジョブのサンプル。必要な行を sudo crontab -e で記述してください。
crontab 内のスクリプトのパスは、実際に配置した場所と一致していなければなりません。
スクリプトを /usr/local/bin/ に置く方法。 FileZilla から直接そこへ書き込むことはできません — ディレクトリは root の所有で、SFTP クライアントは SSH_FX_PERMISSION_DENIED を受け取ります。手順はこうです: まずファイルを /tmp にアップロードし(そこは誰でも書き込めます)、次に一つのコマンドで所定の場所へ移します:
# FileZilla で:「リモートサイト」欄に /tmp を入力し、そこへスクリプトをアップロード、 # 次に SSH で(install が所有者と権限を同時に設定、chown/chmod は不要): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # 確認: ファイルが所定の場所にあり、権限が rwxr-xr-x、構文が正常 bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
ディレクトリを取り違えないでください: 必要なのはサーバールートの /tmp であり、/var/tmp でもパネル内の tmp/ でもありません(後者は www-data の所有で、あなたのユーザーからはアクセスできません)。FileZilla のツリーでは /tmp は最上位のブランチで、var の隣にあり、その中ではありません。
サーバーを自動セットアップで構築しましたか? これらのラッパーとその cron ジョブは、スクリプトによってすでにインストール済みです(/usr/local/bin/、ログは /var/log/arciveo-cron.log)— 手動で行うことは何もありません。
スクリプトがパネルを探す場所。 ラッパーはドメイン非依存です。/home/*/web/*/public_html/var/www/* を巡回してパネルのインストールを見つけ、レポートをその data/ に置きます。パネルが別のパスにある場合は、スクリプト内の for app in … の行に追加してください。そうしないと Lynis/SMART/debsums/Logwatch のレポートがパネルに反映されません。
cron.log とアクセス権。 ファイル logs/cron.log を最初に作成するのは root crontab です — root の所有となり、パネルの「cron ログ」タブはそれを読むことも消去することもできなくなります。事前に web ユーザー(サイトディレクトリの所有者。HestiaCP ではアカウント、例: admin)としてファイルを作成しておいてください — そうすれば root crontab は所有者を変えずに追記するだけになります:
# web ユーザーで事前に作成(cron 行を追加する前に): sudo -u OWNER touch /path/to/monitor/logs/cron.log # cron.log がすでに root crontab で作成されている場合 — web ユーザーに渡す: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
ディレクトリの所有者を調べる: stat -c %U /path/to/monitor
パネルからの管理。「システム」セクションに 「Crontab」ページがあり、SSH なしでジョブの表示・追加ができます。パネルが編集するのは、パネル自身で追加したジョブのみ(root-crontab 内の専用ブロック、サービスコメントで区切られています)。すでに crontab にあるもの(上記のリスト)はすべて、そこに「その他のサーバージョブ」という読み取り専用リストとして表示され、「エディターにコピー」ボタンがあります — このボタンはスケジュール/コマンドを追加フォームに移すだけで、元の行には手を触れません。既存のジョブをパネル管理下に「移行」するには — エディターにコピーして保存し、その後で古い行を手動で削除してください(sudo crontab -e)。でないと二重に実行されます。
サーバー側での一度きりの設定。 このページには特権的なラッパースクリプトが必要です — 生の sudo crontab ではなく(それではパネルのセッションにアクセスできた誰でもが root へ直接昇格できてしまいます)、2 つのコマンド(list/set)だけを持ち、サービスコメントで区切られた自分のブロックのみを操作する限定的なスクリプトです。一度だけインストールしてください:
sudo install -m 0755 -o root -g root /dev/stdin /usr/local/sbin/arciveo-cron <<'ARCIVEO_CRON_EOF' #!/bin/bash set -euo pipefail BEGIN='# >>> ARCIVEO-CRON-MANAGED (edited from the panel; do not edit by hand) >>>' END='# <<< ARCIVEO-CRON-MANAGED <<<' cmd=${1:-} case "$cmd" in list) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} list" >&2; exit 2; } crontab -l -u root 2>/dev/null || true ;; set) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} set (body on stdin)" >&2; exit 2; } body=$(cat) if grep -qF "$BEGIN" <<<"$body" || grep -qF "$END" <<<"$body"; then echo "invalid body: markers not allowed" >&2; exit 2 fi current=$(crontab -l -u root 2>/dev/null || true) tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT { if grep -qF "$BEGIN" <<<"$current"; then awk -v b="$BEGIN" '{print} $0==b{exit}' <<<"$current" else [ -n "$current" ] && printf '%s\n' "$current" echo "$BEGIN" fi printf '%s\n' "$body" echo "$END" if grep -qF "$END" <<<"$current"; then awk -v e="$END" 'f{print} $0==e{f=1}' <<<"$current" fi } > "$tmp" crontab -u root "$tmp" ;; *) echo "usage: ${0##*/} <list|set>" >&2; exit 2 ;; esac ARCIVEO_CRON_EOF echo "www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/arciveo-cron" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c
web ユーザーは www-data と異なる場合があります — サイトの PHP-FPM プールがどのユーザーで動作しているかを確認し(ps -o user= -C php-fpm)、それを sudoers の行に指定してください。
新しいファイルが別の所有者でアップロードされ、ページが「Access denied.」を返す。 ファイル public/crontab_monitor.php が、サイトの他のファイルとは別のシステムユーザー(例: root)で FTP/SFTP 経由でアップロードされると、web サーバーはそれを読めません。隣接ファイルと所有者・権限を照合して合わせてください:
ls -la public/crontab_monitor.php public/ssl_monitor.php sudo chown OWNER:OWNER public/crontab_monitor.php sudo chmod 644 public/crontab_monitor.php

診断

36. ツールがインストール済みなのに「未インストール」と表示される

モニターは dpkg-query(APT のパッケージデータベース)でツールの有無を判定します。apt 以外の方法(手動、snap、ソースからのビルド)でインストールした場合、dpkg では認識されません。

# dpkg で確認: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # バイナリのパスを探す: which ufw fail2ban-client auditctl # www-data からの sudo をテスト: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

37. トラブルシューティング(500、データ表示なし)

500 エラー — PHP、nginx、およびモニター自体のログを確認してください:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # モニターのログ: tail -50 logs/monitor_$(date +%Y-%m-%d).log # フォルダの権限: ls -la data/ tmp/ logs/
ホスティングパネル(HestiaCP、ISPmanager、cPanel)上のダッシュボードですか? そこでは PHP は www-data ではなく ユーザーアカウント(例えば admin — サイトディレクトリの所有者)で動作します。すべての sudo ルールとグループ所属(admsystemd-journal)は このユーザーに対して設定する必要があります。さもないとサービスが稼働していてもモジュールが「非アクティブ / 0」と表示します。実際の PHP ユーザーを調べるには: ps -o user= -C php-fpm | sort -u またはサイトディレクトリの所有者 stat -c '%U' /path/to/monitor。以下のすべてのコマンドで www-data の代わりにそれを使用してください。自動インストールはウェブユーザーを自動的に判別し、それに対して sudoers を設定します。

データが表示されない — ほとんどの場合 sudo 権限が未設定です。ウェブユーザーとして具体的なコマンドを確認してください(www-data を自分のユーザーに置き換え)。フラグ -n = パスワードなし(PHP と同じ)— パスワードを求められる場合、sudoers にルールがありません:

sudo -u www-data sudo -n fail2ban-client status sudo -u www-data sudo -n ufw status verbose sudo -u www-data sudo -n ipset list -t ipsum sudo -u www-data sudo -n /usr/sbin/ausearch -m USER_LOGIN -ts today sudo -u www-data sudo -n /usr/sbin/aa-status sudo -u www-data sudo -n /usr/sbin/psad --Status sudo -u www-data journalctl -u falco --no-pager -n 5
ツールは動作しているのにモジュールが「非アクティブ」/「0」と表示する(例えば端末で sudo aa-status はプロファイルを表示するのに「AppArmor」ページは「非アクティブ」)。原因: ウェブユーザーにそのモジュールのコマンドに対する sudo 権限がありません。上記の一覧から確認してください: パスワードを求められる場合、不足している行を /etc/sudoers.d/monitor に追加してください(「sudo の設定」)。よくある「新しい」コマンド: /usr/sbin/aa-status(MAC)、/usr/sbin/psad --Status(PSAD)。
特定のページ(Falco、ModSecurity、Auditd、UFW の開放ポート)が空の場合、sudo に関するセクションの一覧と照合してください: おそらく apache2ctlausearchaa-statusss が許可されていないか、ウェブユーザーが adm/systemd-journal グループに属していません(そこから fail2ban/auth/modsec のログと journalctl — Falco とカーネルイベント — が読み取られます)。

38. サーバーにデータがあるのにページが空になる

症状:サーバーにはデータがあり(shell では見える)、ページには「データなし」または誤ったステータスが表示される。たとえば AIDE のデータベースは作成済みなのに「未初期化」と表示される。

原因は open_basedir です。多くのパネルやホスティングは PHP-FPM プールをドメインのディレクトリに制限するため、システムパス(/var/lib/aide/var/log/proc など)に対する PHP 関数 file_exists()file_get_contents()filemtime() がブロックされます。モニターはこうしたパスを標準のシステムコマンド(catteststat)で読み取ることで回避します。

# shell からファイルが見えるか(モニターの読み取り方法): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # ドメインのプールの現在の open_basedir 値: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
shell では「見える」(VISIBLE)のにページで見えない場合、それは open_basedir です。正しい対処はシステムコマンドでの読み取りです(AIDE とネットワークモニターでは対応済み)。open_basedir/var/proc に拡張する必要はなく、安全性も下がります。

39. SSLページが動作しない

モニターはポート443経由でドメインに直接接続して証明書を確認します。サーバー自体からドメインにアクセスできない場合や、ポートがファイアウォールで閉じられている場合は、確認が失敗します。

# 証明書を手動で確認: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # 到達性を確認: curl -I https://monitor.example.com
ドメインはモニターがNginxの設定ファイル(/etc/nginx/sites-enabled//etc/nginx/conf.d/)とApache(/etc/apache2/sites-enabled/)から自動で取得し、さらにHTTP_HOSTの現在のホストも含めます。
サブドメインの自動検出。 サブドメインはCertificate Transparencyの公開ログから自動で検出され、ネットワーク経由で確認されます。別のサーバーに配置されている場合でも同様です。手動で追加する必要はありません。

40. 複数あるうち1つのDBしか表示されない

モニターはconfig.phpのユーザーでMySQLに接続しますが、そのユーザーは自分のデータベースにしかアクセスできません。MySQLはinformation_schemaに権限のあるデータベースのみを表示するため、それ以外は見えません。

モニターにすべてのDBを表示させるには、このユーザーに読み取り専用の権限を付与してください(rootで一度だけ実行し、config.phpのユーザー名に置き換えてください):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* は読み取り権限のみを付与します。変更・削除・作成は一切できないため、監視用途では安全です。
このGRANTがない場合、ダッシュボードには自分のデータベースしか表示されません。これはエラーではなく権限の制限です。ダッシュボードはsudo mysqlを使用しません。データベースの一覧は独自のPDO接続で取得しています。

41. PostgreSQL が「データベース」ページに表示されない

PostgreSQL には postgres ユーザー権限が必要ですが、パネルの Web ユーザーにはこの権限がありません。PHP から広い権限の sudo psql を開くのは危険です。代わりにパネルは、パラメーターなしの限定的なラッパーを呼び出し、バージョン・接続数・サイズ付きのデータベース一覧のみを出力します。これを作成してください:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Monitor - read-only PostgreSQL version, connections and per-database size sudo -u postgres psql -tAc "SELECT version();" | grep -oE 'PostgreSQL [0-9.]+' echo "---" sudo -u postgres psql -tAc "SELECT count(*) FROM pg_stat_activity;" echo "---" sudo -u postgres psql -tAc "SELECT datname || '|' || pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;" EOF sudo chown root:root /usr/local/bin/monitor-pgstat sudo chmod 755 /usr/local/bin/monitor-pgstat # /etc/sudoers.d/monitor 内 (ユーザー = PHP-FPM を実行しているユーザー): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
PostgreSQL を使わない場合は、sudoers から monitor-pgstat の行を削除し (手動インストールの手順 13)、スクリプト自体も作成しないでください: PostgreSQL のカードは非アクティブのまま表示されます。

42. アラートが発生した — 対処方法

ダッシュボードは何が起きているかを示します。以下は典型的なケースでどう対処するかです。基本方針は、慌てず、正規のアクティビティ(自分の操作、更新、バックアップ)と照合し、深刻度に応じて対応することです。

  • 攻撃マップ/fail2ban のban多数 — インターネット上のどのサーバーでも通常のことです(ボットが常に SSH/Web を試行します)。重要なのはbanが機能していることです。SSH ログインが鍵のみ(パスワード無効)で、自分の IP が ignoreip にあることを確認してください。
  • ModSecurity がリクエストをブロックした — WAF がサイトへの攻撃を防いでいるだけで、これがその役目です。正規のトラフィックがブロックされる(誤検知)場合は、詳細から rule id を探し、CRS の設定に除外を追加してください。
  • AIDE: ファイルが変更された — 自分がやったこと(パッケージ更新、設定編集は通常)とリストを照合してください。触れていないシステムバイナリの変更は要警戒です。正規の変更後は AIDE のデータベースを更新してください。
  • debsums: バイナリ/ライブラリが変更された/etc 外、/usr/share 外)— 改竄の可能性があります。パッケージを照合し(debsums PACKAGE_NAME)、疑わしければ再インストールしてください(apt install --reinstall)。
  • ClamAV/maldet: 脅威を検出 — 隔離されたファイルを確認し、開かないでください。サイトのディレクトリ内の Web シェルの場合は、サーバーを隔離し侵入経路(脆弱なプラグイン、認証情報の漏洩)を探してください。
  • Falco: 重大なイベント(コンテナ内での shell 起動、機密ファイルへのアクセス)— イベントを解析してください: 誰のプロセスか、何が起動したか。多くは正規の管理者アクティビティです。
  • 外部への露出: DB/キャッシュが赤色 — 直ちに閉じてください: サービスを 127.0.0.1 にバインドするか、UFW でポートを閉じます。これは実際の穴です。
  • SSL の期限切れ間近/期限切れ — 証明書を更新してください(Let's Encrypt は自動更新されます。されない場合は certbot renew やダッシュボードの設定を確認してください)。
  • セキュリティ更新が保留中 — インストールしてください: sudo apt update && sudo apt upgrade。カーネル更新後はサーバーを再起動してください。
実際の侵害の兆候(不明なプロセス/ユーザー、変更されたバイナリ、外向きのスパム、不明な cron ジョブ): サーバーを外部アクセスから遮断し、解析用のバックアップを取り、データが重要であれば信頼できるバックアップからクリーンなサーバーを立ち上げてください — rootkit を確実に除去するのは困難です。
Arcivéo - Security Monitor © 2026