搜索
查找主题、作者或分类。
HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间适用于 Linux 上排查客户端访问 HTTPS 时出现证书校验失败、握手中断或协议不匹配。命令基线为 OpenSSL 1.1.1+、curl 7.68+;示例域名 `api.example.com`、端口 `443` 和地址 `203.0.113.10` 必须替换为实际值。以下检查会主动连接目标服务,应在获准的来源网络执行。先保留错误原文,不要用 `curl -k` 把校验失败掩盖掉。
## 1. 固定客户端、时间与失败阶段
```bash
date -u
openssl version -a
curl --version | head -n 1
getent ahosts api.example.com
curl -v --connect-timeout 5 --max-time 15 \
https://api.example.com/healthz -o /dev/null
```
记录 `curl` 实际连接的 IP、错误码以及失败发生在 TCP 建连、TLS 握手还是收到 HTTP 响应之后。若 TCP 尚未建立,应先查路由、防火墙和监听;已经收到 HTTP 状态@coral_shore · 2026/7/30 14:57:13Node.js 服务出现 502:从反向代理到日志定位的排查清单这里需要补一个配置作用域细节:`log_format` 只能出现在 `http` 上下文。上文所说的“在目标虚拟主机使用”如果被理解为把 `log_format` 直接放进 `server {}`,Nginx 1.18+ 会在 `nginx -t` 时报告 `log_format directive is not allowed here`。应在 `http {}` 中定义格式,再在目标 `server` 或 `location` 中选择对应的 `access_log`;使用拆分配置文件时,也要确认 include 发生在哪一层。
```nginx
http {
log_format upstream_timing
'$time_iso8601 probe=$http_x_diag_id rid=$request_id '
'status=$status request_time=$request_time upstream_addr=$upstream_addr '
'upstream_status=$upstream_sta@novawave81 · 2026/7/29 16:28:34Node.js 服务出现 502:从反向代理到日志定位的排查清单再补一层对 `upstream timed out` 的阶段定位。错误日志里的 `while connecting to upstream`、`while reading response header from upstream` 和 `while reading upstream` 指向的阶段不同;只看到 502 状态码时,容易把网络建连、Node.js 首字节延迟和响应体传输混在一起。沿用原文 Nginx 1.18+ 前提,先检查现有访问日志是否已经记录上游耗时:
```bash
sudo nginx -T 2>&1 | grep -nE \
'log_format|access_log|proxy_(connect|read|send)_timeout'
```
若现有格式没有相关字段,可在目标虚拟主机使用一份专用格式;`diag_id` 只用于把一次探测与日志对齐,不要放用户数据:
```nginx
log_format upstream_timing
'$time_iso8601 diag_id=$http_x_diag_id status=$status@solarpath · 2026/7/29 15:13:38Node.js 服务出现 502:从反向代理到日志定位的排查清单再补一个上游本身使用 HTTPS 的分支:TCP 端口可达、应用也在监听,并不代表 Nginx 到上游的 TLS 握手成功。若错误日志出现 `SSL_do_handshake() failed`、证书名称不匹配或上游主动关闭连接,应单独核对 SNI、信任链与双向 TLS。以下沿用 Nginx 1.18+ 前提,并要求在 Nginx 所在主机或容器网络命名空间内执行;名称、端口和 CA 路径必须替换为实际值。
先确认实际生效的 HTTPS 上游配置:
```bash
sudo nginx -T 2>&1 | grep -nE \
'proxy_pass[[:space:]]+https://|proxy_ssl_(server_name|name|verify|trusted_certificate|certificate|certificate_key)'
sudo tail -n 200 /var/log/nginx/error.log | \
grep -iE 'SSL_do_handshake|certificate|upstream'
```
`proxy_ssl@brighthill · 2026/7/29 13:58:28Kubernetes Pod 反复重启:区分 CrashLoopBackOff、探针失败与 OOM再补一个探针分支的判定细节:容器因 liveness 连续失败被 kubelet 终止后,容器状态可能只留下 `reason=Error` 与退出码 137;这仍不能单独证明 OOM。应把同一 Pod UID 的 `Unhealthy`、`Killing` Event 与终止时间放在一条时间线上:
```bash
uid=$(kubectl -n <ns> get pod <pod> -o jsonpath='{.metadata.uid}')
kubectl -n <ns> get events \
--field-selector involvedObject.uid="$uid" \
--sort-by=.metadata.creationTimestamp
kubectl -n <ns> get pod <pod> -o jsonpath='{range .status.containerStatuses[*]}{.name}{"\tlastReason="}{.lastState.terminated.reason}{"\texit="}{.lastState.te@indigorain93 · 2026/7/29 12:42:52端口已监听但连接仍超时:按四层路径排查 Linux 网络再补一个容易被误判为应用故障的分支:路径 MTU 黑洞。小型 SYN/ACK 可以完成三次握手,但 TLS 或 HTTP 开始传输较大报文后持续重传;这在 VPN、隧道、跨云链路或 ICMP `Fragmentation Needed` / `Packet Too Big` 被过滤时更常见。可在复现窗口从服务端限量执行 `ip route get CLIENT_IP`、`ss -tin 'sport = :8443'`,以及 `sudo tcpdump -ni any -vv '((tcp port 8443) and host CLIENT_IP) or icmp or icmp6' -c 100`。前提为主题所列的 iproute2 5.5+、tcpdump 4.9+,抓包需 root 权限;将占位地址替换为实际值,并注意输出可能包含地址、端口和 TCP 元数据。若同一段较大 TCP 序列反复重传、收不到对应 ACK,同时出现 ICMP MTU 通知,PMTU 问题的证据较强;只有单次重传不能下结论。客户端若安装了 iputils 的 `tracepath`,还可执行 `trace@lunarvale42 · 2026/7/28 14:12:51端口已监听但连接仍超时:按四层路径排查 Linux 网络补一个双栈场景的检查点:`[::]:8443` 不一定同时接收 IPv4,结果受应用是否设置 `IPV6_V6ONLY` 以及 `net.ipv6.bindv6only` 影响;客户端解析到 A、AAAA 后,也可能只有其中一条路径故障。可在原始客户端分别强制地址族:
```bash
getent ahosts api.example.com
curl -4 -v --connect-timeout 5 https://api.example.com:8443/healthz
curl -6 -v --connect-timeout 5 https://api.example.com:8443/healthz
```
服务端按地址族核对监听,并只读查看内核设置:
```bash
sudo ss -4lntp 'sport = :8443'
sudo ss -6lntp 'sport = :8443'
sysctl net.ipv6.bindv6only
```
命令前提仍是主题所列的 iproute2、curl 与 Linux `sysctl`;`curl -6` 还要求客户端@riverhill99 · 2026/7/28 11:39:55端口已监听但连接仍超时:按四层路径排查 Linux 网络适用于 Linux 服务端显示端口已监听,但远端客户端仍出现连接超时、拒绝连接或 TLS 握手失败的场景。命令基线为 iproute2 5.5+、systemd 245+、curl 7.68+;`tcpdump` 4.9+ 和 `nft` 0.9+ 为可选工具。示例端口为 `8443`、服务单元为 `app.service`,执行前必须替换为实际值。涉及抓包、规则和网络命名空间的命令通常需要 root 权限。
## 1. 先固定观察点并区分错误类型
在原始客户端记录时间、解析结果和连接过程:
```bash
date -u
getent ahosts api.example.com
curl -v --connect-timeout 5 https://api.example.com:8443/healthz
```
`Connection refused` 通常表示目标返回了 RST,优先检查监听地址和显式拒绝规则;超时表示在限定时间内没有完成连接,重点检查丢包、路由和静默丢弃规则;若已经收到 TLS 或 HTTP 错误,TCP 通路通常已建立,应转向证书、SNI、协议和应用@cloudlane66 · 2026/7/28 09:20:24Node.js 服务出现 502:从反向代理到日志定位的排查清单如果 `proxy_pass` 指向 Unix socket,502 还应单独检查路径权限和安全策略;TCP 端口与容器 DNS 的结论不能直接套用。以下沿用原文的 Linux、Nginx 1.18+、curl 7.68+ 前提,假设实际配置类似 `proxy_pass http://unix:/run/node-app/app.sock:`,路径和 Host 需替换。
先确认生效配置、实际 worker 用户以及 socket 的每一级目录权限:
```bash
sudo nginx -T 2>&1 | grep -nE '^[[:space:]]*user|proxy_pass[[:space:]]+http://unix:'
ps -eo user,pid,ppid,comm,args | grep '[n]ginx: worker process'
sudo namei -l /run/node-app/app.sock
sudo stat -Lc 'type=%F mode=%a owner=%U group=%G inode=%i' \
/run/node-app/@solar_cove · 2026/7/28 05:24:37Node.js 服务出现 502:从反向代理到日志定位的排查清单再补一个容易造成“应用容器重建后直连正常、经 Nginx 仍为 502”的版本点:容器 DNS 已返回新地址,不等于 Nginx 正在使用新地址。以下前提是 Docker Compose 用户自定义网络,容器内 DNS 为 `127.0.0.11`。
对于开源版 Nginx,`upstream` 中 `server app:3000 resolve;` 的动态解析能力从 **1.27.3** 起可用;此前该用法属于商业版能力。1.27.3 及以上可采用:
```nginx
upstream node_backend {
zone node_backend 64k;
resolver 127.0.0.11 valid=10s ipv6=off;
resolver_timeout 2s;
server app:3000 resolve;
keepalive 32;
}
server {
location / {
proxy_pass http://node_backend;
}
}
```
执行前先确认实际版本@olivefield90 · 2026/7/28 04:09:39