Неверный номер порта возвращен $ _SERVER ['server_port'] - PullRequest
16 голосов
/ 13 декабря 2010

Сценарий: Я работаю на веб-сервере Apache с небольшим количеством PHP.Я указываю моему браузеру на https://my.example.com/test.php, в котором есть следующие строки кода:

<code><pre>
<?php
print_r($_SERVER);
?>

Значение, выведенное для SERVER_PORT, равно 80., а не 443 .Но если я зайду на https://my.example.com:80/test.php barfs веб-сервера (Apache) (Произошла ошибка при подключении к my.example.com:80. SSL получил запись, превышающую максимально допустимую длину. Код ошибки: ssl_error_rx_record_too_long).Если я перейду на https://my.example.com:443/test.php, то URL-адрес перенаправляется на https://my.example.com/test.php без ошибок или проблем, за исключением того, что мой PHP распечатывает, что порт сервера 80 вместо 443.

Вот соответствующий раздел из файла conf.d / ssl.conf (я удалил лишние директивы и заменил фактический IP-адрес словом IP_ADDRESS):

Listen IP_ADDRESS:443    
<VirtualHost *:443>
        ServerName my.example.com
        ServerAlias my
        DocumentRoot "/path/to/document_root/htdocs"
        Options +Indexes
</VirtualHost>

Вот полная распечатка переменной $ _SERVER (данные моего сервера отредактированы / изменены на анонимные примеры):

Array
(
    [HTTP_HOST] => my.example.com
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11
    [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    [HTTP_ACCEPT_LANGUAGE] => en-us,en;q=0.5
    [HTTP_ACCEPT_ENCODING] => gzip,deflate
    [HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
    [HTTP_KEEP_ALIVE] => 115
    [HTTP_CONNECTION] => keep-alive
    [HTTP_COOKIE] => PHPSESSID=randomstring_yes_I'm_that_paranoid
    [PATH] => /sbin:/usr/sbin:/bin:/usr/bin
    [SERVER_SIGNATURE] => 
Apache/2.2.3 (Red Hat) Server at my.example.com Port 80


    [SERVER_SOFTWARE] => Apache/2.2.3 (Red Hat)
    [SERVER_NAME] => my.example.com
    [SERVER_ADDR] => IP_ADDRESS_1
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => IP_ADDRESS_2
    [DOCUMENT_ROOT] => /path/to/document_root/htdocs
    [SERVER_ADMIN] => admin@example.com
    [SCRIPT_FILENAME] => /path/to/document_root/htdocs/test.php
    [REMOTE_PORT] => 49178
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    [QUERY_STRING] => 
    [REQUEST_URI] => /test.php
    [SCRIPT_NAME] => /test.php
    [PHP_SELF] => /test.php
    [REQUEST_TIME] => 1292273758
)

Как видите, SERVER_PORT равен 80 и $ _SERVER [«HTTPS»] не установлен.В соответствии с документами по PHP, я думал, что должно быть установлено непустое значение, если доступ к сценарию PHP осуществляется через HTTPS (что я и делаю).

Есть идеи, что происходит?Я просто веб-разработчик - я не управляю этим сервером, но мой администратор сервера говорит мне, что все работает, но я хотел бы знать, почему $ _SERVER ['SERVER_PORT'] возвращает 80 вместо 443 при просмотре URL-адреса HTTPS.

РЕДАКТИРОВАТЬ: Я отредактировал приведенный выше пример, чтобы проиллюстрировать свои результаты при печати всей переменной $ _SERVER.

РЕДАКТИРОВАТЬ 2: Попыткаhttps://my.example.com:443/test.php, как предлагается в комментариях ниже, делает то же самое - SERVER_PORT равен 80, а HTTPS не установлен (в частности, при попытке этого URL-адреса перенаправляется на https://my.example.com/test.php).

РЕДАКТИРОВАТЬ 3: ОК, я опубликовал, как мне кажется, ответ на этот вопрос ниже (TL; DR: перемещение директив SSL в директиве VirtualHost и изменение этой директивы для ссылки на мой сайт с использованием его IP-адреса, а не подстановочного знака, по-видимому, разрешилопроблема).

Ответы [ 3 ]

15 голосов
/ 04 марта 2013

Я только недавно столкнулся с той же проблемой, потому что какой-то код, который маскировал ту же проблему, попал в путь.

Мой диагноз проблемы следующий:в Apache 2.0.Директива Port больше не является частью директив httpd.conf, по существу, разделена между директивами ServerName и Listen.

Так что мой apache httpd.conf (Apache 2.2.23) содержал эти записи

ServerName myservername.com
Listen: 5150

И все же PHP $ _SERVER ['SERVER_PORT'] возвращал 80 всем запросам, сделанным на порту 5150.

Так что, перебирая документы Apache, я обнаружил, что Port является устаревшей директивой и ServerNameего 101 *

Я установил свою директиву servername следующим образом

ServerName myservername.com:5150
UseCanonicalName On
Listen 5150

, и вдруг скрипт php поступил правильно, сообщив _SERVER ['SERVER_PORT'] как 5150.

В качестве альтернативы ваш httpd.conf может читать

ServerName myservername.com
UseCanonicalName Off
Listen 5150

Итак, я копался в исходном коде php (5.3.20) и исходном коде apache, пока не нашел источник поведения.

Корни этого поведения (по крайней мере, для исходного кода 2.2.23) в dirOfApacheSource/server/core.c Посмотрите на функцию AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)

Здесь вы увидите, что если ваша директива httpd UseCanonicalName установленаЕсли значение «Вкл.», то порт анализируется из директивы ServerName.Если директива ServerName не имеет формы ServerName myserver.com:myport номер, код дела извлекает ap_default_port объекта запроса (который любезно установлен по умолчанию равным 80 для людей apache).

ЕслиВас беспокоит необходимость явного добавления порта в директиву ServerName в httpd.conf. Другой вариант - установить для UseCanonicalName значение «Выкл.», что заставляет код в server / core.c анализировать запрос URI для извлечения.имя сервера и порт.

Шесть из одного, полдюжины другого, настройте файл apache httpd.conf, и вскоре вы увидите ожидаемые результаты.

3 голосов
/ 14 декабря 2010

ОК, думаю, я понял это. Администратор моего сервера изменил conf.d / ssl.conf с

SSLEngine On
# and other SSL directives

<VirtualHost *:443>
        ServerName my.example.com
        ServerAlias my

        # and more directives
</VirtualHost>

до

<VirtualHost IP_ADDRESS:443>
        ServerName my.example.com
        ServerAlias my

        SSLEngine On
        # and other SSL directives

        # and more directives
</VirtualHost>

и теперь PHP видит правильный SERVER_PORT # (443), и $ _SERVER ['HTTPS'] также теперь установлен. Поэтому он либо помещал директивы SSL в директиву VirtualHost для my.example.com, либо изменял директиву VirtualHost, чтобы ссылаться на фактический IP-адрес, а не на подстановочный знак, который решил эту проблему. Спасибо всем за помощь в этом.

2 голосов
/ 14 декабря 2010

Кажется, я помню, как это случилось со мной, когда я обновил свой apache пару лет назад. В итоге он оказался плохим SSLCipherSuite, IIRC. В основном убедитесь, что у вас есть полная конфигурация SSL:

У вас есть определенные шифры, сертификат и ключ? А SSLEngine на? Нечто подобное требуется в вашей конфигурации минимально ...

SSLEngine на

SSLCipherSuite ALL:! ADH:! EXPORT56: RC4 + RSA: + HIGH: + MEDIUM: + LOW: + SSLv2: + EXP: + eNULL SSLCertificateFile /path/to/apache/conf/server.crt SSLCertificateKeyFile /path/to/apache/conf/server.key

... и если вы хотите проверить клиентские сертификаты, вам также нужно что-то вроде:

SSLVerifyClient требуют SSLVerifyDepth 10 SSLCACertificateFile /path/to/apache/conf/trustedpubkeys.crt

Удачи!

Если вы хотите убедиться, что это действительно происходит, запустите сниффер, например, tcpdump или wireshark. Для tcpdump я бы использовал командную строку вроде ...

tcpdump -i eth0 -nn -s 1600 ip proto 17 и хост IP_ADDRESS

(где IP_ADDRESS - квадрат или точка с точками вашего сервера)

Затем получите свою страницу дампа $ _SERVER var или страницу phpinfo () и т. Д.

Ваш $ _SERVER var dump показывает ваш удаленный порт, поэтому вы сможете увидеть, какое из ваших подключений использовало этот порт и было ли оно подключено к порту 80 или 443.

Wireshark позволил бы вам сделать то же самое, если вы скорее человек с графическим интерфейсом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...