【问题标题】:Nginx: pass through HTTPS to different targets based on locationNginx:根据位置通过HTTPS到不同的目标
【发布时间】:2019-10-09 01:17:34
【问题描述】:

我完全是 nginx 反向代理的菜鸟,如果这个问题很愚蠢,请原谅我。我的情况是我运行多个自行管理 HTTPS 证书的 docker 容器,我需要反向代理才能从浏览器访问它们。问题是证书需要在这些容器内进行管理,而不是从 nginx 反向代理。

我在 Google 上搜索并尝试了很多方法,唯一可行的方法是将流直接传递到容器的本地地址。

events { }

stream {
  server {
    listen 443;
    listen [::]:443;

    proxy_pass 10.0.0.1:443;  
  }
}

当我使用流时(据我所知,这是传递所需的),我不知道如何区分我试图到达的目的地。

我需要能够执行以下操作的配置:

https://mail.example.com --> proxy_pass 10.0.0.1
https://mail.example.com --> proxy_pass 10.0.0.1
https://www.example.com --> proxy_pass 10.0.0.2 
https://foo.example.com --> proxy_pass 10.0.0.2

有什么办法吗?

【问题讨论】:

  • 我建议阅读有关位置和服务器块的文档。你想要做的是有多个服务器块,里面有 server_name 指令。没有绝对的解决方案,每个人都会向您展示不同的配置示例。你应该熟悉已经存在的配置示例和文档来了解 nginx 的工作原理。我可以花时间为你写一个可能的配置。因为这不是计费的,也不是stackoverflow的重点,我建议做我刚才建议的事情来找到解决方案。这是微不足道的东西。

标签: docker nginx https nginx-reverse-proxy


【解决方案1】:

您正在寻找的是如何设置 SSL 直通代理(TCP 转发)并使用 SNI 信息进行路由。我不确定你是否可以使用 nginx 来做到这一点,因为在 nginx 中没有办法使用 SNI 信息来管道连接(据我所知)。

我尝试为此使用 docker-compose 创建一个 HAproxy 配置,并且它似乎可以按您的意愿工作。我使用 docker-compose 在一个网络中运行所有应用程序,因此您可以根据 docker-compose 中的名称访问其他服务。

./docker-compose.yml

version: '3'

services:

  proxy:
    image: haproxy:1.9.8
    ports:
      - "443:443"
    volumes:
      - "./haproxy:/usr/local/etc/haproxy"

  mail:
    image: mail    # replace it with your app image, it must have port 443 open
    ports:
      - "445:443"  # this port mapping is for debug purposes only, remove it after

  foo:
    image: foo
    ports:
      - "446:443"

./haproxy/haproxy.cfg

defaults
  maxconn 1000
  mode http
  log global
  option dontlognull # bind *:443 ssl crt .
  timeout http-request 5s
  timeout connect 5000
  timeout client 2000000 # ddos protection
  timeout server 2000000 # stick-table type ip size 100k expire 30s store conn_cur

frontend https
  bind *:443
  mode tcp
  option tcplog
  tcp-request inspect-delay 5s
  tcp-request content accept if { req_ssl_hello_type 1 }
  use_backend foo-servers if { req.ssl_sni -i foo.example.com }
  use_backend mail-servers if { req.ssl_sni -i mail.example.com }

backend foo-servers
  mode tcp
  balance roundrobin
  option ssl-hello-chk
  server server1 foo:443       # You can use service name from docker-compose here

backend mail-servers
  mode tcp
  balance roundrobin
  option ssl-hello-chk
  server server1 mail:443

然后你就可以运行它了:

$ docker-compose up

然后确保您的应用正常运行:

$ curl -k https://localhost:445
mail service
$ curl -k https://localhost:446
foo service

最后我们可以测试我们的代理了:

$ curl -k https://mail.example.com
mail service
$ curl -k https://foo.example.com
foo service

注意:为了使其正常工作,我将 mail.example.com 和 foo.example.com 添加到 /etc/hosts

127.0.0.1   mail.example.com
127.0.0.1   foo.example.com

PS。这是“foo”应用程序的 Dockerfile(相同的配置用于邮件):

./Dockerfile

FROM nginx:latest
COPY ssl.conf                   /etc/nginx/conf.d/ssl.conf
COPY mail.html                  /usr/share/nginx/html/index.html
COPY certs/mail.example.com.crt /etc/nginx/certs/
COPY certs/mail.example.com.key /etc/nginx/certs/
COPY certs/dhparam.pem          /etc/nginx/certs/

./ssl.conf

server {
    listen 443 http2 ssl;

    ssl_certificate       /etc/nginx/certs/mail.example.com.crt;
    ssl_certificate_key   /etc/nginx/certs/mail.example.com.key;
    ssl_dhparam           /etc/nginx/certs/dhparam.pem;

    root /usr/share/nginx/html;

    location / {
    }
}

创建自签名证书:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout certs/foo.example.com.key -out certs/foo.example.com.crt
$ openssl dhparam -out certs/dhparam.pem 2048

构建映像:

$ docker build -t foo .

【讨论】:

    猜你喜欢
    • 2014-07-06
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多