SNI 기반의 Nginx 선택적 TLS 통과 역방향 프록시

SNI 기반의 Nginx 선택적 TLS 통과 역방향 프록시

NAT 뒤에 IoT 장치 시스템이 있으므로 공용 인터넷에서 액세스할 수 없습니다(원하는 경우임에도 불구하고). 이 문제를 극복하기 위해 한 구성원이 공용 인터넷에 노출되어 게이트웨이 역할을 하도록 VPN에 연결했습니다. VPN에는 내부 도메인이 설정되어 있으며 네트워크의 각 구성원에는 다음과 같이 고유 ID(MAC 주소로 이동)를 기반으로 하는 하위 도메인이 있습니다.12a4f81ead4e.vpn.example.com

nginx를 실행하여 프록시 요청 에 대한 역방향 프록시를 만들고 싶습니다 Gatway.

계획은 게이트웨이에 대한 DNS 레코드를 생성하고 에서 로 *.gateway.com(부터) 이동하는 경로(에헴, 프록시) 트래픽을 생성하는 것입니다 . 따라서 최종 사용자는 브라우저에 입력하기만 하면 장치에 액세스할 수 있습니다. 게이트웨이가 이미 다른 목적으로 nginx를 실행하고 있으므로 nginx를 사용하고 싶습니다.12a4f81ead4e.gateway.com12a4f81ead4e.vpn.example.com12a4f81ead4e.gateway.com

나는 HTTP 요청이 쉬울 것으로 기대하며 신중하게 만들어진 nginx proxy_pass지시문을 사용하여 수행할 수 있습니다.

하지만 HTTPS 요청은 어떻습니까? 내가 이해하는 한, SNI 기반 TLS 패스스루는 이제 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 요청은 정상적으로 기존 가상 호스트에 서버하고 싶습니다 . 가능하다면 SSL 연결이 종료되는 것을 방지하고 싶습니다. 실제로 어려운 요구 사항은 아니지만 기술적으로 가능하다면 그렇게 구현하고 싶습니다. 또한 단지 재미를 위해서입니다.

내부적으로 다른 가상 호스트에 대한 대체 포트를 수신하는 것은 괜찮습니다. "전역" 위치를 설정하고 싶을 때 HTTP와 비슷한 작업을 수행했으며 모든 HTTP 가상 호스트를 포트 81로 이동하고 포트에 포괄적인 가상 호스트를 구현했습니다. "전역" 위치를 제공하고 다른 모든 것을 포트 81로 프록시하는 80입니다. :)

그래서... 다음과 같은 것이 필요할 것입니다(분명히 작동하지 않습니다).

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;
    (...)
  }
}

관련 정보