MySQLサーバーがブルートフォース攻撃に「晒された」とき
MySQLのログを確認した際、見覚えのないIPアドレスからの何千行もの Access denied を見て驚いたことはありませんか?ある土曜日の夜、私も同じような状況に陥りました。監視システムがサーバーのCPU使用率が90%に達したことを知らせてきたのです。最初はコードの無限ループかと思いましたが、 processlist を詳しく調べると、認証待ちの状態で大量の接続が滞留していました。
攻撃者は通常、自動スクリプトを使用して数百万通りのパスワードを試行します。たとえパスワードが十分に強力であっても、MySQLが1秒間に数千もの接続要求を処理しなければならない状況は、RAMとCPUを浪費します。実際、各接続スレッドは5MBから10MBのRAMを消費することがあります。これを阻止しなければ、サーバーはすぐにリソースを使い果たし、アプリケーションがハングアップしてしまいます。
複雑なファイアウォール設定に苦労する代わりに、MySQLの Connection Control Plugin を活用できます。このプラグインは、辛抱強い「門番」のように機能します。ログインに失敗した者に対して、次回の試行までの待ち時間を長く強制するのです。
Connection Controlの動作原理
このプラグインはMySQL 5.7.17から利用可能です。その原理は非常に実用的です。入力を間違えれば間違えるほど、サーバーのレスポンスが遅くなります。これは、高速な試行を必要とするブルートフォース・スクリプトの弱点を直接突くものです。
サーバーによる「ペナルティ」の仕組み
この設定は、主に2つの重要なパラメータに基づいています。
- Threshold: 許容される最大ログイン失敗回数の閾値。
- Delay: 閾値を超えた後の失敗した試行に対してサーバーが適用する遅延時間(ミリ秒)。
少し計算してみましょう。通常、スクリプトは1秒間に100個のパスワードを試行できます。もし遅延(delay)を1000ms(1秒)に設定すれば、その速度は1秒間にわずか1個のパスワード試行にまで低下します。完了までに2日かかると予想されていた攻撃は、数年かかる計算になります。
実際のインストールと設定手順
本番サーバーでこの機能を有効にする手順は以下の通りです。
1. プラグインのインストール
デフォルトでは、このプラグインは有効になっていません。root権限でMySQLにログインし、現在のステータスを確認する必要があります。
SHOW PLUGINS LIKE 'connection%';
リストが空の場合は、以下の2つの主要コンポーネントをインストールするコマンドを実行します。
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
SHOW PLUGINS で再度確認してください。ステータスが ACTIVE になっていれば、準備は半分完了です。
2. 最適なパラメータの設定
デフォルト値のままにしないでください。私は通常、チームメンバーが誤ってパスワードを打ち間違えた際にも困らないよう、バランスの取れた設定を推奨しています。
-- 最大3回までの失敗を許可
SET GLOBAL connection_control_failed_connections_threshold = 3;
-- 2秒(2000ms)からペナルティを開始し、最大10秒(10000ms)まで段階的に増加
SET GLOBAL connection_control_min_connection_delay = 2000;
SET GLOBAL connection_control_max_connection_delay = 10000;
ここで、 min_connection_delay は初期のペナルティ時間です。攻撃者が執拗に試行を続けると、待ち時間は max_connection_delay の上限に達するまで徐々に増加します。
3. 設定の永続化
SET GLOBAL コマンドによる設定は、MySQLを再起動すると消えてしまいます。長期的な安全性を確保するために、 my.cnf (またはUbuntuの場合は mysqld.cnf )ファイルにこれらを追加しましょう。
[mysqld]
plugin-load-add = connection_control.so
connection_control_failed_connections_threshold = 3
connection_control_min_connection_delay = 2000
connection_control_max_connection_delay = 10000
その後、サービスを再起動して変更を適用します。
sudo systemctl restart mysql
攻撃遮断の効果を監視する
プラグインが効果的に動作しているかを確認するには、以下の統計テーブルを確認してください。
SELECT * FROM INFORMATION_SCHEMA.CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
このテーブルには、違反しているユーザーとホスト(IP)の詳細がリストされます。もし見慣れないIPの FAILED_ATTEMPTS 数が数百に達していれば、Connection Controlがサーバーを正常に保護している証拠です。
実体験からのアドバイス:自爆に注意
以前、ジュニアエンジニアが移行スクリプトを書いた際、古いパスワードを書き換えるのを忘れていたことがありました。スクリプトはループでデータベースへの呼び出しを繰り返しましたが、Connection Controlのおかげで、接続過多によるサーバーダウンは免れました。スクリプトの動作が非常に遅くなりタイムアウトが発生したことで、わずか5分でミスを発見し対処することができました。
ただし、一つ注意点があります。最初から min_connection_delay を高く設定しすぎない(30〜60秒など)ようにしてください。ネットワークの不安定さが原因で偶発的な認証エラーが発生した場合、正当なユーザーまで遅延キューに巻き込まれ、ユーザー体験が著しく低下してしまいます。
終わりに
Connection ControlはVPNやファイアウォールを完全に代替するものではありませんが、自動スキャン攻撃に対する非常に強力な防御層となります。わずか5分の設定で、データベースの制御権を奪われるリスクを最小限に抑え、サーバーリソースを大幅に節約できます。もしサーバーの3306ポートを公開しているなら、今すぐ有効にすることをお勧めします。

