事件:
客户反馈,为什么配置https请求,使用request.getScheme()、request.getServerPort(),后台获取访问协议和端口的时候还是获取的http和80。。
用户架构: CDN+SLB+EDAS应用
其中
CDN使用443端口回源
SLB配置安全证书使用HTTPS公网IP访问
EDAS使用Alitomcat,server.xml配置
< Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"/>
通过用户沟通已经需求已经比较清晰。
用户希望在后端ECS处,可以拿到客户端真实请求的来源IP(x-forwarded-for)和协议(X-Forwarded-Proto),但目前情况是在自建服务器的tomcat上使用正常,换成阿里服务器后有问题,获得的仍然是http和80。
排查过程:
- 首先用分离的方式将CDN去除。可将域名解析改为SLB公网IP
- 判断SLB是否转发正常。SLB的机制,是将公网入口请求转化为内网请求传给ECS,公网入口走https,内网出口走http,X-Forwarded-Proto属性在SLB中需要单独开启“SLB监听协议”属性,通过X-Forwarded-Proto头字段获取SLB的监听协议进行转发给后端。
- 开启该协议后,验证ECS是否收到了对应的属性。可通过在ECS上抓包的方式来识别。
通过tcpdump抓包,看到在访问SLB的https协议时,X-Forwarded-Proto确实为https
- 那么为什么alitomcat上没有得到对应的https值呢。通过上网查询。由于internalProxies匹配的内网IP不包含SLB的100段的IP,需要配置internalProxies="100.d{1,3}.d{1,3}.d{1,3}"来识别转发IP。
如果没有配置,则默认IP地址为
Regular expression (using java.util.regex) that a proxy's IP address must match to be considered an internal proxy. Internal proxies that appear in the remoteIpHeader will be trusted and will not appear in the proxiesHeader value. If not specified the default value of 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} will be used.
详细内容可以访问
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html
重启应用后,用SLB访问Https测试可得:
验证生效,结果正确。