以前までIPアドレス証明書は、無料の認証局ではZeroSSLのみが対応していました。
ZeroSSLは登録が必須でAPIキーを利用する必要がありました。
この度、以前よりアナウンスされていたLet's EncryptでIPアドレス証明書がGAされましたので、早速試してみます。
IPアドレス証明書は1.1.1.1で利用されていることで有名でした。
DoTなどで活用されています。
仕様
・有効期間は160時間 (6.6日)
・ACMEクライアントで"shortlived" Profileを選択することで利用可能です。
https://letsencrypt.org/2026/01/15/6day-and-ip-general-availability
現在、デフォルトの証明書の有効期間は90日ですが、今後45日に短縮されることが発表されています。
https://letsencrypt.org/2025/12/02/from-90-to-45
有効期間が短い理由として、以下が挙げられています。
IPアドレス証明書は有効期限が短い証明書である必要があります。これは、IPアドレスはドメイン名よりも一時的であるため、より頻繁な検証が重要となるためです。
また用途としては以下が挙げられています
ホスティングプロバイダー向けのデフォルトページ。ユーザーがブラウザに個々のサイト名ではなくサーバーのIPアドレスを貼り付けた場合(現状では通常、ブラウザでエラーが発生します)。
ドメイン名を全く持っていない場合でもウェブサイトにアクセスできる方法(ただし、ドメイン名を取得する場合と比べて、信頼性や利便性は多少劣る)。
DNS over HTTPS (DoH)やその他のインフラストラクチャサービスのセキュリティを確保します。証明書があれば、DoHサーバーはクライアントに対して自身の身元をはるかに容易に証明できます。これにより、DoHユーザーやクライアントがDoHサーバーに接続する際に、有効な公開信頼証明書を要求することが容易になります。
ドメイン名がなくても、一部の家庭用デバイス(ネットワーク接続ストレージサーバーやIoTデバイスなど)へのリモートアクセスを安全に確保する。
クラウドホスティングインフラストラクチャ内の一時的な接続(例えば、あるバックエンドクラウドサーバーと別のバックエンドサーバー間の接続、またはHTTPS経由で新規または短命のバックエンドサーバーを管理するための一時的な接続など)を保護する。ただし、これらのサーバーには少なくとも1つのパブリックIPアドレスが利用可能であることが条件となる
>ホスティング プロバイダーのデフォルト ページ
Nginx等のWebサーバは、初期設定でIPアドレスを利用してアクセスするとホストされているTLS証明書を返し、IPアドレスから何のドメインをホストしているか把握できてしまいます。
対処法としては、HTTP 444を返すなどがありました。
IPアドレス証明書を返すことで、そういった攻撃を防御することができます。
実際に発行してみる
準備
ACMEクライアントの1つであるLegoを利用して、IPアドレス証明書を発行してみましょう。
今回はAWS EC2で試します。
まずLegoをインストールします。
今回はCPUが少ないため、バイナリをダウンロードします。
>wget https://github.com/go-acme/lego/releases/download/v4.31.0/lego_v4.31.0_linux_amd64.tar.gz
>tar zxvf lego_v4.31.0_linux_amd64.tar.gz
>sudo mv lego /usr/local/bin/
>lego -v
lego version 4.31.0 linux/amd64legoのアカウント情報と証明書が保存されるフォルダを用意します。
legoを実行するユーザで書き込めるようにしてください。
>sudo mkdir /etc/lego今回はWebサーバにNginxを利用します。
:80でアクセスが来た際に.well-knownで応答する必要があります。
今回はデフォルトの/var/www/html/を利用します。
legoを実行するユーザで書き込み可能なことを確認してください。
>sudo apt-get install nginx発行
以下のようなコマンドを利用して初回は発行します。
>lego --path "/etc/lego" \
--disable-cn \
--http \
--http.webroot "/var/www/html" \
--domains "13.56.189.127" \ #ご自身のサーバのIPv4アドレス
--domains "2600:1f1c:c39:4c3e:844a:22e7:530:7c24" \ #ご自身のサーバのIPv6アドレス
--email "axle-cavern7k@icloud.com" \ #ご自身のe-mail address
-a run \
--profile shortlived
2026/01/23 03:04:38 [INFO] [13.56.189.127, 2600:1f1c:c39:4c3e:844a:22e7:530:7c24] acme: Obtaining bundled SAN certificate
2026/01/23 03:04:38 [INFO] [13.56.189.127] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/2990097236/647345265206
2026/01/23 03:04:38 [INFO] [2600:1f1c:c39:4c3e:844a:22e7:530:7c24] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/2990097236/647345265226
2026/01/23 03:04:38 [INFO] [13.56.189.127] acme: Could not find solver for: tls-alpn-01
2026/01/23 03:04:38 [INFO] [13.56.189.127] acme: use http-01 solver
2026/01/23 03:04:38 [INFO] [2600:1f1c:c39:4c3e:844a:22e7:530:7c24] acme: Could not find solver for: tls-alpn-01
2026/01/23 03:04:38 [INFO] [2600:1f1c:c39:4c3e:844a:22e7:530:7c24] acme: use http-01 solver
2026/01/23 03:04:38 [INFO] [13.56.189.127] acme: Trying to solve HTTP-01
2026/01/23 03:04:44 [INFO] [13.56.189.127] The server validated our request
2026/01/23 03:04:44 [INFO] [2600:1f1c:c39:4c3e:844a:22e7:530:7c24] acme: Trying to solve HTTP-01
2026/01/23 03:04:50 [INFO] [2600:1f1c:c39:4c3e:844a:22e7:530:7c24] The server validated our request
2026/01/23 03:04:50 [INFO] [13.56.189.127, 2600:1f1c:c39:4c3e:844a:22e7:530:7c24] acme: Validations succeeded; requesting certificates
2026/01/23 03:04:55 [INFO] [13.56.189.127] Server responded with a certificate.SSL証明書が発行されました。
legoのpathで指定したフォルダに証明書が追加されていることを確認します。
今回は/etc/lego/certificatesになります。
>/etc/lego/certificates# ls
13.56.189.127.crt 13.56.189.127.issuer.crt 13.56.189.127.json 13.56.189.127.key最低限の設定でNginxで動作を見てみましょう
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/lego/certificates/13.56.189.127.crt;
ssl_certificate_key /etc/lego/certificates/13.56.189.127.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}>sudo nginx -t
>sudo systemctl reload nginx動作確認
手元のPCよりcurlしてみます。
>curl https://13.56.189.127/ -v
* Trying 13.56.189.127:443...
* Connected to 13.56.189.127 (13.56.189.127) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
* subject: [NONE]
* start date: Jan 23 02:06:20 2026 GMT
* expire date: Jan 29 18:06:19 2026 GMT
* subjectAltName: host "13.56.189.127" matched cert's IP address!
* issuer: C=US; O=Let's Encrypt; CN=YE1
* SSL certificate verify ok.
* using HTTP/1.x>curl "https://[2600:1f1c:c39:4c3e:844a:22e7:530:7c24]" -v
* Trying [2600:1f1c:c39:4c3e:844a:22e7:530:7c24]:443...
* Connected to 2600:1f1c:c39:4c3e:844a:22e7:530:7c24 (2600:1f1c:c39:4c3e:844a:22e7:530:7c24) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
* subject: [NONE]
* start date: Jan 23 02:06:20 2026 GMT
* expire date: Jan 29 18:06:19 2026 GMT
* subjectAltName: host "2600:1f1c:c39:4c3e:844a:22e7:530:7c24" matched cert's IP address!
* issuer: C=US; O=Let's Encrypt; CN=YE1
* SSL certificate verify ok.
* using HTTP/1.xIPv4, IPv6アドレスの双方で動作が確認できました。
ブラウザからも確認してみます。


正常にアクセスできました。
crt.shでCT(Certificate Transparency)を確認してみましょう。
https://crt.sh/?q=13.56.189.127
https://crt.sh/?q=2600:1f1c:c39:4c3e:844a:22e7:530:7c24
https://crt.sh/?id=23927694466

ちゃんと発行された証明書が確認できました。
過去に発行された履歴が確認できますので、クラウドなどIPが再利用される環境だと、以前の人がIPアドレスの証明書を利用していたか確認できますね。
CTが確認できた時点で、該当のドメインを解決し、Aレコードなどと紐づけて保存している人たちもいます。
インターネット上での活動はほとんどが記録されていますね。
ご自身でWebサーバを運用されている方はぜひ試してみてください。
証明書の更新
Legoはデフォルトで証明書が切れる30日前に更新されます。
例えば毎日1回Cronで実行する場合、shortlivedプロファイルだと毎日更新されてしまいます。
証明書の期限は6日強ですので、残り2日を切っていたら更新するようにしましょう。
以下のようなShell Scriptを用意し、SystemdやCronで実行させましょう。
> lego --path "/etc/lego" \
--disable-cn \
--http \
--http.webroot "/var/www/html" \
--domains "13.56.189.127" \
--domains "2600:1f1c:c39:4c3e:844a:22e7:530:7c24" \
--email "axle-cavern7k@icloud.com" \
-a renew \
--profile shortlived \
--days 2定期実行する場合は、Let's Encrypt側の負荷が上昇しないよう、実行タイミングをユニークなものにするようにしてください。
https://go-acme.github.io/lego/usage/cli/renew-a-certificate/index.html#automatic-renewal
お問い合わせ先
この記事に書いてある内容について何らかのご意見やご要望がある方は以下のメールアドレスまでご連絡ください
reze@reze.party
No comments yet