Swoole服务端安全设置怎么做_Swoole服务器防护详解【详解】

2次阅读

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

Swoole服务端安全设置怎么做_Swoole服务器防护详解【详解】

怎么配置安全组和防火墙才不被扫端口

9999 端口(或你自定义的 swoole 监听端口)一旦暴露在公网,没做访问控制,5 分钟内就会被自动化扫描器盯上。宝塔面板里点“安全”加端口只是第一步,关键在方向——公网入方向公网出方向都得显式放行,否则某些云厂商(如阿里云、腾讯云)默认出方向也拦截,导致健康检查失败或日志上报中断。

更稳妥的做法是:只允许白名单 IP 访问,比如 CDN 回源 IP 段、运维跳板机 IP;若必须全开放,至少配合 iptablesufw 做连接频次限制:

  • 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'],查本地缓存(如 SwooleTable)是否超限(比如 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,从不清理
  • SwooleTimer::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_filessl_key_file 必须指向 PEM 格式文件,不能是 PFX 或带密码的 KEY
  • 别在 onMessage 里手动验证书——那是 TLS 层该干的事,应用层只管业务逻辑

最常被忽略的是证书链:Nginx 反代 Swoole 时,若只配了域名证书没配中间 CA,ios 和部分 android 客户端会握手失败,错误提示却是“连接超时”。

text=ZqhQzanResources