Доступ к домашнему серверу без публичного IP

26.06.23

Интеграция - WEB-интеграция

У меня была идея поднять дома сервер, доступный из интернета, с шифрованием трафика и, что самое главное, бесплатный!

Рецепт сервера обычной компании:

  1. Белый IP
  2. Веб-сервер (nginx, apache, IIS, winow и т.д.)
  3. Сертификаты для протокола https

Если есть много денег, то купить ssl сертификаты, белый IP и группу сисадминов для поддержки - это не проблема. Но если ты хочешь создать пет проект в вебе, или создать свой сервис, платить деньги - не вариант. А значит, некоторые ингредиенты рецепта надо заменить на бесплатные альтернативы

 

Рецепт бесплатного сервера:

  1. DynamicDNS
  2. Веб-сервер
  3. Сертификаты Let's Encrypt
  4. Docker, потому что пора бы наконец научиться пользоваться.
  5. Какой-никакой роутер с root доступом и возможностью проброса портов

Итак, начнем по порядку.

 

1. Dynamic DNS

Динамический DNS (далее по тексту DDNS) нужен для того, чтобы вы могли стучаться в свою локальную сеть. Как это работает? Вам дается адрес, чаще всего состоящий из ВашСубДомен.ДоменПоставщика.com/org или любое другое расширение. При отправке запроса на этот адрес, вызов перенаправляется в вашу локальную сеть. Для того, чтобы DDNS знал, куда пересылать запрос, вы периодически обновляете информацию о вашем текущем IP адресе на хосте DDNS. Для каждого DDNS есть своя инструкция по обновлению информации об IP адресе.

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

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

 

 

Далее, ниже создать свой домен, увидеть как он появится в списке личных доменов, проверить что там отображается ваш текущий IP адрес. Проверить свой IP адрес можно с помощью этого ресурса

Запомним токен и домен, далее эти данные нам понадобятся.

 

2. Веб-сервер

Я думаю для 1Сников не надо объяснять что такое веб-сервер. Практически все так или иначе слышали слова apache и IIS. Но на всякий случай, веб-сервер - это такая хитрая штука, которая умеет принимать http-запросы и выдавать http-ответы. Но! Это важно. В нашем случае мы не будем настраивать веб-сервер в привычном для этой фразы понимании. Дело в том, что нам нужен обратный прокси-сервер. Это такая штука, которая принимает http-запросы и пересылает их дальше по требованию. 

 

Почему именно так?

Потому что мы будем настраивать возможность обмена информацией через защищенный протокол https. Наш прокси должен получить https-запрос, дешифровать его в незащищенный http-запрос и передать его на нужный порт в нашей локальной сети. Далее, из нашей локальной сети от принимает незащищенный http-ответ, шифрует его в защищенный https-ответ и отдает клиенту. Такая "архитектура" позволит нам не заморачиваться с сертификатами в наших сервисах, а отдать все действия по шифровке/дешифровке обратному прокси-серверу.

Обратный прокси-сервер мы будем поднимать в докер контейнере, потому что он нам в локальной сети вообще никуда не упал. Это отдельный сервис, пусть живет отдельной жизнью. Поскольку это будет не единственный контейнер, мы будем использовать docker-compose.  

Да, кстати, для обратного прокси-сервера мы будем использовать nginx, потому что пора узнать что есть что-то кроме apache и IIS.

 

Пример конфигурации контейнера в docker-compose файле:

version: '3'

services:
  nginx:
    container_name: nginx
    image: nginx:stable-alpine3.17-slim 
    ports:
      - 8080:80
      - 8443:443
    volumes:
      - ./nginx:/etc/nginx
      - ./letsencrypt:/etc/letsencrypt
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
    extra_hosts:
      - "host.docker.internal:host-gateway"

Что означают все эти буквы?

"version: '3'" - объявляем, какую версию compose файла мы используем

"services:" - внутри мы будем описывать, какие сервисы мы будем использовать

"nginx:" - имя сервиса (придумываем сами)

"container_name: nginx" - имя контейнера (придумываем сами)

"image: nginx:stable-alpine3.17-slim" - указываем, какой docker образ мы будем использовать в сервисе. Все образы можно посмотреть в docker hub

"ports:
      - 8080:80
      - 8443:443"
- проброс портов в формате "порт локального хоста : порт контейнера". В данном случае контейнер будет слушать порт 8080 и 8443 вашего хоста и передавать на порт 80 и 433 соответственно внутренней сети контейнера. Порт контейнера нужно устанавливать такой же, который прописан в конфигурационном файле нашего прокси-сервера (доберемся и до него в порядке живой очереди). Порт хоста нужно задать такой же, как в настройках проброса портов в роутере 

Например: у меня роутер настроен так, все входящее на порт 80 он пробрасывает на порт 8080 моего компьютера, а входящие сообщения на порт 443 отправляет на порт 8443 компьютера.

"volumes:
      - ./nginx:/etc/nginx
      - ./letsencrypt:/etc/letsencrypt"
- монтируем папки в контейнер. То есть папка nginx на вашем компьютере и папка /etc/nginx в контейнере - это одна и та же папка с файлами. Это нужно для того, чтобы мы могли отдавать в контейнер нужные файлы (например конфигурацию или сертификаты) и менять эти файлы в режиме реального времени. 

"command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"" - команда, которая выполнится при старте контейнера. Это рекомендованная строка для запуска nginx взятая из гайдов в интернете. И она работает. Все. Идем дальше.

"extra_hosts:
      - "host.docker.internal:host-gateway""
- эти строки говорят о том, что мы настраиваем связь между сетью контейнера и хостом. Нужна она для того, чтобы мы могли из докера стучаться в сеть хоста. (далее по тексту будет пример, как это работает)

 

Пример конфигурации nginx:

 

events {}
http {

  server {
    listen 80;
    location / {
      return 301 https://domain.duckdns.org$request_uri;
    }
  }

  server {
    listen 443 ssl http2;

    ssl_certificate /etc/letsencrypt/live/domain.duckdns.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.duckdns.org/privkey.pem;
    ssl_session_cache shared:le_nginx_SSL:10m;
    ssl_session_timeout 1440m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

     location / {
      add_header Cache-Control "public, must-revalidate";
      add_header Front-End-Https on;
      add_header Strict-Transport-Security "max-age=2592000; includeSubdomains";
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_pass http://host.docker.internal:443;   
     }
  }
} 

Тут мы остановимся только на тех строках, которые что-то для нас значат. В остальном - это стандартная конфигурация nginx для обратного прокси-сервера.

"listen 80" - сюда пишем порт, который мы указывали в docker-compose файле, для http-запросов

"return 301 https://domain.duckdns.org$request_uri" - если мы получили незашифрованный http-запрос, мы делаем редирект на https, чтобы получить защищенный https-запрос. Вместо domain нужно указать ваш домен в duckdns, который вы придумали и создали.

"listen 443 ssl http2" - сюда пишем порт, который мы указывали в docker-compose файле, для https-запросов.

"ssl_certificate /etc/letsencrypt/live/domain.duckdns.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.duckdns.org/privkey.pem;"
- путь до сертификатов, которые мы получим позже. Что делать со словом domain, думаю, догадаетесь :)

"ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;" - невероятно важный файлик, без которого наш прокси просто не запустится. Скачать можно с официального репозитория

"proxy_pass http://host.docker.internal:443;" - а вот и отправка расшифрованного сообщения на хост. "host.docker.internal" в нашей конфигурации - это IP адрес хоста (вашего ПК/ноута или с чего вы там все это запускаете). А вот с портом сложнее. Тут надо указать такой порт, который слушает ваш сервис/приложение.

Так должен выглядеть файл с названием nginx.conf.

Ну, вроде с nginx более менее разобрались, по крайней мере в контексте настройки нашего прокси.

 

3. Сертификаты

Есть такая компания Let's Encrypt. Эта компания поставила перед собой задачу - перевести весь интернет на протокол https. Как это сделать? Правильно. Дать бесплатные сертификаты. Я не работал с платными TLS сертификатами, так как моя сфера работы чуть чуть другая, поэтому вся разница для меня состоит в цене (учитывая что я поднимаю свой домашний сервер). 

Далее, для удобного получения сертификатов была написана программа/библиотека на python - Certbot. Теперь получить сертификат можно было командой в командной строке, или вызвав программный интерфейс библиотеки, если вы встроили эту библиотеку в свою программу. Но и это еще не все.

Чтобы получить сертификат, вы должны подтвердить, что защищаемый сертификатами домен принадлежит вам. Для этого вы должны разместить специальную строку в специальном месте, которую центр сертификации обязательно проверит. А поскольку мы используем DDNS, мы не можем просто так куда-то что-то там размещать и проверять. Поэтому, сервисы DDNS создали специальный API, используя который вы можете разместить TXT запись в вашем субдомене DDNS для проверки. А где появляются какие-то API, появляются и энтузиасты, пишущие свои библиотеки/программы для использования этого самого API.

В итоге, чтобы не изобретать велосипед, вы должны перелопатить интернет в поисках той самой библиотеки, у которой будет самая адекватная документация, чтобы не тратить много времени на изучения возможностей. И тут мы приходим к интересному проекту, который был написан для интеграции программы certbot c DDNS DuckDNS - certbot_dns_duckdns. Вот ее мы и будем использовать в нашем проекте.

 

Пример конфигурации контейнера в docker-compose файле:

 

version: '3'

services:
  certbot:
    image: "infinityofspace/certbot_dns_duckdns:latest"
    container_name: "certbot"
    volumes:
      - "./letsencrypt:/etc/letsencrypt"
      - "./logs:/var/log/letsencrypt"
    command: certonly
      --non-interactive
      --agree-tos
      --email {YOUR_EMAIL}
      --preferred-challenges dns
      --authenticator dns-duckdns
      --dns-duckdns-token {YOUR_TOKEN}
      --dns-duckdns-no-txt-restore
      --dns-duckdns-propagation-seconds 15
      -d "domain.duckdns.org"
      -d "*.domain.duckdns.org"

Со значениями полей мы уже знакомы. Тут нас интересует поле "command". Это та самая команда, которая при запуске запустит процесс получения сертификатов. Тут нужно исправить несколько значений. "{YOUR_EMAIL}" - тут надо указать свой почтовый адрес, для регистрации сертификата. "{YOUR_TOKEN}" - сюда нужно установить токен, который вы получили в DuckDNS. Токен нужен как раз для интеграции. Со словами "domain" делать тоже, что и всегда - менять на свой домен из DuckDNS.

Итак, с конфигурациями контейнеров мы ознакомились. Теперь нам надо их совместить:

version: '3'

services:
  nginx:
    container_name: nginx
    image: nginx:stable-alpine3.17-slim 
    ports:
      - 8080:80
      - 8443:443
    volumes:
      - ./nginx:/etc/nginx
      - ./letsencrypt:/etc/letsencrypt
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
    extra_hosts:
      - "host.docker.internal:host-gateway"
  
  certbot:
    image: "infinityofspace/certbot_dns_duckdns:latest"
    container_name: "certbot"
    volumes:
      - "./letsencrypt:/etc/letsencrypt"
      - "./logs:/var/log/letsencrypt"
    command: certonly
      --non-interactive
      --agree-tos
      --email {YOUR_EMAIL}
      --preferred-challenges dns
      --authenticator dns-duckdns
      --dns-duckdns-token {YOUR_TOKEN}
      --dns-duckdns-no-txt-restore
      --dns-duckdns-propagation-seconds 15
      -d "domain.duckdns.org"
      -d "*.domain.duckdns.org"

Вот так должен выглядеть файл, с необычным названием docker-compose.yml для запуска (конечно же с вашими правками, которые мы рассмотрели выше).

Структура проекта при этом будет выглядеть примерно так:

 - letsencrypt - директория

 -- ssl-dhparams.pem - файл из п.2

 - nginx - директория

 -- nginx.conf - файл конфигурации из п.2

 - docker-compose.yml - файл вместивший в себя описание контейнеров

Директории будут монтированы в контейнеры для обмена информации

 

4. Запуск

Сначала, надо установить docker и docker-compose

Открыть командную строку и перейти в корневую директорию проекта.

Выполнить команду "docker compose -f "docker-compose.yml" up -d --build"

При первом запуске контейнер с прокси-сервером выдаст ошибку, так как не сможет найти сертификаты, они еще не созданы.

Контейнер certbot предпримет попытку создания сертификатов. Возможно, по какой-то причине не пройдет проверка домена. При этом в контейнере выйдет ошибка 

Certbot failed to authenticate some domains (authenticator: dns-duckdns). The Certificate Authority reported these problems:
   Domain: domain.duckdns.org
   Type:   unauthorized
   Detail: Incorrect TXT record "{какой-то ключ}" found at _acme-challenge.domain.duckdns.org

 Надо проверить, все ли вы правильно указали, соответствует ли ваш IP адрес в 2IP и DuckDNS, и запустить контейнер еще раз.

То, что сертификаты были правильно созданы, будет сопровождаться сообщением в логе:

 Successfully received certificate.
 Certificate is saved at: /etc/letsencrypt/live/domain.duckdns.org/fullchain.pem
 Key is saved at:         /etc/letsencrypt/live/domain.duckdns.org/privkey.pem
 This certificate expires on {какая-то дата окончания}.

При получении такого сообщения, можно запускать контейнер с прокси-сервером. Все готово для работы.

При отправке HTTPS-запроса на адрес или http://domain.duckdns.org, прокси получит данные, расшифрует и отправит HTTP-запрос на ваш хост.

Запускам наш сервис, запускаем контейнер nginx, делаем запрос на адрес https://domain.duckdns.org, получаем результат

 

 

Браузер не ругается на небезопасное соединение, сервис отдает ответ, все работает как и задумывалось.

 

Итог

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

Также, вы должны понимать, что вам понадобится еще несколько настроек. Вам надо отправлять в duckdns свой текущий IP адрес для автоматического обновления. Как это сделать описано тут, ну или вы можете отправлять https-запрос типа https://www.duckdns.org/update?domains={YOURVALUE}&token={YOURVALUE}[&ip={YOURVALUE}]

Также, было бы неплохо настроить контейнер certbot на автоматический перевыпуск сертификатов после окончания их действия (срок жизни сертификата - 90 дней). В противном случае раз в 90 дней вы должны будете руками запускать контейнер для перевыпуска сертификатов.

nginx docker docker-compose прокси-сервер certbot letsencrypt

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    16014    13    18    

13

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    18040    10    15    

14

SALE! 10%

Автоматическая загрузка файлов (например, прайс-листов) из электронной почты, FTP, HTTP, их обработка и выгрузка на FTP (на сайт) и для других целей

Прайсы WEB-интеграция Ценообразование, анализ цен Файловый обмен (TXT, XML, DBF), FTP Автомобили, автосервисы Оптовая торговля, дистрибуция, логистика Управленческий учет Платные (руб)

Программа с заданным интервалом времени (или по ручной команде) скачивает файлы (например, прайс-листы поставщиков) из различных источников: письма электронной почты, FTP или HTTP-адреса, и сохраняет их в каталог упорядоченной структуры. При этом извлекает файлы из архивов, может переименовывать файлы и менять их формат (csv, xls, txt). Можно настроить выгрузку обработанных файлов на сайт (через FTP-подключение). Программа будет полезна компаниям, у которых есть большое количество поставщиков и/или прайс-листы поставщиков обновляются часто (необязательно прайс-листы, файлы могут быть любого назначения). Собранные таким образом актуальные версии прайс-листов можно выгрузить с помощью программы себе на сайт (или на любой FTP-сервер) или выполнить другие необходимые задачи.

28000 25200 руб.

28.05.2015    85221    26    51    

50

Модуль для обмена "1С:Предприятие 8. УАТ. ПРОФ" с FortMonitor

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    12947    32    8    

12

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    89509    163    217    

320
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. SerVer1C 767 26.06.23 14:05 Сейчас в теме
Если у вас серый динамический ip-адрес (т.е. вы сидите за NATом, или, не приснись, за двойным NATом),тогда DynDNS вам не поможет. Лично у меня краснояйцевый оператор таким грешит.
Trucker; kamisov; +2 Ответить
4. nemec 18 29.06.23 16:58 Сейчас в теме
(1) Решение тем не менее есть - покупаем вместо мусора в виде роутера, любое современное устройство компании которое начинается на буку К и на букву К заканчивается (бывшее подразделение компании З. - чтобы не сочли за рекламу), которые в своей прошивке обладает "массой ненужных функций" (ц) диванные интернет эксперты. У них есть совершенно бездвоздмездно, то есть даром, сервис динамического ДНС, в том числе и для серых адресов через собственное облако. В комплекте идет автоматически обновляемый LetsEncrypt, так что вашей задачей будет только указать настройки переадресации или просто добавить уникальное доменное имя для вашего сервера и на этом всё. Т.е. прямо для своего сервера задаете в настройках роутера адрес типа "1ссервер.мойроутердома.к.......к.линк" и вся маршрутизация заворачивается на него
Aleskey_K; Krahmalov; TerveRus; +3 1 Ответить
6. user716566 14.07.23 13:36 Сейчас в теме
(1)А связаться с Вами можно?
2. siamagic 26.06.23 14:47 Сейчас в теме
Я у себя хостинг так держал - докер опять засунули туда где не ждали, школота блин ) лижбы совать и перепечатывать инструкции с инета.
3. agentz 40 29.06.23 16:26 Сейчас в теме
Сидя за NAT вы можете сидеть в серой сети и провайдер а) не даст белый ip, даже динамический б) провайдер не даст открыть порты. Решение: проще не придумаешь ngrok , вариант по сложнее мелкий сервер в облаке и ВПН к нему
5. itmind 310 03.07.23 07:30 Сейчас в теме
Я думаю, что VPS за 150-300 руб в месяц у облачных провайдеров не такая уж и большая сумма для программиста.
Оставьте свое сообщение