nginx之proxy_pass代理后端https请求完全拆解

前言

本文解释了怎么对nginx和后端服务器组或代理服务器进行加密http通信。

内容提纲

  • 前提条件
  • 获取SSL服务端证书
  • 获取SSL客户端证书
  • 配置nginx
  • 配置后端服务器
  • 完整示例

前提条件

  • nginx源码或nginx plus源码
  • 一个代理服务器或一个代理服务器组
  • SSL证书和私钥

获取SSL服务端证书

你可以从一个可信证书颁发机构(CA)购买一个服务器证书, 或者你可以使用openssl库创建一个内部CA, 并给自己颁发证书。这个服务器端证书和私钥需要部署在后端的每一个服务器上。

获取SSL客户端证书

nignx使用一个SSL客户端证书来对后端服务器组来标识自己。这个客户端证书必须是被一个可信CA签名的,并且和相匹配的私钥一起部署在nginx中。
你还需要在后端服务器上配置好所有的来源SSL连接都需要客户端证书,并信任这个CA颁发的nginx客户端证书。 然后当nginx连接后端时,将提供客户端证书,并且后端将会接收这个连接。

配置nginx

首先,改变相应URL到支持SSL连接的后端服务器组。在nginx的配置文件中,指明proxy_pass指令在代理服务器或后端服务器组中使用"https"协议:

location /upstream {
    proxy_pass https://backend.example.com;
}

增加客户端证书和私钥,用于验证nginx和每个后端服务器。使用proxy_ssl_certificate 和 proxy_ssl_certificate_key指令:

location /upstream {  
    proxy_pass                https://backend.example.com;  
    proxy_ssl_certificate     /etc/nginx/client.pem;  
    proxy_ssl_certificate_key /etc/nginx/client.key  
}  

如果你在后端服务器使用了自签名证书或者使用了自建CA,你需要配置proxy_ssl_trusted_certificate. 这个文件必须是PEM格式的。另外还可以配置proxy_ssl_verifyproxy_ssl_verfiy_depth指令, 用来验证安全证书:

location /upstream {
    ...
    proxy_ssl_trusted_certificate /etc/nginx/trusted_ca_cert.crt;
    proxy_ssl_verify       on;
    proxy_ssl_verify_depth 2;
    ...
}

每一个新的SSL连接都需要在服务端和客户端进行一个完整的SSL握手过程,这非常耗费CPU计算资源。为了是nignx代理预先协商连接参数,使用一种简略的握手过程,增加proxy_ssl_session_reuse指令配置:

location /upstream {
    ...
    proxy_ssl_session_reuse on;
    ...
}

可选的,你也可以配置使用的SSL协议和SSL秘钥算法:

location /upstream {
        ...
        proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        proxy_ssl_ciphers   HIGH:!aNULL:!MD5;
}

配置后端服务器

每一个后端服务器都必须配置成接受https连接。每一个后端服务器需要使用ssl_certificatessl_certificate_key指令来指定服务器证书和私钥的文件路径:

server {
    listen              443 ssl;
    server_name         backend1.example.com;

    ssl_certificate     /etc/ssl/certs/server.crt;
    ssl_certificate_key /etc/ssl/certs/server.key;
    ...
    location /yourapp {
        proxy_pass http://url_to_app.com;
        ...
    }
}

使用ssl_client_certificat指令来设定客户端证书的文件路径:

server {
    ...
    ssl_client_certificate /etc/ssl/certs/ca.crt;
    ssl_verify_client      off;
    ...
}

完整示例

http {
    ...
    upstream backend.example.com {
        server backend1.example.com:443;
        server backend2.example.com:443;
   }

    server {
        listen      80;
        server_name www.example.com;
        ...

        location /upstream {
            proxy_pass                    https://backend.example.com;
            proxy_ssl_certificate         /etc/nginx/client.pem;
            proxy_ssl_certificate_key     /etc/nginx/client.key
            proxy_ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
            proxy_ssl_ciphers             HIGH:!aNULL:!MD5;
            proxy_ssl_trusted_certificate /etc/nginx/trusted_ca_cert.crt;

            proxy_ssl_verify        on;
            proxy_ssl_verify_depth  2;
            proxy_ssl_session_reuse on;
        }
    }

    server {
        listen      443 ssl;
        server_name backend1.example.com;

        ssl_certificate        /etc/ssl/certs/server.crt;
        ssl_certificate_key    /etc/ssl/certs/server.key;
        ssl_client_certificate /etc/ssl/certs/ca.crt;
        ssl_verify_client      off;

        location /yourapp {
            proxy_pass http://url_to_app.com;
        ...
        }

    server {
        listen      443 ssl;
        server_name backend2.example.com;

        ssl_certificate        /etc/ssl/certs/server.crt;
        ssl_certificate_key    /etc/ssl/certs/server.key;
        ssl_client_certificate /etc/ssl/certs/ca.crt;
        ssl_verify_client      off;

        location /yourapp {
            proxy_pass http://url_to_app.com;
        ...
        }
    }
}

在这个示例中, proxy_pass指令设置使用了"https"协议,所以nginx转发到后端服务器的流量是安全的。

当一个安全的连接第一次从nginx转发到后端服务器,将会实施一次完整的握手过程。proxy_ssl_certificate指令设置了后端服务器需要的PEM格式证书的文件位置。proxy_ssl_certificate_key指令设置了证书的私钥位置。proxy_ssl_protocolsproxy_ssl_ciphers指令控制使用的协议和秘钥算法。

因为proxy_ssl_session_reuse指令配置,当下一次nginx转发一个连接到后端服务器时,会话参数会被重复使用,从而更快的建立安全连接。

proxy_ssl_trusted_certificate指令设置的那个可信CA证书文件是用来验证后端服务器的证书。proxy_ssl_verify_depth指令指定了证书链检查的深度。proxy_ssl_verify指令验证证书的有效性。

译注

本文为翻译,英文原文地址:https://www.nginx.com/resources/admin-guide/nginx-https-upstreams/ ,尽量遵循原文,不准确的地方,还请指正,谢谢。

<think>好的,我现在要分析用户提供的这个Nginx服务器配置。首先,用户希望了解这段配置的功能和各个部分的作用。我需要逐步拆解,确保自己理解每个指令的意义,同时用中文清晰地解释出来。 首先,整体结构来看,这是一个server块,用于定义一个虚拟主机。监听端口是8078,并且启用了SSL,所以这是一个HTTPS服务。server_name指定了域名,这应该是指向该服务的域名。接下来是SSL证书的配置,指定了证书和私钥的路径。这部分比较基础,但需要确认路径是否正确,用户可能需要检查证书路径是否存在。 然后是location块,匹配/ai-api/路径的请求。这里配置了反向代理,将请求转发到另一个后端服务,即http://ai.chinatowercom.cn:49987/。注意到proxy_pass的URL末尾有斜杠,这意味着在转发时会去掉location匹配的部分,比如请求/ai-api/test会被转发到http://ai.chinatowercom.cn:49987/test。这点可能需要提醒用户注意路径是否正确拼接。 接下来是CORS相关的配置。add_header指令设置了多个响应头,允许跨域请求。Access-Control-Allow-Origin使用了$http_origin变量,动态匹配请求的来源,这样更灵活。但需要注意,如果允许任意来源可能会有安全风险,但这里用了always参数确保即使出错也返回这些头。另外,允许的方法包括GET、POST和OPTIONS,头部字段也涵盖了常用的几种,包括Authorization,这样前端可以携带认证信息。Allow-Credentials设置为true,说明允许携带cookie等凭证,这时Access-Control-Allow-Origin不能是通配符*,而必须指定具体来源,这里使用动态来源是合适的。 处理OPTIONS预检请求的部分,使用if判断请求方法是否为OPTIONS,直接返回204。这种处理方式是标准的,但需要注意的是在Nginx中使用if可能会有性能问题,不过在这种情况下,由于只检查请求方法,可能影响不大。不过也可以建议用户改用更高效的方式,比如使用limit_except指令,但现有的配置在功能上是正确的。 需要检查是否有潜在的安全隐患。比如SSL的配置是否只支持安全的协议和加密套件,但用户提供的配置中没有ssl_protocols或ssl_ciphers的设置,可能需要建议用户添加这些以增强安全性。此外,是否应该限制Access-Control-Allow-Origin的具体来源,而不是动态允许所有来源,这取决于实际需求,但用户当前配置允许任何来源,可能存在CSRF风险。 另外,proxy_pass后面的URL末尾的斜杠是否正确处理了路径。例如,如果location是/ai-api/,而proxy_pass是http://backend/,那么请求的URI会被替换。这部分需要确认用户是否理解路径重写的规则,避免出现404问题。 总结一下,这个配置的主要功能是在8078端口提供HTTPS服务,将/ai-api/下的请求代理后端服务,同时配置了CORS以允许跨域请求。可能需要注意SSL的安全配置、CORS的来源限制以及路径重写是否正确。</think>以下是对该Nginx服务器配置的逐层解析: ### 一、基础服务配置 1. **监听设置** $$server { listen 8078 ssl;$$ - 监听`8078`端口并启用SSL加密 - 同时支持HTTP/HTTPS请求(隐含`ssl`参数包含`http2`特性) 2. **域名绑定** $$server_name auditsmart.chinatowercom.cn;$$ - 仅响应域名`auditsmart.chinatowercom.cn`的请求 3. **SSL证书配置** ```nginx ssl_certificate /path/to/ssl.crt; ssl_certificate_key /path/to/ssl.key; ``` - 证书路径需要替换为实际文件路径 - 建议补充SSL协议版本限制(如`ssl_protocols TLSv1.2 TLSv1.3;`) ### 二、反向代理配置 ```nginx location /ai-api/ { proxy_pass http://ai.chinatowercom.cn:49987/; } ``` - 路径匹配规则:`/ai-api/`开头的请求都会被代理 - 代理行为示例: $$ \text{原始请求} \rightarrow \frac{\text{代理目标地址}}{/ai-api/test} \Rightarrow http://ai.chinatowercom.cn:49987/test $$ ### 三、CORS跨域配置 1. **核心响应头** ```nginx add_header Access-Control-Allow-Origin $http_origin always; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always; add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,Content-Type,Authorization' always; add_header Access-Control-Allow-Credentials 'true' always; ``` - 动态设置请求来源($http_origin变量) - 允许携带凭证(cookies/HTTP认证) - `always`确保所有响应(包括4xx/5xx)都携带CORS头 2. **预检请求处理** ```nginx if ($request_method = 'OPTIONS') { return 204; } ``` - 直接响应`204 No Content`给OPTIONS请求 - 符合浏览器预检请求处理规范 ### 四、安全增强建议 1. **SSL强化配置**(建议补充) ```nginx ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ``` 2. **访问控制**(按需添加) ```nginx # 限制CORS白名单 if ($http_origin !~* "^https?://(allowed.domain.com|localhost)") { return 403; } ``` ### 五、典型工作流程 1. 浏览器发送`OPTIONS`预检请求 $$\begin{cases} \text{请求头包含} & Origin \\ & Access-Control-Request-Method \\ & Access-Control-Request-Headers \end{cases}$$ 2. Nginx响应`204`并返回CORS头 3. 浏览器发送实际请求(GET/POST) 4. 代理请求后端服务,附加CORS头返回响应 建议使用`curl -I`命令测试CORS配置有效性,并通过浏览器开发者工具验证跨域请求处理流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值