通过docker方式部署了chevereto,并要想发布到公网上的时候,通常是通过反向代理,并在反向代理上开启SSL功能,但是这里就引发了一个问题,chevereto并不知道访问者会用https方式来访问(正常情况下docker对外映射的都是http端口,因为https需要在容器里配置证书,而很多人不愿意,包括我~。而且其实也不止chevereto,很多应用都有这种问题。),反向代理在配置目标url的时候也是使用的http方式,那么,这种情况下,就会出现如下报错:
The plain HTTP request was sent to HTTPS port
这个时候,访问chevereto的页面就会是这种效果:
而正常情况如下:
因为前面提到的原因,chevereto响应的内容都是用的http开头,而客户端浏览器在后续访问的时候会用http方式,但是因为反向代理又是用的https,在https端口收到http请求,所以就产生了上述的报错。
解决方式很简单,有2种思路可供选择:
1、直接告诉chevereto用户使用的https协议
"X-Forwarded-Proto"就是告诉后端服务器,客户端使用的真实协议是https,响应的时候需要使用https而不是http,只需要在反向代理配置中加入如下代码:
proxy_set_header X-Forwarded-Proto https;
2、直接修改chevereto的响应内容
反向代理在收到chevereto发回的http的response内容时,直接使用"proxy_redirect"将http修改为https然后再发回给用户,只需要在反向代理配置中加入如下代码:
proxy_redirect http:// https://;
当然,也可以2手一起抓,主打一个双保险:)
不过,这只是最简单的1级反向代理的情形,也就是说是:用户—>反向代理—>chevereto的情形,实际生产环境不可能这么简单,比如我现在是:CDN—>总反向代理—>WAF(也是http反向代理工作方式)—>chevereto,这种情况如果出现问题就要考虑多级反向代理的情况:
1、采用"X-Forwarded-Proto"方式,那么最简单的就是在WAF上进行配置(最接近chevereto的反向代理),因为WAF后面就是chevereto,直接告诉它即可;当然,从规范的角度来说,应该是总反向代理上进行配置,然后通过WAF进行传递(使用http_x_forwarded_proto),这里就不详细说了。
2、采用"proxy_redirect"方式,直接在总反向代理修改chevereto的response即可。随便提一句,"proxy_redirect"非常强大,其实不怕麻烦的话,host都不需要使用,应用的返回的响应不管多离谱都可以直接改~。
另:其实这和应用关系很大,chevereto没有自定义访问协议、域名和端口的功能,而有些应用,比如wordpress,本身就可以定义访问的URL(协议、域名、端口):
所以只需要在反向代理链中将客户端访问的域名用$host参数传递到wordpress的http监听端口,wordpress即可返回正确的URL了,不过只有少数应用有这个功能,绝大部份还是简单粗暴的采用"http端口收到请求就返回http,https端口收到情况就返回https"的方式,所以在多级反向代理的时候,遇到问题就要具体问题具体分析了。