参考)UPKI-certbot-DNS-01チャレンジ対応(設定例)
動作関連図
サーバ概要
要点
example.u-tokyo.ac.jpのgitlabサーバで HTTPS 用証明書を取得します。- サーバは内部セグメントのみで、外部からHTTPで到達できません。
- このため ACME は DNS-01 で行います。
DNS更新の前提
- dns1.example / dns2.example / dns3.example は hidden master を持ちますが、セキュリティのため API で更新しません。
_acme-challenge.example.u-tokyo.ac.jp.を更新するための hidden master(acme-master)を新設します。
DNS構成
要点
- 「_acme-challenge.example.u-tokyo.ac.jp.」は「example.u-tokyo.ac.jp.」の既存ゾーンから分離し、権威DNSサーバ上に専用ゾーンとして作成して別管理します。
- 更新は acme-master のみで受け付け、権威DNSサーバ側は参照専用(ゾーン転送で受け取ります)。
- 「example.u-tokyo.ac.jp.」の通常運用は dns-master が担当します。
役割
| 項目 | 説明 |
|---|---|
| dns-master | example.u-tokyo.ac.jp. の hidden master(既存) |
| acme-master | _acme-challenge.example.u-tokyo.ac.jp. の hidden master(新規)。DNS-01 の更新はここだけで行います。 |
| dns1.example / dns2.example / dns3.example | 権威DNSサーバ(参照用)。acme-master からゾーン転送を受けます。 |
権威DNSサーバ
- dns1.example 133.11.254.1
- dns2.example 130.69.254.1
- dns3.example 157.82.254.1
DNS-01対応のmaster / zone 作成(acme-master)
# ディレクトリの作成 user@acme-master:~$ sudo mkdir -p /etc/bind/keys user@acme-master:~$ ls -l /etc/bind ... # tsigの鍵を作成 user@acme-master:~$ sudo tsig-keygen -a hmac-sha256 [tsig-key-name] > /etc/bind/keys/acme-example.key # tsig鍵ファイルのパーミッションなど設定 user@acme-master:~$ sudo chown root:bind /etc/bind/keys/acme-example.key user@acme-master:~$ sudo chmod 640 /etc/bind/keys/acme-example.key user@acme-master:~$ sudo ls -l /etc/bind/keys/acme-example.key -rw-r----- 1 root bind 109 Nov 11 15:31 /etc/bind/keys/acme-example.key # 内容確認 user@acme-master:~$ sudo cat /etc/bind/keys/acme-example.key key "[tsig-key-name]" { algorithm hmac-sha256; secret "[secret]"; }; # bindの設定 user@acme-master:~$ sudo vi /etc/bind/named.conf // This is the primary configuration file for the BIND DNS server named. // // Please read /usr/share/doc/bind9/README.Debian for information on the // structure of BIND configuration files in Debian, *BEFORE* you customize // this configuration file. // // If you are just adding zones, please do that in /etc/bind/named.conf.local include "/etc/bind/named.conf.options"; include "/etc/bind/named.conf.local"; include "/etc/bind/named.conf.default-zones"; include "/etc/bind/named.conf.utnet"; # 追加したbindの設定 user@acme-master:~$ sudo vi /etc/bind/named.conf.utnet include "/etc/bind/keys/acme-example.key"; zone "_acme-challenge.example.u-tokyo.ac.jp" IN { type master; file "/var/lib/bind/db._acme-challenge.example.u-tokyo.ac.jp"; update-policy { grant [tsig-key-name] name _acme-challenge.example.u-tokyo.ac.jp TXT; }; allow-query { "acme-hosts"; }; allow-transfer { 133.11.254.1; 130.69.254.1; 157.82.254.1; }; also-notify { 133.11.254.1; 130.69.254.1; 157.82.254.1; }; notify yes; }; acl "acme-hosts" { localhost; [example-host-ip]; }; user@acme-master:~$ sudo vi /var/lib/bind/db._acme-challenge.example.u-tokyo.ac.jp $ORIGIN . $TTL 60 ; 1 minute _acme-challenge.example.u-tokyo.ac.jp IN SOA dns1.example.u-tokyo.ac.jp. nocstaff.example.u-tokyo.ac.jp. ( 2025111100 ; serial 300 ; refresh (5 minutes) 60 ; retry (1 minute) 3600 ; expire (1 hour) 60 ; minimum (1 minute) ) NS dns1.example.u-tokyo.ac.jp. NS dns2.example.u-tokyo.ac.jp. NS dns3.example.u-tokyo.ac.jp. $TTL 120 ; 2 minutes user@acme-master:~$ sudo chown bind:bind /var/lib/bind/db._acme-challenge.example.u-tokyo.ac.jp # 設定の反映 user@acme-master:~$ sudo systemctl reload bind9 # FWの設定、exampleからとdns1.example,dns2.example,dns3.exampleからのみBind9での接続受付 user@acme-master:~$ sudo ufw status numbered Status: active To Action From -- ------ ---- ... [ 7] Bind9 ALLOW IN [example-host-ip] [ 8] Bind9 ALLOW IN 133.11.254.1 [ 9] Bind9 ALLOW IN 130.69.254.1 [10] Bind9 ALLOW IN 157.82.254.1
dns-master 設定
_acme-challenge.example.u-tokyo.ac.jp. だけ、別NSに切り出します。
bash-3.1$ sudo vi /etc/namedb/u-tokyo.ac.jp
; 以下を追加
; for acme / dns-01
_acme-challenge.example.u-tokyo.ac.jp. IN NS dns1.example.u-tokyo.ac.jp.
IN NS dns2.example.u-tokyo.ac.jp.
IN NS dns3.example.u-tokyo.ac.jp.
dns1.example / dns2.example / dns3.example 設定(参考)
_acme-challenge.example.u-tokyo.ac.jp. のzone作成(参考情報のみ)。
user@dns1.example:~$ diff /etc/namedb/named.conf-dom.20251111 /etc/namedb/named.conf-dom
699a700,707
> zone "_acme-challenge.example.u-tokyo.ac.jp" in {
> type slave;
> file "bak/dom/_acme-challenge.example.u-tokyo.ac.jp";
> masters {
> [acme-master-ip];
> };
> };
>
user@dns2.example:~$ diff /etc/namedb/named.conf-dom.20251111 /etc/namedb/named.conf-dom
701a702,709
> zone "_acme-challenge.example.u-tokyo.ac.jp" in {
> type slave;
> file "bak/dom/_acme-challenge.example.u-tokyo.ac.jp";
> masters {
> [acme-master-ip];
> };
> };
>
user@dns3.example:~$ diff /etc/namedb/named.conf-dom.20251111 /etc/namedb/named.conf-dom
701a702,709
> zone "_acme-challenge.example.u-tokyo.ac.jp" in {
> type slave;
> file "bak/dom/_acme-challenge.example.u-tokyo.ac.jp";
> masters {
> [acme-master-ip];
> };
> };
>
DNS-01対応のクライアント側作業
HTTP-01チャレンジでのコマンド(参考)
user@example:~$ sudo certbot \ --server https://secomtrust-acme.com/acme/ \ --eab-hmac-key [secret] \ --eab-kid [kid] \ -d example.u-tokyo.ac.jp \ --key-type rsa
DNS-01チャレンジ対応のコマンドオプション
certonlyオプションをつけて、証明書の生成のみにしています。
user@example:~$ sudo certbot certonly \ --server https://secomtrust-acme.com/acme/ \ --eab-hmac-key [secret] \ --eab-kid [kid] \ -d example.u-tokyo.ac.jp \ --key-type rsa \ --dns-rfc2136 \ --dns-rfc2136-credentials /etc/letsencrypt/rfc2136.ini \ --dns-rfc2136-propagation-seconds 60
サーバ側作業(インストールなど)
user@example:~$ sudo apt-get install certbot python3-certbot-dns-rfc2136 [sudo] password for user: Reading package lists... Done Building dependency tree... Done Reading state information... Done ...
certbotのDNS-01チャレンジ用設定ファイル
user@example:~$ sudo vi /etc/letsencrypt/rfc2136.ini
dns_rfc2136_server = [acme-master-ip]
dns_rfc2136_port = 53
dns_rfc2136_name = [tsig-key-name]
dns_rfc2136_secret = [secret]
dns_rfc2136_algorithm = HMAC-SHA256
# 設定ファイルのパーミッション設定
user@example:~$ sudo chown root:root /etc/letsencrypt/rfc2136.ini
user@example:~$ sudo chmod 600 /etc/letsencrypt/rfc2136.ini
実行
user@example:~$ sudo certbot certonly \ --server https://secomtrust-acme.com/acme/ \ --eab-hmac-key [secret] \ --eab-kid [kid] \ -d example.u-tokyo.ac.jp \ --key-type rsa \ --dns-rfc2136 \ --dns-rfc2136-credentials /etc/letsencrypt/rfc2136.ini \ --dns-rfc2136-propagation-seconds 60 Saving debug log to /var/log/letsencrypt/letsencrypt.log Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): user@example.ac.jp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://repo1.secomtrust.net/spcpp/publicly-trusted-cpcps/. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: y Account registered. Requesting a certificate for example.u-tokyo.ac.jp Waiting 60 seconds for DNS changes to propagate Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.u-tokyo.ac.jp/fullchain.pem Key is saved at: /etc/letsencrypt/live/example.u-tokyo.ac.jp/privkey.pem This certificate expires on 2026-02-09. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
証明書の確認
user@example:~$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: example.u-tokyo.ac.jp
Serial Number: 7dafc3b1e77920e6ea035585d2c86223
Key Type: RSA
Domains: example.u-tokyo.ac.jp
Expiry Date: 2026-02-09 06:10:26+00:00 (VALID: 88 days)
Certificate Path: /etc/letsencrypt/live/example.u-tokyo.ac.jp/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.u-tokyo.ac.jp/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
user@example:~$ sudo openssl x509 -in /etc/letsencrypt/live/example.u-tokyo.ac.jp/fullchain.pem -text -noout
定期的に自動更新されることを確認
user@example:~$ systemctl list-timers | grep certbot Thu 2025-11-13 04:46:14 JST 11h - - certbot.timer certbot.service
証明書更新時の反映
証明書ファイル /etc/letsencrypt/live/example.u-tokyo.ac.jp/fullchain.pem と、証明書鍵ファイル /etc/letsencrypt/live/example.u-tokyo.ac.jp/privkey.pem ができるので、これを参照するように設定を実施します。
証明書更新時にWebサーバなどに反映するためのコマンドを実施します。
user@example:~$ sudo vi /etc/letsencrypt/renewal-hooks/deploy/gitlab-reload.sh #!/bin/bash (gitlabのフロントとなるnginxをreloadするshell script, 省略)
参考:nsupdateコマンドについて
nsupdateコマンドで、ゾーンの更新などの確認ができます。
- FWが正しく設定されているか
- ACLが正しく設定されているか
- TSIGが正しく設定されているか
# テストトークンの追加 user@acme-master:~$ sudo nsupdate -k /etc/bind/keys/acme-example.key > server 127.0.0.1 > zone _acme-challenge.example.u-tokyo.ac.jp > update add _acme-challenge.example.u-tokyo.ac.jp. 60 IN TXT "test-token-123" > send > quit # 追加したテストトークンの削除 user@acme-master:~$ dig @localhost _acme-challenge.example.u-tokyo.ac.jp TXT ; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @localhost _acme-challenge.example.u-tokyo.ac.jp TXT ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8393 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; COOKIE: 97659a78206da0680100000069129e446f4de0917d881177 (good) ;; QUESTION SECTION: ;_acme-challenge.example.u-tokyo.ac.jp. IN TXT ;; ANSWER SECTION: _acme-challenge.example.u-tokyo.ac.jp. 60 IN TXT "test-token-123" ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(localhost) (UDP) ;; WHEN: Tue Nov 11 11:24:04 JST 2025 ;; MSG SIZE rcvd: 125 # テストトークンの削除 user@acme-master:~$ sudo nsupdate -k /etc/bind/keys/acme-example.key > server 127.0.0.1 > zone _acme-challenge.example.u-tokyo.ac.jp > update delete _acme-challenge.example.u-tokyo.ac.jp. TXT > send > quit # 削除の確認 user@acme-master:~$ dig @localhost _acme-challenge.example.u-tokyo.ac.jp TXT ; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @localhost _acme-challenge.example.u-tokyo.ac.jp TXT ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28707 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; COOKIE: bdb4a9ff8fe7ea5c0100000069129ec9cc3b342c10da0467 (good) ;; QUESTION SECTION: ;_acme-challenge.example.u-tokyo.ac.jp. IN TXT ;; AUTHORITY SECTION: _acme-challenge.example.u-tokyo.ac.jp. 60 IN SOA dns1.example.u-tokyo.ac.jp. nocstaff.example.u-tokyo.ac.jp. 2025111103 300 60 3600 60 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(localhost) (UDP) ;; WHEN: Tue Nov 11 11:26:17 JST 2025 ;; MSG SIZE rcvd: 164 # 更新したデータは.jnlファイルに保存されている。それをzoneファイルに反映する user@acme-master:~$ sudo rndc sync # zoneファイルの最新の状態を確認する user@acme-master:~$ sudo rndc zonestatus _acme-challenge.example.u-tokyo.ac.jp name: _acme-challenge.example.u-tokyo.ac.jp type: primary files: /var/lib/bind/db._acme-challenge.example.u-tokyo.ac.jp serial: 2025111103 nodes: 1 last loaded: Tue, 11 Nov 2025 01:57:20 GMT secure: no dynamic: yes frozen: no reconfigurable via modzone: no
