У меня есть система 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-запросы будут простыми и могут быть выполнены с помощью тщательно созданного nginx proxy_pass
директива.
Но как насчет 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;
(...)
}
}
Это помогает:
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;
(...)
}
}