💬 くるるちゃんのワンポイント図解解説
【技術背景・解説】
この記事(IPSセキュリティ強化でスマホからアクセスできなくなった話 ─ 自分のIPを自分でブロックした顛末)におけるIT技術の基本概念と重要ポイントを、わかりやすく整理・解説しています。
【アイキャッチ図解のポイント】
構成要素とデータフローを視覚的に整理し、初心者でも要点を掴みやすいグラフィック構造で表示しています。
【資格・要点ノート】
シラバス用語、基本概念の理解、実務への応用ポイント
はじめに
VPSで運用しているWebサービス「のうじゅく」のセキュリティを強化する作業を行っていたところ、思わぬ事態が発生しました。セキュリティを強化したはずなのに、自分自身がサイトにアクセスできなくなってしまったのです。
この記事では、IPSダッシュボードのセキュリティ強化作業の中で起きたトラブルと、その調査・解決の過程を記録します。同じようなミスを防ぐための教訓として、参考になれば幸いです。
やったこと:nginx のセキュリティ強化
今回のセキュリティ強化では、以下の対策をnginx設定に追加しました。
- 悪意あるUser-Agent(curl、wget、python-requests、sqlmap、Niktoなど)を即時切断(444レスポンス)
- 接続数制限(limit_conn)の導入 ─ 同一IPからの同時接続数を制限
- レートリミット強化 ─ ログインは2r/s、APIは10r/s
- IPブロックリスト ─ IPS検知した悪意あるIPをnginxレベルで拒否
- Cloudflare以外のオリジン直叩きを403で拒否
ここまでは順調でした。PCからは問題なくアクセスでき、セキュリティも強化されたと思っていました。
問題発生:スマホからアクセスできない
ところが、スマホ(Android Chrome)からサイトにアクセスしようとすると、「ホストエラー」が表示されてページが全く開けません。PCからは正常にアクセスできるのに、スマホだけがダメ。これは困りました。
調査その1:サーバー側の確認
まず疑ったのはサーバー側の問題です。
- Gunicornプロセスは正常稼働中
- Docker内部からの疎通テストも問題なし
- SSLの証明書も期限内(2026年4月まで有効)
- DNSもCloudflare経由で正しく解決
サーバー自体は完全に正常でした。
調査その2:Cloudflareの520エラー
外部からcurlでアクセスしてみると、Cloudflareが520エラー(Web server returned an unexpected response)を返していることが判明。ただし、これはcurlのUser-Agentがボットフィルタでブロックされていたためでした。ブラウザのUser-Agentでテストすると200が返ります。ここで一度ミスリードされかけました。
調査その3:接続数制限の問題
次に、nginxのエラーログを確認しました。
limiting connections by zone "conn", client: 172.64.213.48, server: kurutann.com
接続数制限(limit_conn)に引っかかっていました。IPSダッシュボードは多数のAPIリクエストを同時に発行するため、同一ユーザーの接続カウントが積み上がって制限超過していたのです。全locationで同一のconnゾーンを共有していたことが原因でした。これはlimit_connの値を緩和(10→20、5→15)して対応しました。
しかし、これだけではスマホの問題は解決しませんでした。
調査その4:真犯人はIPブロックリスト
最終的に、nginxのアクセスログ(perfログ)をモバイルUAでフィルタリングしたところ、決定的な証拠が見つかりました。
172.68.119.113 - 2404:7a82:xxxx:xxxx [13/Mar/2026:21:46:57] "GET / HTTP/2.0" 444 0 reason=connection_closed
スマホのIPv6アドレスが444(即時切断)を食らっていたのです。
nginx設定のIPブロックリストを確認すると……
map {
default 0;
"2404:7a82:xxxx:xxxx:xxxx:xxxx:xxxx:x1" 1;
"2404:7a82:xxxx:xxxx:xxxx:xxxx:xxxx:x2" 1;
"2404:7a82:xxxx:xxxx:xxxx:xxxx:xxxx:x3" 1;
}
ブロックリストに入っている3つのIPv6アドレス、全て自分のネットワークのアドレスでした。
前回のセキュリティ強化時に、IPS検知で「攻撃元」として検出されたIPをブロックリストに追加したのですが、それが自分自身のIPv6アドレスだったのです。IPv6はインターフェースIDが定期的に変わるため、PC(デスクトップ)は新しいIPv6アドレスを取得してブロックを回避できていましたが、スマホのIPv6アドレスがブロックリストに残っていたためアクセスできなかったのです。
解決
IPブロックリストから自分のIPv6アドレスを全て削除し、nginxをリロードしました。これでスマホからもアクセス可能になりました。
加えて、KURUCHAのログインロック(Redis上のkurucha:lock:キー)もかかっていたため、こちらも解除しました。ログインの429エラーが連続していた原因はこれでした。
教訓
- 自分のIPは必ずホワイトリストに入れる ─ 特にIPv6は複数のアドレスを持つため、/64プレフィックスなどCIDRで管理すべき
- IPブロックリスト追加時は、既知の自ネットワークと照合する ─ IPS検知の「攻撃元」が自分自身のテスト通信である可能性を常に考慮
- セキュリティ変更後は必ずPC・スマホ両方からテストする ─ IPv6の挙動はデバイスごとに異なる
- limit_connのゾーン設計に注意 ─ 全locationで同一ゾーンを共有すると、SPA的なページで接続カウントが意図せず積み上がる
- nginxの444レスポンスは痕跡が残りにくい ─ 通常のエラーページが表示されないため、クライアント側では「ホストエラー」としか見えず、原因特定が難しい
まとめ
セキュリティ強化は大切ですが、「自分自身をロックアウトしない」ことの確認が最も重要です。今回はIPv6の動的アドレス割り当てという特性と、IPSの誤検知(自分の通信を攻撃と判定)が重なって起きた問題でした。
調査の流れとしては「サーバー正常確認→Cloudflare 520→接続制限→IPブロックリスト」と段階的に絞り込んでいき、最終的にnginxのperfログでモバイルUAのリクエストが444を返していることを発見して解決に至りました。原因特定に最も役立ったのは、カスタムログフォーマットにとを含めていたことです。ログ設計の重要性を改めて実感しました。
コメント(0件)
まだコメントはありません。最初のコメントを投稿してください!