ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

彻底禁用3DES与DES:SSL/TLS弱加密套件与证书巡检实战

彻底禁用3DES与DES:SSL/TLS弱加密套件与证书巡检实战 上周帮一个做电商的朋友排查线上问题他甩过来一份第三方安全扫描报告第一页红字标着检测到SSL/TLS服务端支持3DES弱加密套件存在Sweet32中间人明文恢复风险。他一脸茫然地问我这证书不是刚换的吗怎么又出问题了。我当时就笑了因为这个问题太典型了——很多人把证书和加密套件混为一谈以为换了张SSL证书、让浏览器显示小锁就万事大吉实际上证书只解决了你是谁的问题而怎么聊这件事是由加密套件决定的3DES和DES就是这套谈判规则里早就该被淘汰的老古董。这篇就聊透一件事怎么把3DES和DES这两个弱加密算法从你的服务端彻底清出去顺带把SSL证书的过期时间巡检、证书链完整性、多域名配置这些容易翻车的点一起捋明白。不管你是运维、后端开发还是自己折腾个人站点的玩家照着走一遍都能落地。1. 先把话说清楚3DES和DES为什么必须下架1.1 DES的56位密钥今天就是纸糊的DESData Encryption Standard是1977年的产物分组长度64位密钥名义上64位但其中8位是奇偶校验位真正参与运算的有效密钥只有56位。56位意味着密钥空间是2的56次方大约是7.2×10的16次方。这个数字放在上世纪七八十年代确实够用但放到今天一块几千块钱的显卡集群就能在合理时间内跑完整个空间。早在1998年电子前哨基金会就用一台专门定制的机器在56小时内破解了DES密钥那还是二十多年前的硬件水平。现在随便一台带几张消费级显卡的工作站暴力枚举DES的速度是当年那台机器的成千上万倍。更麻烦的是DES不光密钥短它的S盒设计还被发现存在理论上的弱点线性密码分析和差分密码分析对它的效率都远高于纯暴力。所以今天任何安全基线里DES都是必禁项没有讨论空间。你在服务端配置里看到DES-CBC3-SHA里的那个DES要小心区分——那是3DES的套件名和单独的56位DES不是一回事后面会详细讲怎么区分。1.2 3DES的问题不在密钥长度而在64位分组很多人觉得3DES是DES的三次叠加有效密钥112位EDE三密钥模式名义168位密钥长度够长了应该没问题。这个判断只对了一半。3DES的密钥空间确实够大暴力破解走不通但它的致命伤在别的地方——分组长度仍然是64位和DES一模一样。64位分组意味着什么意味着根据生日悖论同一条加密连接里只要传输的数据块数量累积到2的32次方约42.9亿个块也就是大约32GB的数据量出现两个相同密文块的碰撞概率就达到50%左右。这个碰撞不是抽象的数学概念攻击者可以利用它做明文恢复。2016年公布的Sweet32攻击CVE-2016-2183就是干这个的在CBC模式下攻击者通过大量注入和观测利用碰撞逐步推断出明文内容尤其是那些反复出现的会话Cookie、认证令牌这类高价值数据。这里有个很关键的实践细节32GB是碰撞概率达到50%的理论门槛但真正要恢复出明文实际需要的数据量更大。Sweet32论文里给出的实测数据是针对3DES的攻击大约需要785GB的传输量才能在约38小时内完成攻击。785GB听起来很夸张但注意——攻击针对的是单条长连接。如果你的站点上有大文件下载、视频流、WebSocket长连接、SSE推送或者客户端复用了连接池长期不关闭累积到几百GB并不是天方夜谭。而且攻击者可以先想办法诱导客户端持续发数据比如页面里塞个定时轮询主动把连接养大。除了Sweet323DES还有几个减分项它的软件实现性能极差大约是AES的六分之一到十分之一白白吃掉CPU它在TLS 1.3里已经被彻底移除也就是说你留着它对现代客户端没有任何兼容性收益再加上它使用的CBC模式存在padding oracle类攻击的隐患。综合下来禁掉它是纯粹的收益没有代价。1.3 合规扫描与等保测评里的硬性要求从合规角度看主流的安全扫描器、基线检查工具早就把3DES和DES列为高危项。你在扫描报告里经常看到的条目包括CWE-327: 使用已被攻破或存在风险的加密算法、SSL Medium Strength Cipher Suites Supported、SWEET32: Birthday attack against 64-bit block ciphers。PCI DSS明确要求在2018年6月30日之后停止使用3DES和RC4等弱算法等保测评的SSL配置检查项里也通常会要求禁用。这意味着哪怕你觉得自己的业务数据不值钱、没人会盯上只要做过测评或者对接过支付、金融类的合作方这条都会被卡住。注意不要抱着我的业务量小达不到785GB的侥幸心理。扫描器是按配置判定的只要套件还在协商列表里报告就是红的。合规意义上的支持和实际被利用的概率是两回事。2. 摸底排查怎么确认自己的站点还在用3DES2.1 三条命令快速定位动手之前先摸清楚现状。最直接的工具就是openssl服务器上基本都有。核心思路是强制客户端只带3DES套件去握手如果服务端能接上说明它还在支持。# 强制只用3DES套件发起TLS 1.2握手 openssl s_client -connect example.com:443 -servername example.com \ -cipher 3DES -tls1_2 /dev/null 21 | head -30如果输出里出现Cipher : ECDHE-RSA-DES-CBC3-SHA或者DES-CBC3-SHA这样的行说明服务端还在协商3DES。如果出现no ciphers available、handshake failure或者alert handshake failure说明已经被禁掉了。同理用-cipher DES可以测纯DES不过纯DES现在基本绝迹了重点测3DES。另外还可以用-cipher ALL:eNULL把所有套件都列一遍看看完整清单里混了哪些不该有的东西。# 列出服务端支持的完整套件清单需要工具配合 nmap --script ssl-enum-ciphers -p 443 example.comnmap的这个脚本会把支持的协议版本、每个版本的套件、以及评级A/B/C/D/F都列出来非常直观。报告里如果有DES-CBC3-SHA并且标注了weak那就是你要处理的目标。2.2 看懂扫描报告里的CWE-327和Sweet32条目第三方扫描报告通常会给出具体命中的套件名和端口。你要学会区分这些套件名因为它们处理方式不一样套件名称说明处理方式DES-CBC3-SHA3DESCBC模式SHA-1完整性必禁属于TLS 1.0/1.1时代的遗留ECDHE-RSA-DES-CBC3-SHA带ECDHE密钥交换的3DES必禁虽然前向安全但分组仍是64位DES-CBC-SHA单DES56位必禁几乎绝迹RC4-SHARC4流密码必禁和3DES一起处理AES128-SHAAES-128-CBC SHA-1可保留但建议优先GCMECDHE-RSA-AES128-GCM-SHA256AES-GCM128位分组现代推荐扫描器报Sweet32的时候一般会明确写出命中的是哪种算法和端口。要注意有些报告会把DES和3DES混在一起统称实际处理时按上表区分。2.3 顺手把证书过期时间和证书链一起查了排查加密套件的时候强烈建议把证书本身的状态一起看了这三件事在运维里是同一个巡检动作。# 查看证书有效期、主体、签发者 echo | openssl s_client -servername example.com -connect example.com:443 2/dev/null \ | openssl x509 -noout -dates -subject -issuer # 查看完整证书链判断中间证书是否缺失 openssl s_client -connect example.com:443 -servername example.com -showcerts /dev/null第一个命令输出里的notAfter就是过期时间。这里有个很多人不知道的点如果你用的是Lets Encrypt这类免费DV证书有效期通常只有90天主流云服务商的免费证书也大多是1年或90天靠手动续期迟早会漏。用certbot的话可以certbot renew --dry-run先演练一遍自动续期确认cron或systemd timer配好了。第二个命令的-showcerts会把服务端发来的整条链打印出来。如果只打印了一张证书你自己的域名证书没有中间CA证书那就是证书链不完整。这会直接导致部分老旧客户端、Android 7以下设备、以及一些Java HTTP客户端握手失败报unable to find valid certification path to requested target。修复方法是把中间证书拼到你的证书文件后面Nginx的ssl_certificate指向的文件里应该按域名证书 中间证书的顺序拼接。提示拼接顺序不能乱。必须先是你的服务器证书再是中间证书最后不要带根证书根证书客户端本地已经有了带上反而增大握手包体积。3. 分场景动手Nginx、Apache、Tomcat、Java全都要改3.1 Nginx用密文套件白名单一刀切Nginx是最好处理的改ssl_ciphers就行。我个人的习惯是不用黑名单排除法直接用白名单因为你永远不知道自己漏了哪个。白名单的长度可能会让配置文件看起来很长但一旦写好基本不用再动。ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;这套配置只保留ECDHE密钥交换保证前向安全、AES-GCM和ChaCha20-Poly1305这两种AEAD模式以及AES-CBCSHA256作为兼容兜底。AES-128-CBCSHA256是为了一些还停留在TLS 1.2早期实现的老客户端AES是128位分组不存在Sweet32问题所以留着是安全的。如果你嫌手写太长可以直接用openssl生成openssl ciphers -v HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA:!SEED:!IDEA | awk {print $1} | paste -sd: -这条命令里!3DES和!DES是关键注意!3DES必须写在!DES前面否则某些版本openssl的匹配逻辑会先匹配到子串DES导致行为不符合预期。生成出来的结果直接替换掉ssl_ciphers的内容。改完记得nginx -t检查语法再nginx -s reload热加载。不要用restartreload是平滑的已建立的连接不会断。3.2 ApacheSSLCipherSuite加排除符Apache的配置逻辑略有不同它用SSLCipherSuite指定默认支持!排除语法。SSLProtocol -all TLSv1.2 TLSv1.3 SSLHonorCipherOrder on SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!DSSSSLHonorCipherOrder on这一项很重要它让服务端而不是客户端决定选哪个套件能防止某些客户端故意协商到弱的那个。改完apachectl configtest验证然后systemctl reload httpd。有个坑要提一句Apache 2.4.7之前的版本不支持TLS 1.2完全配置而且老版本对!3DES的处理有bug建议先httpd -v看版本。低于2.4.7的先升级再说别在配置上折腾。3.3 Tomcat与JDK最容易被忽略的一层这是我最想强调的一节。很多团队把Nginx改得干干净净扫描器第一次查TCP 443端口显示合格结果另一次扫描换了个端口比如8443或者后端服务的8xxx报告又红了。原因就是Tomcat或Java应用自己还开着3DES。Tomcat层面的配置Connector port8443 protocolorg.apache.coyote.http11.Http11NioProtocol SSLEnabledtrue maxThreads200 schemehttps securetrue SSLHostConfigCertificatecertConfig /Connector SSLHostConfig protocolsTLSv1.2,TLSv1.3 honorCipherOrdertrue Certificate certificateKeystoreFile/path/to/keystore.jks certificateKeystorePasswordyourpassword typeRSA / /SSLHostConfigTomcat 8.5以上推荐用SSLHostConfig这种写法ciphers属性也可以直接写在Connector上但那样是全局的不好管理。如果确实要走Connector属性就写ciphersTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384注意这里的套件名是Java风格的下划线连接和OpenSSL风格不一样。但真正的大Boss是JDK本身。Java在TLS握手时会先看java.security文件里的禁用列表如果JDK版本较老默认列表里不包含3DES即使你Tomcat只配了强套件某些走JSSE默认配置的路径比如JVM内部发起的HTTPS调用、JMX over SSL还是会协商到3DES。# 查看当前JDK的禁用算法列表 grep ^jdk.tls.disabledAlgorithms $JAVA_HOME/jre/lib/security/java.securityJDK 8在8u161之前的默认值是SSLv3, RC4, MD5withRSA, DH keySize 1024, EC keySize 224里面没有3DES。需要手动加上jdk.tls.disabledAlgorithmsSSLv3, RC4, DES, MD5withRSA, DH keySize 1024, EC keySize 224, 3DES_EDE_CBC, anon, NULL这里有个非常关键的技术细节加DES只会禁掉56位的单DES不会禁掉3DES。要禁3DES必须显式写3DES_EDE_CBC这是TLS套件里的算法标识符。我第一次做这个的时候就是因为只加了DES改完扫描还是红的查了半天才发现。另一种写法是加DESedeJCE层面的算法名但3DES_EDE_CBC对TLS层更直接。改java.security需要重启JVM才生效。不想改全局文件的可以用启动参数覆盖java -Djdk.tls.disabledAlgorithmsSSLv3,RC4,DES,3DES_EDE_CBC,MD5withRSA -jar yourapp.jar注意用-D参数覆盖时会完全替换默认列表而不是追加所以默认列表里的DH keySize 1024这些也要一并写上否则等于把其他防护也关了。3.4 负载均衡、CDN和硬件设备这一层别漏掉如果你的架构里有四层或七层负载均衡、WAF、CDN那终止TLS的地方可能是它们而不是你的源站。这种情况下改源站配置是没用的扫描器扫到的是边缘节点的配置。主流云服务商的负载均衡和CDN控制台里一般都有加密套件策略或者TLS安全策略的下拉选项选最新的那个通常叫tls_policy_2021或者强加密套件之类它会自动排除3DES和RC4。选完之后一定要重新扫描验证因为有些老策略虽然名字里有加强实际仍保留了3DES做兼容。硬件设备如某些老型号的F5、A10需要登录管理界面改SSL Profile里的cipher group把包含3DES的组移除。这类设备的固件如果太老可能根本不支持TLS 1.3那就至少保证TLS 1.2下全是AES-GCM。注意改边缘节点前先确认后端源站是否要求特定的套件。有些场景下边缘到源站这一段也需要加密如果两边套件集合没有交集会直接502。4. 灰度切换与验证别把线上业务整挂4.1 上线前先做兼容性摸底禁用弱套件的最大风险是砍掉了老客户端的唯一选择。典型受害者包括还在用JDK 6/7的老接口调用方、Windows XP/2003上的老程序、某些嵌入式设备、以及只支持TLS 1.0的老旧SDK。摸底的方法很简单在改配置之前先查一下服务端日志里最近的TLS协商记录统计一下都在用哪些协议版本和套件。# Nginx可以通过日志格式记录协商结果 log_format ssl_log $remote_addr - $ssl_protocol - $ssl_cipher - $http_user_agent;把$ssl_protocol和$ssl_cipher加进access_log跑一两天然后统计awk {print $6, $7} /var/log/nginx/access.log | sort | uniq -c | sort -rn如果统计结果里出现TLSv1.0或TLSv1.1的占比超过1%说明你还有一批老客户端这时候直接一刀切禁掉3DES可能会导致它们全部连不上。可以考虑分两步走先禁用DES和RC4保留3DES作为过渡同步通知调用方升级一两个月后再彻底禁3DES。4.2 变更后的验证清单附命令改完之后不要只看浏览器能不能打开那只能证明你的Chrome没问题。按下面的清单逐项验证检查项命令期望结果3DES是否已禁openssl s_client -connect h:443 -cipher 3DES -tls1_2handshake failure纯DES是否已禁openssl s_client -connect h:443 -cipher DES -tls1_2handshake failureRC4是否已禁openssl s_client -connect h:443 -cipher RC4 -tls1_2handshake failure强套件是否可用openssl s_client -connect h:443 -cipher ECDHE-RSA-AES128-GCM-SHA256握手成功TLS 1.3是否可用openssl s_client -connect h:443 -tls1_3握手成功证书链是否完整openssl s_client -connect h:443 -showcerts输出证书链 ≥2张证书是否临期echo | openssl s_client -connect h:443 2/dev/null | openssl x509 -noout -enddatenotAfter 距今 30天全量套件评级nmap --script ssl-enum-ciphers -p 443 h无 weak 条目评级 A 或 Atestssl.sh也是个好东西一条命令能给出一份完整的评分报告./testssl.sh --sweet32 --protocols --server-defaults https://example.com--sweet32会专门测64位分组密码的问题很适合做交付前的最终验收。4.3 回滚预案要提前写好改Nginx配置前把原文件备份一份cp /etc/nginx/conf.d/ssl.conf /etc/nginx/conf.d/ssl.conf.bak.$(date %Y%m%d%H%M)改完reload之后盯10分钟监控重点看三个指标HTTPS请求的5xx比例、TLS握手失败率、平均响应时间。如果5xx飙升或者握手失败率异常立刻把备份文件复原再reload。Tomcat和JVM的改动回滚成本更高要重启所以建议先在预发环境跑一遍完整的回归测试尤其是那些走HTTPS的内部服务调用别等到线上了才发现某个定时任务连不上。我见过一次事故就是改了jdk.tls.disabledAlgorithms之后某个老的对账系统用的JDK 7客户端连不上导致凌晨对账失败第二天早上才发现手工补数据补了半天。5. 常见问题与排查技巧实录5.1 高频问题速查表现象可能原因排查与解决改了Nginx配置扫描报告仍报3DES扫描的是另一个端口或边缘节点ss -lntp列出所有监听端口逐个测确认CDN/LB策略浏览器能开但某个App报证书错误证书链不完整或缺中间证书-showcerts检查把中间证书拼进证书文件禁了3DES后大量客户端连不上老客户端只支持TLS 1.03DES日志统计协议版本灰度过渡通知升级openssl测试显示握手失败但扫描仍报问题测试用了错误的SNI或IP加上-servername用域名而非IP测试Java应用报SSLHandshakeException: no cipher suites in commonJVM与服务端套件无交集检查jdk.tls.disabledAlgorithms和Tomcat ciphers证书昨天还好今天突然过期免费证书90天周期自动续期没生效certbot renew --dry-run演练检查定时任务多域名站点部分子域报证书不匹配SAN证书未覆盖该域名openssl x509 -noout -text硬编码只加了DES3DES仍生效JDK禁用列表需用3DES_EDE_CBC显式添加3DES_EDE_CBC关键字5.2 几个我踩过的坑第一个坑是关于CDN回源的。有一次我把源站Nginx改得很干净扫描器扫源站IP是A但扫域名还是报3DES。折腾半天才发现域名解析到CDNCDN边缘节点用的是老策略而且CDN到源站回源时又用了另一套配置。所以记住你要改的是扫描器实际连上的那一层不一定是你的服务器。第二个坑是多域名SSL证书的SAN顺序。有些老客户端尤其是某些Android版本和Java客户端在证书SAN列表里找匹配时只认第一个匹配项如果你的主域名排在后面可能报不匹配。生成CSR的时候尽量把主域名放第一位openssl req -new -newkey rsa:2048 -nodes \ -keyout example.key -out example.csr \ -subj /CCN/STBeijing/LBeijing/OExample/CNexample.com \ -addext subjectAltNameDNS:example.com,DNS:www.example.com,DNS:api.example.com,DNS:m.example.com-addext需要openssl 1.1.1及以上版本。低版本要写一个配置文件在[v3_req]段里写subjectAltName然后在签名时用-extensions v3_req。用云服务商签发的证书通常没这个问题但自签或者内部CA签发的要注意。第三个坑是**ssl_prefer_server_ciphers和TLS 1.3的关系**。在TLS 1.3里套件的选择完全由客户端决定服务端的ssl_ciphers配置对TLS 1.3无效TLS 1.3的套件是固定的那几个全都基于AEAD。所以如果你看到配置里写了ssl_prefer_server_ciphers on但没生效别慌TLS 1.3本来就是这么设计的。TLS 1.3从协议层面就不支持3DES和RC4这也是为什么我一直建议大家把TLS 1.3打开——它能帮你自动挡掉一堆历史包袱。5.3 证书侧的配套加固禁完弱算法之后顺手把证书管理这块的几件事做了能省下后面很多救火时间。自动续期一定要配。90天有效期的免费证书靠人肉记日历一定会漏。certbot的方案是配一个systemd timer或者cron# 每天早上3点检查并续期 0 3 * * * /usr/bin/certbot renew --quiet --deploy-hook systemctl reload nginx--deploy-hook是关键续期成功后自动reload避免新证书生效了但Nginx还在用旧的内存缓存。如果你用的是云服务商的托管证书控制台里一般有自动续期开关打开它。加一个过期预警。我习惯在巡检脚本里加一段提前30天就开始告警#!/bin/bash DOMAINexample.com END_DATE$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2/dev/null \ | openssl x509 -noout -enddate | cut -d -f2) END_TS$(date -d $END_DATE %s) NOW_TS$(date %s) DAYS_LEFT$(( (END_TS - NOW_TS) / 86400 )) if [ $DAYS_LEFT -lt 30 ]; then echo 警告$DOMAIN 证书将在 $DAYS_LEFT 天后过期 fi这个脚本丢进cron每天跑一次输出接到告警渠道就行。别小看这几十行它救过我两次。证书链完整性检查也加进去。判断方法很简单数一下-showcerts输出的证书数量。如果是自签或者内部CA中间证书可能不止一层要确保服务端把除了根证书以外的整条链都发出来。6. 把巡检做成常态一个可复用的脚本6.1 一次巡检覆盖算法、协议、证书三件事前面这些检查项手工敲一遍大概要二十分钟而且容易漏。我把它们整合成了一个脚本放在跳板机上每天跑输出一份简报。核心逻辑是三层先测弱套件是否已禁再测强套件是否可用最后查证书状态。#!/bin/bash # ssl_audit.sh - SSL/TLS 配置巡检 DOMAIN${1:-example.com} PORT${2:-443} PASS0 FAIL0 check_fail() { local desc$1; shift local result result$($ 21) if echo $result | grep -qE handshake failure|no ciphers available|alert; then echo [通过] $desc 已禁用 PASS$((PASS1)) else echo [失败] $desc 仍然可协商到 FAIL$((FAIL1)) fi } check_fail 3DES openssl s_client -connect $DOMAIN:$PORT -servername $DOMAIN -cipher 3DES -tls1_2 check_fail DES openssl s_client -connect $DOMAIN:$PORT -servername $DOMAIN -cipher DES -tls1_2 check_fail RC4 openssl s_client -connect $DOMAIN:$PORT -servername $DOMAIN -cipher RC4 -tls1_2 # 强套件必须可用 if echo | openssl s_client -connect $DOMAIN:$PORT -servername $DOMAIN \ -cipher ECDHE-RSA-AES128-GCM-SHA256 2/dev/null | grep -q Cipher is ECDHE; then echo [通过] AES-128-GCM 强套件可用 PASS$((PASS1)) else echo [失败] 强套件不可用可能配置过于激进 FAIL$((FAIL1)) fi # 证书有效期 END_DATE$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:$PORT 2/dev/null \ | openssl x509 -noout -enddate 2/dev/null | cut -d -f2) if [ -n $END_DATE ]; then DAYS_LEFT$(( ($(date -d $END_DATE %s) - $(date %s)) / 86400 )) echo [信息] 证书剩余 $DAYS_LEFT 天到期$END_DATE [ $DAYS_LEFT -lt 30 ] { echo [警告] 证书即将过期请检查续期任务; FAIL$((FAIL1)); } fi echo ---- 巡检结果通过 $PASS 项异常 $FAIL 项 ----用法就是./ssl_audit.sh yourdomain.com 443。输出里出现[失败]或者[警告]就代表有动作要处理。脚本里判断已禁用的依据是openssl返回握手失败关键字这个判断在不同openssl版本下输出文案略有差异如果你发现误判把grep -qE后面的模式补全就行。6.2 用systemd timer替代cron如果你的服务器时间长、机器多建议用systemd timer而不是cron好处是日志统一进journal、能查执行历史、依赖管理清晰。# /etc/systemd/system/ssl-audit.service [Unit] DescriptionSSL/TLS config audit [Service] Typeoneshot ExecStart/opt/scripts/ssl_audit.sh example.com 443# /etc/systemd/system/ssl-audit.timer [Unit] DescriptionRun SSL audit daily [Timer] OnCalendardaily Persistenttrue [Install] WantedBytimers.target启用systemctl enable --now ssl-audit.timer。查看历史journalctl -u ssl-audit.service --since 7 days ago。Persistenttrue这个选项能保证机器停机错过了执行时间点开机后补跑一次不会漏掉。6.3 把结果接到告警渠道脚本本身只输出到标准输出要让它真正发挥作用得把异常结果推出去。最简单的方式是用curl往你的告警Webhook发一条JSON或者用邮件。我一直用的是只在有异常时发通知的策略避免每天一条一切正常把告警渠道刷成噪音最后没人看。OUTPUT$(/opt/scripts/ssl_audit.sh example.com 443) if echo $OUTPUT | grep -qE \[失败\]|\[警告\]; then curl -s -X POST $WEBHOOK_URL \ -H Content-Type: application/json \ -d {\msgtype\:\text\,\text\:{\content\:\$OUTPUT\}} fi这样一来只有真出问题的时候手机才会响平时完全无感。再分享一个小技巧如果你们内部有多个域名、多个端口需要巡检把域名列表写成一个文件用while read循环调用上面这个脚本一条命令全扫完。while read -r line; do [ -z $line ] continue /opt/scripts/ssl_audit.sh $line 443 echo done domains.txtdomains.txt里一行一个域名或者域名 端口。这个做法在多子域、多环境的团队里特别省事比每次手工敲openssl强太多。我个人在实际操作中的体会是禁用3DES和DES这件事最难的从来不是技术本身——配置就那几行命令也就那么几条——难的是改全。你的服务端可能有十几个监听端口边缘有一层CDN内部有若干个JVM进程在发HTTPS请求还有一堆你根本不知道存在的定时任务在用老客户端。所以我的建议是先用巡检脚本把所有资产盘一遍列出清单再一个一个改每改一个跑一次验证。别指望改一个Nginx就能让扫描报告变绿那多半只是你把真正的问题藏到了另一个端口后面。
返回列表