エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

Raspberry Pi OSのMariaDBへ別ホストからアクセスできるようにしたかった

Spring Data JPAについて調べる際に、ラズパイのMariaDBを検証用DBとして使っていたのですが、別ホストからのアクセス制御にちょっと時間を食ったので記録を残しておきたいと思います。なお、JPAについての記載は主題ではないため、あえて割愛しました。

やりたいこと

  • 自宅で稼働させているRaspberry Pi OSのMariaDBに自宅の別ホストからアクセスしたい
    • Raspberry Piとクライアントはどちらも同一ネットワークにいる
    • 外部アクセス専用のMariaDBユーザーを使ってSQL発行したい

動作環境

Raspberry Pi OS

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:   buster

MariaDB(ラズパイ上でsystemdサービスとして動作)

# MariaDB利用に必要なパッケージはaptでインストール済み
$ apt list --installed mariadb-server
一覧表示... 完了
mariadb-server/oldstable,now 1:10.3.31-0+deb10u1 all [インストール済み]

$ mysql --version
mysql  Ver 15.1 Distrib 10.3.31-MariaDB, for debian-linux-gnueabihf (armv8l) using readline 5.2

$ sudo systemctl status mariadb
● mariadb.service - MariaDB 10.3.31 database server
   Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: 
   Active: active (running) since Wed 2022-03-16 00:37:00 JST; 43min ago
...

macOS(クライアント)

% sw_vers
ProductName:    macOS
ProductVersion: 11.6.4
BuildVersion:   20G417

データベースとルートユーザーは既に作成済みとします。

  • アクセス対象のデータベース名: test_database

手順

MariaDBのデフォルト設定ファイルを編集する

MariaDBはデフォルトで外部からのアクセスを拒否している場合があるので、リモートからアクセスさせたい場合は下記の設定ファイルの編集が必要になります。

/etc/mysql/mariadb.conf.d/50-server.cnf

[mysqld]# bind-addressをコメントアウトして無効化する
#bind-address = 127.0.0.1

今回の環境ではループバックアドレスがbind-addressに指定されていたため、アクセスできるのはMariaDBサーバであるラズパイ自身に限定されていました。 このオプションを未指定にすることで、MariaDBは全てのTCP/IP接続をLISTENするようになります。

どうやらUbuntuDebianだとデフォルトでこのオプションが設定される模様。

Server System Variables - MariaDB Knowledge Base

ファイアウォール設定でMariaDB用のポートを許可する

私の場合、ufwファイアウォールを張っていましたので、以下のようにポートを許可しました。

# MariaDBの3306番ポートからのアクセスを許可する
$ sudo ufw allow 3306
Rule added
Rule added (v6)

# 変更内容を反映させるためにufwを再起動する
$ sudo ufw reload
Firewall reloaded

# 変更内容が反映されたか確認する
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
5900                       ALLOW       Anywhere                  
22                         ALLOW       Anywhere                  
3306                       ALLOW       Anywhere                  
5900 (v6)                  ALLOW       Anywhere (v6)             
22 (v6)                    ALLOW       Anywhere (v6)             
3306 (v6)                  ALLOW       Anywhere (v6) 

クライアントから接続テストをする

この段階でMariaDBへの接続自体は可能になっているはずですので、クライアント(macOS)からcurlで接続できるか確認してみます。

% curl -v {Raspberry PiのプライベートIP}:3306
*   Trying ***.****.***.***...
* TCP_NODELAY set
* Connected to ***.****.***.*** (***.****.***.***) port 3306 (#0)
> GET / HTTP/1.1
> Host: ***.****.***.***:3306
> User-Agent: curl/7.64.1
> Accept: */*
> 
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 5)
* Closing connection 0

Connected to ***.****.***.*** (***.****.***.***) port 3306 (#0)が標準出力に出ていれば、接続は成功です。

レスポンスが解釈できない為、Failed writing body (0 != 5)というエラーが出ていますが、今回はあくまで疎通の確認だけがしたかったのでスルーします。

外部から接続するためのユーザーを作成する

運用時に外部からのアクセスについて個別に制御したい場合などに備えて、今回はMariaDBユーザーを新規作成しておきます。 ユーザー名はtest_userとしています。権限設定はセキュリティを考慮してDML(Data Manipulation Language)のみに留めています。

# ルートユーザーでMySQLへ接続する
$ sudo mysql

# 外部アクセス用のユーザーを作成する
MariaDB [(none)]> create user 'test_user'@'%' identified by '{任意のパスワード}';

# ユーザーにSELECT, INSERT, UPDATE, DELETEだけを許可する
MariaDB [(none)]> grant select, insert, delete, update on test_database.* to 'test_user'@'%';

# 正しく設定できているか確認する
MariaDB [(none)]> select user from mysql.user;
+------------+
| user       |
+------------+
| app        |
| test_user |
| root       |
+------------+
3 rows in set (0.001 sec)

MariaDB [(none)]> show grants for test_user;
+-----------------------------------------------------------------------------------------------------------+
| Grants for test_user@%                                                                                   |
+-----------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `test_user`@`%` IDENTIFIED BY PASSWORD '*****************************' |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `test_database`.* TO `test_user`@`%`                                |
+-----------------------------------------------------------------------------------------------------------+
2 rows in set (0.001 sec)

クライアントからMariaDBへ接続する

今回はmacOSのターミナルからmysqlで接続してみます。

# コマンド実行後にパスワードを聞かれるので、MariaDBユーザーのパスワードを入力する
% mysql -h {Raspberry PiのプライベートIP} -u test_user -p test_database
# 接続成功
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 95
Server version: 5.5.5-10.3.31-MariaDB-0+deb10u1 Raspbian 10
...
mysql> 

これで無事接続できました。

参考

Configuring MariaDB for Remote Client Access - MariaDB Knowledge Base