Nginx 仅在特定位置验证客户端证书

Eli*_*ght 18 nginx ssl-certificate

我们使用 Nginx 作为我们的 Web 应用程序服务器的反向代理。Nginx 处理我们的 SSL 等,但在其他方面只是充当反向代理。

我们希望为请求提供有效的客户端证书,/jsonrpc但不要求在其他任何地方使用它们。我们发现的最好方法是

server {
  listen       *:443 ssl;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client optional;

  location /jsonrpc {
    if ($ssl_client_verify != "SUCCESS") { return 403; }

    proxy_pass          http://localhost:8282/jsonrpc-api;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}
Run Code Online (Sandbox Code Playgroud)

这适用于大多数浏览器,但某些浏览器(例如 Safari 和 Chrome-on-Android)最终会提示用户无论在网站上的哪个位置都提供客户端证书。

我们如何让 Nginx 接受但并不真正关心除我们/jsonrpc所在位置以外的任何地方的客户端证书?

Ana*_*oly 10

为什么不试试第二个服务器块呢?代码重复是不好的,但有时是不可避免的。我假设 /jsonrpc 代表一个 API,因此它可以使用自己的子域(如果尚未使用它):

server {
  listen       *:443 ssl;
  server_name api.example.com;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client on;

  location =/jsonrpc {
    proxy_pass          http://localhost:8282/jsonrpc-api;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}

server {
  listen       *:443 ssl;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client off;

  location / {
    proxy_pass          http://localhost:8282/;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在 Apache 中起作用的原因[在传递 `SSLVerifyClient` 文档时提到](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslverifyclient): *[...] 在每个目录中context [此指令] 在读取 HTTP 请求之后但在发送 HTTP 响应之前强制使用重新配置的客户端验证级别进行 SSL 重新协商。* – 不用说 nginx 不提供该选项... (5认同)
  • 如果所有内容都必须响应同一域 www.example.com 怎么办?这样的方法还能奏效吗? (3认同)
  • @NJones:不幸的是,不,这就是我们必须要做的。 (2认同)

gel*_*ida 8

在寻找其他东西时偶然发现了这个问题。

也许我误解了这个问题:

但不应该跟随工作。

它有两个位置设置,但只有一个服务器设置。

server {
  listen       *:443 ssl;
  server_name api.example.com;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

 ssl_verify_client optional;

  location =/jsonrpc {
    if ($ssl_client_verify != "SUCCESS") { return 403; }
    proxy_pass          http://localhost:8282/jsonrpc-api;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }

  location / {
    proxy_pass          http://localhost:8282/;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}
Run Code Online (Sandbox Code Playgroud)