最后更新于:2026年7月

节点存活检测
节点存活检测:5种方法快速判断节点是否被墙,告别盲目切换

节点突然连不上了,是被墙了还是服务器挂了? 这是每个科学上网用户都会遇到的问题。很多人第一反应是——换节点、找客服、等恢复。但如果你能自己判断出问题所在,不仅能节省大量时间,还能在节点被墙的第一时间采取应对措施。

本文不是端口检测基础教程(基础版请移步 端口检测指南),而是节点存活检测的实战手册——从被墙的5种典型症状到自动检测脚本,手把手教你建立一套自己的节点健康监控体系。

【适合谁看?】

  • 自建节点用户,想自己判断节点状态
  • 机场用户,想在被墙前发现问题
  • 技术爱好者,想写自动监控脚本
  • 运维人员,管理多台代理服务器

一、节点被墙的5种典型症状

症状1:连接超时(Timeout)

表现: 客户端显示 “连接超时”、“i/o timeout”、“dial tcp timeout”

可能原因:

如何区分: 用 Ping.pe 测试(见下文第二章)

症状2:连接被重置(RST)

表现: 客户端显示 “connection reset by peer”、“EOF”、“broken pipe”

可能原因:

如何区分: 换端口测试,如果换端口能连上 → 端口被墙

症状3:速度骤降后断连

表现: 本来速度很快,突然降到几乎为零,然后断开

可能原因:

如何区分: 查看日志是否有大量重连

症状4:能连上但无法访问特定网站

表现: 节点状态显示正常,但打不开 Google、YouTube 等网站

可能原因:

如何区分: 换 DNS、测试不同域名

症状5:间歇性可用

表现: 时好时坏,有时能连有时不能

可能原因:

如何区分: 长时间持续监控


二、诊断法:用 Ping.pe 判断封锁类型

Ping.pe 是判断节点状态的黄金标准。它能从全球多个节点同时测试你的服务器。

2.1 使用方法

  1. 打开 https://ping.pe
  2. 输入你的服务器 IP
  3. 点击 Go
  4. 观察全球节点的测试结果

2.2 四种典型结果解读

结果海外节点国内节点结论应对措施
场景A✅ 通❌ 不通IP被黑洞换IP(无解)
场景B✅ 通✅ 通正常检查客户端配置
场景C❌ 不通❌ 不通服务器挂了检查服务器状态
场景D✅ 通✅ 通但端口不通端口被墙换端口

2.3 Ping.pe + 端口检测结合

Ping.pe 只能测 ICMP(ping),不能测端口。要测端口,用它的姐妹站 port.ping.pe

  1. 打开 https://port.ping.pe
  2. 输入 IP:端口(如 1.2.3.4:443
  3. 观察 TCP 端口连通性

综合判断表:

ICMPTCP端口结论
海外通,国内不通海外通,国内不通IP 被黑洞
海外通,国内通海外通,国内不通端口被墙
全部不通全部不通服务器挂了
全部通全部通正常,检查客户端

三、五种检测方法详解

3.1 方法一:ICMP Ping(最基础)

检测 IP 是否可达:

BASH
# 简单 ping
ping 服务器IP -c 10

# 指定间隔和包大小
ping 服务器IP -c 20 -i 0.2 -s 1400

结果解读:

结果含义
全部正常,延迟稳定IP 正常
部分丢包网络不稳定或 QoS
全部超时IP 可能被黑洞或服务器关机
海外通但国内不通IP 被 GFW 黑洞

局限: ICMP 可能被单独封锁(只禁 ping 不禁 TCP),所以只能做初步判断。

3.2 方法二:TCP 连接测试(最常用)

检测 TCP 端口是否开放:

BASH
# telnet 测试
telnet 服务器IP 端口

# nc 测试(更推荐)
nc -vz 服务器IP 端口

# tcping(支持测延迟)
tcping 服务器IP 端口

# curl 测试(HTTP/HTTPS)
curl -v -m 5 http://服务器IP:端口
curl -v -m 5 --insecure https://服务器IP:端口

结果解读:

结果含义
Connected / succeeded端口开放
Connection refused端口未监听
Connection timed out端口被墙或防火墙拦截
Connection reset端口被 RST 注入封锁

3.3 方法三:UDP 连接测试(针对 UDP 协议)

TUIC、Hysteria2 等基于 UDP 的协议需要测 UDP:

BASH
# nc UDP 测试
nc -vuz 服务器IP 端口

# nmap UDP 扫描
nmap -sU -p 端口 服务器IP

# 使用特定协议测试(如 TUIC)
# 通过客户端日志判断 UDP 连通性

注意: UDP 是无连接的,测试结果不如 TCP 准确。nc -uz 只是检查端口是否有响应,不代表协议本身能通。

3.4 方法四:Traceroute 路由追踪

追踪数据包路径,定位问题出现在哪一跳:

BASH
# Linux/macOS
traceroute 服务器IP

# Windows
tracert 服务器IP

# 更详细的 mtr(推荐)
mtr --report --report-cycles 10 服务器IP

结果解读:

结果含义
最后一跳正常路由正常
中间某跳开始超时问题在该跳之后
国内出口后全部超时可能 GFW 介入
国外段超时国际线路问题

3.5 方法五:协议级测试(最精准)

前面四种都是网络层测试,最精准的是直接用代理客户端测试:

BASH
# 用 curl 通过代理测试
https_proxy=http://127.0.0.1:7890 curl -I https://www.google.com

# 测试延迟和下载速度
https_proxy=http://127.0.0.1:7890 curl -o /dev/null -w "%{time_total}" https://speed.cloudflare.com/__down?bytes=100000000

# 用代理链测试节点是否正常工作
# 先连上代理,然后访问 https://ip.sb 看出口 IP 是否正确

如果以上测试都通过,说明节点本身是健康的。 如果客户端显示连不上,问题在客户端配置。


四、自动化:节点健康检测脚本

手动检测太麻烦?写个脚本自动监控。

4.1 基础版 Bash 脚本

BASH
#!/bin/bash

# 配置
SERVER_IP="你的服务器IP"
SERVER_PORT="你的端口"
CHECK_INTERVAL=300  # 5分钟检查一次
LOG_FILE="/var/log/node-check.log"
TELEGRAM_BOT_TOKEN="你的Bot Token"
TELEGRAM_CHAT_ID="你的Chat ID"

# 发送通知
send_notification() {
    local message="$1"
    curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
        -d "chat_id=${TELEGRAM_CHAT_ID}" \
        -d "text=${message}" > /dev/null
    echo "$(date '+%Y-%m-%d %H:%M:%S') [通知] $message" >> "$LOG_FILE"
}

# 检查 TCP 端口
check_tcp() {
    timeout 5 bash -c "cat < /dev/null > /dev/tcp/${SERVER_IP}/${SERVER_PORT}"
    return $?
}

# 检查 ICMP
check_icmp() {
    ping -c 3 -W 2 "$SERVER_IP" > /dev/null 2>&1
    return $?
}

# 主检查逻辑
main() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') 开始检查节点 ${SERVER_IP}:${SERVER_PORT}" >> "$LOG_FILE"
    
    # TCP 检测
    if check_tcp; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') [正常] TCP 端口连通" >> "$LOG_FILE"
        TCP_STATUS="正常"
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') [异常] TCP 端口不通" >> "$LOG_FILE"
        TCP_STATUS="异常"
    fi
    
    # ICMP 检测
    if check_icmp; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') [正常] ICMP Ping 正常" >> "$LOG_FILE"
        ICMP_STATUS="正常"
    else
        echo "$(date '+%Y-%m-%d %H:%M:%S') [异常] ICMP Ping 不通" >> "$LOG_FILE"
        ICMP_STATUS="异常"
    fi
    
    # 综合判断
    if [ "$TCP_STATUS" = "异常" ] && [ "$ICMP_STATUS" = "异常" ]; then
        send_notification "🚨 节点异常\nIP: ${SERVER_IP}\n端口: ${SERVER_PORT}\nICMP: 不通\nTCP: 不通\n可能原因: 服务器宕机或 IP 被黑洞"
    elif [ "$TCP_STATUS" = "异常" ] && [ "$ICMP_STATUS" = "正常" ]; then
        send_notification "⚠️ 节点端口异常\nIP: ${SERVER_IP}\n端口: ${SERVER_PORT}\nICMP: 正常\nTCP: 不通\n可能原因: 端口被墙或服务未运行"
    fi
}

# 持续监控
while true; do
    main
    sleep "$CHECK_INTERVAL"
done

4.2 Python 进阶版(支持多节点)

PYTHON
#!/usr/bin/env python3
import socket
import subprocess
import time
import json
from datetime import datetime

class NodeChecker:
    def __init__(self, config_file="nodes.json"):
        with open(config_file) as f:
            self.nodes = json.load(f)
        self.results = {}
    
    def check_tcp(self, ip, port, timeout=5):
        """检测 TCP 端口"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(timeout)
            result = sock.connect_ex((ip, port))
            sock.close()
            return result == 0
        except Exception:
            return False
    
    def check_icmp(self, ip, count=3):
        """检测 ICMP"""
        try:
            result = subprocess.run(
                ['ping', '-c', str(count), '-W', '2', ip],
                capture_output=True, timeout=10
            )
            return result.returncode == 0
        except Exception:
            return False
    
    def check_http(self, ip, port, use_https=False, timeout=5):
        """检测 HTTP/HTTPS 可达性"""
        import urllib.request
        protocol = "https" if use_https else "http"
        url = f"{protocol}://{ip}:{port}"
        try:
            req = urllib.request.Request(url, method='HEAD')
            req.add_header('User-Agent', 'NodeChecker/1.0')
            response = urllib.request.urlopen(req, timeout=timeout)
            return True, response.getcode()
        except Exception as e:
            return False, str(e)
    
    def diagnose(self, node):
        """综合诊断"""
        ip = node['ip']
        port = node['port']
        name = node['name']
        
        icmp_ok = self.check_icmp(ip)
        tcp_ok = self.check_tcp(ip, port)
        
        # 判断状态
        if icmp_ok and tcp_ok:
            status = "正常"
            reason = "节点健康"
        elif not icmp_ok and not tcp_ok:
            status = "异常"
            reason = "IP可能被黑洞或服务器宕机"
        elif icmp_ok and not tcp_ok:
            status = "异常"
            reason = "端口被墙或服务未运行"
        else:
            status = "可疑"
            reason = "ICMP不通但TCP通,可能禁ping"
        
        return {
            'name': name,
            'ip': ip,
            'port': port,
            'status': status,
            'icmp': '通' if icmp_ok else '不通',
            'tcp': '通' if tcp_ok else '不通',
            'reason': reason,
            'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def check_all(self):
        """检查所有节点"""
        print(f"{'='*60}")
        print(f"节点健康检查 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"{'='*60}")
        
        for node in self.nodes:
            result = self.diagnose(node)
            self.results[node['name']] = result
            
            icon = "✅" if result['status'] == "正常" else "❌"
            print(f"\n{icon} {result['name']}")
            print(f"   IP: {result['ip']}:{result['port']}")
            print(f"   状态: {result['status']}")
            print(f"   ICMP: {result['icmp']} | TCP: {result['tcp']}")
            print(f"   原因: {result['reason']}")
        
        # 统计
        total = len(self.results)
        normal = sum(1 for r in self.results.values() if r['status'] == "正常")
        print(f"\n{'='*60}")
        print(f"总计: {total} 个节点 | 正常: {normal} | 异常: {total - normal}")
        print(f"{'='*60}")

# 配置文件 nodes.json 示例:
# [
#   {"name": "东京01", "ip": "1.2.3.4", "port": 443},
#   {"name": "新加坡01", "ip": "5.6.7.8", "port": 8443}
# ]

if __name__ == "__main__":
    checker = NodeChecker()
    checker.check_all()

4.3 配置文件 nodes.json

JSON
[
  {
    "name": "🇯🇵 东京 IEPL",
    "ip": "1.2.3.4",
    "port": 443
  },
  {
    "name": "🇸🇬 新加坡 BGP",
    "ip": "5.6.7.8",
    "port": 8443
  },
  {
    "name": "🇺🇸 洛杉矶 CN2",
    "ip": "9.10.11.12",
    "port": 2087
  }
]

4.4 加入定时任务

BASH
# 每 10 分钟检查一次
crontab -e

# 添加:
*/10 * * * * /usr/bin/python3 /opt/node-checker/check.py >> /var/log/node-check.log 2>&1

五、节点复活方案

5.1 端口被墙 → 换端口

最简单的方案:

BASH
# 修改服务端配置,换一个高位端口(如 40000-60000 之间)
# 然后重启服务
systemctl restart sing-box

# 客户端同步更新端口

端口选择建议:

端口范围特点被墙概率
443HTTPS 标准端口中等(如果IP没被墙)
80HTTP 标准端口中等
8080替代 HTTP较高
8443替代 HTTPS较低
40000-60000高位随机端口最低

建议: 自建节点尽量用 40000+ 的随机高位端口,被墙概率最低。

5.2 IP 被黑洞 → 换 IP

如果 IP 被黑洞,只能换 IP:

5.3 协议被识别 → 换协议

如果协议特征被识别:

被识别协议建议切换到
Shadowsocks(旧版)VLESS+Reality / TUIC
VMess(无 TLS)VLESS+XTLS / Hysteria2
Trojan(默认配置)Trojan+TLS(加强配置)
简单 TLSREALITY / XTLS

5.4 使用 CDN 隐藏真实 IP

Cloudflare 等 CDN 可以隐藏服务器真实 IP:

  1. 域名接入 Cloudflare
  2. 只暴露 CDN 的 IP
  3. 真实服务器 IP 永不暴露

注意: 只有支持 WebSocket/gRPC 的协议才能走 CDN(如 VLESS+WS+CDN)。


六、总结

6.1 快速诊断流程图

PLAINTEXT
节点连不上?
    │
    ├─→ Ping.pe 测试 IP
    │       │
    │       ├─→ 国内外都不通 → 服务器挂了
    │       │
    │       └─→ 国内不通,海外通 → IP 被黑洞
    │
    ├─→ port.ping.pe 测试端口
    │       │
    │       ├─→ 国内外都不通 → 服务没运行
    │       │
    │       └─→ 国内不通,海外通 → 端口被墙
    │
    └─→ 客户端日志分析
            │
            ├─→ timeout → 网络层问题
            │
            ├─→ reset → 端口/协议被识别
            │
            └─→ 其他错误 → 配置问题

6.2 检测工具速查表

工具检测类型适用场景
Ping.peICMP判断 IP 是否被黑洞
port.ping.peTCP判断端口是否被墙
tcpingTCP + 延迟测试 TCP 连通性和延迟
mtr路由追踪定位网络问题节点
curl + 代理协议级测试代理是否正常工作
自定义脚本综合自动化监控

6.3 预防被墙的建议


【相关推荐】


节点被墙不可怕,可怕的是不知道怎么判断、不知道怎么解决。掌握这套检测方法,你就能在问题出现的第一时间定位原因,而不是盲目地切来切去。🚀

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/node-health-check-guide-2026/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。