1. 先说清楚:这次要解决什么问题,以及TongWeb的SSL到底难在哪
如果你所在的企业还在用TongWeb,那你大概率已经体会过一件事:单独看配置文档,每一步都写得明明白白,但真到自己上手配TLS的时候,要么证书装上之后服务起不来,要么Chrome/Firefox直接给你报“不受信任”,要么一组密码套件配完,安全扫描还是一堆高危。我这次处理的模拟项目X,就是一个典型的国产中间件迁移场景:某政务类应用系统要从旧版中间件整体迁到TongWeb,安全等保测评要求在传输层必须启用TLS 1.2及以上,同时要关闭一批弱密码套件。听起来不算复杂,但落地过程中踩了一串坑,有些坑在官方文档里根本找不到现成答案。
这个项目本身不复杂,核心就三件事:让TongWeb正确加载证书、把TLS协议版本卡在合理范围、把密码套件列表按安全基线收敛。但TongWeb这个东西有点特殊,它跟Tomcat长得像,骨子里也确实是Java系中间件的底子,可它的配置入口、参数命名、生效机制都有自己的一套逻辑。如果你拿Tomcat的思维去套,第一轮配置大概率是“看似成功、实则有偏差”。
这篇博文适合谁看?只要你正在做中间件安全加固、等保整改、国产化适配,或者正准备把自己的应用从Tomcat迁到TongWeb,这篇都能帮你省下至少两到三天的排坑时间。我会把这次实战中遇到的TLS协议与密码套件问题、排查过程、最终配置样例全部梳理出来,同时补上我对“为什么这么配”的理解,让你看完之后不只会抄,还能根据自己项目的实际情况做调整。
2. 配置前的关键准备:不只是把证书丢进去那么简单
2.1 先搞清楚TongWeb的SSL配置入口在哪里
TongWeb的SSL配置跟Tomcat最大的区别在于:Tomcat的server.xml里通过Connector配置SSL,大多数人都习惯直接改XML;而TongWeb在较新版本中,除了支持server.xml体系,还提供了一套管理控制台的图形化配置界面,同时允许通过JVM启动参数覆盖部分属性。很多人在网上搜到的配置示例来源混杂,有些是老的TongWeb 5.0时代的写法,有些是基于Tomcat改过来的,放到当前版本上根本对不上,这是第一个容易掉进去的坑。
我这次处理的版本是TongWeb 7.0(具体小版本号就不报了,不同小版本之间还有差异),它的HTTPS监听器在管理控制台的路径是“实例管理-监听器-新增HTTPS监听器”。但注意,控制台上填的证书信息,最终还是会落到实例目录下的server.xml里。所以我个人的建议是:先用控制台把参数填一遍,再打开server.xml核对实际生成的内容,两头对照,才能确认配置真的生效。
如果你打算跳过控制台直接改XML,那需要关注的核心配置项集中在Connector节点上,大致包括port、protocol、SSLEnabled、scheme、secure、keystoreFile、keystorePass、sslProtocol、sslProtocols、ciphers、clientAuth这几个属性。下面这份配置样例我在测试环境验证过,可以作为一个起步模板:
<Connector port="9443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxThreads="200" scheme="https" secure="true" keystoreFile="/opt/tongweb/conf/keystore/server.p12" keystorePass="changeit" keystoreType="PKCS12" sslProtocol="TLS" sslProtocols="TLSv1.2,TLSv1.3" ciphers="TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384" clientAuth="false" />不过这个样例还不能直接抄,因为具体的cipher名称和JRE版本强相关,后面我会把为什么这样选、哪些参数最容易出问题详细拆开说。
2.2 证书格式与密钥库类型的选择逻辑
第二个关键准备是密钥库,我这次踩了一个比较典型的坑。最开始我图省事,直接用OpenSSL生成的PEM格式证书和Key文件,然后尝试让TongWeb直接加载PEM,结果服务起来了但HTTPS完全不通,日志里报找不到私钥。后来查了TongWeb底层的实现逻辑,发现它虽然基于Java体系,但不同版本对PEM的支持程度不一样,官方文档里明确推荐的是JKS或PKCS12格式的密钥库。
这里我建议直接用PKCS12,别再用JKS了。原因是:JDK 8以后的版本对JKS的支持虽然还在,但Java 9开始官方就在推动PKCS12作为默认密钥库格式,到JDK 17以后JKS已经明显属于“遗留格式”。而且PKCS12是跨工具的标准格式,你后续要是换中间件、做迁移、给其他团队交接,一个.p12文件走到哪都能用。转换命令很简单:
openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name tongweb -password pass:changeit如果证书是从CA那边直接申请来的,一般会拿到三个文件:证书链(CA根证书和中间证书)、服务器证书、私钥。转换的时候记得把证书链按顺序拼接进同一个crt文件,否则后面可能会遇到“握手失败但证书看着没问题”的怪现象,这个细节我在第三节还会展开。
2.3 配置前先用命令行自检证书链,别等启动失败才排查
证书转换完,一定要先做一个独立于TongWeb的验证。我这次的习惯是先用keytool或者openssl把密钥库内容打印出来,确认里面有几个条目、别名是什么、有效期到什么时候。命令分别是:
# 查看PKCS12里到底有什么 keytool -list -v -keystore server.p12 -storetype PKCS12 -storepass changeit # 如果是JKS,用下面这个 keytool -list -v -keystore server.jks -storepass changeit这一步能提前杀掉80%的证书问题。我之前遇到过一种情况:用keytool看密钥库,条目正常,证书有效期也没问题,但在浏览器里访问时总提示证书链不完整。排查到最后发现是CA中间证书没有包含进来,服务器只发了叶子证书,客户端无法构建信任链。这类问题如果不提前自检,全部压到服务启动之后去查,定位成本会翻好几倍。
3. 协议版本配置:不是简单勾选TLS1.2就完事
3.1 sslProtocol、sslProtocols、sslEnabledProtocols到底听谁的
握手阶段客户端和服务端协商出来的协议版本,表面上看是“两边取交集”,但服务端这边能影响结果的参数其实有好几个,而且它们之间是有优先级和覆盖关系的。这次项目里我就踩了一个特别隐蔽的坑:我明明在Connector上写了sslProtocol="TLSv1.2",心想这下肯定只跑TLS1.2了,结果用扫描工具一测,服务端居然还在响应TLS1.0的ClientHello。
后来我把server.xml翻来覆去看,终于发现了问题所在。TongWeb的Connector节点里还蹲着一个sslEnabledProtocols属性,有些版本默认会带上TLSv1和TLSv1.1,导致你在控制台上看到的“协议版本”选项只是表象,实际生效的是这个隐藏属性对应的JSSE算法集合。更头疼的是,TongWeb 7.0的图形界面上,不同版本对这个字段的暴露程度不一样,有的版本把它藏在“高级选项”里,有的版本干脆不显示。
我最后是通过配置覆盖的方式强行卡死的,在Connector里同时写死这几个属性,让它们的值完全一致,不给默认值留发挥空间:
sslProtocol="TLS" sslProtocols="TLSv1.2,TLSv1.3" sslEnabledProtocols="TLSv1.2,TLSv1.3"这里有个知识背景需要说一下:sslProtocol和sslEnabledProtocols在JSSE体系里,前者偏底层、是SOCKET层协议;后者是更细化的“启用的协议版本”列表。如果两边取值不一致,JSSE内部处理时以较宽的那个为准,这就解释了为什么只配了TLSv1.2但实际上TLS1.0/1.1还能通。要解决这个问题,思路不是“少配”,而是“把能影响协议列表的属性全部显式写一遍”,让它们彼此对齐。
3.2 等保要求TLS1.2以上,为什么TLS1.3会带来兼容性问题
这次等保基线要求“启用TLS1.2及以上协议,禁用TLS1.0/1.1”。按道理把TLS1.2、TLS1.3都打开就行,但实际业务系统里还有一批老旧的业务终端,它们的HTTPS客户端基于老版本JDK或是老操作系统内置的加密库,TLS1.3的握手流程跟TLS1.2差异很大——TLS1.3的Hello扩展、密钥共享方式、密码套件命名方式都变了,这些老客户端即使支持TLS1.2,也大概率能支持TLS1.3,但容易被服务端的TLS1.3配置引发兼容问题,尤其是会话恢复相关的扩展处理。
我当时的处理策略是:先启用TLS1.2和TLS1.3,然后用不同版本的客户端做一轮验证,确认内部老终端能握手成功。如果老终端确实有兼容性问题,再考虑降级为只开TLS1.2,并把这个决策记录在安全整改说明里。项目上最终保留了TLS1.3,因为测试下来内部客户端的JDK版本已经足够新,不存在兼容障碍。但如果你手里有一批“上了年纪”的终端,稳妥路线是只开TLS1.2,不要让TLS1.3成为割裂业务兼容性的导火索。
3.3 无外网环境下手动验证协议版本的方法
验证协议版本是否真正生效,不能光看配置和日志。TongWeb在审计日志里记录的是“启动时加载的SSL上下文信息”,但它不会实时告诉你当前某个HTTPS连接到底用了什么协议版本。这时候需要用第三方工具从外部连接来看。
我项目里用的是nmap的ssl-enum-ciphers脚本来扫描协议支持情况,跑完会输出一份很清晰的结果,告诉你服务端支持哪些协议版本和密码套件。命令大致是这样:
nmap --script ssl-enum-ciphers -p 9443 127.0.0.1在企业内网无外网环境下,nmap脚本库如果没装全,你还可以用openssl来手动指定协议版本去握手,一次测一个:
openssl s_client -connect 127.0.0.1:9443 -tls1 openssl s_client -connect 127.0.0.1:9443 -tls1_1 openssl s_client -connect 127.0.0.1:9443 -tls1_2 openssl s_client -connect 127.0.0.1:9443 -tls1_3如果配置生效,TLS1.0和TLS1.1的握手应该直接报错(handshake failure),而TLS1.2/1.3能正常输出证书和会话信息。这一招是最直观的,比看任何文档都靠谱。
4. 密码套件配置:最容易“配了又好像没配”的地方
4.1 先理解密码套件命名的两套体系:OpenSSL名与JSSE名
密码套件是这次项目里最让人抓狂的部分,因为TongWeb(本质是Java)使用的密码套件名跟OpenSSL体系下的名字不一致。比如你用nginx的时候习惯写ECDHE-RSA-AES128-GCM-SHA256,这个在Tomcat/TongWeb里也是合法的,但Java底层JSSE识别的名字还有另一套格式,比如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。有些资料里说TongWeb两种都认,但实测下来,配置ciphers属性时更稳妥的做法是直接用JSSE格式的名字,或者干脆用OpenSSL格式的别名(前提是当前JRE版本支持这个别名映射)。
我在第一次配置时,从某个安全扫描报告里抄了一整段OpenSSL格式的密码套件列表,直接填进了ciphers属性,结果启动正常、页面也能打开,但用扫描工具复核时发现返回的密码套件跟我配置的完全不是一回事——它返回的是一组JSSE默认列表。后来我查了日志才发现,TongWeb在解析ciphers属性时会做合法性校验,不合法的条目会被静默丢弃,剩下合法的再跟JRE默认集合并集处理。也就是说,你配置了但有一个名字不合法,不会报错,它只会默默忽略,这比直接报错更坑。
所以这里给出一个重要经验:配完密码套件后,不能只看“服务能起、页面能开”,一定要用外部工具扫描实际协商结果。至于用什么名字,建议全部统一为JSSE标准名,也就是“TLS_”开头的这种。
4.2 密码套件优先级顺序怎么定,以及为什么顺序影响握手结果
密码套件列表的顺序不是摆设,它代表了服务端的优先级偏好。TLS握手时,客户端会带着自己支持的套件列表,服务端从中挑选一个双方都支持的,如果服务端没有偏好配置,就默认选择自己列表里的第一个。有些安全扫描工具之所以报“服务端支持弱密码套件”,往往不是因为它真的用了弱套件,而是因为服务端把强套件排在后面,或者弱套件残留在列表里被扫描工具探测到了。
我这次的做法是把套件列表按强度从高到低排列:优先放TLS1.3专属的AEAD套件,然后放ECDHE+AEAD,最后才放DHE类的。一个参考顺序是:
TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384这里我特意没放CBC类套件,也把RSA密钥交换的套件全部排除在列表之外。原因是RSA密钥交换不支持前向保密,一旦服务端私钥泄露,历史流量全部可被解密,这在等保测评里属于明确扣分项。ECDHE虽然也依赖RSA做签名,但密钥交换用的是临时密钥,私钥泄露影响不到历史流量。
4.3 为什么你写了ciphers列表,扫描结果里还是出现弱套件
在4.1节我提到了被静默丢弃的情况,这里还有一种更隐蔽的情况:如果你配置的ciphers属性没有包含任何“合法且被当前JRE支持的套件”,或者列表里的套件名与协议版本不匹配(比如把TLS1.3专属的TLS_AES_256_GCM_SHA384写进去,同时又把协议锁死在TLS1.2),JSSE不会全部禁用所有套件,而是会回退到默认套件列表。这就导致了“我明明配置了,为什么扫描还有弱套件”的终极困惑。
举例来说,TLS_AES_256_GCM_SHA384和TLS_AES_128_GCM_SHA256是TLS1.3专属套件,如果协议只开TLS1.2,这俩套件永远不会被协商,但你把它们填在列表里,Java解析器不会报错。反过来,如果你协议开了TLS1.3,却把这两个套件从ciphers列表里删除,默认列表又会把一组TLS1.3套件加回来。所以配置密码套件时,一定要跟协议版本放在一起整体思考,不要分开逐项调整。
这次项目中,我在测试环境做了一组对照实验,把协议锁在TLS1.2、ciphers里只写四个TLS1.3套件,然后用openssl去扫,结果服务端实际返回的是JSSE默认TLS1.2套件组。这就是“你以为禁了,实际上全放开了”的典型场景。正确的做法是:TLS1.2的套件和TLS1.3的套件都显式列出来,缺一不可。
4.4 调整密码套件影响性能?我的实测结论
谈到密码套件,免不了有人问:把套件收窄之后,性能会不会变差?这次我顺手做了个性能对照,结论是:在同等硬件条件下,ECDHE-RSA-AES128-GCM-SHA256与ECDHE-RSA-AES256-GCM-SHA384的吞吐差异很小,AES128比AES256大概有5%左右的性能优势,但绝对数值差距远低于网络延迟和CPU主频带来的波动。如果你是在高并发网关场景,可以选择AES128作为首选,同时保留AES256供特殊等级需求使用。
真正影响性能的不是套件名里的AES位数,而是密钥交换算法的选择。ECDHE比DHE快得多,因为DHE需要做大规模素数模幂运算,CPU开销高且延迟大。所以如果性能敏感,密码套件排序里应该把ECDHE系列放在DHE前面。
5. 双向HTTPS认证的坑:clientAuth不是填个true就完事
5.1 双向认证的场景需求和准备工作
这次项目因为涉及敏感数据系统,安全基线要求“双向HTTPS认证”,也就是客户端也要带证书,服务端要验证客户端身份。TongWeb里开启这个功能很简单,Connector上clientAuth改成true就行,但真正麻烦的是信任库的配置和客户端证书链的校验逻辑。
双向认证有两个库要准备:一个是密钥库(keystore),存的是服务端自己的证书和私钥;另一个是信任库(truststore),存的是服务端信任的CA根证书。TongWeb的连接器里,keystoreFile指定密钥库,truststoreFile指定信任库,两个不能混为一谈。我见过有人把客户端证书直接塞进keystore,折腾了半天握手永远报“客户端证书验证失败”。
正确的做法是:如果客户端的证书是内部CA签发的,只需要把这个内部CA的根证书导入truststore,服务端就能信任所有由该CA签发的客户端证书。命令如下:
keytool -import -alias internal-ca -file ca-root.crt -keystore truststore.p12 -storetype PKCS12 -storepass changeit5.2 开启双向认证后,日志报“no trusted certificate found”
我这次在测试阶段遇到的典型报错是:服务端日志里出现“no trusted certificate found”或“unable to find valid certification path to requested target”。一开始我以为是truststore没配好,后来排查发现是客户端证书已经过期了——签发给测试终端的那张证书过期时间是上个月,测试时压根没注意。
这类报错表面上看是信任问题,实际上要分成三种情况来排查:
- 第一种:truststore没配置或路径错误——检查truststoreFile和truststorePass是否匹配;
- 第二种:truststore里没有对应的CA根证书——把客户端证书的签发链拉出来,找到根CA导入;
- 第三种:客户端证书本身无效、过期、被吊销——用keytool查看客户端证书有效期。
我把这三步固化成了排查清单,之后再有类似问题基本十分钟之内定位。
5.3 双向认证下浏览器直接访问会怎样
还有一个小坑顺手提一下:如果你在客户端没装证书的情况下用浏览器直接访问开启了双向认证的服务,浏览器会弹窗提示选择客户端证书,如果你点了取消,就会看到“ERR_BAD_SSL_CLIENT_AUTH_CERT”之类的错误。很多业务同事第一次遇到这种页面,第一反应是“服务挂了”,实际上服务是好的,只是没通过客户端身份验证。
所以如果项目要做双向认证,一定要提前跟业务方和终端用户说明清楚,给每台终端发证书、指导安装,否则上线当天会接到一堆“网站打不开”的报障。
6. 配置不生效、改完又变回去:TongWeb的配置生效机制
6.1 为什么你改了server.xml,重启之后被“还原”了
这个坑是很多TongWeb运维的老大难问题:你在服务器上直接编辑了server.xml,保存,重启,然后打开一看,改动“凭空消失”了,配置又变回之前的样子。原因在于:TongWeb的管理控制台会把配置持久化到它自己的仓库里,server.xml只是运行时生成的一个产物。你直接改XML,等于改了“结果”没改“源头”,重启时控制台再按自己的配置生成一份新的XML,你的修改就被覆盖了。
所以正确操作路径有两类:一是全程在管理控制台操作,改完通过控制台保存和重启;二是如果必须改XML,需要先确认当前实例的管理方式,把控制台自动维护配置的功能关掉,或者修改控制台仓库里的源配置。我建议非特殊情况都走控制台,因为XML直改的隐蔽问题太多,出了问题不好回溯。
6.2 控制台填了密码套件保存成功,怎么验证真的生效
控制台操作也有自己的“假成功”陷阱。我这次在TongWeb控制台的HTTPS监听器页面里填了一长串密码套件,保存之后没有任何报错,界面上也显示保存成功。但用nmap扫完之后发现,套件列表跟配置完全不一致。后来我自己分析原因,主要有两种可能:一是控制台保存的密码套件格式不被底层JSSE识别(被丢弃),二是这个页面的密码套件输入框在7.0版本里根本不生效,需要改XML。
这里我给一个最实操的建议:不管你在控制台怎么配的,最终都去实例目录下把server.xml打开看一眼,以XML里的最终内容为准。TongWeb的控制台虽然可视化程度高,但SSL相关的复杂配置,最终解释权还是属于XML。
6.3 用一条命令重启并快速验证配置是否加载
每次改完配置,都要重启TongWeb实例,而这个重启动作在不同部署方式下差异很大。如果TongWeb是作为系统服务跑的,用service命令重启;如果是部署在自定义目录下的,走bin目录的启动脚本。重启后第一件事不是看页面通不通,而是看日志里SSL相关初始化行是否正常输出。
我习惯用下面这条命令来做启动后的快速验证:
tail -f /opt/tongweb/logs/tongweb.log | grep -i ssl如果看到类似“SSL context initialized”或者“Keystore loaded successfully”的日志,说明配置被加载了。如果日志里出现异常堆栈,直接定位关键字“SSL”或“keystore”,大多数问题都能在日志里找到答案。
7. 项目实战中遇到的高频故障与排查思路速查表
这一节我把自己在这次项目中遇到的高频问题整理成一个速查表,方便你以后直接对照排错。
| 现象 | 可能原因 | 排查步骤 | 解决办法 |
|---|---|---|---|
| 启动失败,报Keystore was tampered with或password incorrect | 密钥库密码错误,或密钥库类型与文件实际格式不一致 | 用keytool -list验证密码是否正确 | 确认storepass与文件密码一致;统一使用PKCS12 |
| 页面能开,但浏览器地址栏显示不安全 | 证书链不完整,客户端无法构建信任链 | 用openssl s_client查看服务端返回的证书链 | 把中间证书和根证书按顺序拼入证书文件再生成p12 |
| 扫描发现TLS1.0/1.1仍可协商 | 有隐藏的sslEnabledProtocols默认值在起作用 | 检查server.xml中所有协议相关属性 | 显式写全sslProtocol、sslProtocols、sslEnabledProtocols |
| 配置了ciphers但扫描结果不一致 | 个别密码套件名不被JRE识别,被静默丢弃 | 逐个核对套件名是否属于当前JDK支持的列表 | 改用JSSE标准名,并显式补齐TLS1.2和TLS1.3两组套件 |
| 双向认证时出现no trusted certificate found | truststore缺少CA根证书,或客户端证书过期 | 检查truststore条目和客户端证书有效期 | 导入正确CA根证书;更换有效期内客户端证书 |
| 改了server.xml重启后配置被还原 | 控制台自动生成配置覆盖了手动改动 | 检查实例配置来源 | 走管理控制台修改,或关闭自动生成配置功能 |
| 网页能访问但很慢 | 密码套件列表里DHE套件排在前面 | 查看实际协商套件 | 把ECDHE系列调整到优先位置 |
这张表是我在项目收尾阶段整理出来的,把排障时间从“小时级”压缩到“分钟级”靠的就是这类表格。遇到问题时,先不要急着改配置,先把现象归到表里对应的一行,按排查步骤走一遍,基本能解决大多数SSL配置问题。
8. 最终落地的安全基线配置样例与个人使用心得
最后给出一个我在模拟项目X里验证通过、并被安全扫描复核确认无高危项的配置模板,你可以根据自己的环境微调。这个模板适用于TongWeb 7.0系列、JDK 8以上版本,如果你的JDK版本比较新(比如JDK 17),里面个别套件名可能需要按当前环境的JSSE支持列表做增删。
<Connector port="9443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" keystoreFile="/opt/tongweb/conf/keystore/server.p12" keystorePass="changeit" keystoreType="PKCS12" truststoreFile="/opt/tongweb/conf/keystore/truststore.p12" truststorePass="changeit" truststoreType="PKCS12" sslProtocol="TLS" sslProtocols="TLSv1.2,TLSv1.3" sslEnabledProtocols="TLSv1.2,TLSv1.3" ciphers="TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" />个人实际使用中有几个体会想分享。
第一,TongWeb的SSL配置排错,最忌讳“猜”。每次改配置,都把改前和改后的server.xml存一个备份,标记时间和变更内容,一旦出问题可以快速对比差异。这个习惯在多次变更时尤其有用,能帮你准确判断是哪一步引入的问题。
第二,安全扫描结果和实际配置不一致时,第一时间不是怀疑扫描器,而是怀疑配置的静默丢弃逻辑。Java体系的中间件在SSL参数处理上,对不合法值经常是“宽容性忽略”,这跟Tomcat、TongWeb这类容器的设计理念一致——启动优先,配置错误后续再说。这种设计对用户不友好,但理解了它的逻辑之后,排障思路就清晰了。
第三,如果是生产环境做TLS整改,建议先在一台测试机完整走一遍配置、扫描、验证、回滚的全流程,再批量推送到生产。SSL配置不像普通参数修改,错了不会马上报错,但它会影响所有外部访问。我自己在测试环境踩完所有坑之后,生产环境基本一次通过,靠的就是这个“先测试、后生产”的顺序。
最后再提一个小技巧:配置完SSL后,建议把TongWeb的日志级别临时调整到调试模式,观察几次握手过程的日志,确认服务端选择的协议版本和密码套件确实在预期范围内。确认无误后再调回正常级别。这个动作虽然不起眼,但它能直观地告诉你“真实协商结果”和“配置文件”是否一致,避免被“表面配置成功”骗过去。