应限制端口9999仅白名单ip访问,结合iptables限流,并在onopen中分层校验ip与请求频次,避免内存泄漏需清理static缓存、闭包引用及协程连接,https/wss必须配置有效pem证书及完整证书链。

怎么配置安全组和防火墙才不被扫端口
9999 端口(或你自定义的 Swoole 监听端口)一旦暴露在公网,没做访问控制,5 分钟内就会被自动化扫描器盯上。宝塔面板里点“安全”加端口只是第一步,关键在方向——公网入方向和公网出方向都得显式放行,否则某些云厂商(如阿里云、腾讯云)默认出方向也拦截,导致健康检查失败或日志上报中断。
更稳妥的做法是:只允许白名单 IP 访问,比如 CDN 回源 IP 段、运维跳板机 IP;若必须全开放,至少配合 iptables 或 ufw 做连接频次限制:
- 用
iptables -A INPUT -p tcp --dport 9999 -m connlimit --connlimit-above 10 -j REJECT防止单 IP 建立过多连接 - 避免直接在宝塔“安全”页删掉所有规则再重开——容易误关 SSH(22 端口)导致失联
- 别把
0.0.0.0/0当万能解,它等于把门敞开等撞
onOpen 里怎么拦恶意 IP 和异常连接
swoole_websocket_server::onOpen 是第一道过滤闸,但很多人只做简单 in_array 判断,漏掉动态 IP、代理头伪造、高频重连等场景。
真实业务中建议分两层处理:
- 基础层:取
$request->server['remote_addr'],查本地缓存(如Swoole\Table)是否超限(比如 1 分钟内 >5 次新连接),超则$server->close($request->fd) - 增强层:解析
$request->header['x-forwarded-for'](仅当走 Nginx 反向代理时可信),结合 Redis 做分布式限流,驱动选redis而非local - 注意:不要在
onOpen里调用阻塞 IO(如 file_get_contents、curl),会卡住整个 Reactor 线程
为什么 max_request 设成 10000 还会内存泄漏
max_request 是兜底手段,不是根治方案。Swoole 进程常驻,只要代码里有 static 数组、全局变量缓存、闭包循环引用,worker 重启前内存就一直涨。
典型翻车点:
- 类里写
public static $cache = [];,每次请求往里push,从不清理 - 用
Swoole\Timer::tick时,闭包里用了$this或未清空$timerId,导致对象无法 GC - 协程里开了 Redis/MySQL 连接但没
defer关闭,连接句柄越积越多
验证方法:用 kill -USR2 {master_pid} 触发内存统计,看 memory_usage 是否随请求单调上升。
HTTPS 和 WSS 不配证书会出什么错
浏览器强制要求 WebSocket 安全上下文,ws:// 在 HTTPS 页面里会被直接拒绝连接,控制台报 SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS。
后端不配 TLS,问题更隐蔽:
- 客户端能连上
ws://,但中间人可篡改消息(比如把登录 token 替换成攻击者自己的) - 用 Let’s Encrypt 免费证书即可,但注意:Swoole
ssl_cert_file和ssl_key_file必须指向 PEM 格式文件,不能是 PFX 或带密码的 KEY - 别在
onMessage里手动验证书——那是 TLS 层该干的事,应用层只管业务逻辑
最常被忽略的是证书链:Nginx 反代 Swoole 时,若只配了域名证书没配中间 CA,iOS 和部分 Android 客户端会握手失败,错误提示却是“连接超时”。










