ERROR 2003修正: MySQLサーバーへの接続拒否エラー (Connection Refused)

intermediate🗄️ MySQL2026-05-31| MySQL 5.7 / 8.0、Ubuntu / Debian / CentOS、リモートクライアント接続

Error Message

ERROR 2003 (HY000): Can't connect to MySQL server on 'hostname' (111)
#mysql#接続#リモート#ファイアウォール#bind-address

状況

別のマシン(ステージングサーバー、クラウドVM、専用DBホストなど)で動作しているMySQLサーバーに接続しようとしています。次のコマンドを実行すると:

mysql -h 192.168.1.100 -u myuser -p

すぐにこのエラーが表示されます:

ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.1.100' (111)

(111)が重要なヒントです。これはLinuxのECONNREFUSEDに対応するerrno値で、サーバーがTCP接続を明示的に拒否したことを意味します。パケットが無音でドロップされるタイムアウト(110)とは異なります。MySQLが接続を受け取る前に何かがブロックしているか、MySQLがそのアドレスでリッスンしていないかのどちらかです。

まず診断する — 推測しない

設定を変更する前に、接続が失敗している箇所を正確に特定しましょう。クライアントマシンから以下を実行します:

# ホストに到達できるか確認
ping 192.168.1.100

# ポート3306が開いていて接続を受け付けているか確認
nc -zv 192.168.1.100 3306
# または
telnet 192.168.1.100 3306

ncからConnection refusedが返る場合は、ファイアウォールまたはMySQLのbindアドレスの問題です。タイムアウトはファイアウォールがパケットを無音でドロップしていることを意味します。接続に成功した場合はMySQLへの到達は可能ですが、その場合は2003とは異なるエラーが表示されるはずです。

原因1:MySQLがローカルホストのみでリッスンしている

これが最も一般的な原因です。デフォルトでは、MySQLは127.0.0.1にバインドされており、同じマシンからの接続しか受け付けません。リモートからの接続試行はすぐに拒否されます。

MySQLが実際に何をリッスンしているか確認します — DBサーバー上で実行してください:

sudo ss -tlnp | grep 3306
# または古いシステムの場合:
sudo netstat -tlnp | grep 3306

127.0.0.1:3306と表示される場合、MySQLはローカル接続しか受け付けていません — これが原因です。0.0.0.0:3306の場合はすでに全インターフェースでリッスンしているので、原因2に進んでください。

修正:my.cnfのbind-addressを変更する

MySQLの設定ファイルを探します — Ubuntu/Debianでは通常/etc/mysql/mysql.conf.d/mysqld.cnf、CentOS/RHELでは/etc/my.cnfです:

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

bind-addressの行を見つけて変更します:

[mysqld]
# 変更前:
bind-address = 127.0.0.1

# 変更後(全インターフェースでリッスン):
bind-address = 0.0.0.0

全インターフェースではなく特定のLAN IPでリッスンしたい場合は、そのIPを指定します:

bind-address = 192.168.1.100

MySQLを再起動して変更を反映します:

sudo systemctl restart mysql
# または古いシステムの場合:
sudo service mysql restart

MySQLが正しいアドレスでリッスンしているか確認します:

sudo ss -tlnp | grep 3306
# 0.0.0.0:3306 または指定したIPが表示されるはず

原因2:ファイアウォールがポート3306をブロックしている

MySQLが全インターフェースでリッスンしていても、到達できないことがあります。OSのファイアウォールやクラウドのセキュリティグループが、ポート3306への受信トラフィックを到達前にドロップしている可能性があります。

Ubuntu/Debian(UFW)での修正

# 特定のIPからのアクセスを許可(推奨):
sudo ufw allow from 192.168.1.50 to any port 3306

# またはサブネットからのアクセスを許可:
sudo ufw allow from 192.168.1.0/24 to any port 3306

# 状態を確認:
sudo ufw status

CentOS/RHEL(firewalld)での修正

# MySQLポートを許可:
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload

# または特定のソースからのアクセスを許可:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload

iptablesで直接修正する

sudo iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT
# 永続化する:
sudo iptables-save > /etc/iptables/rules.v4

AWS、GCP、Azureを使用している場合は、セキュリティグループ / VPCファイアウォールルールも確認してください。OSのファイアウォールとクラウドのファイアウォールは別々のレイヤーです — UFWを修正するのに20分かけたのに、セキュリティグループでポート3306がまだブロックされていたという経験があります。

原因3:MySQLが起動していない

正直なところ、他の何よりも先に確認すべきことです:

sudo systemctl status mysql
# または:
sudo systemctl status mysqld

起動していない場合は、起動して自動起動を有効にします:

sudo systemctl start mysql
sudo systemctl enable mysql

起動に失敗する場合は、ログに原因が記録されています:

sudo journalctl -u mysql --no-pager -n 50
# または:
sudo tail -100 /var/log/mysql/error.log

原因4:ポートまたはホスト名が間違っている

非標準ポートは意外と多くの人を混乱させます。サーバーでMySQLが実際に使用しているポートを確認します:

sudo ss -tlnp | grep mysql

そして明示的にポートを指定して接続します:

mysql -h 192.168.1.100 -P 3307 -u myuser -p

IPの代わりにホスト名を使用している場合は、DNSが正しく解決されているか確認します:

nslookup db.example.com
# または:
dig db.example.com

接続を修正した後 — MySQLユーザーにリモートアクセスを付与する

TCPは開いていて、MySQLもリッスンしているのに、今度はAccess deniedが表示される場合があります。MySQLのユーザーアカウントは接続元のホストに紐付けられています。'myuser'@'localhost'として作成されたユーザーは、正しいパスワードを使っていてもリモートからログインできません。

DBサーバーにローカルでログインし、リモートアクセスを付与します:

mysql -u root -p

-- 任意のIPからのアクセスを許可(開発環境では問題ないが、本番環境ではリスクあり):
CREATE USER 'myuser'@'%' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%';
FLUSH PRIVILEGES;

-- より安全:特定のIPに制限する:
CREATE USER 'myuser'@'192.168.1.50' IDENTIFIED BY 'your_password';
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'myuser'@'192.168.1.50';
FLUSH PRIVILEGES;

'%'ワイルドカードは任意のIPからの接続を許可します。ローカル開発では便利ですが、本番環境では絶対に使用しないでください。

修正を確認する

# クライアントマシンから — まずTCP接続をテスト:
nc -zv 192.168.1.100 3306
# 期待される結果: Connection to 192.168.1.100 3306 port [tcp/mysql] succeeded!

# 次にMySQLログインをテスト:
mysql -h 192.168.1.100 -u myuser -p mydb
# 期待される結果: MySQLプロンプト

TCPは通るがMySQLログインに失敗する場合は、ERROR 2003を超えて認証の問題になっています — 上記のユーザー権限を確認してください。

セキュリティに関する注意 — ポート3306を全世界に開放しない

ファイアウォールルールは常に特定のIPまたはサブネットに限定してください。公開サーバーでMySQLを0.0.0.0/0に公開するのは危険です — 自動スキャナーが数分以内にポート3306を発見し、プローブを開始します。アプリサーバーとDBが同じVPCにある場合は、そのサブネットに制限してください。リモート開発者のアクセスには、SSHトンネルの方がよりクリーンで安全です:

# SSHトンネル — ローカルポート3307をリモートMySQLに転送
ssh -L 3307:127.0.0.1:3306 user@192.168.1.100 -N -f

# その後ローカルで接続:
mysql -h 127.0.0.1 -P 3307 -u myuser -p

MySQLはネットワークに公開する必要はまったくありません。

Tips

複数のサブネットにまたがるファイアウォールルールを記述する際、CIDRレンジの計算ミスは起こりがちです。192.168.1.50のようなIPが192.168.1.0/24の範囲内に実際に含まれているかどうかを、ルールを確定する前に素早く確認するために、ToolCraftのSubnet Calculatorを使っています。ブラウザベースでデータのアップロードなし — さっと確認するのに重宝します。

Related Error Notes