1-Intro
ๆไธไบ็ฎๅ็ๅทฅๅ
ท็ฑป๏ผไฝๆฏๆ่ง tomcat ็ๅ
้จๅฎ็ฐๆดๅ ็้ ่ฐฑ๏ผ่ฟ้ๅๆไธไธๆบ็ .
1)-็ฎๅๅฎ็ฐ
ๆฃๆฅไธไธ็ฎๅ็ HTTP-HEADER
public static String getIP(HttpServletRequest request) {
Assert.notNull(request, "HttpServletRequest is null");
String ip = request.getHeader("X-Requested-For");
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return StrUtil.isBlank(ip) ? null : ip.split(",")[0];
}
2)-TOMCAT ๆบ็ ๅๆ
ๆบ็ ไฝ็ฝฎ:
org.apache.catalina.filters.RemoteIpFilter#doFilter(jakarta.servlet.http.HttpServletRequest, jakarta.servlet.http.HttpServletResponse, jakarta.servlet.FilterChain)
3)-็่งฃไธๆฌกไปฃ็็่กไธบ
ๅ่ฎพๅชๆไธๅฑไปฃ็ NGINX, ็ถๅ็จๆท้่ฟๆต่งๅจ่ฎฟ้ฎ https://www.example.com . ็ถๅไผๆๅฆไธ็้ฎ้ข:
Webๆๅกๅจๅฆไฝ็ฅ้ ๅๅง็่ฏทๆฑๆฏHTTPS;Webๆๅกๅจๅฆไฝ็ฅ้็จๆทๅฎ้ ไธ่ฎฟ้ฎ็ๆฏwww.example.com
่ไปฃ็ๆๅกๅจๆไธไบๅฅ็บฆ็.
X-Forwarded-Proto: ไผ่ฏดๆ ยWebๆๅกๅจๅๅง่ฏทๆฑไฝฟ็จ็ๅ่ฎฎ๏ผHTTPๆHTTPS๏ผ;X-Forwarded-Host: ไผๅ่ฏWebๆๅกๅจๅๅง่ฎฟ้ฎ็Hostๆฏไปไน ;
2-Design
2-1 ๅ ้จไปฃ็็ฝๆฎต
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}|" +
"100\\.6[4-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.[7-9]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" +
"100\\.1[0-1]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.12[0-7]{1}\\.\\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");IANA ๆ่ฟไบ็ฝๆฎตไฟ็ไธบ็งๆ็ฝๆฎต.
- 10.0.0.0 ๅฐ 10.255.255.255
- 192.168.0.0 ๅฐ 192.168.255.255
- 169.254.0.0 ๅฐ 169.254.255.255
- 127.0.0.0 ๅฐ 127.255.255.255
- 100.64.0.0 ๅฐ 100.127.255.255
- 172.16.0.0 ๅฐ 172.31.255.255
- ::1 ๅ 0:0:0:0:0:0:0:1 (IPv6 ๅ็ฏๅฐๅ)
ๅ ไธบ Java ไธ่ฌๆฏๅ็ซฏ็ฝ็ป๏ผๅ้ขไธ่ฌๆฏ NGINX ็ญ็ญ PROXY .
public XForwardedRequest(HttpServletRequest request) {
super(request);
this.localName = request.getLocalName();
this.localPort = request.getLocalPort();
this.remoteAddr = request.getRemoteAddr();
this.remoteHost = request.getRemoteHost();
this.scheme = request.getScheme();
this.secure = request.isSecure();
this.serverName = request.getServerName();
this.serverPort = request.getServerPort();
headers = new HashMap<>();
for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
String header = headerNames.nextElement();
headers.put(header, Collections.list(request.getHeaders(header)));
}
}requestไฟกๆฏๅคๅถ
2-2 ่งฃๆ X-Forwarded-For ๅคด
for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
ย ย String currentRemoteIp = remoteIpHeaderValue[idx];
ย ย remoteIp = currentRemoteIp;
ย ย if (internalProxies != null && internalProxies.matcher(currentRemoteIp).matches()) {
ย ย ย ย // ๅ
้จไปฃ็ IP๏ผ็ปง็ปญๅๅทฆๆฅๆพ
ย ย } else if (trustedProxies != null && trustedProxies.matcher(currentRemoteIp).matches()) {
ย ย ย ย // ๅฏไฟกไปฃ็ IP๏ผๆทปๅ ๅฐไปฃ็้พไธญ
ย ย ย ย proxiesHeaderValue.addFirst(currentRemoteIp);
ย ย } else {
ย ย ย ย // ๆพๅฐ็ฌฌไธไธช้ๅ
้จ้ๅฏไฟก็ IP๏ผ่ฎคไธบๆฏๅฎขๆท็ซฏ IP
ย ย ย ย break;
ย ย }
}ไปๅณๅๅทฆ้ๅ๏ผๆพๅฐ็ฌฌไธไธช ้ๅ
้จ็ IP
2-3 ่งฃๆ X-Forwarded-By ๅคด
if (remoteIp != null) {
xRequest.setRemoteAddr(remoteIp);
if (getEnableLookups()) {
// This isn't a lazy lookup but that would be a little more
// invasive - mainly in XForwardedRequest - and if // enableLookups is true is seems reasonable that the // hostname will be required so look it up here. try {
InetAddress inetAddress = InetAddress.getByName(remoteIp);
// We know we need a DNS look up so use getCanonicalHostName()
xRequest.setRemoteHost(inetAddress.getCanonicalHostName());
} catch (UnknownHostException e) {
log.debug(sm.getString("remoteIpFilter.invalidRemoteAddress", remoteIp), e);
xRequest.setRemoteHost(remoteIp);
}
} else {
xRequest.setRemoteHost(remoteIp);
}
if (proxiesHeaderValue.size() == 0) {
xRequest.removeHeader(proxiesHeader);
} else {
String commaDelimitedListOfProxies = StringUtils.join(proxiesHeaderValue);
xRequest.setHeader(proxiesHeader, commaDelimitedListOfProxies);
}
if (newRemoteIpHeaderValue.size() == 0) {
xRequest.removeHeader(remoteIpHeader);
} else {
String commaDelimitedRemoteIpHeaderValue = StringUtils.join(newRemoteIpHeaderValue);
xRequest.setHeader(remoteIpHeader, commaDelimitedRemoteIpHeaderValue);
}
}2-4 ่งฃๆ protocolHeader ๅคด
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)) {
xRequest.setSecure(true);
xRequest.setScheme("https");
setPorts(xRequest, httpsServerPort);
} else {
xRequest.setSecure(false);
xRequest.setScheme("http");
setPorts(xRequest, httpServerPort);
}
}- ๆ นๆฎ่ฟไธชๅคด๏ผ้ๆฐ่ฎพ็ฝฎ
http่ฟๆฏhttps
2-5 ่งฃๆ hostHeader
if (hostHeader != null) {
String hostHeaderValue = request.getHeader(hostHeader);
if (hostHeaderValue != null) {
try {
int portIndex = Host.parse(hostHeaderValue);
if (portIndex > -1) {
log.debug(sm.getString("remoteIpFilter.invalidHostWithPort", hostHeaderValue, hostHeader));
hostHeaderValue = hostHeaderValue.substring(0, portIndex);
}
xRequest.setServerName(hostHeaderValue);
if (isChangeLocalName()) {
xRequest.setLocalName(hostHeaderValue);
}
} catch (IllegalArgumentException iae) {
log.debug(sm.getString("remoteIpFilter.invalidHostHeader", hostHeaderValue, hostHeader));
}
}
}3-Conclusion
้่ฟ Wrapper ็ๆนๅผๅปๆๅฎ . X-Forwarded-Proto X-Forwarded-Host ๅ X-Forwarded-For ๅคด .
่่ไบ ๅ
็ฝ็ฝๆฎต, HTTPS ็ญ็ญๆนๅผ๏ผ็ธๅฏนๆฏ่พๅฎๅ