У меня есть система устройств IoT за NAT, поэтому они не доступны из публичного интернета (хотя это желательно). Чтобы преодолеть это, я связал их в VPN, где один участник открыт для публичного интернета, чтобы действовать как шлюз. VPN имеет настроенный внутренний домен, и каждый участник сети имеет поддомен на основе уникального идентификатора (давайте использовать MAC-адрес), например:12a4f81ead4e.vpn.example.com
Я хочу создать обратный прокси-сервер для Gatway
прокси-запросов, запустив nginx.
План состоит в том, чтобы создать запись DNS для шлюза, *.gateway.com
и маршрутизировать (кхм, прокси) трафик, идущий в/из 12a4f81ead4e.gateway.com
в 12a4f81ead4e.vpn.example.com
. Таким образом, конечному пользователю нужно будет просто ввести 12a4f81ead4e.gateway.com
в своем браузере, чтобы получить доступ к своему устройству. Я хотел бы использовать nginx, так как шлюз уже запускает nginx для других целей.
Я ожидаю, что HTTP-запросы будут простыми и их можно будет реализовать с помощью тщательно продуманной proxy_pass
директивы nginx.
Но что насчет HTTPS-запросов? Насколько я понимаю, TLS-проброс на основе SNI теперь реализован в nginx, но все примеры, которые я видел до сих пор, создают статическую карту для... ну, сопоставления входящего SNI с целевым восходящим потоком:
stream {
map $ssl_preread_server_name $selected_upstream {
example.org upstream_1;
example.net upstream_2;
example.com upstream_3;
default upstream_4;
}
upstream upstream_1 { server 10.0.0.1:443; }
upstream upstream_2 { server 10.0.0.2:443; }
upstream upstream_3 { server 10.0.0.3:443; }
upstream upstream_4 { server 10.0.0.4:443; }
server {
listen 10.0.0.5:443;
proxy_pass $selected_upstream;
ssl_preread on;
}
}
Проблема в том, что устройства динамически добавляются/удаляются из VPN, и я не хочу постоянно переписывать файлы конфигурации nginx. Если чтение карты из файла возможно, это шаг в правильном направлении, хотя я думаю, что nginx нужно будет перезагружать каждый раз, когда это изменяется, что вызывает проблемы с разрешениями, которые можно обойти с помощью правил sudo, конечно, но это не лучшее решение.
Также я хочу только проксировать запросы, входящие в *.gateway.com
, и обслуживать другие https-запросы обычным образом на существующих vhosts. Если это вообще возможно, я бы хотел избежать разрыва SSL-соединения. Не очень-то сложное требование, но хотелось бы реализовать его таким образом, если это технически осуществимо. Также просто ради прикола.
У меня все в порядке с внутренним прослушиванием на альтернативном порту для других виртуальных хостов, я сделал что-то похожее для HTTP, когда хотел задать «глобальное» местоположение, и переместил все HTTP-виртуальные хосты на порт 81, и реализовал универсальный виртуальный хост на порту 80, который обслуживал «глобальное» местоположение, и проксировал все остальное на порт 81. :)
Итак... Мне нужно что-то вроде этого (очевидно, не работает):
stream {
map $ssl_preread_server_name $selected_upstream {
(.*).gateway.com $1.vpn.example.com;
default normal_serve;
}
upstream normal_serve { server 127.0.0.1:8443; }
server {
listen 0.0.0.0:443;
proxy_pass $selected_upstream;
ssl_preread on;
}
server {
listen 127.0.0.1:8443;
server_name other.website.com;
(...)
}
}
решение1
Это сработает:
stream {
resolver 8.8.8.8;
map $ssl_preread_server_name $selected_upstream {
~(.*).gateway.example.com $1.vpn.example.com:443;
default 127.0.0.1:8443;
}
server {
listen 0.0.0.0;
proxy_pass $selected_upstream;
ssl_preread on;
}
}
http {
resolver 8.8.8.8;
server {
listen 127.0.0.1:8443 ssl;
(...)
}
}