强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

IRC 服务器搭建完全指南 / 第 11 章:故障排查

第 11 章:故障排查

当 IRC 服务器出现问题时,系统化的排查方法是快速恢复的关键。本章整理了最常见的故障场景及其诊断方案。


11.1 故障排查流程

开始排查
    │
    ├── 1. 确认故障现象
    │   ├── 能否连接?
    │   ├── 能否认证?
    │   ├── 能否加入频道?
    │   └── 能否发送消息?
    │
    ├── 2. 检查服务端状态
    │   ├── 进程是否运行?
    │   ├── 端口是否监听?
    │   ├── 配置文件是否正确?
    │   └── 磁盘/内存是否足够?
    │
    ├── 3. 检查网络
    │   ├── 防火墙规则?
    │   ├── DNS 解析?
    │   └── TLS 证书?
    │
    ├── 4. 查看日志
    │   ├── 服务端日志
    │   ├── 系统日志
    │   └── 客户端日志
    │
    └── 5. 定位并修复
        └── 验证修复 → 结束

11.2 连接问题

11.2.1 无法连接到服务器

症状: 客户端显示 “Connection refused” 或 “Connection timed out”

诊断步骤:

# 1. 检查进程
ps aux | grep -E 'ergo|unrealircd|inspircd'
systemctl status ergo

# 2. 检查端口监听
ss -tlnp | grep -E '6697|6667|8080'
# 如果没有输出,说明服务未监听

# 3. 检查防火墙
sudo iptables -L -n | grep -E '6697|6667'
sudo ufw status

# 4. 本地连接测试
openssl s_client -connect localhost:6697 -brief
# 或
telnet localhost 6697

# 5. 远程连接测试
nc -zv your-server-ip 6697

常见原因与解决方案:

原因 症状 解决方案
服务未启动 Connection refused systemctl start ergo
端口未开放 Connection timed out ufw allow 6697/tcp
配置错误 服务启动失败 检查配置语法
地址绑定错误 本地可连远程不行 检查 listen 配置中的 IP
DNS 解析失败 Unknown host 检查 DNS 记录

11.2.2 TLS 握手失败

症状: “SSL handshake failed” 或 “Certificate error”

# 1. 测试 TLS 连接
openssl s_client -connect irc.example.com:6697 \
  -servername irc.example.com

# 2. 检查证书有效性
openssl x509 -in /path/to/server.crt -text -noout

# 3. 检查证书过期
openssl x509 -in /path/to/server.crt -enddate -noout

# 4. 检查证书与私钥匹配
openssl x509 -noout -modulus -in server.crt | md5sum
openssl rsa -noout -modulus -in server.key | md5sum
# 两个 md5sum 应该一致

# 5. 检查证书链
openssl verify -CAfile chain.pem server.crt

# 6. 检查 TLS 版本
openssl s_client -connect irc.example.com:6697 -tls1_2
openssl s_client -connect irc.example.com:6697 -tls1_3

常见 TLS 问题:

问题 原因 解决方案
自签名证书不被信任 客户端不信任 CA 安装 Let’s Encrypt 证书
证书过期 证书有效期到了 certbot renew
主机名不匹配 CN/SAN 与域名不一致 重新申请正确域名的证书
私钥权限 服务端无法读取私钥 chmod 600 server.key
协议版本不匹配 客户端/服务端 TLS 版本不同 配置支持 TLS 1.2+

11.2.3 SASL 认证失败

症状: “SASL authentication failed” 或 “Password incorrect”

# 1. 检查 NickServ 密码
# 在 IRC 客户端中
/NS IDENTIFY mypassword

# 2. 检查 SASL 配置(Weechat)
/set irc.server.example.*

# 3. 检查服务包日志
tail -f /opt/anope/logs/services.log | grep -i sasl

# 4. 手动测试 SASL
# 生成 PLAIN 认证字符串
echo -ne '\0alice\0mypassword' | base64
# 输出: AGFsaWNlAG15cGFzc3dvcmQ=

# 5. 检查 SASL 机制是否支持
# 连接时发送
CAP LS 302
# 查看服务器返回的 sasl 机制列表

常见 SASL 问题:

问题 原因 解决方案
密码错误 输入了错误的密码 重置密码 /NS SET PASSWORD
机制不支持 客户端与服务器机制不匹配 检查支持的 SASL 机制
证书未注册 EXTERNAL 模式未添加证书 /NS CERT ADD
服务包未运行 NickServ 未在线 检查 Anope/Atheme 状态

11.3 服务器运行问题

11.3.1 服务启动失败

# 1. 查看启动错误
journalctl -u ergo --no-pager -n 50
# 或
tail -50 /opt/ergo/logs/ergo.log

# 2. 验证配置文件
# UnrealIRCd
/opt/unrealircd/unrealircd configtest

# InspIRCd
/opt/inspircd/bin/inspircd --configtest

# Ergo(手动启动观察输出)
./ergo run --config ergo.yaml

# 3. 检查文件权限
ls -la /opt/ergo/
ls -la /opt/ergo/ergo.yaml
ls -la /opt/ergo/certs/

# 4. 检查端口冲突
ss -tlnp | grep :6697
# 如果被其他进程占用
lsof -i :6697

常见启动失败原因:

错误信息 原因 解决方案
Address already in use 端口被占用 杀死占用进程或更换端口
Permission denied 权限不足 检查文件权限
Cannot open config 配置文件不存在 检查路径
Invalid syntax 配置语法错误 修正配置
Certificate not found TLS 证书缺失 检查证书路径
Database locked 数据库被锁定 删除 .lock 文件

11.3.2 服务器内存占用过高

# 1. 检查进程内存
ps aux | grep ergo | awk '{print $2, $4, $6, $11}'
# 或使用 top/htop

# 2. 检查连接数
ss -tnp | grep :6697 | wc -l

# 3. 检查日志文件大小
du -sh /opt/ergo/logs/*

# 4. 配置内存限制(Docker)
# docker-compose.yml
# mem_limit: 512m

优化建议:

# Ergo 内存优化配置
limits:
  max-connections-per-ip: 3
  # 限制频道数
  channels-per-client: 50
  # 减少历史记录
  away-count: 3
  whowas-entries: 5

11.3.3 频道/用户数据丢失

# 1. 检查数据库文件
ls -la /opt/ergo/data/ergo.db

# 2. 检查最近备份
ls -lt /opt/backups/ergo/

# 3. 恢复备份
systemctl stop ergo
cp /opt/backups/ergo/ergo_latest.db /opt/ergo/data/ergo.db
systemctl start ergo

# 4. 检查文件系统
df -h

11.4 网络问题

11.4.1 服务器互联失败

# 1. 检查互联端口
ss -tlnp | grep :6900

# 2. 测试互联连接
openssl s_client -connect other-server:6900

# 3. 检查互联配置
# UnrealIRCd
grep -A 10 'link' /opt/unrealircd/conf/unrealircd.conf

# 4. 检查密码是否匹配
# 两端的 link password 必须一致

# 5. 检查 SID 是否冲突
# 每个服务器的 SID 必须唯一

互联问题排查清单:

检查项 状态 说明
互联端口开放 6900/TCP
TLS 证书有效 双方证书有效
密码一致 link password 一致
SID 唯一 不同 SID
防火墙规则 允许互联 IP
DNS 解析 服务器名解析正确

11.4.2 DNS 问题

# 1. 检查 DNS 解析
dig irc.example.com A
dig irc.example.com AAAA
dig _irc._tcp.example.com SRV

# 2. 检查反向解析
dig -x your-server-ip

# 3. 测试 DNS 传播
nslookup irc.example.com 8.8.8.8
nslookup irc.example.com 1.1.1.1

# 4. 检查 hosts 文件
cat /etc/hosts | grep irc

11.4.3 IPv6 连接问题

# 1. 检查 IPv6 支持
ip -6 addr show

# 2. 测试 IPv6 连接
telnet -6 irc.example.com 6697

# 3. 检查 IPv6 监听
ss -tlnp | grep -6

# 4. 临时禁用 IPv6
sysctl -w net.ipv6.conf.all.disable_ipv6=1

11.5 调试工具

11.5.1 命令行调试工具

工具 用途 命令
openssl s_client TLS 调试 openssl s_client -connect host:6697
nc / ncat TCP 连接测试 nc -v host 6697
nmap 端口扫描 nmap -p 6697 host
tcpdump 抓包分析 tcpdump -i eth0 port 6697
wireshark 图形化抓包 GUI 工具
strace 系统调用跟踪 strace -p <pid>
lsof 打开文件查看 lsof -i :6697
dig DNS 查询 dig irc.example.com
curl HTTP 测试 curl -v https://irc.example.com
journalctl systemd 日志 journalctl -u ergo -f

11.5.2 手动 IRC 协议调试

# 使用 netcat 手动发送 IRC 命令
{
    echo "NICK testbot"
    echo "USER testbot 0 * :Test Bot"
    sleep 2
    echo "JOIN #test"
    sleep 2
    echo "PRIVMSG #test :Hello, world!"
    sleep 5
    echo "QUIT :Testing"
} | openssl s_client -connect irc.example.com:6697 -quiet

11.5.3 IRC 内置调试命令

/* Oper 调试命令 */
/REHASH                    /* 重载配置 */
/CONNECT <server>          /* 连接到服务器 */
/SQUIT <server>            /* 断开服务器 */
/TIME                      /* 查看服务器时间 */
/TRACE <target>            /* 跟踪路由 */
/WHOWAS <nick>             /* 历史用户查询 */
/LUSERS                    /* 服务器统计 */
/LINKS                     /* 服务器拓扑 */
/MAP                       /* 服务器地图 */

11.5.4 Weechat 调试

# 启用 Weechat 调试日志
/export DEBUG 1

# 查看服务器原始消息
/set irc.look.debug_raw 1

# 查看 SASL 调试
/set irc.server.example.sasl_timeout 60

11.6 日志分析

11.6.1 常见日志模式

# 搜索连接错误
grep -i 'error\|failed\|denied' /opt/ergo/logs/ergo.log

# 统计连接数
grep 'Client connected' /opt/ergo/logs/ergo.log | wc -l

# 查找断开连接
grep 'Client disconnected' /opt/ergo/logs/ergo.log

# 查看封禁
grep -i 'kline\|gline\|zline\|shun' /opt/ergo/logs/ergo.log

# 统计错误频率
grep -c 'ERROR' /opt/ergo/logs/ergo.log

# 实时监控
tail -f /opt/ergo/logs/ergo.log | grep --color -E 'error|warn|fail'

# 按时间段过滤
grep '2026-05-10' /opt/ergo/logs/ergo.log

11.6.2 日志级别调整

# Ergo 临时调整日志级别
logging:
  - method: "file"
    filename: "/opt/ergo/logs/ergo.log"
    level: "debug"          # 临时设为 debug

11.7 常见问题 FAQ

Q1: 用户无法注册昵称

症状: /NS REGISTER 返回 "Registration is disabled"
原因: 配置中禁用了注册
解决:
  # Ergo
  accounts:
    registration:
      enabled: true

  # Anope
  nickserv {
      registration yes
  }

Q2: 频道模式不生效

症状: 设置了 +m 但非成员仍能发言
原因: 模式设置不正确,或有 +n 外的权限冲突
排查:
  /mode #channel         # 查看当前模式
  /mode #channel +mn     # 同时设置 +m 和 +n

Q3: 服务器占用 CPU 100%

症状: CPU 使用率持续 100%
可能原因:
  - 死循环脚本/Bot
  - 大量并发连接
  - 配置错误导致的循环
排查:
  top -c | grep ergo
  strace -p <pid> -c      # 统计系统调用
  # 检查是否有异常 Bot

Q4: 用户被莫名封禁

症状: 用户报告无法连接
排查:
  # 查看服务器封禁列表
  /STATS k               # K-lines
  /STATS g               # G-lines
  /STATS z               # Z-lines

  # 检查 fail2ban
  sudo fail2ban-client status ircd

  # 检查 IP 是否被封
  sudo iptables -L -n | grep <user-ip>

Q5: 桥接 Bot 消息延迟

症状: 桥接消息延迟 10 秒以上
可能原因:
  - 网络延迟
  - 桥接进程资源不足
  - API 速率限制
排查:
  # 检查桥接进程
  docker logs matterbridge --tail 50

  # 检查网络延迟
  ping bridge-server

  # 检查速率限制日志
  grep 'rate limit' /var/log/matterbridge.log

Q6: WebSocket 连接失败

症状: Web 客户端无法通过 WebSocket 连接
排查:
  # 检查 WebSocket 端口
  ss -tlnp | grep 8443

  # 测试 WebSocket
  wscat -c wss://irc.example.com:8443

  # 检查 Nginx 配置
  nginx -t

11.8 性能优化

11.8.1 连接优化

# Ergo 性能配置
server:
  # 启用 TCP Fast Open
  # (需要系统支持)
  # tor-enabled: false

limits:
  # 限制连接数
  max-connections-per-ip: 3

  # 减少资源占用
  channels-per-client: 50
  away-count: 3
  whowas-entries: 5

11.8.2 系统级优化

# 增加文件描述符限制
echo "ergo soft nofile 65536" >> /etc/security/limits.conf
echo "ergo hard nofile 65536" >> /etc/security/limits.conf

# 优化内核参数
cat >> /etc/sysctl.conf << EOF
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
EOF
sysctl -p

11.9 ⚠️ 注意事项

事项 说明
修改前备份 修改任何配置前先备份
逐项排查 一次只改一个变量
记录变更 记录所有配置变更
灰度发布 重大变更先在测试环境验证
及时更新 关注安全公告并及时更新
监控告警 配置监控和告警系统

扩展阅读


下一章: 第 12 章:最佳实践 — 运维规范、社区管理、备份策略和性能优化。