以前まで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アドレス証明書が必要な加入者は通常、既にそのことをご存じです。当社が把握しているユースケースとしては、以下のようなものがあります。
- ホスティング プロバイダーのデフォルト ページ。個別のサイト名ではなく、サーバーの IP アドレスをブラウザーに貼り付けた場合に表示されます (現時点では、通常、ブラウザーでエラーが発生します)。
- ドメイン名をまったく持っていない場合に Web サイトにアクセスする方法 (ドメイン名を取得する場合と比べて、信頼性と利便性が多少犠牲になります)。
- DNS over HTTPS (DoH)やその他のインフラストラクチャサービスのセキュリティ確保。証明書があれば、DoHサーバーはクライアントに対して自身のIDを証明しやすくなります。これにより、DoHユーザーやクライアントがDoHサーバーに接続する際に、有効な公的に信頼された証明書の提示を必須とすることがより容易になります。
- ドメイン名がなくても、一部の家庭用デバイス (ネットワーク接続ストレージ サーバーや IoT デバイスなど) へのリモート アクセスを保護します。
- クラウド ホスティング インフラストラクチャ内の一時的な接続を保護します。たとえば、1 つのバックエンド クラウド サーバーと別のクラウド サーバー間の接続や、新しいバックエンド サーバーや短期間しか使用できないバックエンド サーバーを 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
>sudo mv lego /usr/local/bin/
>lego -v
lego version 4.31.0 linux/amd64
legoのアカウント情報と証明書が保存されるフォルダを用意します。
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 "[email protected]" \ #ご自身の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.x
IPv4, 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 "[email protected]" \
-a renew \
--profile shortlived \
--days 2
定期実行する場合は、Let’s Encrypt側の負荷が上昇しないよう、実行タイミングをユニークなものにするようにしてください。
https://go-acme.github.io/lego/usage/cli/renew-a-certificate/index.html#automatic-renewal
お問い合わせ先
この記事に書いてある内容について何らかのご意見やご要望がある方は以下のメールアドレスまでご連絡ください
[email protected]
