On 05/17/2016 02:04 PM, Robert Viduya wrote:
We run a cluster of directory servers (4 masters, 2 hubs, 14 slaves)
behind a set of F5 Bigip load balancers. Our Bigip admins recently
decided to switch the boxes to "one-armed" mode and that services
would have to use X-Forwarded-For headers or equivalent to get the
actual client IP address. Obviously, LDAP has no equivalent.
So, I've hacked something together and I'm posting it looking for
feedback. If the stuff is actually usable for other folks, that's
good too.
On the load balancer side, the code is specifically for the F5 Bigips.
But if other load balancers have similar abilities to trigger on
events and can insert binary data into the datastream, it should be
adaptable.
Essentially what I've done is defined a new LDAP Extended Operation
with a payload that's a string containing the source IP address of the
incoming connection. The load balancer sends this LDAP operation as
soon as it opens a connection to the LDAP server, before any other
traffic gets sent. On the directory server side, I've written an
Extended Operation plugin that then logs the string. All we need is
logging, so that's good enough for us. There's room for improvement
there though, like making the address available for IP based ACls
(which we don't use).
In order to insert an LDAP operation into the stream, the code on the
load balancer needs to choose an LDAP message-id that hopefully the
real client isn't going to use. Going on the assumption that the
client will start at 0 and increment up, I had the code insert a
message-id of 0x70000000. I initially thought I'd have to have the
code on the load balancer look for the response message and throw it
away so the client doesn't see it, but I've found that the clients
just seem to ignore it with no ill effects, so I haven't bothered
filtering the response out. The less the code on the load balancer
does, the better.
There's a possibility that the client could send it's own xff extended
operation, but since the load balancer always sends first, we can just
ignore any subsequent log entries.
On the directory server plugin side, I needed to be able to log this
to the access log, not to the error log. The slapi_log_access
function isn't declared in the plugin header file, so I had to declare
it manually.
Here's what our log entries look like now, for both 636 (SSL) and 389
(cleartext before starttls):
[17/May/2016:15:34:22 -0400] conn=230843 fd=156 slot=156 SSL
connection from 130.207.167.12 to 130.207.183.16
[17/May/2016:15:34:22 -0400] conn=230843 op=0 EXT
oid="1.3.6.1.4.1.636.2.11.11.1" name="forwarded-for extended op"
[17/May/2016:15:34:22 -0400] conn=230843 op=0 forwarded for
130.207.167.12
[17/May/2016:15:34:22 -0400] conn=230843 op=0 RESULT err=0 tag=120
nentries=0 etime=0
[17/May/2016:15:34:22 -0400] conn=230844 fd=156 slot=156
connection from 130.207.167.12 to 130.207.183.16
[17/May/2016:15:34:22 -0400] conn=230844 op=0 EXT
oid="1.3.6.1.4.1.636.2.11.11.1" name="forwarded-for extended op"
[17/May/2016:15:34:22 -0400] conn=230844 op=0 forwarded for
130.207.167.12
[17/May/2016:15:34:22 -0400] conn=230844 op=0 RESULT err=0 tag=120
nentries=0 etime=0
We haven't switched our Bigips yet, so the "connection from" line
still shows the actual client IP address.
F5 Bigip code fragments are called "irules" and are written in TCL.
The tar file below contains two different irule files, one for
cleartext streams and one for SSL streams. By SSL streams, I mean
where SSL connections from the client are terminated at the load
balancer and then re-SSLed to the ldap server. Sorry, I'm not writing
the other kind.
This is really nice, and a big help for tracing connections through load
balancers and other similar devices.
Are you interested in contributing this to 389?