Выпуск TLS-сертификата без домена

3 мин 14.05.2026

Что делать, если хочется оперативно развернуть в сети Интернет свой веб-сервер и прикрутить к нему валидный TLS-сертификат, выпущенный с помощью Let's Encrypt, и при этом обойтись без регистрации домена и возни с настройками DNS?

Тут нам на помощь приходит sslip.io


Как работает sslip.io

sslip.io – бесплатный DNS-сервис с простой идеей: любой поддомен, содержащий IP-адрес, автоматически резолвится в этот IP. Никакой регистрации, настройки DNS-записей или панели управления – всё работает через wildcard DNS.

sslip.io принимает IP-адрес в трёх форматах:

Формат Домен Резолвится в
Точки 186.246.5.239.sslip.io 186.246.5.239
Дефисы 186-246-5-239.sslip.io 186.246.5.239
Hex BAF605EF.sslip.io 186.246.5.239

Проверяем все три на реальном IP:

$ host 186.246.5.239.sslip.io
186.246.5.239.sslip.io has address 186.246.5.239

$ host 186-246-5-239.sslip.io
186-246-5-239.sslip.io has address 186.246.5.239

$ host BAF605EF.sslip.io
BAF605EF.sslip.io has address 186.246.5.239

Произвольные поддомены тоже работают – sslip.io распознаёт IP в любой части имени:

$ host app.186.246.5.239.sslip.io
app.186.246.5.239.sslip.io has address 186.246.5.239

$ host www.186-246-5-239.sslip.io
www.186-246-5-239.sslip.io has address 186.246.5.239

Для IPv6 используются только дефисы, двойное двоеточие (::) кодируется двойным дефисом (--):

$ host 2a01-4f8-c012-1234--1.sslip.io
2a01-4f8-c012-1234--1.sslip.io has IPv6 address 2a01:4f8:c012:1234::1

nip.io – аналогичный сервис с теми же форматами. Полезен как запасной вариант, если sslip.io упрётся в rate limits (об этом ниже):

$ host 186.246.5.239.nip.io
186.246.5.239.nip.io has address 186.246.5.239

Выпуск сертификата: пошаговый пример

Ниже – реальный лог выпуска сертификата на свежем VPS (Ubuntu 24.04, 186.246.5.239). Всё от подключения до проверки HTTPS.

1. Подключение и установка certbot

$ ssh root@186.246.5.239

root@msk-1-vm-87qh:~# apt-get update -qq && apt-get install -y -qq certbot
...
Setting up python3-acme (2.9.0-1) ...
Setting up python3-certbot (2.9.0-1) ...
Setting up certbot (2.9.0-1) ...

2. Выпуск сертификата

certbot в режиме --standalone поднимает временный HTTP-сервер на порту 80. Let's Encrypt обращается к домену, убеждается, что он указывает на этот сервер, и выдаёт сертификат:

root@msk-1-vm-87qh:~# certbot certonly --standalone --non-interactive \
  --agree-tos -m admin@example.com -d 186.246.5.239.nip.io

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for 186.246.5.239.nip.io

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/186.246.5.239.nip.io/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/186.246.5.239.nip.io/privkey.pem
This certificate expires on 2026-08-05.

Готово – от запуска команды до готового сертификата прошло несколько секунд.

3. Проверка сертификата

root@msk-1-vm-87qh:~# openssl x509 -in /etc/letsencrypt/live/186.246.5.239.nip.io/fullchain.pem \
  -noout -subject -issuer -dates

subject=CN = 186.246.5.239.nip.io
issuer=C = US, O = Let's Encrypt, CN = E8
notBefore=May  7 11:28:32 2026 GMT
notAfter=Aug  5 11:28:31 2026 GMT

Валидный сертификат от Let's Encrypt, подписанный промежуточным CA E8. Действителен 90 дней, certbot автоматически продлит его по таймеру.

4. Проверка HTTPS

Поднимаем простейший HTTPS-сервер на полученном сертификате и проверяем curl'ом:

root@msk-1-vm-87qh:~# python3 -c "
import ssl, http.server
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain(
    '/etc/letsencrypt/live/186.246.5.239.nip.io/fullchain.pem',
    '/etc/letsencrypt/live/186.246.5.239.nip.io/privkey.pem')
srv = http.server.HTTPServer(('0.0.0.0', 443), http.server.SimpleHTTPRequestHandler)
srv.socket = ctx.wrap_socket(srv.socket, server_side=True)
srv.handle_request()
" &

root@msk-1-vm-87qh:~# curl -s -o /dev/null -w "HTTP %{http_code}, TLS %{ssl_verify_result}\n" \
  https://186.246.5.239.nip.io/
HTTP 200, TLS 0

TLS 0 – сертификат прошёл полную цепочку валидации. Браузер откроет этот адрес без предупреждений.


Rate limits: подводный камень sslip.io

Изначально сертификат планировалось выпустить именно на sslip.io – он упоминается в большинстве гайдов как основной сервис. Но при попытке на том же сервере certbot вернул ошибку:

root@msk-1-vm-87qh:~# certbot certonly --standalone --non-interactive \
  --agree-tos -m admin@example.com -d 186-246-5-239.sslip.io

Requesting a certificate for 186-246-5-239.sslip.io
An unexpected error occurred:
too many certificates (250000) already issued for "sslip.io"
in the last 168h0m0s, retry after 2026-05-07 12:26:42 UTC

250 000 сертификатов за неделю – sslip.io настолько популярен, что регулярно упирается в лимиты Let's Encrypt. Именно из-за этой ошибки выше в примере используется nip.io, а не sslip.io: nip.io – тот же механизм, но с другим доменом и отдельным счётчиком лимитов. Оба сервиса присутствуют в Public Suffix List, поэтому Let's Encrypt считает их как разные «registered domains» с независимыми счётчиками.

Вывод: не закладывайтесь на один сервис. Если sslip.io выдаёт rate limit – пробуйте nip.io, и наоборот.


Использование с веб-серверами

Caddy

Caddy получает сертификаты автоматически – достаточно указать домен:

186.246.5.239.nip.io {
    reverse_proxy localhost:8000
}

При запуске Caddy сам пройдёт ACME-challenge и начнёт обслуживать HTTPS. Для этого порты 80 и 443 должны быть доступны снаружи: HTTP-01 challenge от Let's Encrypt стучится на :80, и сервер не должен прятаться за CGNAT или закрытым фаерволом.

Nginx

server {
    listen 443 ssl;
    server_name 186.246.5.239.nip.io;

    ssl_certificate     /etc/letsencrypt/live/186.246.5.239.nip.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/186.246.5.239.nip.io/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}

Автоматизация при первой загрузке

Весь процесс укладывается в cloud-init / bootstrap-скрипт – сервер получает HTTPS сразу при первом запуске:

#!/usr/bin/env bash
set -euo pipefail

IP=$(curl -s ifconfig.me)
DOMAIN="$IP.nip.io"

apt-get update -qq && apt-get install -y -qq certbot
certbot certonly --standalone --non-interactive --agree-tos \
  -m admin@example.com -d "$DOMAIN"

echo "Сертификат готов: https://$DOMAIN"

Свой wildcard DNS

sslip.io – open source на Go. Если вы не хотите зависеть от чужих DNS-серверов и их rate limits, можно поднять свой экземпляр на собственном домене. Готовые бинарники доступны на странице релизов.

Минимальный запуск:

curl -sLO https://github.com/cunnie/sslip.io/releases/download/5.0.1/sslip.io-dns-server-linux-amd64
chmod +x sslip.io-dns-server-linux-amd64
./sslip.io-dns-server-linux-amd64

Для полноценной работы нужно делегировать поддомен вашего домена (например, ip.example.com) на сервер с запущенным sslip.io-dns-server – через NS-записи в DNS. После этого 1-2-3-4.ip.example.com будет резолвиться в 1.2.3.4, и rate limits Let's Encrypt будут считаться по вашему домену, а не по общему sslip.io.


Ограничения

  • Rate limits Let's Encrypt. Как мы видели, sslip.io может упираться в лимиты из-за своей популярности. nip.io – запасной вариант, но и он не застрахован. Для массового деплоя лучше поднять свой экземпляр (см. выше) или использовать собственный домен.
  • Зависимость от внешнего DNS. Если DNS-серверы сервиса станут недоступны, новые клиенты не смогут зарезолвить домен. Уже установленные TLS-соединения продолжат работать. Свой экземпляр снимает эту проблему.
  • Смена IP = смена домена. При переназначении IP-адреса сервера старый домен перестанет работать – потребуется перевыпустить сертификат на новый.
  • Не для продакшена. Для боевых сервисов с пользователями лучше использовать нормальный домен – он запоминается, не привязан к конкретному IP и выглядит профессионально.