[MINOR] checks: add support for LDAPv3 health checks

This patch provides a new "option ldap-check" statement to enable
server health checks based on LDAPv3 bind requests.
(cherry picked from commit b76b44c6fed8a7ba6f0f565dd72a9cb77aaeca7c)
This commit is contained in:
Gabor Lekeny 2010-09-29 18:17:05 +02:00 committed by Willy Tarreau
parent b824b002cd
commit b4c81e4c81
5 changed files with 101 additions and 1 deletions

View File

@ -898,6 +898,7 @@ option httpclose (*) X X X X
option httplog X X X X
option http_proxy (*) X X X X
option independant-streams (*) X X X X
option ldap-check X - X X
option log-health-checks (*) X - X X
option log-separate-errors (*) X X X -
option logasap (*) X X X -
@ -3120,6 +3121,29 @@ no option independant-streams
See also : "timeout client" and "timeout server"
option ldap-check
Use LDAPv3 health checks for server testing
May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes
Arguments : none
It is possible to test that the server correctly talks LDAPv3 instead of just
testing that it accepts the TCP connection. When this option is set, an
LDAPv3 anonymous simple bind message is sent to the server, and the response
is analyzed to find an LDAPv3 bind response message.
The server is considered valid only when the LDAP response contains success
resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9).
Logging of bind requests is server dependent see your documentation how to
configure it.
Example :
option ldap-check
See also : "option httpchk"
option log-health-checks
no option log-health-checks
Enable or disable logging of health checks

View File

@ -118,6 +118,7 @@
#define DEF_RISETIME 2
#define DEF_CHECK_REQ "OPTIONS / HTTP/1.0\r\n"
#define DEF_SMTP_CHECK_REQ "HELO localhost\r\n"
#define DEF_LDAP_CHECK_REQ "\x30\x0c\x02\x01\x01\x60\x07\x02\x01\x03\x04\x00\x80\x00"
#define DEF_HANA_ONERR HANA_ONERR_FAILCHK
#define DEF_HANA_ERRLIMIT 10

View File

@ -139,6 +139,7 @@
#define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */
#define PR_O2_SSL3_CHK 0x00100000 /* use SSLv3 CLIENT_HELLO packets for server health */
#define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with server eventhough we close */
#define PR_O2_LDAP_CHK 0x00400000 /* use LDAP check for server health */
/* end of proxy->options2 */
/* bits for sticking rules */

View File

@ -2748,6 +2748,7 @@ stats_error_parsing:
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options |= PR_O_HTTP_CHK;
if (!*args[2]) { /* no argument */
curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
@ -2779,6 +2780,7 @@ stats_error_parsing:
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options2 |= PR_O2_SSL3_CHK;
}
else if (!strcmp(args[1], "smtpchk")) {
@ -2788,6 +2790,7 @@ stats_error_parsing:
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options |= PR_O_SMTP_CHK;
if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
@ -2814,8 +2817,23 @@ stats_error_parsing:
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options2 |= PR_O2_MYSQL_CHK;
}
else if (!strcmp(args[1], "ldap-check")) {
/* use LDAP request to check servers' health */
free(curproxy->check_req);
curproxy->check_req = NULL;
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options2 |= PR_O2_LDAP_CHK;
curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
}
else if (!strcmp(args[1], "forwardfor")) {
int cur_arg;

View File

@ -743,7 +743,8 @@ static int event_srv_chk_w(int fd)
if ((s->proxy->options & PR_O_HTTP_CHK) ||
(s->proxy->options & PR_O_SMTP_CHK) ||
(s->proxy->options2 & PR_O2_SSL3_CHK) ||
(s->proxy->options2 & PR_O2_MYSQL_CHK)) {
(s->proxy->options2 & PR_O2_MYSQL_CHK) ||
(s->proxy->options2 & PR_O2_LDAP_CHK)) {
int ret;
const char *check_req = s->proxy->check_req;
int check_len = s->proxy->check_len;
@ -866,6 +867,7 @@ static int event_srv_chk_r(int fd)
struct server *s = t->context;
char *desc;
int done;
unsigned short msglen;
if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) {
/* in case of TCP only, this tells us if the connection failed */
@ -1024,6 +1026,60 @@ static int event_srv_chk_r(int fd)
set_server_check_status(s, HCHK_STATUS_L7STS, desc);
}
}
else if (s->proxy->options2 & PR_O2_LDAP_CHK) {
if (!done && s->check_data_len < 14)
goto wait_more_data;
/* Check if the server speaks LDAP (ASN.1/BER)
* http://en.wikipedia.org/wiki/Basic_Encoding_Rules
* http://tools.ietf.org/html/rfc4511
*/
/* http://tools.ietf.org/html/rfc4511#section-4.1.1
* LDAPMessage: 0x30: SEQUENCE
*/
if ((s->check_data_len < 14) || (*(s->check_data) != '\x30')) {
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
}
else {
/* size of LDAPMessage */
msglen = (*(s->check_data + 1) & 0x80) ? (*(s->check_data + 1) & 0x7f) : 0;
/* http://tools.ietf.org/html/rfc4511#section-4.2.2
* messageID: 0x02 0x01 0x01: INTEGER 1
* protocolOp: 0x61: bindResponse
*/
if ((msglen > 2) ||
(memcmp(s->check_data + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
goto out_wakeup;
}
/* size of bindResponse */
msglen += (*(s->check_data + msglen + 6) & 0x80) ? (*(s->check_data + msglen + 6) & 0x7f) : 0;
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
* ldapResult: 0x0a 0x01: ENUMERATION
*/
if ((msglen > 4) ||
(memcmp(s->check_data + 7 + msglen, "\x0a\x01", 2) != 0)) {
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
goto out_wakeup;
}
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
* resultCode
*/
s->check_code = *(s->check_data + msglen + 9);
if (s->check_code) {
set_server_check_status(s, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
} else {
set_server_check_status(s, HCHK_STATUS_L7OKD, "Success");
}
}
}
else {
/* other checks are valid if the connection succeeded anyway */
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);