SSL сертификат Let’s Encrypt wildcard для https на базе Nginx

gost-main-letsencrypt Роутеры

Предисловие

Добро пожаловать, уважаемые читатели!
В одном из своих циклов статей, я реализовывал возможность обращаться к различным сервисам через поддомены.
В последней статье про Plex один из читателей поинтересовался, а почему не завести все запросы с http(80) и https(443) на единый nginx?

Павел:
Уважаемый автор, статья отличная, но как новичку мне не совсем понятен вопрос с веб-сервером nginx: его назначение, необходимость установки в каждый контейнер – неужели нельзя его сделать единым на все контейнеры с Transmission и Plex’ом? Напишите об этом поподробнее здесь как дополнение или же вообще отдельной статьёй с упором на практическое применение в домашней сети!
Собственно, «а почему нет?» и я решил изменить подход, прикрутив SSL на https(443). Браузеры нынче очень не любят непонятные сертификаты для https. Меня это раздражало в Proxmox, он работает на https по умолчанию, но сертификаты не доверенные.
Вот тот самый цикл статей:

  1. Домашний Сервер: Часть 1 – Предисловие, аппаратная и софтовая начинка
  2. Домашний Сервер: Часть 2 – Установка системы виртуализации Proxmox
  3. Домашний Сервер: Часть 3 – Внутренний DNS сервис на BIND9 или свои доменные имена в локальной сети
  4. Домашний Сервер: Часть 4 – Настройка Transmission daemon в контейнере LXC Proxmox-VE
  5. Домашний Сервер: Часть 5 – Установка и настройка Plex Media Server в контейнере LXC Proxmox-VE

Подготовка

Для того, чтобы все завести на один Nginx, я решил запустить отдельный LXC контейнер.
Ставим необходимое в контейнере. (Как поставить LXC контейнер, можно найти в цикле статей)

apt install nginx git -y

Клонируем файлы клиента Certbot

git clone https://github.com/certbot/certbot /opt/letsencrypt
ln -s /opt/letsencrypt/certbot-auto /usr/bin/certbot
Certbot — это клиент протокола ACME, который устанавливается на конечном сервере и используется для запроса сертификата, валидации домена, установки сертификата и дальнейшего автоматического продления сертификатов от Let’s Encrypt.

Тут я хочу остановится подробнее.
Я поставил себе задачу, чтобы можно было через поддомены открывать свои сервисы, как в локальной сети, так и из интернета.
Для этого необходимо будет перенаправить 80 и 443 порты на данный контейнер. Но об этом чуть позже.
Let’s Encrypt обычно требует, чтобы ваш IP адрес на который назначен домен или поддомен был доступен из вне, но т.к. у меня вся сеть закрыта Firewall-ом роутера возникают сложности. Можно было бы найти IP адреса сервисов Let’s Encrypt, но это не благодарное занятие.
Помочь в этой ситуации может Wildcard сертификат.

https://ru.wikipedia.org/wiki/Wildcard-сертификат
Wildcard-сертификат — сертификат открытого ключа, который может использоваться с несколькими подобластями домена.
Поддерживается только один уровень поддоменов! Т.е. *.example.com позволит поддерживать поддомены first.example.com, second.example.com и т.д., а вот для once.first.example.com данный сертфикат уже работать не будет.
При этом можно создать сертификат для поддомена второго уровня: *.first.example.com
В этом случае сертификат будет работать для любых поддоменов второго уровня: one.first.example.com, two.first.example.com и .т.д.
Let’s Encrypt реализовал возможность получения Wildcard сертификата в марте 2018 года (14 марта 2018)
Я буду получать сертификат для поддомена первого уровня, а все сервисы повешу на поддомены второго уровня и мне не придется получать сертификаты для каждого сервиса по отдельности.
У меня есть хостинг и управление доменом я веду на нем. Чтобы была возможность заходить на поддомены сервисов, вам необходим основной домен доступный из интернета.

Для домена на своем хостинге нужно создать основной поддомен, для примера я возьму такой:
home.gregory-gost.ru

Запускаем certbot для получения сертификата.

certbot certonly --agree-tos -d home.gregory-gost.ru -d *.home.gregory-gost.ru --preferred-challenges dns --manual --server https://acme-v02.api.letsencrypt.org/directory --manual-public-ip-logging-ok
Please deploy a DNS TXT record under the name
_acme-challenge.home.gregory-gost.ru with the following value:

fgfgDFDFuReJBUTYbYO71os_BKdfJDJFdfhfHDHFDFJHFD

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Certbot будет выдавать такие сообщения. У меня было два таких.
Нужно занести обе TXT записи в DNS настройки основного домена. Также добавить/заменить А запись, своим статическим IP роутера, в поддоменах.

Сертификаты будут лежать по пути
/etc/letsencrypt/live/home.gregory-gost.ru/

Далее создаем поддомены второго уровня для сервисов: plex.home.gregory-gost.ru и т.д.

В Cron появится файл автоматической проверки и продления сертификата.
Проверим это правило:

cat /etc/cron.d/certbot
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
#
# Important Note!  This cronjob will NOT be executed if you are
# running systemd as your init system.  If you are running systemd,
# the cronjob.timer function takes precedence over this cronjob.  For
# more details, see the systemd.timer manpage, or use systemctl show
# certbot.timer.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

Все вроде бы хорошо, за одним исключением. Можно попроще и после обновления сертификатов хорошо бы автоматически перезагрузить Nginx.
И это можно сделать отредактировав конфигурационный файл Certbot для нашего домена.

Файл конфигурации лежит по пути: /etc/letsencrypt/renewal/home.gregory-gost.ru.conf
Для того, чтобы выполнить какую-либо команду ДО или ПОСЛЕ обновления сертификатов у Certbot есть специальные ключи

  • —pre-hook — выполнять команду перед запуском certboot
  • —post-hook — выполнять команду после запуска certboot
  • —renew-hook — выполнять команду только после успешного продления сертификата

Самым удобным в этом случае выглядит ключ —renew-hook, он позволяет перезапускать службы только после успешного продления сертификата, а не просто дважды в день, как у ключа —post-hook
Добавим команду перезапуска в файл конфигурации, в раздел [renewalparams]:

nano /etc/letsencrypt/renewal/home.gregory-gost.ru.conf
# renew_before_expiry = 30 days
version = 0.28.0
archive_dir = /etc/letsencrypt/archive/home.gregory-gost.ru
cert = /etc/letsencrypt/live/home.gregory-gost.ru/cert.pem
privkey = /etc/letsencrypt/live/home.gregory-gost.ru/privkey.pem
chain = /etc/letsencrypt/live/home.gregory-gost.ru/chain.pem
fullchain = /etc/letsencrypt/live/home.gregory-gost.ru/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = manual
account = 9471dfdhjdhghg1a8c1a2a07fde01
pref_challs = dns-01,
manual_public_ip_logging_ok = True
server = https://acme-v02.api.letsencrypt.org/directory
renew-hook = service nginx restart

Делаем проверку на продление сертификата проще.
Удаляем или комментируем строки в файле /etc/cron.d/certbot и копируем файл в /etc/cron.weekly

cp /etc/cron.d/certbot /etc/cron.weekly/
chmod +x /etc/cron.weekly/certbot
nano /etc/cron.weekly/certbot
#!/bin/bash
/usr/bin/certbot -q renew
Если при обновлении сертификата возникают ошибки, то выпустите сертификат заново.

certbot certonly --agree-tos -d home.gregory-gost.ru -d *.home.gregory-gost.ru --preferred-challenges dns --manual --server https://acme-v02.api.letsencrypt.org/directory --manual-public-ip-logging-ok

Далее настраиваем nginx.

Файлы конфигурации nginx

snippets/letsencrypt.conf
nano /etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
        allow all;
        root /var/lib/letsencrypt/;
        default_type "text/plain";
        try_files $uri =404;
}
nginx.conf
error_log               /var/log/nginx/error.log crit;
pid                     /var/run/nginx.pid;
worker_rlimit_nofile    8192;
timer_resolution        100ms;
include                 /etc/nginx/modules-enabled/*.conf;

events {
        multi_accept    on;
        accept_mutex    off;
        use             epoll;
}

http {
        include         /etc/nginx/mime.types;
        include         /etc/nginx/fastcgi.conf;
        default_type    application/octet-stream;

        sendfile        on;
        tcp_nopush      on;
        tcp_nodelay     on;

        #ssl_session_cache      shared:SSL:10m;
        #ssl_session_timeout    10m;

        include         /etc/nginx/conf.d/*.conf;

}
home.conf
upstream home.gregory-gost.ru  {
        server 192.168.88.6:8006;
}

server {
        listen 80;
        server_name home.gregory-gost.ru;

        include snippets/letsencrypt.conf;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;
        server_name home.gregory-gost.ru;

        include snippets/letsencrypt.conf;

        ssl_certificate /etc/letsencrypt/live/home.gregory-gost.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/home.gregory-gost.ru/privkey.pem;

        proxy_redirect off;
        location / {
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade"; 
                proxy_pass https://home.gregory-gost.ru;
                proxy_buffering off;
                client_max_body_size 0;
                proxy_connect_timeout  3600s;
                proxy_read_timeout  3600s;
                proxy_send_timeout  3600s;
                send_timeout  3600s;
        }
}
transmission.conf
upstream torrent.home.gregory-gost.ru {
        server          192.168.88.9:9091;
        keepalive       32;
}

server {
        listen 80;
        server_name torrent.home.gregory-gost.ru;

        include snippets/letsencrypt.conf;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;
        server_name torrent.home.gregory-gost.ru;

        include snippets/letsencrypt.conf;

        ssl_certificate /etc/letsencrypt/live/home.gregory-gost.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/home.gregory-gost.ru/privkey.pem;

        send_timeout    100m;

        gzip            on;
        gzip_vary       on;
        gzip_min_length 1000;
        gzip_proxied    any;
        gzip_types      text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
        gzip_disable "MSIE [1-6]\.";

        client_max_body_size 100M;

        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_redirect off;
        proxy_buffering off;

        location / {
                #rewrite ^/$ http://$http_host;
                proxy_pass http://torrent.home.gregory-gost.ru;
        }

}
plex.conf
upstream plex.home.gregory-gost.ru {
        server          192.168.88.8:32400;
        keepalive       32;
}

server {
    listen 80;
    server_name plex.home.gregory-gost.ru;

    include snippets/letsencrypt.conf;
    return 301 https://$host$request_uri;
}

server {
        listen          443 ssl;
        server_name     plex.home.gregory-gost.ru;

        #access_log  /var/log/nginx/plex.home.gregory-gost.ru.access.log;
        error_log  /var/log/nginx/plex.home.gregory-gost.ru.error.log;

        send_timeout    100m;

        gzip            on;
        gzip_vary       on;
        gzip_min_length 1000;
        gzip_proxied    any;
        gzip_types      text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
        gzip_disable "MSIE [1-6]\.";

        client_max_body_size 100M;

        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_redirect off;
        proxy_buffering off;

        include snippets/letsencrypt.conf;

        ssl_certificate /etc/letsencrypt/live/home.gregory-gost.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/home.gregory-gost.ru/privkey.pem;

        location / {
                if ($http_x_plex_device_name = '') {
                        rewrite ^/$ https://$http_host/web/index.html;
                }
                proxy_pass https://plex.home.gregory-gost.ru;
        }

}
openhab2.conf
upstream openhab.home.gregory-gost.ru {
        server 192.168.88.10:8080;
        keepalive 32;
}

server {
        listen 80;
        server_name openhab.home.gregory-gost.ru;

        include snippets/letsencrypt.conf;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;
        server_name openhab.home.gregory-gost.ru;

        include snippets/letsencrypt.conf;

        ssl_certificate /etc/letsencrypt/live/home.gregory-gost.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/home.gregory-gost.ru/privkey.pem;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_redirect off;
                proxy_set_header Host $http_host;
                proxy_pass http://openhab.home.gregory-gost.ru;
        }
}

Другие сервисы по аналогии.

Перенастройка локальных доменных зон

Само собой необходимо изменить основной IP адрес для доменных зон в bind9
Открываю зону прямого просмотра и редактирую

db.gregory-gost.ru
nano /etc/bind/zone/db.gregory-gost.ru
;
; Zone Front view
;
$TTL 3600
@               IN      SOA     gregory-gost.ru.        email.gregory-gost.ru. (
        2019122702      ; Serial
                1d      ; Refresh
                1h      ; Retry
                1w      ; Expire
                2h      ; Negative Cache TTL
)

@               IN      NS      ns1.example.ru.
www             IN      CNAME   gregory-gost.ru.

@               IN      NS      ns.gregory-gost.ru.
ns              IN      A       192.168.88.7

home                    IN      A       192.168.88.14
plex.home               IN      A       192.168.88.14
torrent.home            IN      A       192.168.88.14
openhab.home            IN      A       192.168.88.14
Окрываю зону обратного просмотра и также редактирую
db.gregory-gost.ru.inverse
nano /etc/bind/zone/db.gregory-gost.ru.inverse
;
; Zones invert view
;
$TTL 3600
@               IN      SOA     gregory-gost.ru.  email.gregory-gost.ru. (
        2019122702      ; Serial
                1d      ; Refresh
                1h      ; Retry
                1w      ; Expire
                2h      ; Negative Cache TTL
)

@               IN      NS      ns1.example.ru.
@               IN      NS      ns.gregory-gost.ru.
7               IN      PTR     ns.gregory-gost.ru.

14              IN      PTR     home.gregory-gost.ru.
14              IN      PTR     plex.home.gregory-gost.ru.
14              IN      PTR     torrent.home.gregory-gost.ru.
14              IN      PTR     openhab.home.gregory-gost.ru.

На примере роутера MikroTik приведу правила перенаправления 80 и 443 порта:

/ip firewall nat
add action=dst-nat chain=dstnat comment="HTTP(S) to LXC" dst-port=80 in-interface-list=Internet protocol=tcp src-address-list="Access IP" to-addresses=192.168.88.14 to-ports=80
add action=dst-nat chain=dstnat dst-port=443 in-interface-list=Internet protocol=tcp src-address-list="Access IP" to-addresses=192.168.88.14 to-ports=443

Соответственно src-address-list=»Access IP» это список разрешенных адресов прошедших PortKnocking.

На этом можно закончить, все должно работать.
У меня точно работает 🙂

Как это работает?

Немного расскажу, как это работает с точки зрения обычного пользователя. Т.е. тут не будет каких-то объемных технических подробностей по работе DNS или Nginx.
Опишу два примера, один это запрос с устройства из локальной сети, а второй это запрос с устройства откуда-то из интернета.
Запрашивать буду доменное имя:
— plex.home.gregory-gost.ru

gost-dns-nginx-example-1
Пример запроса домена с устройства в локальной сети
Давайте посмотрим, что происходит в первом случае:

  1. Мы на локальном устройстве с IP адресом 192.168.88.40 пытаемся открыть в браузере WEB интерфейс Plex Media Server
  2. Т.к. мы запросили доменное имя, то необходимо распознать это имя в IP адрес. В локальной сети всем устройствам выдаются DNS адреса 192.168.88.7 и 192.168.88.1
    Это означает, что первый DNS запрос попадет на IP 192.168.88.7 на котором у нас в свою очередь работает DNS сервер BIND9
  3. BIND9 получив такой запрос проводит сверку по спискам доступа ACL, далее проверяет есть ли такая запись в его базе.
    Если записи нет, отправляет запрос дальше. Например может отправить на роутер с IP адресом 192.168.88.1 согласно спискам ACL, а роутер отправит его провайдеру(если роутер получает от провайдера DNS) и т.д. пока доменное имя не преобразуется в IP адрес
    Нам повезло, имя home.gregory-gost.ru есть в базе BIND9 и вот, что там написано:
    cat /etc/bind/zone/db.gregory-gost.ru
    plex.home   IN   A   192.168.88.14
    cat /etc/bind/zone/db.gregory-gost.ru.inverse
    14   IN   PTR   plex.home.gregory-gost.ru.
  4. Как мы видим DNS сервер преобразует имя и направляет нас на IP адрес: 192.168.88.14
  5. IP 192.168.88.14 в свою очередь привязан к LXC контейнеру на котором установлен Nginx.
    Nginx слушает стандартные WEB порты 80 и 443. Наш запрос приходит на 80 порт т.к. мы указали http: и не указывали принудительно https:
  6. Создаваемые для Nginx файлы конфигураций работают на одном порту, но отвечают за различные сервисы.
    Nginx решает, какой из файлов «серверов» должен обработать запрос с помощью сравнения заголовка Host в запросе, оно же «доменное имя», которое мы запросили.
    Пример запроса браузера Opera. Вы можете найти заголовок Host самостоятельно:

    GET / HTTP/1.1
    Host: plex.home.gregory-gost.ru
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36 OPR/65.0.3467.78
    Sec-Fetch-User: ?1
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    Sec-Fetch-Site: none
    Sec-Fetch-Mode: navigate
    Accept-Encoding: gzip, deflate, br
    Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7

    Заголовки(Headers): https://ru.wikipedia.org/wiki/Список_заголовков_HTTP

  7. В конфигурационных файлах Nginx указаны непосредственные IP адреса и порты служб, которые могут работать совершенно в разных контейнерах, устройствах, виртуальных средах и т.д.
    Например в этом файле nginx указан IP адрес и порт на котором работает Plex Media Server

    cat /etc/nginx/conf.d/plex.conf
    upstream plex.pve.gregory-gost.ru {
            server          192.168.88.8:32400;
            keepalive       32;
    }
    location / {
                    if ($http_x_plex_device_name = '') {
                            rewrite ^/$ https://$http_host/web/index.html;
                    }
                    proxy_pass https://plex.pve.gregory-gost.ru;
            }

    А это непосредственное перенаправление на страницу https://192.168.88.8:32400/web/index.html

  8. В результате, в окне браузера под адресом plex.home.gregory-gost.ru мы видим тоже самое, что увидели бы при прямом заходе на https://192.168.88.8:32400/web/index.html
    Единственное, мы через Nginx дополнительно подключили сертификат SSL, поэтому мы можем спокойно использовать https: вместо простого http:
gost-dns-nginx-example-2
Пример запроса доменного имени с устройства из сети интернет
Давайте посмотрим, что происходит во втором случае:

  1. Мы на каком-то устройстве с динамическим рандомным IP адресом пытаемся открыть в браузере WEB интерфейс Plex Media Server, например сидя в кафе или у друзей.
  2. Т.к. мы запросили доменное имя, то необходимо, все также, распознать это имя в IP адрес. Только делать это будет уже сервис, где мы проводили регистрацию домена, по другому это еще называется «парковка» домена.
    Чтобы запрос корректно обрабатывался в панели администрирования необходимо добавить все необходимые поддомены по аналогии с локальной реализацией.
    Отличием будет, удобное добавление через панель управления сервиса и необходимость указывать статический IP адрес, выданный нашему роутеру провайдером.
    Например у меня домен обслуживает хостинг провайдер, у которого также обслуживается сам сайт и есть удобная панель управления. У разных хостеров и регистраторов разные панели управления!
  3. При вводе доменного имени, запрос так или иначе попадет к нашему хостеру и его DNS служба перенаправит нас на указанный, в «A» записи, IP адрес и порт.(стандартно — http: 80 и https: 443)
  4. Т.к. мы указываем в «А» записи, статический IP адрес нашего роутера, то запрос попадет на роутер. Тут-то и необходимо правило перенаправления 80 и 443 порта.
    Но перенаправлять мы будем уже не на BIND9, а сразу на LXC контейнер с Nginx с адресом 192.168.88.14. BIND9 в этом случае не требуется т.к. запрос идет извне нашей локальной среды.
  5. Далее обработка идет по аналогии с первым случаем.

Надеюсь мне удалось объяснить принцип взаимодействия с доменными именами, как из локальной сети, так и из глобальной интернет среды.

Заключение

Вот таким не хитрым способом можно уйти от использования IP адресов для своих сервисов в локальной домашней или офисной сети. Заходить по одному домену, как из внешних сетей, так и внутри локальной сети.
На последок, одно важное замечание!

НЕ держите открытыми порты 80 и 443 на вашем роутере! Это увеличение количества дыр в безопасности, если вы не уверены в сервисах к которым открываете доступ.
В моем случае порты открыты только для списка разрешенных IP адресов, в который можно попасть только через PortKnocking.
MikroTik : RouterOS : Стучимся к себе домой. Firewall Filter PortKnocking

Благодарю за ваше время!
Всего хорошего на просторах Интернета 😉

Выразить благодарность автору
Если Вам не безразлична судьба блога или Вы просто хотите отблагодарить Автора за его труд, смело переходите на страницу Поддержки, там описана вся информация, по тому, как это сделать. Заранее благодарен вам за данную инициативу!
#seo
  • Как заставить видеть сайт по домену в локальной сети
  • Доступ к локальному серверу по доменному имени
  • Настройка зоны DNS для доступа к серверу из локальной сети по имени домена
  • Свой домен в локальной сети
  • Доступ к компьютерам по именам
  • Как настроить доменную сеть

UPD 05.01.2020:
Добавлен блок «Как это работает?» для более лучшего понимания процесса запрос-ответ.

Хочешь получать уведомления о выходе новых статей?
Loading
GregoryGost

Мир интересен, если вы достаточно любопытны!!!

Оцените автора
GREGORY GOST
Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

  1. Alexey

    День добрый, Григорий
    В описанном Вами сценарии автопродление сертификата работать не будет, потому что вы генерировалиего в интерактивном режиме (ключ —manual), что является обязательным требованием при выпуске wildcard сертификатов. При запуске команды certbot -q renew вы получите ошибку:

    certbot.errors.PluginSelectionError: The manual plugin is not working; there may be problems with your existing configuration.
    The error was: PluginError(‘An authentication script must be provided with —manual-auth-hook when using the manual plugin non-interactively.’)

    Т.к. необходимо опять вручную изменить TXT записи в DNS.

    Тут есть два выхода:
    1. Заново запустить первоначальный скрипт генерации сертификатов и внести изменения в DNS вручную.
    2. Если ваш хостинг DNS поддерживает API, написать скрипт автоматического внесения изменений в DNS authenticator.sh
    https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks

    Ответить
    1. Pavel

      да, автопродление не работает, каждый раз вручную приходится вносить изменения в DNS

  2. Pavel

    Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN —
    tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN —
    tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN —
    tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN —
    tcp6 0 0 :::22 :::* LISTEN —
    tcp6 0 0 ::1:25 :::* LISTEN —

    Ответить
    1. Pavel

      Так и не получилось решить проблему с https при внешнем IP из access list. Чёт какая-то мистика( В итоге пришлось делать костыль, надеюсь временный (приму любые идеи и помощь :D). Пример plex.conf:

      upstream plex.home.example.com {
              server          192.168.88.9:32400;
              keepalive       32;
      }
      
      geo $local_users {
          default 0;
          192.168.88.0/24 1;
      }
      
      server {
          listen 80;
          server_name plex.home.example.com;
          include snippets/letsencrypt.conf;
          if ($local_users) {
          	return 301 https://$host$request_uri;
          }
          location / {
      	if ($http_x_plex_device_name = '') {
      		rewrite ^/$ http://$http_host/web/index.html;
      	}
      	proxy_pass http://plex.home.example.com;
          }   
      }
      
      server {
      	listen          443 ssl;
      	server_name     plex.home.example.com;
      
      	access_log  /var/log/nginx/plex.home.example.com.access.log;
      	error_log  /var/log/nginx/plex.home.example.com.error.log;
      
      
      	send_timeout    100m;
      
      	gzip            on;
      	gzip_vary       on;
      	gzip_min_length 1000;
      	gzip_proxied    any;
      	gzip_types      text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
      	gzip_disable "MSIE [1-6]\.";
      
      	client_max_body_size 100M;
      
      	proxy_http_version 1.1;
      	proxy_set_header Host $host;
      	proxy_set_header X-Real-IP $remote_addr;
      	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      	proxy_set_header X-Forwarded-Proto $scheme;
      	proxy_set_header Upgrade $http_upgrade;
      	proxy_set_header Connection "Upgrade";
      
      	proxy_redirect off;
      	proxy_buffering off;
      
      	include snippets/letsencrypt.conf;
      
      	ssl_certificate /etc/letsencrypt/live/home.example.com/fullchain.pem;
      	ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;
      
      	location / {
      		if ($http_x_plex_device_name = '') {
      			rewrite ^/$ https://$http_host/web/index.html;
      		}
      		proxy_pass https://plex.home.example.com;
      	}
      }
  3. Pavel

    После дальнейшего исследования обнаружил, что если убрать ssl с plex.home…..com, то из вне получается зайти по http. Https запросы как-будто дропаются роутером…

    Ответить
    1. GregoryGost автор

      Интересная ситуация.
      L2TP может влиять только если MTU не соответствующий, но это маловероятно, при условии, что все остальное работает корректно.
      Если кол-во байт в Firewall NAT увеличивается, значит запрос попадает на nginx (кстати какой порт увеличивает счетчик ? 80 или 443?). Лучше конечно убедиться в этом… Включите на nginx access log и посмотрите, что попадает в него в момент запроса ресурса.

      Еще я бы проверял через мобильный браузер (отключившись от своего WiFi конечно), как отрабатывает wildcard сертификат при переходе по доменному имени, а не через curl.
      По сути, у вас, на внешнем хостинге должны быть прописаны все ваши поддомены (plex, torrent и т.д.) и для них указан только ваш статический IP роутера отдаваемый провайдером.

      Вроде ничего не упустил.

    2. Pavel

      кол-во пакетов увеличивается на форварде 80ого порта, на 443 всегда 0. Т е пакеты попадают на 80 порт nginx (192.168.88.14), он делает редирект на https — и всё вот тут происходит таймаут, при том пакеты на форварде 443 порта 0. Еще интересный факт — если попытаться telnet 192.168.88.1 443 — будет opertation timeout, а если это сделать изнутри сети — то либо refused либо timeout

    3. GregoryGost автор

      А контейнер с nginx корректно слушает порт 443?

      netstat -nltp
  4. Pavel

    Григорий, в рамках дальнейшего изучения Вашего ресурса, решил переделать сетап
    на ssl с отдельным nginx контейнером, как вот в этой статье. Всё работает без
    проблем по https. Также у меня сделан icmp knocking, согласно Вашей статье
    MikroTik : RouterOS : Стучимся к себе домой. Firewall Filter PortKnocking. Он
    тоже работает и я могу получить доступ к своему роутеру после того, как мой айпи
    попадет в Access IP лист. Проблема заключается в том, что у меня не открываются
    внутренние ресурсы (такие как plex, torrent и тд) из вне даже после того, как
    айпи попал в Access IP лист. Форвардинг портов 80 и 443 у меня сделан также как
    у вас и на роутере я вижу, что кол-во байт увеличивается когда я делаю запрос,
    если пробую запросить через curl http://plex.home.example.com то выдает 301
    permanently moved, но браузер не открывает ни одну внутреннюю страницу и
    кидает ошибку request timeout. У меня интернет дома по L2TP, т е ethernet провод
    провайдера и по нему устанавливается тунель L2TP, в остальном сетап полностью
    как у Вас, включая даже локальные IP. Фаервол настроен также как в статье про
    порт кнокинг у Вас. Помогите пожалуйста разобраться!

    Ответить
  5. Павел

    Григорий, напишу здесь свой вопрос и пожелание: возможно ли настроить мониторинг сервера Proxmox и особенно состояние дисков используя The Dude от Mikrotik? Какова будет функциональность этого решения по сравнению с Zabbix’ом или Prometeus’ом?
    Можно ли продолжить статьи про функционал The Dude и его практическое применение в собственной сети?

    Ответить
    1. GregoryGost автор

      Возможно ли настроить мониторинг сервера Proxmox и особенно состояние дисков используя The Dude от Mikrotik?

      Конечно возможно, правда это делается с помощью скриптов и расширенных OID в SNMP (Extend), для The Dude необходимо создавать Function и Probe на основе этих функций.
      Я у себя реализовал мониторинг состояния ZFS пулов zpool(rpool,rpoolz) и используемого в них места. Планирую прикрутить еще температуру CPU и температуру каждого диска.

      Какова будет функциональность этого решения по сравнению с Zabbix’ом или Prometeus’ом?

      Насколько мне известно, для Zabbix можно найти готовые темплейты под Proxmox. Но по моему их нужно допиливать. В целом кому-то Zabbix может больше понравится т.к. можно поставить отдельного агента на хост и виртуалки или испльзовать тот же самый SNMP. Меня пока полностью устраивает The Dude. К Zabbix можно еще прикрутить Graphana для красивой визуализации графиков.
      С Prometeus’ом не работал, не подскажу.

      Можно ли продолжить статьи про функционал The Dude и его практическое применение в собственной сети?

      Продолжить конечно можно. Все зависит от объема и уникальности материала т.к. я стараюсь давать что-то интересное и полезное не лежащее на поверхности.
      Как наберу достаточно материала, буду оформлять и публиковать, а пока я собираю информацию в черновики.

  6. Павел

    Григорий, очень ценное и как всегда подробное дополнение, написанное ясно и понятно, к тому же ещё и с такими картинками! Теперь у меня всё начинает складываться в одну общую картинку, спасибо ещё раз за твои труды и прояснение всех непонятных моментов. Не скрою у меня давно уже назрела насущная необходимость иметь работающий в локальной сети WEB-сервер и вовсе не для сайтов (хотя в дальнейшем и для них тоже) а для того чтобы сделать с него загрузку на компьютеры по сети загрузочных образов — это было бы намного быстрее чем используя устаревший протокол TFTP. Но это будет целая большая тема, которой я скоро займусь т.к. теперь мне уже в теории ясно как это может быть организовано практически, а пока я опять как внимательный читатель увидел, что на картинке «Список всех поддоменов основного домена» показан имеющийся сертификат SSL на основной домен gregory-gost.ru а на все поддомены таких сертификатов нет, но как они получены как раз и рассказывается в этой статье! Пусть конечно же не на каждый из этих сервисов а на все сразу но почему его не видно в этих списках?

    Ответить
    1. GregoryGost автор

      Все потому, что у хостеров, сертификаты Let’s Encrypt идут на конкретный домен.
      И для всех поддоменов необходимо также регистрировать отдельные сертификаты, что не удобно т.к. я не знаю сколько поддоменов у меня может быть в будущем.

      Также эти поддомены, в основном, используются в локальной сети и обслуживаются в ней же, к тому же она закрыта Firewall-ом роутера.
      Соответственно и сертификаты необходимо получать не на хостинге, а в локальной сети. И Nginx для этого подходит очень хорошо, как и wildcard сертификат от Let’s Encrypt.

  7. Павел

    Григорий, на связи вновь тот самый внимательный читатель чьё любопытство послужило причиной написания этой статьи. Не скрою, было очень приятно получить так быстро и так развёрнуто ответ на свой вопрос, спасибо за это! Конечно же я повторю у себя всё что узнал из этой статьи но пока мне, к сожалению, мешает отсутствие некоторых базовых знаний, к примеру я так и не понял как так получается что в файлах конфигурации db.gregory-gost.ru и db.gregory-gost.ru.inverse указывается адрес 192.168.88.14 но происходит переход по адресам сервисов, а именно openhab.home.gregory-gost.ru, plex.home.gregory-gost.ru, openhab.home.gregory-gost.ru, torrent.home.gregory-gost.ru. Думаю я не один такой, в связи с этим предлагаю написать также обстоятельно и подробно статью (или цикл статей) про устройство и работу с внешними DNS, работу со своими доменами, — словом всё то что осталось в этой статье за кадром, это будет интересно всем читателям, заранее спасибо и благодарю за труд!

    Ответить
    1. GregoryGost автор

      Павел, приветствую.
      Добавил в статью блок «Как это работает?»
      Надеюсь не сильно замудрено. 🙂