From d34cb2598b4199d01a67eba37c800910ac4e409d Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Mon, 4 May 2020 17:46:12 +0200 Subject: [PATCH] proxy v2 skip address length bytes when LOCAL command is specified Signed-off-by: Ludovic Orban --- .../jetty/server/ProxyConnectionFactory.java | 4 + .../jetty/server/ProxyConnectionTest.java | 33 ++++++++ .../jetty/server/ProxyProtocolTest.java | 77 +++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java index 6cb0f7f9571..4163b87c43f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java @@ -662,6 +662,10 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory if (LOG.isDebugEnabled()) LOG.debug("Proxy v2 {} {}", getEndPoint(), proxyEndPoint.toString()); } + else + { + _buffer.position(_buffer.position() + _length); + } if (LOG.isDebugEnabled()) LOG.debug("Proxy v2 parsing dynamic packet part is now done, upgrading to {}", _nextProtocol); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java index 7e1f6ab8cdf..92908ed8f34 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java @@ -151,6 +151,39 @@ public class ProxyConnectionTest assertThat(response, Matchers.containsString("remote=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:12345")); } + @ParameterizedTest + @MethodSource("requestProcessors") + public void testLocalV2(RequestProcessor p) throws Exception + { + String proxy = + // Preamble + "0D0A0D0A000D0A515549540A" + + + // V2, LOCAL + "20" + + + // 0x1 : AF_INET 0x1 : STREAM. + "11" + + + // Address length is 16. + "0010" + + + // gibberish + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + ; + String http = "GET /path HTTP/1.1\n" + + "Host: server:80\n" + + "Connection: close\n" + + "\n"; + + String response = p.sendRequestWaitingForResponse(TypeUtil.fromHexString(proxy), http.getBytes(StandardCharsets.US_ASCII)); + + assertThat(response, Matchers.containsString("HTTP/1.1 200")); + assertThat(response, Matchers.containsString("pathInfo=/path")); + assertThat(response, Matchers.containsString("local=0.0.0.0:0")); + assertThat(response, Matchers.containsString("remote=0.0.0.0:0")); + } + @ParameterizedTest @MethodSource("requestProcessors") public void testMissingField(RequestProcessor p) throws Exception diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyProtocolTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyProtocolTest.java index da6d185a6b2..d6dac5ca7a1 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyProtocolTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyProtocolTest.java @@ -193,4 +193,81 @@ public class ProxyProtocolTest } } } + + @Test + public void testProxyProtocolV2Local() throws Exception + { + start(new AbstractHandler() + { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + baseRequest.setHandled(true); + } + }); + + try (Socket socket = new Socket("localhost", connector.getLocalPort())) + { + String proxy = + // Preamble + "0D0A0D0A000D0A515549540A" + + + // V2, LOCAL + "20" + + + // 0x1 : AF_INET 0x1 : STREAM. Address length is 2*4 + 2*2 = 12 bytes. + "11" + + + // length of remaining header (4+4+2+2+6+3 = 21) + "0015" + + + // uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port; + "C0A80001" + + "7f000001" + + "3039" + + "1F90" + + + // NOOP value 0 + "040000" + + + // NOOP value ABCDEF + "040003ABCDEF"; + + String request1 = + "GET /1 HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "\r\n"; + OutputStream output = socket.getOutputStream(); + output.write(TypeUtil.fromHexString(proxy)); + output.write(request1.getBytes(StandardCharsets.UTF_8)); + output.flush(); + + InputStream input = socket.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + String response1 = reader.readLine(); + assertTrue(response1.startsWith("HTTP/1.1 200 ")); + while (true) + { + if (reader.readLine().isEmpty()) + break; + } + + // Send a second request to verify that the proxied IP is retained. + String request2 = + "GET /2 HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Connection: close\r\n" + + "\r\n"; + output.write(request2.getBytes(StandardCharsets.UTF_8)); + output.flush(); + + String response2 = reader.readLine(); + assertTrue(response2.startsWith("HTTP/1.1 200 ")); + while (true) + { + if (reader.readLine() == null) + break; + } + } + } }