はじめに
FreeBSD 12を使用した自宅サーバの構築を行った。FreeBSD 12はリリースされて間もない状態ですが、カーネルに標準でVIMAGEが取り込まれDNSの外向きと、内向きを別々のシステム(jail+VIMAGE)が同一ホストで構築できることから採用することにしました。その時の構築手順を備忘録の意味も含め、具体的にいくつかに渡り説明する。
-
基本システム編その1
- 背景
- 基本のインストール
- 日本語環境の設定
-
基本システム編その2
- セキュリティ
- ftpサーバ
-
基本システム編その3
- jail
- 基本システム編おわり
-
jail内基本システム編
- 基本の設定(jail1・jail2共通)
-
DNS編
- DNSの構築におけるこれまでの問題
- bind9インストール
- NTPサーバ
-
Let's Encrypt編(この記事)
- Let's Encryptについて
- certbotのインストール
- 各種設定
- 証明書の取得
-
Webサーバ編
- インストール(apache2.4・webalizer・php7.3・postgresql11.2・mysql8.0)
- 設定
-
メールサーバ編
- インストール(cyrus-sasl・postfix・dovecot・procmail・pflogsumm・policyd-spf)
- 設定・起動
- spfレコード送信設定
-
ファイルサーバ編
- sambaの選択
- samba3のインストール
-
メールサーバ編その2
- 概要
- OpenDKIM
- OpenDMARC
- ClamAV (clamav-milter)
- Spamassasin (spamass-milter)
Let's Encryptについて
これまで、証明書の取得は個人で実施するには金銭的・手続き的にハードルが高くできないものと決めつけていました。しかし、無償で手続きもネットで簡単に行えそうであることを最近知り、情報を集め実行しました。手続き的にはdnsやhttpなどいくつかの方法がありましたが、以下のサイトを参照しdnsを使って証明書を取得することができました。
dnsをviewにより外向きと内向きを同一システムで運用していたことで問題があり今回の自宅サーバ再構築のきっかけとなりました。
なお、上記サイトは分かりやすく丁寧に説明されていますので詳細はそちらを参照していただき、以下は具体的にやった手順をまとめる。
また、外部dnsと連携して認証するためjail1(外部用)にインストールし作業を行う。
加えて、この作業の性質上1からやり直し確認しづらく、これまでにやったことをまとめたものである。jailの中からはまだ実施していないため問題が出る可能性があり、最終的にシステム移行時に確認予定。
結果報告(2019/9/23)
最初に自動更新が確認されたときに追記する予定が、随分とサボってしまった。現在自動更新を無事に4回実施できています。証明書ファイルの添字も”5”になりファイルの日付を見ると約2ヶ月毎に更新されているのが確認できた。また、運用始めてから今までに問題も発生していないことを追加報告します。
問題発生(2019/10/19)
pkgをアップデート後自動更新が行われていないことに気づき、土曜日にcronで更新プログラムが起動するので、その結果を確認した。
すると以下のメッセージが
/usr/local/sbin/renew-letsencript: certbot: not found
ソフトがなくなっている?
確認すると
/usr/local/bin# ls -l cert*
-rwxr-xr-x 1 root wheel 393 Sep 28 10:23 certbot-2.7*
-rwxr-xr-x 1 root wheel 326216 Oct 3 10:19 certtool*
プログラム名にpythonのバージョンが入ったようだ(python3用も出来たのか?)
とりあえずリンクを張って更新できるようになった。
/usr/local/bin# ln -s certbot-2.7 certbot
また、有効期限まで19日であったことから先週には、最初の自動更新失敗のメールが来ているはずであるが、気づかずに廃棄したようだ(よく確認しないと)。しかし、本日Let's Encrypt Expiry Bot expiry@letsencrypt.orgからLet's Encrypt certificate expiration notice for domain "*.example.jp"のメールを受け取りありがたく思っている。
Hello,
Your certificate (or certificates) for the names listed below will expire in 19 days (on 07 Nov 19 15:11 +0000).
Please make sure to renew your certificate before then, or visitors to your website will encounter errors.
(以下省略)
certbotのインストール
certbotのオプションを選択することにより認証方式を選ぶことができる。今回はdnsを使用するためcertbot-dns-rfc2136をインストールする。プログラム自身はpythonで書かれているため以下のようにたくさんのモジュールがインストールされる。
jail1 /root # pkg install security/py-certbot-dns-rfc2136
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 63 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
py27-certbot-dns-rfc2136: 0.31.0
py36-certbot-dns-rfc2136: 0.31.0
py27-certbot: 0.31.0,1
py27-openssl: 18.0.0
py27-cryptography: 2.3
py27-ipaddress: 1.0.22
py27-idna: 2.7
py27-six: 1.12.0
py27-enum34: 1.1.6
py27-cffi: 1.11.5
py27-pycparser: 2.18
py27-asn1crypto: 0.22.0
py27-josepy: 1.1.0
py27-acme: 0.31.0,1
py27-requests-toolbelt: 0.8.0
py27-requests: 2.21.0
py27-chardet: 3.0.4
py27-certifi: 2018.11.29
py27-urllib3: 1.22,1
py27-pysocks: 1.6.8
py27-pytz: 2018.9,1
py27-pyrfc3339: 1.1
py27-zope.interface: 4.6.0
py27-zope.component: 4.2.2
py27-zope.event: 4.1.0
py27-parsedatetime: 2.4_1
py27-configobj: 5.0.6_1
py27-configargparse: 0.14.0
py27-dnspython: 1.15.0
py27-mock: 2.0.0
py27-pbr: 3.1.1
py27-pip: 9.0.3
py27-funcsigs: 1.0.2
py36-certbot: 0.31.0,1
py36-openssl: 18.0.0
py36-cryptography: 2.3
python36: 3.6.8
py36-idna: 2.7
py36-setuptools: 40.8.0
py36-six: 1.12.0
py36-cffi: 1.11.5
py36-pycparser: 2.18
py36-asn1crypto: 0.22.0
py36-josepy: 1.1.0
py36-acme: 0.31.0,1
py36-requests-toolbelt: 0.8.0
py36-requests: 2.21.0
py36-chardet: 3.0.4
py36-certifi: 2018.11.29
py36-urllib3: 1.22,1
py36-pysocks: 1.6.8
py36-pytz: 2018.9,1
py36-pyrfc3339: 1.1
py36-zope.interface: 4.6.0
py36-zope.component: 4.2.2
py36-zope.event: 4.1.0
py36-parsedatetime: 2.4_1
py36-configobj: 5.0.6_1
py36-configargparse: 0.14.0
py36-dnspython: 1.15.0
py36-mock: 2.0.0
py36-pbr: 3.1.1
py36-pip: 9.0.3
Number of packages to be installed: 63
The process will require 207 MiB more space.
42 MiB to be downloaded.
(以下省略)
各種設定
dns更新用パスワード作成
証明書を取得する際、要求元が確かに要求されたドメインの管理者であることを証明するためにISRG(証明書発行元)から送られてきた認証コードをdnsのTXTレコードとしてISRGに応答することで証明書が発行される(詳細は上記サイトを参照)。
このことから、ダイナミックにTXTレコードを書き換える必要があり、certbotからdnsをアクセスするためのパスワードを作成する。
jail1 /root # tsig-keygen certbot-key > /usr/local/etc/namedb/certbot-key.key
key "certbot-key" {
algorithm hmac-sha256;
secret "/9a5f/hobiMY9BuycJOehKDNB1QzDMPliFbnSBecZZM=";
};
bindの設定
前節の設定に追加し以下のようにする。
include "/usr/local/etc/namedb/certbot-key.key"; // 認証鍵の読み込み
include "/usr/local/etc/namedb/rndc_key";
controls {
inet 127.0.0.1 port 953 allow {127.0.0.1;} keys {"rndc-key";};
};
options {
directory "/usr/local/etc/namedb/working";
pid-file "/var/run/named/pid";
dump-file "/var/dump/named_dump.db";
statistics-file "/var/stats/named.stats";
listen-on-v6 { none; };
allow-transfer { 192.168.1.0/24; };
};
// wan側の設定
// 自ドメイン正引き
zone "example.jp" {
type master;
file "/usr/local/etc/namedb/master/example.jp.zone";
check-names ignore;
};
zone "_acme-challenge.example.jp" {
type master;
file "/usr/local/etc/namedb/dynamic/_acme-challenge.example.jp.zone";
check-names ignore;
update-policy {
grant certbot-key. name _acme-challenge.example.jp. TXT;
};
};
example.jpのゾーンファイルに最後の行を追加する
$TTL 3600
@ IN SOA ns1.example.jp. root.example.jp. (
20190020101 ; Serial
3600 ; Refresh
900 ; Retry
3600000 ; Expire
3600 ; Minimum
)
IN NS ns1.example.jp.
IN NS ns2.example.jp.
IN MX 10 mail.example.jp.
IN A 111.222.333.100
ns1 IN A 111.222.333.100
ns2 IN A 111.222.333.200
mail IN A 111.222.333.100
www IN CNAME ns1.example.jp.
www2 IN CNAME ns2.example.jp.
ftp IN CNAME ns1.example.jp.
_acme-challenge IN NS ns1.example.jp.
_acme-challengeサブドメインのゾーンファイルをdynamicディレクトリーに作成
$TTL 3600
@ IN SOA ns1.example.jp. root.example.jp. (
20190020101 ; Serial
3600 ; Refresh
900 ; Retry
3600000 ; Expire
3600 ; Minimum
)
IN NS ns1.example.jp.
パーミッションの設定
jail1 /usr/local/etc/namedb/dynamic # chmod 644 _acme-challenge.example.jp.zone
jail1 /usr/local/etc/namedb/dynamic # chown bind:bind _acme-challenge.example.jp.zone
certbotの設定
# _acme-challenge.example.jpゾーンのmasterサーバのアドレス
dns_rfc2136_server = 111.222.333.100
# アクセスするポート番号
dns_rfc2136_port = 53
# 認証鍵の名前
dns_rfc2136_name = certbot-key.
# 認証鍵の値
dns_rfc2136_secret = /9a5f/hobiMY9BuycJOehKDNB1QzDMPliFbnSBecZZM=
# 鍵の生成に用いたアルゴリズム
dns_rfc2136_algorithm = HMAC-SHA256
証明書の取得
アカウントの作成
以下は連絡用のメールをシェアする場合でありしない場合は--eff-emailを--no-eff-emailとすれば良い
jail1 /root # certbot register --email admin@example.jp --agree-tos --eff-email
Saving debug log to /var/log/letsencrypt/letsencrypt.log
IMPORTANT NOTES:
- Your account credentials have been saved in your Certbot
configuration directory at /usr/local/etc/letsencrypt. You should
make a secure backup of this folder now. This configuration
directory will also contain certificates and private keys obtained
by Certbot so making regular backups of this folder is ideal.
証明書の取得
jail1 /root # certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /usr/local/etc/letsencrypt/dns-rfc2136.ini -d '*.example.jp'
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-rfc2136, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for example.jp
Waiting 60 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/usr/local/etc/letsencrypt/live/example.jp/fullchain.pem
Your key file has been saved at:
/usr/local/etc/letsencrypt/live/example.jp/privkey.pem
Your cert will expire on 2019-04-27. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
取得した証明書は以下のように実態のソフトリンクになっている。更新していくとリンク先のファイル名の添字が変わっていく(例cert1.pem → cert2.pem)。
jail1 /root # ls -l /usr/local/etc/letsencrypt/live/example.jp/
total 4
-rw-r--r-- 1 root wheel 692 Jan 27 15:16 README
lrwxr-xr-x 1 root wheel 31 Jan 27 15:16 cert.pem@ -> ../../archive/example.jp/cert1.pem
lrwxr-xr-x 1 root wheel 32 Jan 27 15:16 chain.pem@ -> ../../archive/example.jp/chain1.pem
lrwxr-xr-x 1 root wheel 36 Jan 27 15:16 fullchain.pem@ -> ../../archive/example.jp/fullchain1.pem
lrwxr-xr-x 1 root wheel 34 Jan 27 15:16 privkey.pem@ -> ../../archive/example.jp/privkey1.pem
証明書の更新
初期認証条件などが記録されているため、更新は以下のコマンドで簡単に更新できる。
jail1 /root # certbot renew
証明書を使用しているアプリケーションに対し更新したことを通知する必要があり以下のスクリプトをクロンで呼び出すことで自動更新ができる(上記参考サイトに公開されているスクリプトをそのまま使用)。
#!/bin/sh
LANG=C
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/sbin:/usr/sbin
letsencrypt_dir=/usr/local/etc/letsencrypt/
services="apache24 postfix dovecot"
check_update() {
dir=$1
[ $(find ${dir} -mtime -1 -print | wc -l) -gt 1 ]
}
if [ $(id -u) != 0 ]
then
echo "This command requires root previlege." 1>&2
exit 1
fi
certbot renew
if check_update ${letsencrypt_dir}
then
for service in ${services}
do
service ${service} reload || exit $?
done
fi
exit 0
crontabに以下を追加する。
45 3 * * 6 /usr/local/sbin/renew-letsencrypt
これで、毎週土曜日に更新要求される。有効期間が30日未満になると実際に更新され、使用しているアプリケーションにreload指示が発行される。