openSSL无法与PHP内置Web服务器配合使用

28

操作系统:Ubuntu 12.04 64位

PHP版本:5.4.6-2~precise+1

当我通过内置的Web服务器(php5 -S localhost:8000)测试自己编写的https页面时,Firefox(16.0.1)显示“问题加载:连接中断”,而终端则告诉我“::1:37026无效请求(不支持的SSL请求)”。

phpinfo() 告诉我:

  • 注册的流套接字传输:tcp,udp,unix,udg,ssl,sslv3,tls
  • [curl] SSL:是
  • SSL版本:OpenSSL / 1.0.1
  • openssl:

    OpenSSL支持:启用

    OpenSSL库版本 OpenSSL 1.0.1 14 Mar 2012

    OpenSSL头版本 OpenSSL 1.0.1 14 Mar 2012

是的,http页面运行良好。

有什么想法吗?


1
可能应该在ServerFault上发布。 - quantum
不完全是您想要的,但您可以尝试使用ngrok。https://dev59.com/r2855IYBdhLWcg3wpmHw#23243958 - Pacerier
4个回答

49

请参考手册中有关内置 Web 服务器的部分:
http://php.net/manual/zh/features.commandline.webserver.php

它不支持 SSL 加密,只能用于普通的 HTTP 请求。与此无关的是 openssl 扩展和函数的支持情况。它不接受基于流包装器的请求或发送响应。

如果您想在其上运行 SSL,请尝试使用 stunnel 包装器:

php -S localhost:8000 &   
stunnel3 -d 443 -r 8080  

反正这只是用来玩的。


1
一个人在哪里可以找到带有这些选项的stunnel版本?根据stunnel.org上的文档,那里提供的应用程序不支持“-d”或“-r”选项。 - Mr. Lance E Sloan
1
使用stunnel3。看起来stunnel4主要作为守护进程/通过iptables运行,并需要配置文件。 - mario
2
@Pacerier,这仍然是最简单设置的选项。对于测试,mitmproxy可能是一个不错的替代品。而对于长期的设置,Tinyproxy或者只用普通的Apache + mod_proxy来转发HTTPs到PHP的服务器也OK。 - mario
7
关于上面的代码(php -S localhost:8000 &; stunnel3 -d 443 -r 8080)stunnel3命令似乎将端口443的https请求重定向到端口8080,而php命令似乎提供对端口8000的请求。stunnel3命令应该重定向到端口8000吗? - MgFrobozz
5
我需要执行以下命令:openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem && sudo mv stunnel.pem /etc/stunnel && sudo stunnel3 -p /etc/stunnel/stunnel.pem -d 443 -r 8000。执行该命令后,将生成一个名为stunnel.pem的文件并将其移动到/etc/stunnel目录下,然后使用sudo stunnel3命令将本地端口443与远程端口8000进行绑定。 - Jacek Kobus
显示剩余5条评论

11

距离上一次更新已经过去了三年,以下是我如何在2021年在macOS上使其工作的方式(作为对mario答案的扩展):

# Install stunnel
brew install stunnel

# Find the configuration directory
cd /usr/local/etc/stunnel

# Copy the sample conf file to actual conf file
cp stunnel.conf-sample stunnel.conf

# Edit conf
vim stunnel.conf

修改 stunnel.conf 文件,使其像这样: (可以删除所有其他选项)

; **************************************************************************
; * Global options                                                         *
; **************************************************************************

; Debugging stuff (may be useful for troubleshooting)
; Enable foreground = yes to make stunnel work with Homebrew services
foreground = yes
debug = info
output = /usr/local/var/log/stunnel.log

; **************************************************************************
; * Service definitions (remove all services for inetd mode)               *
; **************************************************************************

; ***************************************** Example TLS server mode services

; TLS front-end to a web server
[https]
accept = 443
connect = 8000
cert = /usr/local/etc/stunnel/stunnel.pem
; "TIMEOUTclose = 0" is a workaround for a design flaw in Microsoft SChannel
; Microsoft implementations do not use TLS close-notify alert and thus they
; are vulnerable to truncation attacks
;TIMEOUTclose = 0

这个配置接受 HTTPS / SSL 的 443 端口连接,并连接到本地运行在 8000 端口的 Web 服务器,使用 stunnel 默认的伪证书位于 /usr/local/etc/stunnel/stunnel.pem。日志级别为 info,并将日志输出写入 /usr/local/var/log/stunnel.log

启动 stunnel:

brew services start stunnel # Different for Linux

启动Web服务器:

php -S localhost:8000

现在你可以访问https://localhost:443 来访问你的web服务器:截图

会出现证书错误,你需要点击浏览器警告,但这样你就可以使用HTTPS请求来访问你的本地服务器进行开发了。


4
非常感谢你的答案,真是救命稻草。小补充:对于m1 / Apple Silicon Macs,stunnel配置文件似乎位于“/opt/homebrew/etc/stunnel”下面。 - timotgl

2

最近我在学习nginx和Laravel,但是遇到了很多错误。要诊断问题很难,因为你需要同时调整nginx和Laravel以及操作系统中的SSL设置(假设你正在制作自签名证书)。

如果你使用Windows,那么情况会更加困难,因为处理SSL证书时必须处理unix回车符。有时候你可以正确地执行步骤,但是却由于证书验证问题而失败。我发现诀窍是在Ubuntu或Mac上创建证书,然后将它们发送给自己,或者使用Linux子系统。

在我的情况下,我一直遇到一个问题,即在某个地方声明了HTTPS,但是php artisan serve只能使用HTTP

即使SSL已经连接好,我仍然再次引起了Invalid request (Unsupported SSL request)错误。原来是我在使用Axioshttps://发出POST请求。将其更改为POST http://即可解决。

我向任何人推荐的建议是查看HTTP/HTTPS的使用位置和方式。

教科书式的定义可能是php artisan serve只能通过HTTP工作,但需要底层SSL层。


2

使用Ngrok

  1. 像这样公开您的服务器端口: ngrok http <服务器端口>

  2. 使用ngrok的安全公共地址(https)进行浏览。

注意:虽然它可以完美地工作,但似乎有些过度,因为它需要互联网,希望能提供更好的建议。


1
对我来说,这是一个好主意,很实用。已点赞。 - CalfCrusher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接