Apache反向代理访问报SSL_ERROR_RX_RECORD_TOO_LONG排查
问题根因
你遇到的SSL_ERROR_RX_RECORD_TOO_LONG/ERR_SSL_PROTOCOL_ERROR和端口转发能力无关,完全是配置错误+端口冲突导致的,核心问题如下:
- 端口占用逻辑错误:Apache做反向代理必须独占443端口,所有外部HTTPS请求先经过Apache处理,你当前让phpMyAdmin直接绑定443、Node服务独立开启HTTPS监听3000,和Apache的端口监听逻辑冲突,无法完成基于域名的SNI分流
- 虚拟主机语法错误:
- 反向代理的
VirtualHost规则错误把域名写在地址位(chat.domain.me:443),基于域名的虚拟主机必须统一写*:443,靠ServerName字段匹配请求域名 - 反向代理虚拟主机的
ServerName填的是rproxy.domain.me,和你预期用于访问聊天服务的chat.domain.com完全不匹配 - 反向代理虚拟主机未开启SSL引擎、未配置对应域名的SSL证书,HTTPS请求到达后直接返回明文内容,触发浏览器SSL协议报错
- 反向代理规则写的是转发到
https://localhost:3000,本地回环通信重复做SSL握手无意义,还易触发证书校验错误 - 80端口跳转规则错误配置为跳转到
https://localhost:443,会把外部用户引导到用户本地设备的443端口
- 反向代理的
- 域名匹配逻辑错误:phpMyAdmin的虚拟主机
ServerName填的是phpmyadmin.domain.me,和你预期使用的vps.domain.com不匹配,且配置了_default_:443兜底规则,所有未匹配到其他虚拟主机的443请求都会被引导到phpMyAdmin,而其他虚拟主机因配置错误根本未生效。
修正步骤
第一步:调整后端服务,解决端口冲突
- 关闭Node服务端的HTTPS配置,让Node服务仅以HTTP协议监听
127.0.0.1:3000,不要绑定公网地址,SSL证书卸载全交给Apache处理,本地回环通信无需加密 - 取消phpMyAdmin对443端口的独立占用,改为通过Apache的PHP解析模块运行,执行
ss -tulpn | grep :443确认只有Apache进程监听443端口,无其他进程抢占
第二步:修正80端口HTTP跳转配置(000-default.conf)
替换原有错误的跳转规则,实现所有HTTP请求自动跳转到对应域名的HTTPS地址:
# 000-default.conf <VirtualHost *:80> ServerName default.domain.me ServerAlias chat.domain.com vps.domain.com RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L] ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
第三步:修正聊天服务反向代理配置(reverse_proxy.conf)
修正虚拟主机语法,配置对应域名的SSL证书,添加WebSocket支持适配聊天应用的长连接需求:
# reverse_proxy.conf <VirtualHost *:443> ServerName chat.domain.com # 填写chat.domain.com对应的SSL证书路径 SSLEngine on SSLCertificateFile /etc/letsencrypt/live/chat.domain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/chat.domain.com/privkey.pem Protocols h2 http/1.1 Header always set Strict-Transport-Security "max-age=63072000" # 反向代理基础配置 ProxyRequests Off ProxyPreserveHost On ProxyPass / http://127.0.0.1:3000/ ProxyPassReverse / http://127.0.0.1:3000/ # 适配聊天应用的WebSocket长连接 RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L] ErrorLog ${APACHE_LOG_DIR}/chat_proxy_error.log CustomLog ${APACHE_LOG_DIR}/chat_proxy_access.log combined </VirtualHost>
若你必须保留Node服务端的HTTPS配置,需在上述配置中添加
SSLProxyEngine on,同时将代理地址改回https://localhost:3000/、wss://localhost:3000/,但该方案无实际安全收益,会额外增加通信延迟和配置复杂度,不推荐使用。
第四步:修正phpMyAdmin虚拟主机配置(phpmyadmin.conf)
修正ServerName为实际使用的域名,取消默认兜底规则避免抢占其他域名的请求:
# phpmyadmin.conf <VirtualHost *:443> ServerName vps.domain.com DocumentRoot /usr/share/phpmyadmin SSLEngine on SSLCertificateFile /etc/letsencrypt/live/vps.domain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/vps.domain.com/privkey.pem Protocols h2 http/1.1 Header always set Strict-Transport-Security "max-age=63072000" <Directory /usr/share/phpmyadmin> Options FollowSymLinks DirectoryIndex index.php Require all granted <IfModule mod_php.c> php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp php_admin_value open_basedir /usr/share/phpmyadmin/:/usr/share/doc/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/:/usr/share/javascript/ </IfModule> </Directory> <Directory /usr/share/phpmyadmin/templates> Require all denied </Directory> <Directory /usr/share/phpmyadmin/libraries> Require all denied </Directory> ErrorLog ${APACHE_LOG_DIR}/phpmyadmin/error.log CustomLog ${APACHE_LOG_DIR}/phpmyadmin/access.log combined </VirtualHost> # 全局SSL配置可保留 SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder off SSLSessionTickets off SSLUseStapling On SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
第五步:生效配置
执行以下命令启用必要模块、校验配置合法性并重载Apache:
a2enmod proxy proxy_http proxy_wstunnel rewrite ssl headers apachectl configtest systemctl reload apache2
生效后逻辑
配置生效后Apache会通过SNI自动识别请求域名:
- 访问
chat.domain.com:443时,匹配聊天服务虚拟主机,完成SSL卸载后将请求转发到本地3000端口的Node服务 - 访问
vps.domain.com:443时,匹配phpMyAdmin虚拟主机,直接返回PHP应用内容 - 所有80端口的HTTP请求自动跳转到对应域名的HTTPS地址,不会再触发SSL协议错误。
内容的提问来源于stack exchange,提问作者maximob
相关产品推荐
相关产品推荐

