NTLM authenticating proxy check script

How-Tos Published on 5 mins Last updated

We do quite a bit of work with web proxy vendors, load balancing multiple web filters/proxies with our appliances and our customers have requested a way of health checking through the proxy when they have NTLM authentication enabled. Always happy to help where we can, I have created a script that will retrieve a web page via your proxy (logging in first of course) if it retrieves it successfully then the program exits with a code 0, if it fails it exits with a code 1. Simple!

This script was designed primarily to be tied into Ldirectord but feel free to adapt it to your needs, and if you do make changes dont be a stranger post your adaptations below!

I wrote it in bash as we weren't sure it was even possible (always good to start simple) but if it becomes a permanent option in our loadbalancer I might have another crack at it and use something like python and make the script a bit more robust, which I will of course add to this blog entry.

Right onto the good bit - Our tests were run on a 2003 domain with a popular web filter (probably best not to mention the name of the company as im about to be mean). Why did you not test with a 2008 domain  controller I hear you ask??? We used an entire day testing with 2008 trying everything we could think of to get the NTLM authentication working via the proxy but to no avail. Things were thrown, puppies threatened and Im pretty sure our windows engineer was about to go on a killing spree at one point. What exasperated the issue was that unlike our loadbalancer we didnt have root access to the appliance so we couldnt check anything and there were NO LOGFILES viewable from the user interface so it was literally a process of trial and error until we found the solution. NO LOGFILES!!!! WHO LIVES LIKE THAT!!!!!

Now hindsight being a wonderful thing we should have given up at this point and tried another proxy but we didn't we persevered and eventually came to using a 2003 domain controller (which worked first time). I'm mentioning this as clearly something has changed between 2003 and 2008 which might mean that this script wont work with a 2008 domain controller. But it should be easy enough to test (if you have a working setup) just run the curl command included in this script.

As it was designed to be used with Ldirectord the script expects it to be run with the following parameters - virtual ip port real ip port so to run it from the command line enter:

./http_ntlm_proxy_check.sh  vip port rip port 

The rip ip and port  number  should be that of your proxy server, and you can set the vip and port number as anything you like, as I said before its designed for Ldirectord so those are the values that get passed to it when its running the check.

An additional option I added is that some times when the NTLM authentication service was disabled the proxy would still return a webpage, it was an error message but as far as curl was concerned it was still a page. Which ment that curl exited with a status code of zero instead of failing to retrieve the page (all will become clear when I post the code below) So you can add a search string so that it looks for something on the page that curl returns. For our test proxy it returned "Authentication failed" so I greped the output of curl for that and if it was found the check would be deemed a failure.

Here's the code - Hopefully if I have written it well it should be fairly self explanatory:

#Script to check ntlm authentication is still running via a web proxy by logging in with ntlm and attempting
#to grab a page via the proxy.
#user defined variables
#the next variable is where it gets complicated some proxies return an authentication failed page when the ntlm service is not responding so curl exits with a code
#of zero as a page was returned  theoretically passing the check. So you can set this value for something that is returned on the page that would indicate to you that the check has failed, this can be disabled by setting the variable $PAGE_CHECK to 0
STRING_TO_CHECK_FOR="Authentication failed"
#specify the proxy server as virtual_ip and virtual_port so when this is sent from ldirectord it will query your vip.
#on calling the script you can ignore the real server bit its not important
#but ldirectord will still pass it so its best to accept it

#Command Line Parameters

#program starts

CURL_OUTPUT=$(curl -s 0 --proxy-ntlm --proxy-user $DOMAIN$USERNAME:$PASSWORD --url $WEB_PAGE --proxy $REAL_IP:$REAL_PORT)
if [ "$?" -eq "0" ]; then
if [ $PAGE_CHECK -eq "1" ]; then
echo "$CURL_OUTPUT" | grep "$STRING_TO_CHECK_FOR" >> /dev/null
if [ "$?" -eq "0" ]; then

# set the exiting return code

You can also download the code from -https://github.com/loadbalancer-org/ntlm_proxy_auth_check

Any problems let us know.


p.s if you wish to get this working with our load balancer you need to configure the following -

Upload the http_ntlm_proxy_check.sh script to your loadbalancer, put it in /etc/loadbalancer.org then dont forget to chmod +x it to make it executable

Global Options Layer 4 -

You need to increase the Check Timeout as the curl command can take some time to execute, this is exasperated if you are checking a page on the public internet. Ive currently got my test set to 30 seconds but you might be able to use lower, a bit of tuning will be required (note this will also effect the timeout of your other health checks).

Then after you have added your virtual IPs and your real servers go back to the virtial ip configuration and change the Check Type to external and the check port to none.

In the Check Command box enter the location of the script in this case it's /etc/loadbalancer.org/http_ntlm_proxy_check.sh then hit update and your servers should go green. Feel free to test by forcing a failure. As a simple test I just changed the username and password so it was incorrect.

For those of you not using our product but still interested in using this script with ldirectord here's the configuration -

# Ldirectord configuration file generated by load balancer appliance
# Global options
virtual= gate VIP_Name
real= gate 1 "check.txt","OK" RIP_Name 0 0
fallback= gate