Поэтому я сократил свою проблему до простого сценария PHP
test.php
<?php
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); //for logging
if($con = ldap_connect( 'ldaps:domain.com', 636 )){
$bind_return = ldap_bind($con, 'username', 'super_secret_password');
}
?>
Когда я иду в localhost\test.php
браузер указывает, что он ожидает ответа и просто зависнет там …. навсегда (точнее, пока я не остановлю его, иногда через час, но вы поняли). Используя xdebug, я могу точно определить зависание ldap_bind()
вызов. Когда я пытаюсь перешагнуть или в строку кода ldap_bind (), мой xdebug зависает и перестает отвечать на запросы.
Зарегистрированный вывод из ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
является:
ldap_create
ldap_url_parse_ext(domain.com)
ldap_bind_s
ldap_simple_bind_s
ldap_sasl_bind_s
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP domain.com:636
ldap_new_socket: 15
ldap_prepare_socket: 15
ldap_connect_to_host: Trying domain.com:636
ldap_pvt_connect: fd: 15 tm: -1 async: 0
А потом ничего после этого. Я не уверен, что с этим делать, и Google не был добрым.
ldap_connect()
успешно, возвращение что-то вроде (resource) resource id='2' type='ldap link'
, max_execution_time
НЕ прерывает выполнение скрипта. Если я поставлю что-то вроде while(true){}
перед проблемной строкой кода, то max_execution_time
сработает и я увижу ошибку. Так ldap_bind()
каким-то образом даже останавливает среду php от тайм-аута. Обертывание кода в блоке try / catch никак не облегчает зависание.
Я пытался:
1) Перезагрузка сервера много, много раз
2) Переустановка php5, php-ldap, libapache2-mod-php5 и apache2
3) прочесывать интернет
Самое смешное ldap_bind()
Несколько недель назад он отлично работал, он все еще отлично работает на моей производственной площадке, но я уже давно пытаюсь это выяснить, и я так близок к тому, чтобы зажечь мой компьютер в огне. Любая помощь приветствуется.
ОБНОВИТЬ:
Поэтому я установил ldap-utils и запустил ldapsearch -H ldaps://domain.com
и повесил. Я запустил его с опцией отладки ldapsearch -d 1 -H ldaps://domain.com
и вывод был:
ldap_url_parse_ext(ldaps://domain.com/)
ldap_create
ldap_url_parse_ext(ldaps://domain.com:636/??base)
ldap_pvt_sasl_getmech
ldap_search
put_filter: "(objectclass=*)"put_filter: simple
put_simple_filter: "objectclass=*"ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP domain.com:636
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying domain.com:636
ldap_pvt_connect: fd: 3 tm: -1 async: 0
^^^^It hangs right here^^^^
Кажется знакомым, нет? Выполнение команды strace для всей команды приводит к длинной трассировке, но в этот момент зависает
write(3, "\26\3\0\0p\1\0\0l\3\3T\254/\31\24\200\25 \247\221\7\251\240\271\35\"\272\203V \305"..., 117) = 117
read(3,
Опять же, он висит прямо здесь, курсор просто мигает после «read(3,
«
Я наткнулся этот отчет об ошибке с openldap, который жутко идентичен моей собственной проблеме, вплоть до strace, висящего по команде чтения. Тем не менее, похоже, что обсуждение решений не ведется, поскольку openldap указывает пальцем на gnuTLS.
Похоже, это что-то экологическое. Это может быть изменение брандмауэра, изменение сетевого маршрута, истечение срока действия сертификата SSL, изменение на сервере LDAP и т. Д.
Я бы выполнил серию диагностических протоколов, работающих со стеком ISO.
Начните с telnet на порт 636 на удаленном сервере. Если это работает, загрузите openldap и сделайте это. Посмотрите, можете ли вы вручную подключиться к этому. Если это работает, запустите вашу отладочную версию в производственном режиме (из командной строки) и посмотрите, что будет следующим шагом после ldap_pvt_connect. Кроме того, попробуйте версию командной строки, у вас есть более ограниченный контроль над вещами, и у вас нет веб-сервера в миксе.
У меня была такая же проблема, которая сводилась к брандмауэру. Демон slapd работает на том же сервере, что и веб-сервер, поэтому мне нужно было либо указать «localhost» вместо «domain.com» при вызове ldap_connect (), либо добавить соответствующее правило в таблицу фильтров ядра, чтобы специально разрешить соединение на сервер со своего IP-адреса.