之前在網(wǎng)上搜索到的很多文章在描述 Nginx + Tomcat 啟用 HTTPS 支持的時(shí)候,都必須在 Nginx 和 Tomcat 兩邊同時(shí)配置 SSL 支持。但我一直在想為什么就不能按照下面的方式來配置呢?就是 Nginx 上啟用了 HTTPS,而 Nginx 和 Tomcat 之間走的卻是普通的 HTTP 連接。但是搜索很多沒有解決辦法,最后還是老老實(shí)實(shí)的 Nginx 和 Tomcat 同時(shí)配置的 SSL 支持。
最終配置的方案是瀏覽器和 Nginx 之間走的 HTTPS 通訊,而 Nginx 到 Tomcat 通過 proxy_pass 走的是普通 HTTP 連接。當(dāng)時(shí)由于系統(tǒng)用到了websocket,一
下面是詳細(xì)的配置(Nginx 端口 80/443,Tomcat 的端口 8080):
Nginx 這一側(cè)的配置沒什么特別的:
worker_processes? 16;
error_log logs/error.log;
events {
worker_connections? 10240;
}
http{
include mime.types;
map $http_upgrade $connection_upgrade {
default upgrade;
''? ? ? close;
}
upstream websocket {
#ip_hash;
server 192.168.0.23:8080? weight=50;
server 192.168.0.25:8080? weight=50;
}
server {
listen? ? ? 443 ssl;
ssl_certificate? /app/nginx/conf/server.crt;
ssl_certificate_key? /app/nginx/conf/server_nopwd.key;
server_name? 192.168.0.23;
ssl_prefer_server_ciphers? on;
charset utf-8;
ssi on;
location ^~/asims {
proxy_pass http://websocket;
proxy_connect_timeout 60;
proxy_read_timeout 86400;
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_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
fastcgi_param? SCRIPT_NAME? ? ? ? "";
}
location ^~ /docs {
deny all;
}
location ^~ /examples {
deny all;
}
location ^~ /host-manager {
deny all;
}
location ^~ /manager {
deny all;
}
}
server {
listen? ? ? 80;
server_name? 192.168.0.23;
rewrite ^ https://$server_name$request_uri? permanent;
}
}
其中最為關(guān)鍵的就是 ssl_certificate 和 ssl_certificate_key 這兩項(xiàng)配置,其他的按正常配置。不過多了一個(gè) proxy_set_header X-Forwarded-Proto https; 配置。
最主要的配置來自 Tomcat,下面是我測(cè)試環(huán)境中的完整 server.xml:
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
? <Service name="Catalina">
? ? <Connector port="8080" protocol="HTTP/1.1"
? ? ? ? ? ? ? ?connectionTimeout="20000"
? ? ? ? ? ? ? ?redirectPort="443"
? ? ? ? ? ? ? ?proxyPort="443"/>
? ? <Engine name="Catalina" defaultHost="localhost">
? ? ? <Host name="localhost" ?appBase="webapps"
? ? ? ? ? ? unpackWARs="true" autoDeploy="true">
? ? ? ? ? ? <Valve className="org.apache.catalina.valves.RemoteIpValve"
? ? ? ? ? ? ? ? ? remoteIpHeader="x-forwarded-for"
? ? ? ? ? ? ? ? ? remoteIpProxiesHeader="x-forwarded-by"
? ? ? ? ? ? ? ? ? protocolHeader="x-forwarded-proto"
? ? ? ? ? ? />
? ? ? ? ? ? <Context path="" docBase="/oschina/webapp" reloadable="false"/>
? ? ? </Host>
? ? </Engine>
? </Service>
</Server>
上述的配置中沒有什么特別的,但是特別特別注意的是必須有proxyPort="443",這是整篇文章的關(guān)鍵,當(dāng)然 redirectPort 也必須是 443。同時(shí)節(jié)點(diǎn)的配置也非常重要,否則你在 Tomcat 中的應(yīng)用在讀取 getScheme() 方法以及在 web.xml 中配置的一些安全策略會(huì)不起作用。當(dāng)然最最主要的還是org.apache.catalina.valves.RemoteIpValve配置,否則webscocket的請(qǐng)求投就不會(huì)正確。