Выпуск TLS-сертификата без домена
Что делать, если хочется оперативно развернуть в сети Интернет свой веб-сервер и прикрутить к нему валидный 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 и выглядит профессионально.
Войдите, чтобы оценить заметку или добавить её в закладки.
По всем вопросам (технические, личные или по содержанию заметок) обращайтесь в бота поддержки или на почту iam@kgmnotes.ru.