Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#11729] RFC 7239 Forwarded Header based RealIpHeaderResolver #11730

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@
import com.navercorp.pinpoint.common.util.StringUtils;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
* @author Woonduk Kang(emeroad)
*/
public class RealIpHeaderResolver<T> implements RemoteAddressResolver<T> {

private static final String FORWARDED_HEADER_NAME = "Forwarded";
private static final Pattern FORWARDED_FOR_PATTERN = Pattern.compile("(?i:for)=\"?([^;,\"]+)\"?");

Check warning on line 34 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L34

Added line #L34 was not covered by tests

private final String realIpHeaderName;
private final String realIpHeaderEmptyValue;

Expand All @@ -38,21 +43,41 @@

@Override
public String resolve(RequestAdaptor<T> requestAdaptor, T request) {
final String realIp = requestAdaptor.getHeader(request, realIpHeaderName);
if (StringUtils.isEmpty(realIp)) {
final String realIpHeaderValue = requestAdaptor.getHeader(request, realIpHeaderName);

Check warning on line 46 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L46

Added line #L46 was not covered by tests
if (StringUtils.isEmpty(realIpHeaderValue)) {
return null;
}

if (realIpHeaderEmptyValue != null && realIpHeaderEmptyValue.equalsIgnoreCase(realIp)) {
if (realIpHeaderEmptyValue != null && realIpHeaderEmptyValue.equalsIgnoreCase(realIpHeaderValue)) {
return null;
}

String firstRealIpHeaderValue = getFirstRealIpHeaderValue(realIpHeaderValue);

Check warning on line 55 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L55

Added line #L55 was not covered by tests

if ("Forwarded".equalsIgnoreCase(realIpHeaderName)) {
Matcher matcher = FORWARDED_FOR_PATTERN.matcher(firstRealIpHeaderValue);

Check warning on line 58 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L58

Added line #L58 was not covered by tests
if (matcher.find()) {
String ip = matcher.group(1).trim();
int portSeparatorIdx = ip.lastIndexOf(':');
int squareBracketIdx = ip.lastIndexOf(']');

Check warning on line 62 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L60-L62

Added lines #L60 - L62 were not covered by tests
if (portSeparatorIdx > squareBracketIdx) {
return ip.substring(0, portSeparatorIdx);

Check warning on line 64 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L64

Added line #L64 was not covered by tests
}

return ip;

Check warning on line 67 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L67

Added line #L67 was not covered by tests
}
}

return firstRealIpHeaderValue;

Check warning on line 71 in agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java

View check run for this annotation

Codecov / codecov/patch

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/request/util/RealIpHeaderResolver.java#L71

Added line #L71 was not covered by tests
}

private static String getFirstRealIpHeaderValue(String realIp) {
final int firstIndex = realIp.indexOf(',');

if (firstIndex == -1) {
return realIp;
} else {
return realIp.substring(0, firstIndex);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
* @author Woonduk Kang(emeroad)
*/
public class RemoteAddressResolverFactoryTest {
public static final String FORWARDED = "forwarded";
public static final String X_FORWARDED_FOR = "x-forwarded-for";
public static final String UNKNOWN = "unknown";

@Test
public void getRemoteAddress0() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, "x-forwarded-for", "unknown");
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, X_FORWARDED_FOR, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
when(httpServletRequest.getHeader(X_FORWARDED_FOR)).thenReturn("127.0.0.1");

Expand All @@ -49,7 +50,7 @@ public void getRemoteAddress0() throws Exception {
@Test
public void getRemoteAddress1() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, "x-forwarded-for", "unknown");
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, X_FORWARDED_FOR, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
when(httpServletRequest.getHeader(X_FORWARDED_FOR)).thenReturn("127.0.0.1, proxy1, proxy2");

Expand All @@ -61,11 +62,76 @@ public void getRemoteAddress1() throws Exception {
@Test
public void getRemoteAddress2() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, "x-forwarded-for", "unknown");
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, X_FORWARDED_FOR, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("127.0.0.2", requestAdaptor.getRemoteAddress(httpServletRequest));
}
}

@Test
public void getRemoteAddress3() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, FORWARDED, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getHeader(FORWARDED)).thenReturn("for=\"_gazonk\"");

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("_gazonk", requestAdaptor.getRemoteAddress(httpServletRequest));
}

@Test
public void getRemoteAddress4() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, FORWARDED, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getHeader(FORWARDED)).thenReturn("For=\"[2001:db8:cafe::17]:4711\"");

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("[2001:db8:cafe::17]", requestAdaptor.getRemoteAddress(httpServletRequest));
}

@Test
public void getRemoteAddress5() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, FORWARDED, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getHeader(FORWARDED)).thenReturn("for=192.0.2.60;proto=http;by=203.0.113.43");

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("192.0.2.60", requestAdaptor.getRemoteAddress(httpServletRequest));
}

@Test
public void getRemoteAddress6() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, FORWARDED, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getHeader(FORWARDED)).thenReturn("for=192.0.2.43, for=198.51.100.17");

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("192.0.2.43", requestAdaptor.getRemoteAddress(httpServletRequest));
}

@Test
public void getRemoteAddress7() throws Exception {
RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
requestAdaptor = RemoteAddressResolverFactory.wrapRealIpSupport(requestAdaptor, FORWARDED, UNKNOWN);
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);

when(httpServletRequest.getHeader(FORWARDED)).thenReturn("for=192.0.2.43,for=198.51.100.17");

when(httpServletRequest.getRemoteAddr()).thenReturn("127.0.0.2");

assertEquals("192.0.2.43", requestAdaptor.getRemoteAddress(httpServletRequest));
}
}