Nginx селективный TLS-проброс обратного прокси-сервера на основе SNI

Nginx селективный TLS-проброс обратного прокси-сервера на основе SNI

У меня есть система устройств 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;
    (...)
  }
}

Связанный контент