AWSのセキュリティグループに頼り切りの人生なので、自分で設定するとなると怖かったです(感想)
前提
Lightsailでbitnami社のblueprintを使って構築したワードプレス環境に含まれているMySQLサーバに対して、インターネッツからアクセスしたい。
例えばDataStudioとかRedashとかでクエりたい時がきっとある。
もしくは個人のマシンから接続したいなど。
ちなみに今回はインスタンスは構築済みとします。
解決すべき問題と対処法
- bitnamiイメージで構築されたワードプレス環境のMySQLは、デフォルトではlocalhostからのアクセスしか想定していない
- ローカルホスト以外から接続するためのユーザーを追加する
- デフォルト状態では、Lightsailインスタンスは3306ポートへの通信を許可していない
- LightsailのGUIでファイアウォール設定を変える
- LightsailインスタンスのファイアウォールはAWSのVPCセキュリティグループみたいに通信元・通信先を設定できない
- インスタンス内でiptablesを使って通信可能なホストを絞る
解決する順番
気にし過ぎなのかもしれないですが、上記問題を解決するにあたって順番が結構重要な気がしている。
3つめの問題点が割とクセモノで、1, 2を先に解決してしまうと、3306に対して誰でも通信できちゃうことになる。
まあ1で作成するユーザーにpass付いてるので大丈夫っちゃ大丈夫な気もするが、念の為。
なので、解決の順番は 1 -> 3 -> 2で進めることにする。
MySQLにユーザーを追加する
まずはLightsaileインスタンスにSSHログインしましょう。
Lightsailにログインするとインスタンス一覧があるので、対象のインスタンスを選択します
するとでっかい「Connect using SSH」ボタンがあると思うので、それをクリックしましょう。
したらブラウザでターミナルチックなやつが開いて、SSHログインした状態になります。
ここから後の作業にはroot権限が必要になるため、予め
$ sudo su -
でrootユーザーになっておきましょう。
MySQLへの接続元設定を解除
デフォルトではMySQLへの接続がローカルホストにバインドされているとのことなので、下記で設定を変更します。
$ vim /opt/bitnami/mysql/my.cnf
...
# bind-address=127.0.0.1 <- コメントアウトする
...
上記保存してからMySQLを再起動。
注: 再起動中はWordpressが表示できなくなるので、ダウンタイムが気になる方は深夜などに作業しましょ
$ /opt/bitnami/ctlscript.sh restart mysql
MySQLログイン
下記コマンドでパスワードが表示されるので、それを使ってMySQLにログインします。
$ cat /home/bitnami/bitnami_application_password
YOURPASSHERE
$ mysql -u root -p
Enter password: (パス入力してEnter)
MySQLにユーザーを追加
最近のbitnamiイメージで環境を作った場合、MySQLのバージョンが8系になっているはず。
なので真面目に、ユーザーを追加して、grantして、flushします。
mysql> CREATE USER 'root'@'%' identified by 'YOUR_PASSWORD';
mysql> GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
ここまででMySQL自体の設定が完了。
引き続きSSH環境で作業します。
Lightsailインスタンスのiptablesを設定する
iptables
とは、一般的なLinuxに搭載されているパケットフィルタのこと。。らしい。
AWSに慣れている人であれば、セキュリティグループでできることはこいつでできると思ってれば良い。
ただし、単純にiptablesにルールを追加しただけだと、インスタンス自体が再起動した際にルールが保持されないとのこと。
そこで、iptables-persistent
を同時に利用していく。
iptables-persistentのインストール
$ apt-get install iptables-persistent
上記コマンドを進めていくと、ターミナルが普段あまり見慣れない赤紫?色になり、
Save current IPv4 rules?
と聞かれるのでYES
と答えておく。
次に
Save current IPv6 rules?
と出るのでNO
にしておく。 (IPv6のルールも作りたければYESで。)
iptablesにルールを追加する
まずは現状のiptablesの中身を覗いてみよう。
おそらく同様に出力されるはず。
$ iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
INPUT, FORWARD, OUTPUTはそれぞれ、インスタンスに入ってきたデータの経路(チェイン)を表す。
(policy ACCEPT)
となっているのはデフォルト設定で、それぞれの経路についてルールが指定されていなければすべてACCEPT
or DROP
する、という挙動になる。
今回利用するのはINPUTのみ。
いきなりだが、ルールを追加していく。
$ iptables -A INPUT -p tcp --dport 3306 -j ACCEPT -s 127.0.0.1 -d 127.0.0.1
$ iptables -A INPUT -p tcp --dport 3306 -j ACCEPT -s <ipアドレス>/<サブネット> # ここに必要なipを入れる
$ iptables -A INPUT -p tcp --dport 3306 -j REJECT
コマンドを分解すると、
-A <CHAIN> : INPUTチェインにルールを追加(Add)
-p <PROTOCOL> : tcpプロトコルを指定
--dport <port> : データ受信側のポート指定
-j <TARGET> : パケットを許可(ACCEPT)/拒否(DROP|REJECT)する
-s <ip>/<sub> : データ送信元ip
-d <ip>/<sub> : データ送信先ip
となる。
つまり、それぞれ
$ iptables -A INPUT -p tcp --dport 3306 -j ACCEPT -s 127.0.0.1 -d 127.0.0.1
-> 3306番ポートに対して、ローカルから受けてローカルに返す通信は許可する
$ iptables -A INPUT -p tcp --dport 3306 -j ACCEPT -s <ipアドレス>/<サブネット>
-> 3306番ポートに対して、指定のipから受ける通信は許可する (送信先は指定していないため何でもOK)
$ iptables -A INPUT -p tcp --dport 3306 -j REJECT
-> 3306番ポートに対しての通信を拒否する
という設定となる。
ローカル通信については、WordpressからこのDBを参照するために必要となる。
この時、iptablesの設定は上から順に適用されるため、最後のREJECTにたどり着くまでの間に適合するルールがあれば、その通信はREJECTされずに通過できる。
逆に言えば、上記でACCEPTされた以外のソースからの通信はすべてREJECTされる。
iptablesのルールを永続化する
$ iptables-save >/etc/iptables/rules.v4 # 保存
$ cat /etc/iptables/rules.v4 # 確認。上記で追加したルールが表示されればOK
これで通信可能なホストを絞ることができた。
これ以上インスタンスを直接いじる必要はないので、タブを閉じて大丈夫です。
最後にLightsailのファイアウォール設定を開いて完了。
Lightsailのファイアウォール設定を変える
LightsailのGUIに戻り、作業対象のインスタンスのNetworking
タブを選択する。
するとFirewallの設定があるので、Add another
して下記のように設定しましょう。
これで設定完了!
接続をテストする
Hostはご自身のLightsailインスタンスのパブリックip
Userは、このマニュアル通りならroot
PasswordはMySQLにユーザーを追加部分で入力したパスワード
データベースはbitnami_wordpress
(2020/04/08現在)
接続できました!
めでたしめでたし。
参考にさせていただいた記事
ありがとうございましたm(_ _)m
https://dev.classmethod.jp/articles/access-lightsail-wordpress-outside-instance/
https://qiita.com/na0AaooQ/items/781b3823b79fd3b747a3
https://stackoverflow.com/questions/11001368/restricting-mysql-3306-port-to-localhost-with-iptables
https://eng-entrance.com/linux-firewall
https://unix.stackexchange.com/questions/125833/why-isnt-the-iptables-persistent-service-saving-my-changes