ProxyConnectionFactory should not ignore TLVs

Signed-off-by: Dmitry Kornilov <dmitry.kornilov@oracle.com>
This commit is contained in:
Dmitry Kornilov 2020-02-19 15:07:38 +01:00
parent 5fe202f29f
commit ab94409574
4 changed files with 98 additions and 10 deletions

View File

@ -95,7 +95,17 @@ import org.eclipse.jetty.util.thread.Invocable;
*/
public interface EndPoint extends Closeable
{
/**
* Marks an <code>EndPoint</code> that wraps another <code>EndPoint</code>.
*/
public interface Wrapper
{
/**
* @return The wrapped <code>EndPoint</code>
*/
EndPoint unwrap();
}
/**
* @return The local Inet address to which this <code>EndPoint</code> is bound, or <code>null</code>
* if this <code>EndPoint</code> does not represent a network connection.

View File

@ -457,7 +457,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
return getEndPoint().flush(output);
}
public class DecryptedEndPoint extends AbstractEndPoint
public class DecryptedEndPoint extends AbstractEndPoint implements EndPoint.Wrapper
{
private final Callback _incompleteWriteCallback = new IncompleteWriteCallback();
private Throwable _failure;
@ -469,6 +469,12 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
super.setIdleTimeout(-1);
}
@Override
public EndPoint unwrap()
{
return getEndPoint();
}
@Override
public long getIdleTimeout()
{
@ -682,7 +688,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
try
{
_underflown = false;
unwrapResult = unwrap(_sslEngine, _encryptedInput, appIn);
unwrapResult = SslConnection.this.unwrap(_sslEngine, _encryptedInput, appIn);
}
finally
{
@ -1554,5 +1560,6 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
return String.format("SSL@%h.DEP.writeCallback", SslConnection.this);
}
}
}
}

View File

@ -49,7 +49,7 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
{
public static final String TLS_VERSION = "TLS_VERSION";
private static final Logger LOG = Log.getLogger(ProxyConnectionFactory.class);
public ProxyConnectionFactory()
{
this(null);
@ -366,9 +366,10 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
{
0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A
};
private final String _nextProtocol;
private int _maxProxyHeader = 1024;
private ProxyV2ConnectionFactory(String nextProtocol)
{
super("proxy");
@ -649,6 +650,13 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
}
break;
}
// PP2_TYPE_MIN_CUSTOM .. PP2_TYPE_MAX_CUSTOM
case 0xE0: case 0xE1: case 0xE2: case 0xE3:
case 0xE4: case 0xE5: case 0xE6: case 0xE7:
case 0xE8: case 0xE9: case 0xEA: case 0xEB:
case 0xEC: case 0xED: case 0xEE: case 0xEF:
proxyEndPoint.setCustomValue(type, value);
break;
case 0x01: // PP2_TYPE_ALPN
case 0x02: // PP2_TYPE_AUTHORITY
case 0x03: // PP2_TYPE_CRC32C
@ -751,11 +759,15 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
}
}
public static class ProxyEndPoint extends AttributesMap implements EndPoint
public static class ProxyEndPoint extends AttributesMap implements EndPoint, EndPoint.Wrapper
{
private static final int PP2_TYPE_MIN_CUSTOM = 0xE0;
private static final int PP2_TYPE_MAX_CUSTOM = 0xEF;
private final EndPoint _endp;
private final InetSocketAddress _remote;
private final InetSocketAddress _local;
private byte[][] customValues;
public ProxyEndPoint(EndPoint endp, InetSocketAddress remote, InetSocketAddress local)
{
@ -764,6 +776,40 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
_local = local;
}
public EndPoint unwrap()
{
return _endp;
}
/**
* Sets a custom TLV vector. See section 2.2.7 of the PROXY
* protocol specification.
*
* @param type must be between 0xE0..0xEF inclusive.
* @param value the custom value
*/
public synchronized void setCustomValue(int type, byte[] value)
{
int index = type - PP2_TYPE_MIN_CUSTOM;
if (customValues == null)
{
customValues = new byte[PP2_TYPE_MAX_CUSTOM - PP2_TYPE_MIN_CUSTOM + 1][];
}
customValues[index] = value;
}
/**
* Gets a custom TLV vector.
*
* @param type must be between 0xE0..0xEF inclusive.
* @return the custom value or null if not set
*/
public synchronized byte[] getCustomValue(int type)
{
return customValues == null ? null
: customValues[type - PP2_TYPE_MIN_CUSTOM];
}
@Override
public void close(Throwable cause)
{

View File

@ -25,10 +25,14 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.ProxyConnectionFactory.ProxyEndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.AfterEach;
@ -118,15 +122,29 @@ public class ProxyProtocolTest
{
final String remoteAddr = "192.168.0.1";
final int remotePort = 12345;
final byte[] customE0 = new byte[] {1, 2};
final byte[] customE1 = new byte[] {-1, -1, -1};
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (remoteAddr.equals(request.getRemoteAddr()) &&
if (validateEndPoint(baseRequest) &&
remoteAddr.equals(request.getRemoteAddr()) &&
remotePort == request.getRemotePort())
baseRequest.setHandled(true);
}
private boolean validateEndPoint(Request request)
{
HttpConnection con = (HttpConnection)request.getAttribute(HttpConnection.class.getName());
EndPoint endPoint = con.getEndPoint();
ProxyEndPoint proxyEndPoint = (ProxyEndPoint)endPoint;
return Arrays.equals(customE0, proxyEndPoint.getCustomValue(0xE0)) &&
Arrays.equals(customE1, proxyEndPoint.getCustomValue(0xE1)) &&
proxyEndPoint.getCustomValue(0xE2) == null;
}
});
try (Socket socket = new Socket("localhost", connector.getLocalPort()))
@ -141,8 +159,8 @@ public class ProxyProtocolTest
// 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" +
// length of remaining header (4+4+2+2+3+6+5+6 = 32)
"0020" +
// uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port;
"C0A80001" +
@ -154,7 +172,13 @@ public class ProxyProtocolTest
"040000" +
// NOOP value ABCDEF
"040003ABCDEF";
"040003ABCDEF" +
// Custom 0xEO {0x01,0x02}
"E000020102" +
// Custom 0xE1 {0xFF,0xFF,0xFF}
"E10003FFFFFF";
String request1 =
"GET /1 HTTP/1.1\r\n" +
@ -193,4 +217,5 @@ public class ProxyProtocolTest
}
}
}
}