一次nginx返回422状态码的经历

故事背景

后端使用Docker Compose部署一个代码片段管理应用:snibox,某天因为云服务卡死重启之后再次访问时,登录或退出都返回422状态码。
界面提示如下:
snibox_log_422
snibox_code_422

不过奇怪的是;直接通过IP+PORT访问是没问题的,但是使用域名方式访问就会报错。

前端使用nginx作为反向代理,并配置了SSL。
配置信息如下:

server {
   listen       80;
   server_name  snibox.zhangsan.org.cn;
   
   rewrite ^(.*)$  https://$host$1 permanent;
}

server {
   listen 443 ssl;
   server_name  snibox.zhangsan.org.cn;

   ssl_certificate  /data/ssl/zhangsan.org.cn_cert_chain.pem;
   ssl_certificate_key  /data/ssl/zhangsan.org.cn_key.key;
   ssl_session_timeout 5m;
   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   ssl_prefer_server_ciphers on;

   client_max_body_size 10M;

   location / {
       proxy_pass_header Server;
       proxy_set_header Host $http_host;
       proxy_redirect off;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Scheme $scheme;
       proxy_pass http://snibox;
   }
}

既然直接使用IP+PORT方式是可以正常访问的,但是使用域名方式确异常,问题应该出在nginx配置上。

解决办法

在nginx配置中设置X-Forwarded-Proto(明确指定客户端与nginx的通信协议为https),即:

proxy_set_header X-Forwarded-Proto https;

最终的nginx完整配置为:

server {
   listen       80;
   server_name  snibox.zhangsan.org.cn;
   
   rewrite ^(.*)$  https://$host$1 permanent;
}

server {
   listen 443 ssl;
   server_name  snibox.zhangsan.org.cn;

   ssl_certificate  /data/ssl/zhangsan.org.cn_cert_chain.pem;
   ssl_certificate_key  /data/ssl/zhangsan.org.cn_key.key;
   ssl_session_timeout 5m;
   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   ssl_prefer_server_ciphers on;

   client_max_body_size 10M;

   location / {
       proxy_pass_header Server;
       proxy_set_header Host $http_host;
       proxy_redirect off;
       proxy_set_header X-Forwarded-Proto https;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Scheme $scheme;
       proxy_pass http://snibox;
   }
}

关于X-Forwarded-Proto

参考MDN解释

X-Forwarded-Proto (XFP) 是一个事实上的标准首部,用来确定客户端与代理服务器或者负载均衡服务器之间的连接所采用的传输协议(HTTP 或 HTTPS)。在服务器的访问日志中记录的是负载均衡服务器与服务器之间的连接所使用的传输协议,而非客户端与负载均衡服务器之间所使用的协议。为了确定客户端与负载均衡服务器之间所使用的协议, X-Forwarded-Proto 就派上了用场。

简而言之,X-Forwarded-Proto在nginx中配置时用于明确指定客户端与nginx之间的通信协议。

【参考】
https://feilong.home.blog/2018/12/22/nginx反向代理huginn部分请求422/ Nginx反向代理Huginn部分请求422
https://github.com/snibox/snibox/issues/26 enable cors with specified host
https://techoverflow.net/2022/05/03/how-to-set-x-forwarded-proto-header-in-nginx/ How to set X-Forwarded-Proto header in nginx

posted @ 2022-08-17 19:50  nuccch  阅读(501)  评论(0编辑  收藏  举报