2016年4月に、無料で取得可能なSSL証明書サービス「Let’s Encrypt」が始まりました。ここでは、SSL(暗号化)接続に対応している IRC サーバデーモン charybdis に、Let’s Encrypt で取得した証明書を使って、SSL対応のIRCサーバを設定してみます。

前提条件

2016年9月3日時点で公開されている、最新のパッケージを適用してある CentOS 7.2.1511 を使って説明します。

また、このサーバでは既に nginx で HTTP/HTTPS サーバを起動しているものとします。

IRC デーモンの charybdis は、この記事の通りにインストールされているものとします。
ただし、この記事を書くために使用したバージョンは 3.5.2 です。

証明書を取得する

Let’s Encrypt のインストールと証明書の取得

ここでは最新版を用いるため、github からプログラムをダウンロードしますが、epel リポジトリを有効にしている場合は certbot パッケージを利用することもできます。

$ sudo mkdir /opt
$ cd /opt
$ sudo git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
$ ./certbot-auto

最後のコマンドでテスト実行をしています。内部的に root 権限が必要になるため、sudo のプロンプトが出ますので、実行したユーザーのパスワードを入力してください。
不足するパッケージがあった場合、システムにインストールされます。

次に、certbot-auto コマンドをパスの通っているディレクトリからリンクを張ります。

$ cd /usr/local/bin
$ sudo ln -s /opt/letsencrypt/certbot-auto .

最後に利用するドメインの証明書を取得します。

$ certbot-auto certonly --standalone \
--pre-hook 'systemctl stop nginx' \
--post-hook 'systemctl start nginx' \
--email admin@example.com \
-d irc.example.com

certbot-auto コマンドは証明書を取得するとき、Let’s Encrypt のサーバーからDNSを引いて、DNSの宛先になっているサーバーから実行されているかどうかを確認します。
そのときに 80・443 番ポートにアクセスするため、既に HTTP/HTTPS サーバがこれらのポートを利用していると、certbot-auto コマンドがこれらのポートを利用できず、証明書の取得に失敗します。
そのため、上記コマンド行の2~3行目で、証明書取得前後に nginx デーモンを終了・起動するように引数で指定します。
Apache など、他のデーモンを利用している場合、適切に書き換えてください。

またそのため、DNS の設定を先に行ない、指定するドメイン全てが certbot-auto コマンドを実行するサーバを指している必要があります。

証明書に記載する連絡先に使用するメールアドレスを4行目で指定します。

ここではマルチドメイン対応の証明書にしていませんが、複数のドメインの証明書を取得する場合には5行目以降に -d domain.name という形式で複数指定することができます。

初回起動の場合は利用規約が表示されるので、よく読んで同意してください。

正常に証明書が取得されると、/etc/letsencrypt 以下にサブディレクトリが作成され、証明書が保存されます。

格納ディレクトリの所有者・パーミッションを変更する

certbot-auto が作成するディレクトリは、デフォルトで root 以外に読み取ることができないよう設定されています。
しかし、charybdis は root 権限で起動できないため、特定の一般ユーザーのみ証明書を読み取ることができるように設定を変更します。

$ sudo groupadd letsencrypt
$ sudo gpasswd -a charybdis letsencrypt
$ sudo chgrp letsencrypt /etc/letsencrypt/{archive,live}
$ sudo chmod 750 /etc/letsencrypt/{archive,live}

これで、charybdis 実行ユーザーの権限では証明書を読み取ることができ、関係ないユーザーからは読み取れないようにできました。

証明書の更新を自動化する

取得した証明書には有効期限があります。期限を切らす前に自動的に更新するよう設定します。

ここでは systemd の timer ユニットを利用します。以下のサンプルを利用することを前提に説明します。
必要に応じて書き換えてください。

[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/local/bin/certbot-auto renew --standalone --pre-hook 'systemctl stop nginx' --post-hook 'systemctl start nginx'
ExecStartPost=/bin/systemctl reload charybdis.service

$ wget https://gist.github.com/607e7a55167f40d9ee3e3d60dfaa2806
$ wget https://gist.github.com/62e1209db8f3b20e13c5d5ac01f0e328
$ sudo mv certbot.{service,timer} /etc/systemd/system/
$ sudo mv certbot.{service,target} /etc/systemd/system/ (2016-11-26修正)
$ sudo systemctl daemon-reload

これで毎日決まった時間に systemd が更新プログラムを実行し、更新の必要があれば証明書が更新されます。
同様のことは、もちろん従来通りの crond で設定することもできます。

charybdis の設定を変更する

charybdis の設定を変更し、SSL 対応にします。

必要なファイルを用意する

設定ファイルのコメントを外せば良いように、証明書へはリンクを張ります。
DH パラメータが必要になるため、それも一緒に生成します。

$ sudo su - charybdis -s /bin/bash
charybdis$ cd ircd/etc
charybdis$ ln -s /etc/letsencrypt/live/irc.example.com/privkey.pem ssl.key
charybdis$ ln -s /etc/letsencrypt/live/irc.example.com/fullchain.pem ssl.pem
charybdis$ openssl dhparam -out dh.pem 2048

最後の行では DH パラーメータを生成していますが、この処理にはマシンの能力によっては時間がかかることがあります。

設定ファイルを書き換える

SSL 関連の部分を書き換えます。必要になるのは5箇所です。

相対パスで指定する場合、インストール時に ./configure –prefix で指定したディレクトリが基点になります。

serverinfo セクション:4箇所

  • ssl_cert
    公開する証明書を指定します。先ほどリンクを張った、ssl.pem のパスを指定します。
    設定例: ssl_cert = “etc/ssl.pem”;
  • ssl_private_key
    証明書と対になる秘密鍵を指定します。ssl.key のパスを指定します。
    設定例: ssl_private_key = “etc/ssl.key”;
  • ssl_dh_params
    DH パラメータを保存した、dh.pem のパスを指定します。
    設定例: ssl_dh_params = “etc/dh.pem”;
  • ssld_count
    charybdis 本体とは別に、SSL 通信を管理するデーモンがフォークされます。このプロセスを用意する数を指定します。”マシンに搭載されているCPUコア – 1″ が目安だそうです。
    2コアCPUの場合の設定例: ssld_count = 1;

listen セクション:1箇所

  • sslport
    暗号化しない(通常の)接続とSSL接続では、使用するポートを分ける必要があります。port で指定している通常の接続で使うポート(大抵は6667番付近)とは別に、ポートを一つ以上設定します。port/sslport の設定値に同じポートを指定することはできません。
    設定例: sslport = 6697;

以上の部分を書き換えたらファイルを保存し、文法チェックを行ないます。

charybdis$ cd ../
charybdis$ bin/ircd -conftest

エラーメッセージが出力されなかったら設定は問題ないということです。

charybdis を再読込し、設定を適用します。

charybdis$ exit
$ sudo systemctl reload charybdis

ファイアーウォールでポートを開放する

今まで使っていなかったポートを使うように設定した場合、新たにファイアーウォールで遮断していたポートを開放する必要があります。

この設定例を使う場合、次のように操作してください。

$ wget https://gist.github.com/2aa520fcc8eb06dae891c8e8433261fc
$ sudo mv ircs.xml /etc/firewalld/services/ircs.xml
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --add-services ircs --permanent
$ sudo firewall-cmd --reload

これでポートが開放されました。

サーバ側の設定は全て完了です。

クライアントからSSL接続をしてみる

ここでは、Windows 版の LimeChat2.40 (64bit) からアクセスしてみます。

LimeChat2 IRCS

「ポート番号」と「SSL接続」の設定値を、さきほど charybdis に設定したとおりに変更します。

後はいつも通りに接続すると、ステータスメッセージの中に
*<yournick> mode +Zi
という行が見つかると思います。

charybdis は、初期設定ではSSL接続をしているユーザーに +Z モードを設定します。
また、whois コマンドを使っても、SSL接続をしているかどうかを確かめられます。

*Reply(671) <yournick> is using a secure connection

LimeChat2 の「ユーザー情報」ダイアログでは対応していないため、上記のメッセージはサーバからのステータスメッセージとして表示されます。

この出力があるユーザーは、安全な接続(=SSL接続)をしている、ということです。