Nginx+Springboot配置https后的scheme和port问题

1.环境

反向代理:Nginx (nginx version: nginx/1.14.2)

网关:Zuul (2.2.9.RELEASE)

服务:SpringBoot使用内置Tomcat (9.0.71)

2.相关配置

Nginx:设置请求头,向后面的代理或服务传递真实的协议、域名(ip)、端口

 proxy_set_header Host $host:$server_port;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 proxy_set_header X-Forwarded-Scheme $scheme;
 proxy_set_header X-Forwarded-Port $server_port;
 proxy_redirect http://  $scheme://;

Zuul

server.tomcat.remoteip.remote-ip-header=X-Forwarded-For
server.tomcat.remoteip.protocol-header=X-Forwarded-Proto
server.tomcat.remote.port-header=X-Forwarded-Port
server.forward-headers-strategy=native
zuul.add-host-header=true
zuul.add-proxy-headers=false

SpringBoot

server.tomcat.remoteip.remote-ip-header=X-Forwarded-For
server.tomcat.remoteip.protocol-header=X-Forwarded-Proto
server.tomcat.remote.port-header=X-Forwarded-Port
server.forward-headers-strategy=native
server.tomcat.remoteip.internal-proxies=192\.168\.16\.50|10\.\d{1,3}\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}|0:0:0:0:0:0:0:1|::1

3.常见问题

3.1.request.getScheme()获取的是http

1.确认Nginx配置:proxy_set_header X-Forwarded-Proto $scheme;

2.确认SpringBoot配置:server.tomcat.remoteip.protocol-header=X-Forwarded-Proto

3.上面都配置,还不行;去看看代码哪里设置的这个请求头(X-Forwarded-Proto)

类:org/apache/catalina/valves/RemoteIpValve.java
方法:public void invoke(Request request, Response response) 
 
if (protocolHeader != null) {
	String protocolHeaderValue = request.getHeader(protocolHeader);
	if (protocolHeaderValue == null) {
		// Don't modify the secure, scheme and serverPort attributes
		// of the request
	} else if (isForwardedProtoHeaderValueSecure(protocolHeaderValue)) {
		request.setSecure(true);
		request.getCoyoteRequest().scheme().setString("https");
		setPorts(request, httpsServerPort);
	} else {
		request.setSecure(false);
		request.getCoyoteRequest().scheme().setString("http");
		setPorts(request, httpServerPort);
	}
}

前提条件:
final String originalRemoteAddr = request.getRemoteAddr();
boolean isInternal = internalProxies != null &&
		internalProxies.matcher(originalRemoteAddr).matches();

if (isInternal || (trustedProxies != null &&
		trustedProxies.matcher(originalRemoteAddr).matches())) {
		#满足条件
}

就是request.getRemoteAddr()要满足这个2个正则之一:internalProxies、trustedProxies
private Pattern internalProxies = Pattern.compile(
	"10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
	"192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
	"169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
	"127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
	"172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
	"172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
	"172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
	"0:0:0:0:0:0:0:1|::1");
private Pattern trustedProxies = null;

trustedProxies没找到设置的地方,internalProxies是可以配置的
server.tomcat.remoteip.internal-proxies=xxxx

关键问题,为啥request.getRemoteAddr()没有匹配internalProxies;我内网测试一直没问题。
我在出问题的环境,用arthas拿一下request.getRemoteAddr()这个值:watch org.apache.catalina.connector.Request getRemoteAddr  "{params,returnObj}" -x 2 
结果拿出来,是这台机器的公网ip,不满足上面的正则;参考上面springboot把拿到的ip配置到server.tomcat.remoteip.internal-proxies就好了。



3.2.request.getServerPort()获取不到正确的端口

1.确认Nginx配置:proxy_set_header X-Forwarded-Port $server_port;

2.确认SpringBoot配置:server.tomcat.remoteip.protocol-header=X-Forwarded-Port

3.使用的是其他端口,但是取到的是443

Nginx+Springboot配置https后的scheme和port问题_第1张图片

现象:
request.getServerPort()得到443
request.getHeader("X-Forwarded-Port")得到:9999,9999

方案1:将Nginx和springboot配置和获取的请求头调整为X-Forwarded-tPort
方案2(推荐):Zuul配置:zuul.add-proxy-headers=false

你可能感兴趣的:(nginx,https,运维,spring,boot)