NioServer: retain links by address string to minimize resource leak (#3525)

Every time a client connects, the NioServer will retain the link against
the InetSocketAddress object. If the same agent/client reconnects, it
will grow older links over time and in case of denial of service attack
or a client/script/monitoring-service reconnecting aggressively against
port 8250 will cause the `_links` weak hashmap to grow over time and
very quickly.

The fix will ensure that only one Link gets weakly retained for an
incoming client based on its address string.

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2019-10-22 14:53:11 +05:30 committed by GitHub
parent 294813e8fe
commit 9ee129ae6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 8 additions and 7 deletions

View File

@ -489,7 +489,7 @@ public class Link {
try { try {
sslEngine.closeInbound(); sslEngine.closeInbound();
} catch (SSLException e) { } catch (SSLException e) {
s_logger.warn("This SSL engine was forced to close inbound due to end of stream."); s_logger.warn("This SSL engine was forced to close inbound due to end of stream.", e);
} }
sslEngine.closeOutbound(); sslEngine.closeOutbound();
// After closeOutbound the engine will be set to WRAP state, // After closeOutbound the engine will be set to WRAP state,

View File

@ -25,6 +25,7 @@ import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey; import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel; import java.nio.channels.ServerSocketChannel;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.apache.cloudstack.framework.ca.CAService; import org.apache.cloudstack.framework.ca.CAService;
@ -36,13 +37,13 @@ public class NioServer extends NioConnection {
protected InetSocketAddress _localAddr; protected InetSocketAddress _localAddr;
private ServerSocketChannel _serverSocket; private ServerSocketChannel _serverSocket;
protected WeakHashMap<InetSocketAddress, Link> _links; protected Map<String, Link> _links;
public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService) { public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService) {
super(name, port, workers, factory); super(name, port, workers, factory);
setCAService(caService); setCAService(caService);
_localAddr = null; _localAddr = null;
_links = new WeakHashMap<InetSocketAddress, Link>(1024); _links = new WeakHashMap<String, Link>(10240);
} }
public int getPort() { public int getPort() {
@ -61,7 +62,7 @@ public class NioServer extends NioConnection {
_serverSocket.register(_selector, SelectionKey.OP_ACCEPT, null); _serverSocket.register(_selector, SelectionKey.OP_ACCEPT, null);
s_logger.info("NioConnection started and listening on " + _serverSocket.socket().getLocalSocketAddress()); s_logger.info("NioServer started and listening on " + _serverSocket.socket().getLocalSocketAddress());
} }
@Override @Override
@ -75,12 +76,12 @@ public class NioServer extends NioConnection {
@Override @Override
protected void registerLink(final InetSocketAddress addr, final Link link) { protected void registerLink(final InetSocketAddress addr, final Link link) {
_links.put(addr, link); _links.put(addr.getAddress().toString(), link);
} }
@Override @Override
protected void unregisterLink(final InetSocketAddress saddr) { protected void unregisterLink(final InetSocketAddress saddr) {
_links.remove(saddr); _links.remove(saddr.getAddress().toString());
} }
/** /**
@ -93,7 +94,7 @@ public class NioServer extends NioConnection {
* @return null if not sent. attach object in link if sent. * @return null if not sent. attach object in link if sent.
*/ */
public Object send(final InetSocketAddress saddr, final byte[] data) throws ClosedChannelException { public Object send(final InetSocketAddress saddr, final byte[] data) throws ClosedChannelException {
final Link link = _links.get(saddr); final Link link = _links.get(saddr.getAddress().toString());
if (link == null) { if (link == null) {
return null; return null;
} }