让我们使用 nginx 反向代理进行加密

0x4*_*450 53 nginx https jira lets-encrypt

介绍

我有一个开发服务器(目前运行 Ubuntu 14.04 LTS),我已经使用了一段时间来在不同端口上托管各种开发工具。因为端口很难记住,所以我决定将端口 80 用于我的所有服务,并根据主机名在内部进行端口转发。

而不是写 domain.com:5432,我可以简单地通过 sub.domain.com 访问它

例如,使用端口 7547 并在 sub.domain.com 上运行的应用程序 X 具有以下 nginx 配置:

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            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_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

鉴于我选择的当前配置结构,是否可以使用 letencrypt 并在 https 下运行不同的服务?

puz*_*ent 91

是的,您可以将 nginx 代理请求发送到 HTTP 服务器,然后本身通过 HTTPS 响应客户端。这样做时,您需要确保 nginx<->proxy connect 不太可能被您预期的攻击者嗅探到。足够安全的方法可能包括:

  • 代理到同一台主机(就像你一样)
  • 代理到防火墙后面的其他主机

代理到公共 Internet 上的另一台主机不太可能足够安全。

以下是使用您用作代理的同一网络服务器获取 Let's Encrypt 证书的说明。

从 Let's Encrypt 请求您的初始证书

修改您的server子句以允许.well-known从本地目录提供子目录,例如:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}
Run Code Online (Sandbox Code Playgroud)

http://sub.domain.com/.well-known 是 Let's Encrypt 服务器将寻找其问题的答案的地方。

然后,您可以使用certbot客户端使用webroot插件(以 root 身份)从 Let's Encrypt 请求证书:

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com
Run Code Online (Sandbox Code Playgroud)

您的密钥、证书和证书链现在将安装在 /etc/letsencrypt/live/sub.domain.com/

配置 nginx 以使用您的证书

首先创建一个新的服务器子句,如下所示:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

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

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}
Run Code Online (Sandbox Code Playgroud)

重新加载nginx:

service nginx reload
Run Code Online (Sandbox Code Playgroud)

验证HTTPS现在通过访问工作https://sub.domain.com,并https://www.sub.domain.com在您的浏览器(和你特别希望的任何其他浏览器的支持),并检查他们不报告证书错误。

推荐:还可以查看raymii.org:nginx 上的强大 SSL 安全性 并在SSL 实验室测试您的配置。

(推荐)将 HTTP 请求重定向到 HTTPS

一旦您确认您的站点使用https://URL 版本,而不是让某些用户因为访问 而提供不安全的内容,而是http://sub.domain.com将他们重定向到站点的 HTTPS 版本。

将整个端口 80server条款替换为:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}
Run Code Online (Sandbox Code Playgroud)

您现在还应该在端口 443 配置中取消注释此行,以便浏览器记住甚至不要尝试该站点的 HTTP 版本:

add_header Strict-Transport-Security "max-age=31536000";
Run Code Online (Sandbox Code Playgroud)

自动更新您的证书

您可以使用此命令(以 root 身份)更新所有 certbot 已知的证书并使用新证书(与现有证书具有相同的路径)重新加载 nginx:

certbot renew --renew-hook "service nginx reload"
Run Code Online (Sandbox Code Playgroud)

certbot 只会尝试更新超过 60 天的证书,因此非常安全(并推荐!)非常定期地运行此命令,并在可能的情况下自动运行。例如,您可以将以下命令放入/etc/crontab

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"
Run Code Online (Sandbox Code Playgroud)

您可以使用试运行来测试续订,这将联系 Let's Encrypt 登台服务器以对联系您的域进行真正的测试,但不会存储生成的证书:

certbot --dry-run renew
Run Code Online (Sandbox Code Playgroud)

或者您可以通过以下方式强制提前续订:

certbot renew --force-renew --renew-hook "service nginx reload"
Run Code Online (Sandbox Code Playgroud)

注意:您可以根据需要进行多次试运行,但真正的续订受Let's Encrypt 速率限制

  • @Alko ,答案的说明是正确的,涵盖了这个问题。使用 `certbot` 或任何其他工具时,您不能忘记以 www 和非 www 格式指定您的域才能工作。 (3认同)