Debian 9 (stretch) で MySQL 8.0 の設定ファイルを /etc/my.cnf にする

Debian 9 へ MySQL APT Repository から MySQL 8.0 をインストールすると、my.cnf は alternatives で管理されて、サーバ設定とクライアント設定が複数のファイルで管理される。
複数のファイルで管理すると「この設定、どのファイルから読まれてるの?」問題が結構あるので、Debian 系のお作法からは外れるかもしれないけど /etc/my.cnf にすることにした。

デフォルトの設定ファイル

alternatives で管理されていて、/etc/mysql/mysql.cnf へのシンボリックリンクになっている。

$ ls -al /etc/mysql/my.cnf
lrwxrwxrwx 1 root root 24  5月  6 17:54 /etc/mysql/my.cnf -> /etc/alternatives/my.cnf
$ ls -al /etc/alternatives/my.cnf 
lrwxrwxrwx 1 root root 20  5月  6 17:54 /etc/alternatives/my.cnf -> /etc/mysql/mysql.cnf

/etc/mysql/mysql.cnf は /etc/mysql/mysql.conf.d/mysqld.cnf(サーバ設定) と /etc/mysql/conf.d/mysql.cnf(クライアント設定) を include するようになっている。

$ grep 'include' /etc/mysql/mysql.cnf
.....
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

起動時に読み込む設定ファイルを /etc/my.cnf に設定

1) /etc/my.cnf を準備する*1

$ sudo cp -a /etc/mysql/mysql.conf.d/mysqld.cnf /etc/my.cnf

2) alternatives 設定を変更する

$ sudo update-alternatives --remove-all my.cnf
$ sudo update-alternatives --install /etc/mysql/my.cnf my.cnf /etc/my.cnf 200

3) mysqld を再起動する

$ sudo systemctl restart mysql.service

*1:とりあえず、/etc/mysql/mysql.conf.d/mysqld.cnf をコピー

Debian 9 (stretch) へ MySQL 8.0 をインストール

MySQL 8.0 が GA になったので、Debian 9 へインストールした。
とりあえず、MySQL 8.0 を起動するまでの作業ログ。

環境

APT Repository 設定

$ wget https://dev.mysql.com/get/mysql-apt-config_0.8.10-1_all.deb
$ sudo dpkg -i mysql-apt-config_0.8.10-1_all.deb
$ sudo apt update

MySQL 8.0 インストール

$ sudo apt install mysql-server mysql-client

設定ファイル

デフォルトだと以下のファイルが設定値として読み込まれている。

  • /etc/mysql/mysql.conf.d/mysqld.cnf : サーバ設定
  • /etc/mysql/conf.d/mysql.cnf : クライアント設定

設定値確認

performance_schema の variables_info と global_variables を使うといい感じに確認できる。

mysql> SELECT variables_info.VARIABLE_NAME, variables_info.VARIABLE_PATH, global_variables.VARIABLE_VALUE, variables_info.MIN_VALUE, variables_info.MAX_VALUE FROM performance_schema.variables_info LEFT OUTER JOIN performance_schema.global_variables ON variables_info.VARIABLE_NAME = global_variables.VARIABLE_NAME;
+-----------------------------+---------------+----------------+-----------+-----------+
| VARIABLE_NAME               | VARIABLE_PATH | VARIABLE_VALUE | MIN_VALUE | MAX_VALUE |
+-----------------------------+---------------+----------------+-----------+-----------+
| activate_all_roles_on_login |               | OFF            | 0         | 0         |
| auto_generate_certs         |               | ON             | 0         | 0         |
| auto_increment_increment    |               | 1              | 1         | 65535     |
+-----------------------------+---------------+----------------+-----------+-----------+

YAPC::Okinawa 2018 ONNASON に行ってきた #yapcjapan

yapcjapan.org

YAPC::Okinawa 2018 ONNASON に行ってきました。
控えめに言って、最高の YAPC でした。

前夜祭

ビール飲みながらトークを聞くという最高の環境だったので、細かいことは憶えていません。

印象的だったトーク

  • 知られざる、Alibaba Cloudを支えるオープンソース
    • MySQL100%互換な AliSQL が気になった。
  • 綺麗なコードの書き方
    • 綺麗なコードとは実行可能な画像。最高でした。

YAPC::Okinawa 2018 ONNASON 本編

印象的だったトーク

  • HTTP/2 で速くなるときとならない時 @kazuho
    • HTTP/2 は多重化してデータ送信するので、HTTP/1 より速いと断定されることが多いけど、環境によってはそうではないこともある
    • パケットロスが多い環境では、接続数が多い HTTP/1 の方がバンド幅が大きくなり、HTTP/2 より速いことがある
    • 「HTTP/2 が速いよ」とか「HTTP/1 が速いよ」とか断言する人は信用しない方がいい
    • ユースケースにあったベンチマークをすることが大切
  • 正規表現と曖昧性】マッチングの困難さについて @sinya8282
  • High (Availability|Performance) WebSocket for Perl Real-Time Application @mackee_w
    • 同じような設計の websocket サーバを運用しているが、kuiperbelt の方が優れている点があって、参考になった
    • 趣味プロダクトを本番投入するまでも勉強になった
    • ミドルウェアは信頼されてなんぼ
  • Perl6のエコシステム @shoichikaji
    • パフォーマンスも良くなっているようなので、Perl6 使おうと思った
    • リリース直後よりもエコシステム(モジュール配布場所/index/installer)も整備されていることが分かって勉強になった
    • Perl6 エコシステム
      • 配布場所 : CPAN(via PAUSE)
      • index : App::ecogen
      • installer : zef

懇親会

ビール飲んで細かいことは憶えてませんが、いろいろな方と話せたと思います。
星空を見ながらのオリオンビールは最高でした。 楽しかったです!!

まとめ

今回の YAPC も学ぶことが多かったし、刺激も受けました。
最近あまり Perl を書かなくなったので、もっと Perl 書こうと思いました。
運営のみなさん、参加されたみなさん、ありがとうございました。
沖縄最高でした!

次は

yapcjapan.org

ポートノッキングで少しだけ SSH 接続をセキュアにした

決められた順番でポートノッキングした時だけ、SSH 接続ができるようにしました。

ポートノッキングとは?

決められた順番でポートを叩くことで、あらかじめ設定してあるコマンドを実行する仕組みのことです。
今回は、ポートノッキングされた時にファイアウォール (iptables) に穴を空ける設定をしました。

逃げ道の確保

設定ミスにより、一切 SSH 接続ができなくなるといった事態を避けるために逃げ道を確保しておきます。
複数ポートで sshd を起動する、特定のネットワークからは(ポートノッキングを使わない) SSH 接続を許可するなど設定を行ってください。

knockd インストール

$ sudo apt install -y knockd

knockd 設定

設定(1)

$ sudo vi /etc/default/knockd  
START_KNOCKD=1         #knockd 自動起動
KNOCKD_OPTS="-i ens3"  #ネットワークインタフェース設定、さくらの VPS なら ens3 のはず(?)  

設定(2)
ポートノッキングに 10001/tcp, 10002/tcp, 10003/tcp を使いました。

$ sudo vi /etc/knockd.conf  
[options]  
    logfile = /var/log/knockd.log     #ログ出力設定  
  
[openSSH]  
    sequence    = 10001:tcp,10002:tcp,10003:tcp  
    seq_timeout = 5  
    command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT  
    tcpflags    = syn  
  
[closeSSH]  
    sequence    = 10003:tcp,10002:tcp,10001:tcp  
    seq_timeout = 5  
    command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT  
    tcpflags    = syn  

“sequence” で設定した順番でポートノッキングすると、"command" が実行されます。
[openSSH] で SSH 通信許可ルールを追加して、[closeSSH] で SSH 接続ルールを削除しています。

iptables 設定

iptables で許可していた SSH 接続は REJECT します。

$ sudo vi /etc/iptables/rules.v4  
-A INPUT -p tcp --dport 22 -j REJECT  
$ sudo iptables-restore < /etc/iptables/rules.v4  
$ sudo iptables -L  
.....  
REJECT     tcp  --  anywhere             anywhere             tcp dpt:ssh reject-with icmp-port-unreachable  
.....  

knockd 起動

$ sudo systemctl start knockd.service  

確認

ローカル Mac から動作確認を行います。

knock インストール

ローカル Mac へ knock をインストールします。

$ brew install knock  

動作確認

ポートノッキングする前の状態を確認します。

$ nmap %remote-server%  
PORT     STATE  SERVICE  
22/tcp   closed ssh    

STATE が “closed” になっていて、SSH 接続ができない状態です。
knock コマンドで、ポートノッキングします。

$ knock -v -d 100 %remote-server% 10001:tcp 10002:tcp 10003:tcp  

STATE が “open” になっていることを確認します。

$ nmap %remote-server%  
PORT     STATE  SERVICE  
22/tcp   open   ssh  

ポートノッキングして、ポートを閉じます。

$ knock -v -d 100 %remote-server% 10003:tcp 10002:tcp 10001:tcp  
$ nmap %remote-server%  
PORT     STATE  SERVICE  
22/tcp   closed ssh  

ポートノッキング後に 10 秒間だけポートを空けるように設定

上記の設定だと明示的にポートノッキングしないと、SSH 切断後もポートが空いたままになってしまうので、ポートノッキング時に 10 秒間だけポートを空けるように設定します。
SSH 接続時のポートノッキングは、.ssh/config の ProxyCommand 設定で行えるので、組み合わせることで SSH 接続時のみポートが空くような動作になります。

knockd 設定

サーバ側の knockd 設定を以下のように変更します。

$ sudo vi /etc/knockd.conf  
[options]  
    logfile = /var/log/knockd.log  
  
[opencloseSSH]  
    sequence    = 10001:tcp,10002:tcp,10003:tcp  
    seq_timeout = 5  
    tcpflags    = syn  
    start_command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT  
    cmd_timeout = 10  
    stop_command      = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT  

ポートノッキングされると、"start_command" が実行され、10 秒 (cmd_timeout) 後に “stop_command” が実行されます。

ssh 設定

ローカル Mac の .ssh/config に “ProxyCommand” を設定することで、SSH 接続直前にポートノッキングを行います。

$ vi ~/.ssh/config  
Host %remote-server%  
  Port 22  
  ProxyCommand bash -c '/usr/local/bin/knock -d 100 %h 10001:tcp 10002:tcp 10003:tcp; sleep 1; exec /usr/bin/nc %h %p'  

このように設定することで、ポートノッキングを意識しないで SSH 接続できます。

knockd がシステムブート時に自動起動しない問題

/etc/default/knockd で自動起動設定したけど、Debian 9 では自動起動しませんでした。
どうやらバグのようです。

ということで対応

$ sudo vi /etc/systemd/system/knockd.service  
[Unit]  
Description=Port-Knock Daemon  
After=network.target  
Documentation=man:knockd(1)  
  
[Service]  
EnvironmentFile=-/etc/default/knockd  
ExecStart=/usr/sbin/knockd $KNOCKD_OPTS  
ExecReload=/bin/kill -HUP $MAINPID  
KillMode=mixed  
SuccessExitStatus=0 2 15  
ProtectSystem=full  
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN  
  
[Install]  
WantedBy=multi-user.target  

設定を反映させます。

$ sudo systemctl daemon-reload  
$ sudo systemctl enable knockd.service  

これでシステムブート時に自動起動するようになります。

まとめ

ポートノッキングで少しだけ SSH 接続をセキュアにしました。
ポートノッキングはセキュリティ的には気休めに過ぎないので、sshd 設定はこれまで通りセキュアにしましょう。

Amazon WorkMail でメール受信

AWS SES でメール受信の続き。
* AWS SES でメール受信 - jitsu102's blog
特定の受信者のみ Amazon WorkMail で受信し、それ以外は上記エントリで設定したように S3 に保存されるようにします。
Amazon WorkMail は、1 ユーザあたり $4/月 かかります。

WorkMail 設定

  1. [WorkMail] -> [Get started] をクリック
  2. [Quick setup] をクリック
  3. [Organization name] を入力し、[Create] をクリック
  4. Organizations 画面で、[Status] が [Active] になるまで待つ
  5. [Active] になったら、[Alias] 名を選択
  6. 左メニューから [Domains] を選び、[Add domain] をクリック
  7. [Domain name] を入力し、[Add domain] をクリック
  8. TXT レコード・MX レコード・CNAME レコードが表示されるので、DNS に設定
  9. Domains 画面で、追加したドメインチェックボックスを選択し、[Set as default] をクリック
  10. 左メニューから [Users] を選び、[Create user] をクリック
  11. [User name] と [Display name] を入力し、[Next Step] をクリック
  12. [Email Address] と [Password] を入力し、[Add user] をクリック
  13. 左メニューから [Organization settings] を選ぶ
  14. [Web Application] にある URL にアクセスし、作成したユーザで WorkMail へログイン

SES 設定

  1. SES に Rule Sets が追加されているので、追加されたルールを一番最初に変更
    1.1. 追加されたルールを選択し、[Run after rule] を [Beginning] に設定
  2. 追加されたルールの [Action] に [Stop Rule Set] を追加
    1.1. WorkMail で受信するメールは、以後のルール(S3 保存)を評価しないで終了

テストメール送信

テストメールを送信し、WorkMail で受信できることを確認する。
WorkMail で受信設定したアドレス以外のメールは S3 に保存されることを確認する。