cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
6554
Views
20
Helpful
9
Replies

ACE 4710 LDAP probe

andrels
Level 1
Level 1

Folks,

We'll be adding a farm this weekend to do some kind of balance for LDAP and LDAPs servers.

I've been thinking about what would be the best way to probe that servers.

I assume an generic TCP probe has to be created testing 389 and 636, but i honestly don't know what should i expect coming from the real servers.

Does anyone have a LDAP farm in place or something like that.. ? I've found an script on the internet, but it seems a little bit further that what i can understand.. therefore i'm not really confident to use this.

Thanks for any advices.

Andre

9 Replies 9

ciscocsoc
Level 4
Level 4

Hi Andre,

The ACE comes with some sample probe scripts - one of which tests LDAP by performing an anaonymous bind.  I've written elsewhere in this forum (https://supportforums.cisco.com/message/458388#458388
https://supportforums.cisco.com/message/461739#461739) about how to modify the script to use non-anonymous credentials. You need to create a copy of the provided script, modify the mysterious hex sequence which is ASN.1 formatted, re-import the script and then reference it.

To help with creating magic hex strings I whipped up a small PERL script:

#
# Prepare an ASN.1 BER encoded string to do an LDAP Bind with
# username and password.
#
#

$username = "cn=AceHealthCheck,o=something";
$password = "somethingssecret";

$len_username = length($username);
$xlen_username = sprintf("%02x", $len_username);
$len_password = length($password);
$xlen_password = sprintf("%02x", $len_password);

$username =~s/(.)/sprintf("%x",ord($1))/eg;
$password =~s/(.)/sprintf("%x",ord($1))/eg;

$temp = "020103" . "04" . $xlen_username . $username . "80" . $xlen_password . $password;
$tlen = length($temp) / 2;
$xtlen = sprintf("%02x",$tlen);

$temp = "020101" . "60" . $xtlen . $temp;

$tlen = length($temp) / 2;
$xtlen = sprintf("%02x",$tlen);

$temp = "30" . $xtlen . $temp;

print $temp . "\n";

Not pretty or elegant but it does the job.

Note that if you're using Active Directory as the LDAP server then you'll either need to enable anonymous bind and you'll need to modify the script code that looks for the return code as AD uses the extended length encoding mechanism of ASN.1.

There is no easy way of checking LDAPS beyond a simple TCP probe to check that the port is open and can complete a three-way handshake.

Hope this helps

Cathy

sachinga.hcl
Level 4
Level 4

Hi Andre,

You can use scripted ldap probe (LDAP_PROBE) available with ACE. It sends an anonymous bind request and check for bind success.


probe tcp LDAPS_Probe
  port 636
probe tcp LDAP_Probe
  port 389



This is how you can apply the script for LDAP port 389.

script file 1 LDAP_PROBE
!
probe scripted LDAP_PROBE_389
interval 5
passdetect interval 30
receive 5
script LDAP_PROBE

!

serverfarm host SF-LDAP-389
description SF LDAP Port 389
predictor leastconns
probe LDAP_PROBE_389
rserver LDAP-RS1-389
inservice

----------

The only supported LDAP probe on the ACE module is the unsecure scripted probe,

http://www.cisco.com/en/US/docs/interfaces_modules/services_modules/ace/vA2_3_0/configuration/slb/guide/script.html#wp1111558

-------

The pre-made TCL script probes available from the Software download page also contains an LDAP probe that you can use to verify the health of the LDAP servers.


The ace_scripts.tgz zip file contains these scripts and is located at this URL:

http://www.cisco.com/pcgi-bin/tablebuild.pl/cat6500-ace

To unzip this file, use the gunzip command in Exec mode,

http://www.cisco.com/en/US/docs/app_ntwk_services/data_center_app_services/ace_appliances/vA1_7_/configuration/slb/guide/script.html#wp1107470

For your convenience, the following sample scripts for the ACE are available to support the TCL feature and are supported by Cisco TAC:

•CHECKPORT_STD_SCRIPT

•ECHO_PROBE_SCRIPT

•FINGER_PROBE_SCRIPT

•FTP_PROBE_SCRIPT

•HTTP_PROBE_SCRIPT

•HTTPCONTENT_PROBE

•HTTPHEADER_PROBE

•HTTPPROXY_PROBE

•IMAP_PROBE

•LDAP_PROBE -----------------> "The LDAP probe you are looking for"

•MAIL_PROBE

•POP3_PROBE

•PROBENOTICE_PROBE

•RTSP_PROBE

•SSL_PROBE_SCRIPT

•TFTP_PROBE


-------------


Also remember that the binding request should be send as a binary and not via ASCII. To get a packet capture of a succeessful credential binding request with username and password and then convert this to HEX value and insert it in the script.

The easiest way is to capture a packet with the authentication credentials and then replace the hex bind string in the example.


The alternative is to handcode the BER coded ASN.1 data string - which while more fun is time consuming. The remainder of the script can stay the same.


You can do this on an ACE module. You have to be aware that 300c02010160 in the example script string is a sort of "header" that holds the request id (1). This will be different in your packet capture.


If you look at the decomposition of the example you'll be able to see how it is put together and what you need to change.


0x30 The start of a universal constructed sequence

0x0c The length of the sequence minus the tag and length bytes = 12 bytes

0x02 Next field is an integer

0x01 The length of the next field (1 byte)

0x01 Value (this is the message ID)

0x60 Application, number 0, use RFC2251 to decode. This is a Bind Request

0x07 Length of data to follow.

0x02 Integer

0x01 Length 1

0x03 3 - this is the LDAP version.

0x04 String

0x00 Length 0

0x80 Simple Authentication

0x00 Length 0



Just keep the id the same in the unbind.


The string I use is:

302d02010160280201030418636e3d41636550726f78792c6f3d556e69766572736974798009ffffffffffffffffff


where I've replaced the 9 character password with 9*x'ff'.


The username for binding is AceProxy.  If you want to use the same script then create that username and set the password in the string above (in hex).  If for example you set the password to Example12 then you need to set the 9*x'ff' to '4578616d706c653132' - which is the hex representation of the ASCII.


Note that if you use fewer or more than 9 characters then you'll need to change other values in the string because they refer to lengths.


--
You need to create a copy of the standard LDAP probe into your own file and then replace the hex string in the "puts" line which you identified above with the new string.


Then copy the file to the ACE:


ace1/ldap# copy ftp: disk0:

Enter source filename[]? My-LDAP_PROBE

Enter the destination filename[]? [My-LDAP_PROBE]

Enter hostname for the ftp server[]?

1.2.3.4

Enter username[]? anonymous

Enter the file transfer mode[bin/ascii]: [bin]

Password:

Passive mode on.

Hash mark printing on (1024 bytes/hash mark).

##



In the context create a scripted probe definition:


probe scripted PROBE-LDAP-389

  interval 60

  receive 20

  script My-LDAP_PROBE


Load the script into the context:


script file 10 My-LDAP_PROBE


And then add it to the serverfarm:


serverfarm host FARM-LDAP

  probe PROBE-LDAP-389



The manual implies that you can pass arguments to a scripted probe, but you would then have to build the hex string dynamically - taking care that all the length values were correct.


This should be enough to enable you to implement the script.


-----------------

Find another example on this

URL:http://scuq.abyle.org/?page_id=201

#!name = ADV_LDAP_PROBE
################################################################################
########
#### > user for linux tclsh !/usr/bin/tclsh8.4
# Stefan Nistelberger
# changes to cisco's original probe
# * username and password with ldap simple bind (dynamically generated packets)
# * unable to connect exception handling
# * debug message for invalidCredentials
#-------------------------------------------
# debug procedure
# set the EXIT_MSG environment variable to help debug
# also print the debug message when debug flag is on
#-------------------------------------------

proc ace_debug { msg } {
    global debug ip port EXIT_MSG

    set EXIT_MSG $msg
    if { [ info exists ip ] && [ info exists port ] } {
        set EXIT_MSG "[ info script ]:$ip:$port: $EXIT_MSG "
    }
    if { [ info exists debug ] && $debug } {
        puts $EXIT_MSG
    }
}

#-------------------------------------------
# main
#-------------------------------------------

# parse cmd line args and initialize variables
## set debug value
set debug 1
if { [ regsub -nocase "DEBUG" $argv "" argv] } {
    set debug 1
}

ace_debug "initializing variable"
set EXIT_MSG "Error config:  script ADV_LDAP_PROBE \[DEBUG\]"

set ip $scriptprobe_env(realIP)
set port "0"

set ldap_start "30"
set ldap_bindheader "02010160"
set ldap_bind "0201"
set ldap_version "02"
set ldap_gap1 "04"
set ldap_gap2 "80"

set ldap_bindheader_len 5
set base_len 0c

set ldap_simple_auth "8007"

proc toASCII { char } {
   scan $char %c value
   return [format %-x $value]
}

set username [ lindex $argv 0 ]
set hexusername ""

set password [ lindex $argv 1 ]
set hexpassword ""

foreach char [split $username ""] {
     set hexchar [toASCII $char]
     append hexusername $hexchar
}

foreach char [split $password ""] {
     set hexchar [toASCII $char]
     append hexpassword $hexchar
}

set username_len [string length $username]
ace_debug $username_len

set password_len [string length $password]
ace_debug $password_len

set base_len [expr 0x$base_len]

set seq_len [expr $username_len + $password_len + $base_len]

set sub_seq_len [expr $seq_len - $ldap_bindheader_len]
set seq_len [format %02x $seq_len]
set sub_seq_len [format %02x $sub_seq_len]

set hexldapbindpckt ""
append hexldapbindpckt $ldap_start
append hexldapbindpckt "$seq_len"
append hexldapbindpckt $ldap_bindheader
append hexldapbindpckt $sub_seq_len
append hexldapbindpckt $ldap_bind
append hexldapbindpckt $ldap_version
append hexldapbindpckt $ldap_gap1
append hexldapbindpckt [format %02x $username_len]
append hexldapbindpckt $hexusername
append hexldapbindpckt $ldap_gap2
append hexldapbindpckt [format %02x $password_len]
append hexldapbindpckt $hexpassword

# if port is zero the use well known ldap port 389
if { $port == 0 } {
    set port 389
}
#ace_debug $hexldapbindpckt

#####################
# PROBE START
#####################

set errorcode [catch {
        set sock [ socket $ip $port ]
} msg ]
if {$errorcode != 0} {
        ace_debug $msg
        exit 30002
}

fconfigure $sock -buffering line -translation binary

# anonymous bind request
#puts -nonewline $sock [ binary format "H*" 300c020101600702010304008000 ]

puts -nonewline $sock [ binary format "H*" $hexldapbindpckt ]

set code "ffffff"
flush $sock
ace_debug "bef"
set line [read $sock 22]
ace_debug "aft"
binary scan $line H* res
binary scan $line @15H6 code
close $sock

#  make probe fail by exit with 30002 if ldap reply code != success code  0x0a0100
if {  $code != "0a0100" } {
    if {  $code == "0a0131" } {
        ace_debug " probe failed : expect response code \'0a0100\' but received
\'$code\' = invalidCredentials"
    } else {
        ace_debug " probe failed : expect response code \'0a0100\' but received
\'$code\'"
    }
    exit 30002
}

## make probe success by exit with 30001
ace_debug "probe success"
exit 30001

--------------------

URL for reference:

https://cisco-support.hosted.jivesoftware.com/thread/132800?decorator=print&displayFullThread=true

HTH

Sachin Garg

Hi Andre,

Kindly update the status. If your issue resolved.

Kind Regards,

Sachin Garg

Hi Sachinga,

I'm still trying to get all teams together to implement this.. the server team put this on hold for now.. and we won't be able to execute this change until the end of this year.

Anyways.. Thanks for your help.

Regards,

Hi,

I wanted to post about my experiences in getting this probe to work with Active Directory using credentials. I did not use the Perl script to generate the HEX string for the probe, but did a capture of LDAP traffic on the ACE appliance instead.

I had to copy the capture to disk0: before copying it to my PC in order to open it in Wireshark. In Wireshark, I copied the LDAP bind request as HEX and replaced the HEX value in the LDAP_PROBE script (in puts -nonewline $sock [ binary format "H*" HEXSTRINGINSERTEDHERE ])

I also had to change the script code related to the response because Active Directory did not have the "0a0100" response at the same offset. So I changed:

#  read string back from server
ace_debug "receiving ldap bind result"
set line [read $sock 14]
binary scan $line H* res
binary scan $line @7H6 code
ace_debug "recived $res with code $code"

To:

#  read string back from server
ace_debug "receiving ldap bind result"
set line [read $sock 22]
binary scan $line H* res
binary scan $line @15H6 code
ace_debug "recived $res with code $code"

And now the probe works towards Active Directory using a username and password!

Hello Erik,

can you help me little bit with the resolution? What that individual parameters mean and how did you get to those. I assume it's position where to read the string and what to expect, but could you translate it to someone like me?

Thank you

Hi Michal,

Time flies, it's been 5 years since I made that post. I tried to figure it out again, but I just don't have the time to do it. You are right though, the @15H6 is the offset where the scan should begin, and the response the scan is looking for is "0a0100".

So if the offset is wrong, the script won't find the "0a0100" code, that's what you're looking for.

No worries Erik,

update - so it's not really "kosher" solution, but here is how you can trick it with regex search instead of exact position search. Hope this helps someone else.

#read 20B from the sock to the line variable

set line [read $sock 20]

#convert it to the hexa mode and into res variable
binary scan $line H* res

#predefine success respond

set suc 0a0100

#find suc in the res variable, return 30001 if found

if { [regexp -nocase $suc $res match] } {
 exit 30001
} else {
 exit 30002
}

Hi Sachin,

I am facing the some problem...when I tried to config probe with TCP port the SF getting error PROBE_FAILED on port 389 and 636.

Probe tcp VIS_389
port 389

Probe tcp VIS_636
port 636


But when I do UDP the SF is up...Operational.

Also without probe on single port 389 its working config below:

serverfarm host VIS_389
rserver VIS1 389
inservice
rserver VIS2 389
inservice

Regards

Darshan P