XServer VPS セキュリティ復旧&n8n/Dify再構築ノウハウ
XServer VPS セキュリティ復旧&n8n/Dify再構築ノウハウ
何が起きたか
2026年1月10日、VPSが不正アクセスを受けマルウェア(XMRig仮想通貨マイナー)に感染。XServerがアウトバウンド通信を全ブロック。約2ヶ月間、外部通信が不通の状態が続いた。
侵入経路
- 主因:Difyの脆弱性(CVE-2025-67732)を突かれた
- 副因:rootへのSSHパスワード認証が有効だった
感染の証拠
ps aux | grep -v "\["
# uid=1001のプロセスが実行中:
# pkill -f donate-level ← XMRig(仮想通貨マイナー)の競合排除
# pkill -f curl
教訓
脆弱性通知メールは即日対応
XServerからの通知メールを見逃したことが最終的な原因。
仕組みで防ぐことが重要。
監視の仕組み化
# /usr/local/bin/security_check.sh
SUSPICIOUS=$(ps aux | grep -E "xmrig|minerd|donate-level" | grep -v grep)
if [ -n "$SUSPICIOUS" ]; then
echo "$SUSPICIOUS" | mail -s "【警告】VPSに不審なプロセスを検知" your@email.com
fi
# crontabで1時間ごとに実行
Watchtowerで自動更新+通知
watchtower:
image: containrrr/watchtower
environment:
- WATCHTOWER_NOTIFICATIONS=email
- WATCHTOWER_SCHEDULE=0 0 2 * * * # 毎日深夜2時
- WATCHTOWER_CLEANUP=true
復旧手順
1. データのバックアップ(SSH経由)
# n8nワークフローのエクスポート
docker exec n8n n8n export:workflow --all --output=/tmp/workflows.json
docker cp n8n:/tmp/workflows.json /root/workflows_backup.json
# ローカルPCにダウンロード
scp root@210.131.212.67:/root/workflows_backup.json ~/Desktop/
2. OS再インストール
XServerコントロールパネルから実行。SSH公開鍵をこの時点で登録する。
3. SSH接続時の警告対処
# ホストキーが変わるため古い情報を削除
ssh-keygen -R 210.131.212.67
ssh -i ~/.ssh/xvps_ed25519 root@210.131.212.67
4. SSHセキュリティ強化
# /etc/ssh/sshd_config
PermitRootLogin prohibit-password # 鍵認証のみ許可
PasswordAuthentication no # パスワード認証を無効化
Note: パスワード認証を無効にしてもブルートフォース攻撃自体は来る。ただし全て弾かれるので問題なし。Fail2banを入れるとさらに安全。
Dify + n8n 再構築
構成
foresthill.xvps.jp/ → Dify
foresthill.xvps.jp/n8n/ → n8n
Nginxがパスで振り分けるため互いに干渉しない。
docker-compose.yamlへのn8n追加
# services セクションの末尾に追加
n8n:
image: n8nio/n8n:latest
container_name: docker-n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_RUNNERS_ENABLED=true
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_PATH=/n8n/
- WEBHOOK_URL=https://foresthill.xvps.jp/n8n/
- N8N_EDITOR_BASE_URL=https://foresthill.xvps.jp/n8n/
volumes:
- n8n_data:/home/node/.n8n
# volumes セクションの末尾に追加
n8n_data:
NginxへのLocation追加
重要ポイント:
~/dify/docker/nginx/conf.d/default.confは自動生成されるので直接編集しないdefault.conf.templateを編集する- templateは
envsubstで処理されるため$nginx変数はそのまま書ける $http_upgradeは未定義になるため使わない →include proxy.confに任せる- git pull時にtemplateが上書きされる可能性があるため 別ファイルで管理するのがベスト
# conf.d/n8n.conf は単体では動かない(server{}ブロックが必要)
# templateに直接追加する方式が正解
nano ~/dify/docker/nginx/conf.d/default.conf.template
追加するlocationブロック(location / の直前):
location /n8n/ {
proxy_pass http://n8n:5678/;
include proxy.conf;
}
Gotcha: WebSocket用に
proxy_set_header Upgrade $http_upgrade;を追加するとenvsubstで空に置換されてNginxが起動失敗する。proxy.confに必要なヘッダーが含まれているのでそれで十分。
再起動
cd ~/dify/docker
docker compose up -d n8n
docker compose restart nginx
docker ps | grep -E "n8n|nginx"
ワークフローのインポート
docker cp ~/workflows_backup.json docker-n8n:/tmp/
docker exec docker-n8n n8n import:workflow --input=/tmp/workflows_backup.json
SSL証明書について
XServerの「ドメイン・SSLクイック設定」または2025年1月22日以降のDifyアプリイメージを使用している場合、自動更新されるため手動対応不要。
アウトバウンド通信が回復すれば自動的に証明書が更新され、HTTPSの鍵が閉まる。
診断コマンド集
# 不審プロセス確認
ps aux | grep -E "xmrig|minerd|donate-level|kworkerds"
# アウトバウンド通信確認
curl -I https://google.com --max-time 10
# certbot接続確認
curl -v https://acme-v02.api.letsencrypt.org/directory --max-time 10
# Nginxエラーログ
docker logs docker-nginx-1 --tail 20
# SSH攻撃ログ
grep "Failed\|Accepted" /var/log/auth.log | tail -30
関連リンク
- XServer VPS パケットフィルター設定
- [n8n CVE-2026-27494/27495/27498](github/n8n-io/n8n 🔗
- Dify公式Docker構成|github/langgenius/dify)]] 🔗)