Nginx/Apache实现非标准(80/443)端口HTTP跳转HTTPS

80 端口是为 HTTP(HyperText Transport Protocol)即超文本传输协议开放的,此为上网冲浪使用次数最多的协议,主要用于 www(World Wide Web)即万维网传输信息的协议。443 端口即网页浏览端口,主要是用于 HTTPS 服务,是提供加密和通过安全端口传输的另一种HTTP。

80 与 443 这两为默认网页浏览端口,我们称之为标准网页服务端口吧。使用标准端口的网站服务器,在我们浏览网站的时候,只需要输入域名,不需要输入端口号即可正常访问,非常方便。

但是对于我们在家庭宽带下部署的网站,由于运营商限制了标准默认的网页服务端口 80 与 443 ,因此在家庭服务器上部署的网站服务等,都只能使用非标准端口对外提供服务。那么我们访问非标准端口下的网站只能输入完整的 <协议类型><域名>:<端口> 才能正常访问网站,非常麻烦。

例如我目前搭建的 WordPress 网站使用的端口为 8888 ,那么要访问我这个 WordPress 网站就要在浏览器上完整输入 https://sgtfz.cn 才能正常访问。如果只输入 sgtfz.top:8888 这样是无法正常访问的,Nginx 服务器会出现如下报错

400 Bad Request

The plain HTTP request was sent to HTTPS port

因为服务器监听 8888 这个端口配置了 SSL 证书,必需使用 https 协议访问。没有输入前缀协议 https:// ,默认以 http://sgtfz.top:8888 访问必然会报错而无法正常访问。

非标准端口实现 HTTP 跳转 HTTPS

这个问题老早就已经发现了,但没有找到任何有用的解决方法,所以一直搁置到如今。在一个不经意间,发现了 Nginx 的奇妙重定向,不是一般的重定向。是 error_page 497 重定向,解决了这个历史遗留问题!

error_page 497 https://$server_name:$server_port$request_uri;

目前我的 WordPress Nginx 服务器配置文件:

登录查看完整内容

如果按照正常逻辑,搜索关于 400 Bad Request 这个报错,或搜索关于 The plain HTTP request was sent to HTTPS port 这个相关的问题,是很难发现 error_page 497 玄机的。

实际上我折腾解决 Nginx 这个非标准端口 http 重定向至 https 的历史遗留问题后,想继续折腾 Apache2 也是关于这个问题的重定向,Apache2 的报错如下:

Bad Request

Your browser sent a request that this server could not understand.
Reason: You’re speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

使用浏览器开发者工具,发现 Apache2 报错也是 400 Bad Request 。其实在我写这个文章前,我没有注意 Nginx 报错也是 400 Bad Request ,以为 Nginx 是 497 报错,在写这篇文章时重现 Nginx 报错才发现。折腾 Apache2 一直都在寻找关于 400 的报错,被 400 报错迷惑导致了最终的失败?那么是不是可以借鉴 Nginx error_page 497 这个方法来继续折腾 Apache2 呢?

好吧,时间允许的话,继续吧!问题是明天要很早去扫墓哟 @.@

2022年4月3日 2:40

还是忍不住搞定了 Apache2 的非标准端口 http 重定向至 https 的问题了!直接上配置文件示例:

<VirtualHost *:8883>
  # 开启 HTTP/2
  Protocols h2 h2c http/1.1

  DocumentRoot "/xxx/"

  # Apache 的 ServerName 貌似必需加上端口号
  ServerName  sgtfz.top:8883

  # 日志
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  # Enable/Disable SSL for this virtual host.
  SSLEngine on

  # 证书公钥配置
  SSLCertificateFile /etc/apache2/cert/sgtfztop_cert.pem
  # 证书私钥配置
  SSLCertificateKeyFile /etc/apache2/cert/sgtfztop_key.pem
  # 证书链配置
  SSLCertificateChainFile /etc/apache2/cert/sgtfztop_chain.pem
  ......
  # 重定向 400 错误 到 https://sgtfz.top:8883/ 
  ErrorDocument 400 https://sgtfz.top:8883/
</VirtualHost>

精准针对 400 错误 重定向 https://sgtfz.top:8883/

如下 2 种方法都行:

  • ErrorDocument 400 https://sgtfz.top:8883/
  • ErrorDocument 400 "https://%{SERVER_NAME}:%{SERVER_PORT}/"

简单粗暴。但 Apache 的这种方式重定向,有一个致命的缺点:

  • 不管你访问任何目录或文件都只能重定向到指定页面 https://sgtfz.top:8883/
    • 例如访问 sgtfz.top:8883/others/ 将会重定向到 https://sgtfz.top:8883/

因此,如果非标准端口 HTTP 跳转 HTTPS ,Nginx 才有最完美的解决方案。

发表回复