LDAP Java client hangs after some time of inactivity

Feb 26, 2017

(aka the half-closed connection problem)

The problem described in this page can affect not only LDAP clients but also several other kind of network applications. I’m explaining this issue using LDAP as example because this can easily happen with LDAP Java clients, due to default settings used by standard classes.

So, if you are here, probably you have just set up a web application that uses a Java library to connect to an LDAP server and all seems working good… but when you access again that application some hours later it remains stuck for 15 endless minutes!

Ok, don’t panic. There is a firewall between you and the LDAP server? I think so.

It’s a very common issue, when you are behind a NAT proxy or a firewall, to be disconnected without a reason. This behavior is caused by the connection tracking procedures implemented in proxies and firewalls, which keep track of all connections that pass through them. Because of the physical limits of these machines, they can only keep a finite number of connections in their memory. The most common and logical policy is to keep newest connections and to discard old and inactive connections first.

How to solve the problem

Basically, the solution is to set up a proper keep alive on the connection. You have 3 options:

1. Check your library settings

If you are using a good library it probably supports some keep alive settings. RTFM

2. Modify the source

A typical way to create an LDAP client is passing to the InitialDirContext constructor a Hashtable with the desired settings

Note the client has timer “off” while the server has it set on “keepalive”.

Let’s do a joke to our poor client, adding this rule to the server firewall:

iptables -A OUTPUT -p tcp --sport 389 -j DROP

Now, if we shutdown the LDAP server it will send a FIN, ACK TCP packet to properly close its connection, but that packet will be dropped by the firewall and the client will never see it. This create a “half-closed connection”: the server has closed it but the client still sees it in the ESTABLISHED state.

This is what it can be seen using Wireshark when the client makes a new request:

A long sequence of TCP Retransmission packets that can last up to 15 minutes. According to Linux TCP manual this should depend by tcp_retries2 settings:

The maximum number of times a TCP packet is retransmitted in established state before giving up. The default value is 15, which corresponds to a duration of approximately between 13 to 30 minutes, depending on the retransmission timeout.