【问题标题】:Incorrect port number returned by $_SERVER['server_port']$_SERVER['server_port'] 返回的端口号不正确
【发布时间】:2011-05-24 21:51:16
【问题描述】:

场景:我正在使用一些 PHP 开发 Apache Web 服务器。我将浏览器指向 https://my.example.com/test.php,其中包含以下代码行:

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

为 SERVER_PORT 打印的值是 80,而不是 443。但是,如果我转到 https://my.example.com:80/test.php 网络服务器 (Apache) barfs(连接到 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 文档,我认为如果通过 HTTPS 访问 PHP 脚本(这就是我正在做的),它应该设置为非空值。

知道发生了什么吗?我只是 Web 开发人员 - 我不管理此服务器,但我的服务器管理员告诉我一切正常,但我想知道为什么 $_SERVER['SERVER_PORT'] 在查看 HTTPS URL 时返回 80 而不是 443。

编辑:我已经编辑了上面的例子来说明我打印出整个 $_SERVER 变量的结果。

编辑 2: 按照下面 cmets 中的建议尝试 https://my.example.com:443/test.php 会做同样的事情 - SERVER_PORT 为 80 并且未设置 HTTPS(特别是尝试将此 URL 重定向到 https://my.example.com/test.php)。

编辑 3: 好的,我已经在下面发布了我认为的答案(TL;DR:在 VirtualHost 指令中移动 SSL 指令并更改该指令以使用它的 IP 地址而不是通配符似乎已经解决了问题)。

【问题讨论】:

  • 这听起来可能很愚蠢,但我知道 apache 作为反向代理运行并将请求传递给仅在本地接口上运行的 lighttpd 服务器的一种情况
  • 为什么不尝试转储完整的 $_SERVER 变量并在其中搜索(反向)代理标头?
  • 重要的是$_SERVER['HTTPS']...那里的价值是什么?
  • 显然这不是 php 问题,而是与网络服务器有关的问题。你可以在这里找到更多信息:bugs.php.net/bug.php?id=40579
  • @dev-null-dweller - 我没有做类似的事情 - 只是一个普通的 Red Hat/Apache 服务器使用 VirtualHost 来托管几个不同的域。

标签: php ssl


【解决方案1】:

我最近遇到了同样的问题,因为我的一些代码掩盖了同样的问题。

我对问题的诊断如下: 这是 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 包含它的花絮。

我将 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源代码,直到找到了行为的根源。

该行为植根于(至少对于 apached 2.2.23 源代码) 在 dirOfApacheSource/server/core.c 看功能 AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)

在这里您会看到,如果您的 httpd UseCanonicalName 指令设置为“On”,那么端口会从 ServerName 指令中解析出来。当 ServerName 指令的形式不是 ServerName myserver.com:myport number 时,案例代码将获取请求对象的 ap_default_port(apache 人员将其默认设置为 80)。

如果您需要将端口显式添加到 httpd.conf 中的 ServerName 指令而困扰您,您的另一个选择是将 UseCanonicalName 设置为“Off”,这会强制 server/core.c 中的代码解析用于提取服务器名称和端口的 URI 请求。

六个一个,六个另一个,调整您的 apache httpd.conf 文件,您很快就会看到预期的结果。

【讨论】:

  • 如果您设置UseCanonicalName On,您还必须设置UseCanonicalPhysicalPort On 才能获得“真实”端口。
  • 我正在使用在默认端口和 Symfony2 PHP 框架上配置为普通和 TLS 的 Apache。我让 Apache 告诉我它的 http 端口是 443(当然,这是错误的:那是它的 https 端口)。 UseCanonicalPhysicalPort On 解决了我的问题,太胖了+1!! :)
【解决方案2】:

好吧,我想我明白了。我的服务器管理员将 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 指令放入 my.example.com 的 VirtualHost 指令中,要么将 VirtualHost 指令更改为引用实际 IP 地址而不是解决此问题的通配符。感谢大家对此的帮助。

【讨论】:

  • 是的!这对我有用。 IP_ADDRESS 实际上使我的服务器完全失败(服务于服务器的默认站点,而不是我的 VirtualHost)。所以我建议你使用这些设置:&lt;VirtualHost *:443&gt; SSLEngine On SSLCertificateFile /etc/pki/tls/certs/mycert.crt SSLCertificateKeyFile /etc/pki/tls/private/mycert.key SSLCACertificateFile /etc/pki/tls/certs/mycert.ca-bundle 然后运行apachectl restart
【解决方案3】:

我似乎记得几年前我升级我的 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 需要 SSL验证深度 10 SSLCACertificateFile /path/to/apache/conf/trustedpubkeys.crt

祝你好运!

如果您想验证这是否真的发生,请启动像 tcpdump 或 wireshark 这样的嗅探器。对于 tcpdump,我会使用类似 ...

的命令行

tcpdump -i eth0 -nn -s 1600 ip proto 17 和主机 IP_ADDRESS

(其中 IP_ADDRESS 是您的服务器的 fqdn 或虚线四边形)

然后获取您的 $_SERVER var 转储页面,或 phpinfo() 页面等。

您的 $_SERVER var 转储显示了您的远程端口,因此您应该能够看到您的哪些连接使用了该端口,以及它是连接到端口 80 还是 443。

Wireshark 会让你做同样的事情,如果你更喜欢 GUI 人的话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 2022-01-09
    相关资源
    最近更新 更多