| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.catalina.valves; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import javax.servlet.ServletException; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import org.apache.catalina.AccessLog; |
| import org.apache.catalina.connector.Request; |
| import org.apache.catalina.connector.Response; |
| |
| /** |
| * {@link RemoteIpValve} Tests |
| */ |
| public class TestRemoteIpValve { |
| |
| static class RemoteAddrAndHostTrackerValve extends ValveBase { |
| private String remoteAddr; |
| private String remoteHost; |
| private String scheme; |
| private boolean secure; |
| private int serverPort; |
| private String forwardedFor; |
| private String forwardedBy; |
| |
| public String getRemoteAddr() { |
| return remoteAddr; |
| } |
| |
| public String getRemoteHost() { |
| return remoteHost; |
| } |
| |
| public String getScheme() { |
| return scheme; |
| } |
| |
| public int getServerPort() { |
| return serverPort; |
| } |
| |
| public boolean isSecure() { |
| return secure; |
| } |
| |
| public String getForwardedFor() { |
| return forwardedFor; |
| } |
| |
| public String getForwardedBy() { |
| return forwardedBy; |
| } |
| |
| @Override |
| public void invoke(Request request, Response response) throws IOException, ServletException { |
| this.remoteHost = request.getRemoteHost(); |
| this.remoteAddr = request.getRemoteAddr(); |
| this.scheme = request.getScheme(); |
| this.secure = request.isSecure(); |
| this.serverPort = request.getServerPort(); |
| this.forwardedFor = request.getHeader("x-forwarded-for"); |
| this.forwardedBy = request.getHeader("x-forwarded-by"); |
| } |
| } |
| |
| public static class MockRequest extends Request { |
| @Override |
| public void setAttribute(String name, Object value) { |
| getCoyoteRequest().getAttributes().put(name, value); |
| } |
| |
| @Override |
| public Object getAttribute(String name) { |
| return getCoyoteRequest().getAttribute(name); |
| } |
| } |
| |
| @Test |
| public void testListToCommaDelimitedString() { |
| List<String> elements = Arrays.asList("element1", "element2", "element3"); |
| String actual = RemoteIpValve.listToCommaDelimitedString(elements); |
| assertEquals("element1, element2, element3", actual); |
| } |
| |
| @Test |
| public void testListToCommaDelimitedStringEmptyList() { |
| List<String> elements = new ArrayList<>(); |
| String actual = RemoteIpValve.listToCommaDelimitedString(elements); |
| assertEquals("", actual); |
| } |
| |
| @Test |
| public void testCommaDelimitedListToStringArrayNullList() { |
| String actual = RemoteIpValve.listToCommaDelimitedString(null); |
| assertEquals("", actual); |
| } |
| |
| @Test |
| public void testInvokeAllowedRemoteAddrWithNullRemoteIpHeader() throws Exception { |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = request.getHeader("x-forwarded-for"); |
| assertNull("x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("x-forwarded-by must be null", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "192.168.0.10", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "remote-host-original-value", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| |
| } |
| |
| @Test |
| public void testInvokeAllProxiesAreTrusted() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10|192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, proxy1, proxy2"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = remoteAddrAndHostTrackerValve.getForwardedBy(); |
| assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void testInvokeAllProxiesAreTrustedOrInternal() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10|192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for") |
| .setString("140.211.11.130, proxy1, proxy2, 192.168.0.10, 192.168.0.11"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = remoteAddrAndHostTrackerValve.getForwardedBy(); |
| assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void testInvokeAllProxiesAreInternal() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10|192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, 192.168.0.10, 192.168.0.11"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are internal, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("all proxies are internal, x-forwarded-by must be null", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void testInvokeAllProxiesAreTrustedAndRemoteAddrMatchRegexp() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("127\\.0\\.0\\.1|192\\.168\\..*|another-internal-proxy"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("proxy1"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("proxy2"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = remoteAddrAndHostTrackerValve.getForwardedBy(); |
| assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void test172dash12InternalProxies() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("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}"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("172.16.0.5"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("209.244.0.3"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-proto").setString("https"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "209.244.0.3", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "209.244.0.3", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "209.244.0.3", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| |
| boolean isSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertTrue("request from internal proxy should be marked secure", isSecure); |
| |
| String scheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("Scheme should be marked to https.","https",scheme); |
| |
| request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("172.25.250.250"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("209.244.0.3"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-proto").setString("https"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor); |
| |
| actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "209.244.0.3", actualRemoteAddr); |
| |
| actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "209.244.0.3", actualRemoteHost); |
| |
| actualPostInvokeRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "209.244.0.3", actualPostInvokeRemoteAddr); |
| |
| actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| |
| isSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertTrue("request from internal proxy should be marked secure", isSecure); |
| |
| scheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("Scheme should be marked to https.","https",scheme); |
| |
| |
| } |
| |
| |
| @Test |
| public void testInvokeXforwardedProtoSaysHttpsForIncomingHttpRequest() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| // client ip |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("192.168.0.10"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| // protocol |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-proto").setString("https"); |
| request.setSecure(false); |
| request.setServerPort(8080); |
| request.getCoyoteRequest().scheme().setString("http"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| // client ip |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("no intermediate non-trusted proxy, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("no intermediate trusted proxy", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteHost); |
| |
| // protocol |
| String actualScheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("x-forwarded-proto says https", "https", actualScheme); |
| |
| int actualServerPort = remoteAddrAndHostTrackerValve.getServerPort(); |
| assertEquals("x-forwarded-proto says https", 443, actualServerPort); |
| |
| boolean actualSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertTrue("x-forwarded-proto says https", actualSecure); |
| |
| boolean actualPostInvokeSecure = request.isSecure(); |
| assertFalse("postInvoke secure", actualPostInvokeSecure); |
| |
| int actualPostInvokeServerPort = request.getServerPort(); |
| assertEquals("postInvoke serverPort", 8080, actualPostInvokeServerPort); |
| |
| String actualPostInvokeScheme = request.getScheme(); |
| assertEquals("postInvoke scheme", "http", actualPostInvokeScheme); |
| } |
| |
| @Test |
| public void testInvokeXforwardedProtoIsNullForIncomingHttpRequest() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| // client ip |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("192.168.0.10"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| // protocol |
| // null "x-forwarded-proto" |
| request.setSecure(false); |
| request.setServerPort(8080); |
| request.getCoyoteRequest().scheme().setString("http"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| // client ip |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("no intermediate non-trusted proxy, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("no intermediate trusted proxy", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteHost); |
| |
| // protocol |
| String actualScheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("x-forwarded-proto is null", "http", actualScheme); |
| |
| int actualServerPort = remoteAddrAndHostTrackerValve.getServerPort(); |
| assertEquals("x-forwarded-proto is null", 8080, actualServerPort); |
| |
| boolean actualSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertFalse("x-forwarded-proto is null", actualSecure); |
| |
| boolean actualPostInvokeSecure = request.isSecure(); |
| assertFalse("postInvoke secure", actualPostInvokeSecure); |
| |
| int actualPostInvokeServerPort = request.getServerPort(); |
| assertEquals("postInvoke serverPort", 8080, actualPostInvokeServerPort); |
| |
| String actualPostInvokeScheme = request.getScheme(); |
| assertEquals("postInvoke scheme", "http", actualPostInvokeScheme); |
| } |
| |
| @Test |
| public void testInvokeXforwardedProtoSaysHttpForIncomingHttpsRequest() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| // client ip |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("192.168.0.10"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| // protocol |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-proto").setString("http"); |
| request.setSecure(true); |
| request.setServerPort(8443); |
| request.getCoyoteRequest().scheme().setString("https"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| // client ip |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("no intermediate non-trusted proxy, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = remoteAddrAndHostTrackerValve.getForwardedBy(); |
| assertNull("no intermediate trusted proxy", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteHost); |
| |
| // protocol |
| String actualScheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("x-forwarded-proto says http", "http", actualScheme); |
| |
| int actualServerPort = remoteAddrAndHostTrackerValve.getServerPort(); |
| assertEquals("x-forwarded-proto says http", 80, actualServerPort); |
| |
| boolean actualSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertFalse("x-forwarded-proto says http", actualSecure); |
| |
| boolean actualPostInvokeSecure = request.isSecure(); |
| assertTrue("postInvoke secure", actualPostInvokeSecure); |
| |
| int actualPostInvokeServerPort = request.getServerPort(); |
| assertEquals("postInvoke serverPort", 8443, actualPostInvokeServerPort); |
| |
| String actualPostInvokeScheme = request.getScheme(); |
| assertEquals("postInvoke scheme", "https", actualPostInvokeScheme); |
| } |
| |
| @Test |
| public void testInvokeXforwardedProtoIsNullForIncomingHttpsRequest() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| // client ip |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("192.168.0.10"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| // protocol |
| // Don't declare "x-forwarded-proto" |
| request.setSecure(true); |
| request.setServerPort(8443); |
| request.getCoyoteRequest().scheme().setString("https"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| // client ip |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertNull("no intermediate non-trusted proxy, x-forwarded-for must be null", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("no intermediate trusted proxy", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "140.211.11.130", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteHost); |
| |
| // protocol |
| String actualScheme = remoteAddrAndHostTrackerValve.getScheme(); |
| assertEquals("x-forwarded-proto is null", "https", actualScheme); |
| |
| int actualServerPort = remoteAddrAndHostTrackerValve.getServerPort(); |
| assertEquals("x-forwarded-proto is null", 8443, actualServerPort); |
| |
| boolean actualSecure = remoteAddrAndHostTrackerValve.isSecure(); |
| assertTrue("x-forwarded-proto is null", actualSecure); |
| |
| boolean actualPostInvokeSecure = request.isSecure(); |
| assertTrue("postInvoke secure", actualPostInvokeSecure); |
| |
| int actualPostInvokeServerPort = request.getServerPort(); |
| assertEquals("postInvoke serverPort", 8443, actualPostInvokeServerPort); |
| |
| String actualPostInvokeScheme = request.getScheme(); |
| assertEquals("postInvoke scheme", "https", actualPostInvokeScheme); |
| } |
| |
| @Test |
| public void testInvokeNotAllowedRemoteAddr() throws Exception { |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10|192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("not-allowed-internal-proxy"); |
| request.setRemoteHost("not-allowed-internal-proxy-host"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, proxy1, proxy2"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = request.getHeader("x-forwarded-for"); |
| assertEquals("x-forwarded-for must be unchanged", "140.211.11.130, proxy1, proxy2", actualXForwardedFor); |
| |
| String actualXForwardedBy = request.getHeader("x-forwarded-by"); |
| assertNull("x-forwarded-by must be null", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "not-allowed-internal-proxy", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "not-allowed-internal-proxy-host", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "not-allowed-internal-proxy", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "not-allowed-internal-proxy-host", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void testInvokeUntrustedProxyInTheChain() throws Exception { |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setInternalProxies("192\\.168\\.0\\.10|192\\.168\\.0\\.11"); |
| remoteIpValve.setTrustedProxies("proxy1|proxy2|proxy3"); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProxiesHeader("x-forwarded-by"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("remote-host-original-value"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for") |
| .setString("140.211.11.130, proxy1, untrusted-proxy, proxy2"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| String actualXForwardedFor = remoteAddrAndHostTrackerValve.getForwardedFor(); |
| assertEquals("ip/host before untrusted-proxy must appear in x-forwarded-for", "140.211.11.130, proxy1", actualXForwardedFor); |
| |
| String actualXForwardedBy = remoteAddrAndHostTrackerValve.getForwardedBy(); |
| assertEquals("ip/host after untrusted-proxy must appear in x-forwarded-by", "proxy2", actualXForwardedBy); |
| |
| String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr(); |
| assertEquals("remoteAddr", "untrusted-proxy", actualRemoteAddr); |
| |
| String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost(); |
| assertEquals("remoteHost", "untrusted-proxy", actualRemoteHost); |
| |
| String actualPostInvokeRemoteAddr = request.getRemoteAddr(); |
| assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr); |
| |
| String actualPostInvokeRemoteHost = request.getRemoteHost(); |
| assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost); |
| } |
| |
| @Test |
| public void testCommaDelimitedListToStringArray() { |
| String[] actual = RemoteIpValve.commaDelimitedListToStringArray("element1, element2, element3"); |
| String[] expected = new String[] { |
| "element1", "element2", "element3" |
| }; |
| assertArrayEquals(expected, actual); |
| } |
| |
| @Test |
| public void testCommaDelimitedListToStringArrayMixedSpaceChars() { |
| String[] actual = RemoteIpValve.commaDelimitedListToStringArray("element1 , element2,\t element3"); |
| String[] expected = new String[] { |
| "element1", "element2", "element3" |
| }; |
| assertArrayEquals(expected, actual); |
| } |
| |
| @Test |
| public void testRequestAttributesForAccessLog() throws Exception { |
| |
| // PREPARE |
| RemoteIpValve remoteIpValve = new RemoteIpValve(); |
| remoteIpValve.setRemoteIpHeader("x-forwarded-for"); |
| remoteIpValve.setProtocolHeader("x-forwarded-proto"); |
| RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve(); |
| remoteIpValve.setNext(remoteAddrAndHostTrackerValve); |
| |
| Request request = new MockRequest(); |
| request.setCoyoteRequest(new org.apache.coyote.Request()); |
| // client ip |
| request.setRemoteAddr("192.168.0.10"); |
| request.setRemoteHost("192.168.0.10"); |
| request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130"); |
| // protocol |
| request.setServerPort(8080); |
| request.getCoyoteRequest().scheme().setString("http"); |
| |
| // TEST |
| remoteIpValve.invoke(request, null); |
| |
| // VERIFY |
| Assert.assertEquals("org.apache.catalina.AccessLog.ServerPort", |
| Integer.valueOf(8080), |
| request.getAttribute(AccessLog.SERVER_PORT_ATTRIBUTE)); |
| |
| Assert.assertEquals("org.apache.catalina.AccessLog.RemoteAddr", |
| "140.211.11.130", |
| request.getAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE)); |
| |
| Assert.assertEquals("org.apache.catalina.AccessLog.RemoteHost", |
| "140.211.11.130", |
| request.getAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE)); |
| } |
| |
| private void assertArrayEquals(String[] expected, String[] actual) { |
| if (expected == null) { |
| assertNull(actual); |
| return; |
| } |
| assertNotNull(actual); |
| assertEquals(expected.length, actual.length); |
| List<String> e = new ArrayList<>(); |
| e.addAll(Arrays.asList(expected)); |
| List<String> a = new ArrayList<>(); |
| a.addAll(Arrays.asList(actual)); |
| |
| for (String entry : e) { |
| assertTrue(a.remove(entry)); |
| } |
| assertTrue(a.isEmpty()); |
| } |
| } |