はじめに
最近、負荷分散のためにアプリケーションサーバーとMySQLサーバーを分離し、MySQLに外部ホストから接続する必要があったのですが、その際に知識不足でいくつか躓いた点があったため、まとめます。
MySQLに外部ホストから接続するために必要な設定は、大きく以下の3点です。
- MySQLサーバーの
bind-address - アカウント管理
- 権限管理
※ MySQLの外側のファイアーウォールなどについては言及しないです
bind-address
bind-addressは、MySQLサーバーがどのネットワークインターフェース(IPアドレス)で接続を待ち受けるのかを指定するものです。
デフォルトの設定だと、bind-addressにはループバックアドレスである127.0.0.1のみが指定されているため、外部から接続可能なIPアドレスを持っていたとしても、外部ホストからの接続を受けることはできません。
SHOW VARIABLES LIKE "bind%";
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| bind_address | 127.0.0.1 |
+---------------+-----------+
1 row in set (0.01 sec)
外部ホストからの接続を許可するためには、このbind-addressに接続を待ち受けるネットワークインターフェースのIPアドレスを追加する必要があります。
今回はプライベートネットワークで、自ホストに192.168.0.1、外部ホストに192.168.0.2が割り当てられていると想定します。
この場合、接続を待ち受けるネットワークインターフェースのIPアドレスである192.168.0.1をbind-addressに追加します。
bind-addressは設定ファイルの[mysqld]セクションで管理されているため、そちらを変更します。(設定ファイルは/etc/mysql/配下にあります)
[mysqld]
# ...
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1,192.168.0.1
# ...
MySQLサーバーの設定の変更であるため、変更後はリスタートが必要です。
この状態だと外部ホストから通信ができるようになりましたが、接続するためのアカウントが存在しないため、操作ができません。
アカウント管理
MySQLのアカウントは、「ユーザー名」と「接続元ホスト」の組み合わせによって一意に識別されます。
形式はユーザー名@接続元ホストになります。
外部ホストから接続をするためには、対象ホストが「接続元ホスト」に指定されているアカウントを作成する必要があります。
同様に自ホストが192.168.0.1、外部ホストが192.168.0.2を想定して、「接続元ホスト」を192.168.0.2としてアカウントを作成します。
特に「接続元ホスト」を指定せずに「ユーザ名」のみを指定して作成した場合、Hostにはワイルドカード(%)が入ります。
CREATE USER 'tsuzuki-takaaki'@'192.168.0.2' IDENTIFIED BY 'password';
SELECT User, Host FROM mysql.user;
+-------------------+-------------+
| User | Host |
+-------------------+-------------+
| tsuzuki-takaaki | 192.168.0.2 |
| debian-sys-maint | localhost |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+-------------------+-------------+
これによって、外部ホスト(今回の例だと192.168.0.2)からの接続が可能になります。
$ mysql -utsuzuki-takaaki -ppassword -h192.168.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.42-0ubuntu0.24.04.1 (Ubuntu)
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
これで外部ホストからの接続は可能になったのですが、このままだとアカウントに権限がなく、データベースに対する操作がほとんどできないため、権限の設定についても確認しておきます。
権限管理
アカウントがどのスコープ(データベースやテーブルなど)に対して、どの操作を実行できるかを制御するのが、権限管理です。
上記の例のようにアカウントを作成しただけだと、特に権限が付与されておらず、ほとんど何もできない状態です。
USAGE権限は、「権限なし」を意味しています。
https://dev.mysql.com/doc/refman/8.4/en/privileges-provided.html#priv_usage
SHOW GRANTS FOR 'tsuzuki-takaaki'@'192.168.0.2';
+-------------------------------------------------------+
| Grants for tsuzuki-takaaki@192.168.0.2 |
+-------------------------------------------------------+
| GRANT USAGE ON *.* TO `tsuzuki-takaaki`@`192.168.0.2` |
+-------------------------------------------------------+
1 row in set (0.00 sec)
GRANTステートメントで、アカウントに対して権限を付与します。
- グローバル
- スキーマ(データベース)
- テーブル
の3つのスコープがあり、それぞれ以下のように権限を付与することができます。
-- グローバル
GRANT AUTHORITY_NAME ON *.* TO ACCOUNT;
-- スキーマ(データベース)
GRANT AUTHORITY_NAME ON SCHEMA_NAME.* TO ACCOUNT;
-- テーブル
GRANT AUTHORITY_NAME ON SCHEMA_NAME.TABLE_NAME TO ACCOUNT;
(※ 上記のAUTHORITY_NAME, SCHEMA_NAME, TABLE_NAME, ACCOUNTは適宜読み替えてください)
付与できる権限は以下で確認していただけます。
今回は検証なので、作成したアカウントに対してグローバルスコープで「読み取り権限」を付与しておきます。
GRANT SELECT ON *.* TO `tsuzuki-takaaki`@`192.168.0.2`;
SHOW GRANTS FOR 'tsuzuki-takaaki'@'192.168.0.2';
+--------------------------------------------------------+
| Grants for tsuzuki-takaaki@192.168.0.2 |
+--------------------------------------------------------+
| GRANT SELECT ON *.* TO `tsuzuki-takaaki`@`192.168.0.2` |
+--------------------------------------------------------+
1 row in set (0.00 sec)
これで想定通りに外部ホストからMySQLサーバーに対して、接続・操作ができるようになります。
Refs