Nginx,具有多个转发域和一个 letsencrypt 证书

Nginx,具有多个转发域和一个 letsencrypt 证书

我正在尝试将 Nginx 设置为位于我的静态 IP 后面的所有开发服务器的转发代理。

我读过这个问题: 使用 nginx 反向代理进行加密

已经,它让我部分地这就是它让我在其中一个虚拟服务器上获取 .well-known 目录),但是我的设置有很大不同,我需要另一个步骤才能使其工作,到目前为止,我还不能解决这个步骤,如果有任何 Nginx 专家,我肯定可以帮上忙。

当前设置

因此,基本上,目前我有一个静态 IP,为了解决这个问题,我们称之为

1.2.3.4

在我的主机提供商 DNS 中,我设置了 2 个通配符 DNS 路由(顺便说一下,我自己可以完全控制这些,所以如果最终发现修改 DNS 记录比使用文件更容易,那么我就会这么做),2 条通配符路线是

*.example.com -> 1.2.3.4
*.anotherexample.com -> 1.2.3.4

因此基本上无论这两个域输入什么,它们总是会到达同一个静态 IP。

http://example.com/http://doodah.example.com/http://biscuits.anotherexample.com/以此类推,全部到达 1.2.3.4

在该 IP 地址内,通过 NAT 控制的端口从外部的 80 转发到内部的 80(我可以根据需要打开其他,例如:443) 是只具有一项作业的服务器。

这台服务器在 Ubuntu 16.04 LTS 上运行 Nginx,它检查入站主机名,然后将该连接传递到另一台服务器。

例如

http://www.example.com/将通过代理转发到运行该网站的服务器

http://application.anotherexample.com/将代理转发到运行与该主机名关联的应用程序的服务器

其中两个虚拟服务器比较特殊,因为它们被设置为响应

*.example.com 和 *.anotherexample.com

因此,如果收到请求idonetexist.example.com它最终将为示例.com同样地noserverhere.anotherexample.com也会这么做。

这意味着无论该代理服务器接收的主机/子域是什么,都会传送某些内容。

因此,到目前为止,我要处理这两个通配符情况的是以下两个配置文件:

server {

  listen 80;

  server_name
    example.com
    www.example.com
    *.example.com;

  location /.well-known {
    alias /var/www/html/letsencrypt;
  }

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://address.of-the.internal.example-webserver
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
    access_log /var/log/nginx/example.com.log;
    error_log /var/log/nginx/example.com.log error;

  }
}

server {

  listen 80;

  server_name
    anotherexample.com
    www.anotherexample.com
    *.anotherexample.com;

  location /.well-known {
    alias /var/www/html/letsencrypt;
  }

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://address.of-the.internal.anotherexample-webserver
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
    access_log /var/log/nginx/anotherexample.com.log;
    error_log /var/log/nginx/anotherexample.com.log error;

  }
}

到目前为止,这一切都运行良好,并且来自 let's encrypt 的任何请求对于在“.well-known”目录中检查 SSL 证书都有效,然而正是在这一点上,我的用例开始偏离我在问题顶部链接的原始问题。

为了实现其他虚拟服务器(例如指向应用程序的虚拟服务器)以及我两个注册域中的任意一个上的其他子域,我有多个虚拟服务器配置,例如,我将有其他配置,如下所示:

server {

  listen 80;

  server_name application1.example.com;

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://internal.address.of-example-app-one
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
    access_log /var/log/nginx/exampleappone.access.log;
    error_log /var/log/nginx/exampleappone.error.log error;

  }
}

server {

  listen 80;

  server_name application2.example.com;

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://internal.address.of-example-app-two
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
    access_log /var/log/nginx/exampleapptwo.access.log;
    error_log /var/log/nginx/exampleapptwo.error.log error;

  }
}

server {

  listen 80;

  server_name application1.anotherexample.com;

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://internal.address.of-anotherexample-app-one
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
    access_log /var/log/nginx/anotherexampleappone.access.log;
    error_log /var/log/nginx/anotherexampleappone.error.log error;

  }
}

当将新应用程序添加到内部服务器时,将创建一个基于上述内容的新配置文件,并在其中进行适当的更改,然后保存在/etc/nginx/站点可用/以及所有其他配置文件。

当 Nginx 重新加载时,它会选择新文件并激活它,以便该应用程序可用。

这样做的原因是,网络中正在运行一个应用程序生成器,并且应用程序创建向导在运行过程中写入此配置文件,允许内部用户登录并使用应用程序创建器程序创建应用程序。

我想要实现的目标

通过上面链接的第一个问题的答案,我开始使用站点的“默认”处理,即没有单独配置来将它们代理到不同服务器的站点,并且它使 Let's encrypt 保持快乐,因为它可以找到它的身份文件来证明我拥有这两个域。

不幸的是,单独的配置不受 SSL 保护,而且它们也不受到通配符 SSL 保护。

我想要做的是找到一种方法,让我可以从 let's encrypt 获得一个 *.example.com 和一个 *.anotherexample.com 通配符证书,全部使用 certbot 自动完成,并自动更新。

原始问题向我展示了如何对默认通配符站点执行此操作,但此证书不包括指向应用程序的单独配置文件,即使它们在技术上都是主域的子域。

在我看来,有些东西告诉我,关键在于将 SSL 实际应用于 Nginx 创建的实际“默认”服务器,但由于我无法为其分配多个证书,因此我认为我无法在一台虚拟服务器上分配 example.com 和 anotherexample.com 证书。

我需要(我认为)是将证书分配给处理 *.... 主机名的每个虚拟服务器,然后让该证书传播到该域的任何子域,这些子域具有与域默认值相同的顶级域(如果这有道理的话

我还有另一个想法(我打完这些字后要玩一玩)是将另一个代理放在前面,其唯一职责是接受连接,发送证书,然后将连接传递给 Nginx,由其决定将连接发送到哪个虚拟服务器,我认为在这种情况下可能是 HAProxy 或类似的东西。

总之

1)如果我没有单独的配置文件覆盖各个子域,那么原始问题的原始答案就可以完美地发挥作用。

2)实际上,我需要将子域合并到将指定证书的主域中,但仍保持文件分离。

3)我需要 SSL 从 *... 通配符 SSL 证书透明地工作,并且不想为创建的每个单独的子域都创建新的 SSL 请求。

对于如何做到这一点,我非常感激任何想法,最好是在原始问题的基础上进行构建。

更新(2018/08/22)

因此,根据 Drifter 在评论中给出的建议,我最终为我的“通配符虚拟服务器”提出了以下内容,即:如果没有更具体的子域配置,这些服务器将对域中的任何内容做出响应。

server {

  listen 80;

  server_name
    example.com
    www.example.com
    *.example.com;

  location /.well-known {
    alias /var/www/html/letsencrypt;
  }

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://internal-default-web-server-for-wildcard;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;

    access_log /var/log/nginx/example.access.log;
    error_log /var/log/nginx/example.error.log error;

  }
}

server {

  listen 443 ssl;

  server_name
    example.com
    www.example.com
    *.example.com;

  include "example-cert.inc";

  ssl_stapling on;
  ssl_stapling_verify on;

  # maintain the .well-known directory alias for renewals
  location /.well-known {
    alias /var/www/html/letsencrypt;
  }

  location / {

    proxy_pass_header Authorization;
    proxy_pass http://internal-default-web-server-for-wildcard;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;

    access_log /var/log/nginx/example.sslaccess.log;
    error_log /var/log/nginx/example.sslerror.log error;
  }
}

如你所见,服务器块现在由激活 HTTPS 的服务器块组成,文件中不再包含服务器证书的名称,而是

include "example-cert.inc"

在“example-cert”文件中,内容如下

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

这会导致 Nginx 在加载处理这些通配符域的 VS 配置时加载包含这些证书名称的文件。

对于所有具有自己目的地的子域的其他配置,我都做了类似的事情,主要区别在于不包含“.well-known”路由,并且代理/服务器目的地和日志文件名不同。

按照链接问题中的信息,并以这种方式指定与证书的链接,由于证书是通配符,因此允许我对一个域使用一组证书,对另一个域使用另一组证书。

这实际上回答了我的问题,现在我只需要弄清楚如何使用 let's encrypt 自动更新证书。由于我使用的是通配符证书,因此不允许使用除“DNS-01”之外的任何验证方法,并且目前只能手动完成,除非您使用由 certbot 插件支持的云提供商之一提供的 DNS 服务。

我不是,我的 DNS 只是标准 DNS,因此每次续订时,我都需要重新生成新的 TXT 记录并更改我的 DNS 记录,然后续订才能生效。我可以使用“webroot”方法完全自动化,但 webroot 不允许您请求通配符证书,只允许您请求固定的多域列表。

Drifter,如果你把你的评论写成答案,我会给你+10

相关内容