websocket 实现了统计在线人数,那 websocket 该如何防爆,防跨站?

2021-01-25 10:27:27 +08:00
 douyacun

站点在线人数统计实现思路: https://www.douyacun.com/article/d189d3d86915f5ff4c3be6a517570a0a

  1. 如何检测跨站点 WebSocket 劫持漏洞
    1. 我使用 jwt 来下发 token
    2. 申请 token 的接口也是对外暴露的
  2. 同一设备 ws 连接数如何限制,避免 bug 导致连接数过多导致服务挂掉
5324 次点击
所在节点    Go 编程语言
29 条回复
airyland
2021-01-25 10:57:15 +08:00
侧边栏弹出来遮住右侧内容是 feature?
ferock
2021-01-25 10:58:03 +08:00
用 tcp 长链统计在线人数???也是醉了
jobsofchina
2021-01-25 10:59:56 +08:00
@ferock 这种方式有什么问题吗?展开说说
notgod
2021-01-25 11:17:37 +08:00
@jobsofchina 量,N 万 百万 在线, 你试下
douyacun
2021-01-25 11:18:20 +08:00
@ferock wss 统计在线人数,代价还是很低的,一般只是端口不够用

我之前的测试,库使用 gorilla/websocket 1 万个连接测试

占用 147.93MB RAM, 平均连接每个占用 15kb 测试代码见:[github gwebsocket]( https://github.com/douyacun/gwebsocket/blob/master/v3_ws_ulimit/wsserver.go)

```shell
(pprof) top
Showing nodes accounting for 137.93MB, 93.24% of 147.93MB total
Dropped 6 nodes (cum <= 0.74MB)
Showing top 10 nodes out of 51
flat flat% sum% cum cum%
73.79MB 49.88% 49.88% 73.79MB 49.88% bufio.NewWriterSize
34.63MB 23.41% 73.29% 34.63MB 23.41% bufio.NewReaderSize
11MB 7.44% 80.73% 11MB 7.44% runtime.malg
4MB 2.70% 83.44% 5.50MB 3.72% net/textproto.(*Reader).ReadMIMEHeader
3MB 2.03% 85.46% 3.50MB 2.37% github.com/gorilla/websocket.newConn
3MB 2.03% 87.49% 10.50MB 7.10% net/http.readRequest
2.50MB 1.69% 89.18% 16.50MB 11.16% net/http.(*conn).readRequest
2.50MB 1.69% 90.87% 3.50MB 2.37% context.propagateCancel
2MB 1.35% 92.23% 2MB 1.35% syscall.anyToSockaddr
1.50MB 1.01% 93.24% 1.50MB 1.01% net.newFD
(pprof) web
failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in $PATH
(pprof) list flat
Total: 147.93MB
```
goroutine 是 10003,每个 goroutine 占用 4kb 的内存

```shell
(pprof) top
Showing nodes accounting for 10001, 100% of 10003 total
Dropped 24 nodes (cum <= 50)
Showing top 10 nodes out of 19
flat flat% sum% cum cum%
10001 100% 100% 10001 100% runtime.gopark
0 0% 100% 9998 100% bufio.(*Reader).Peek
0 0% 100% 9998 100% bufio.(*Reader).fill
0 0% 100% 9999 100% github.com/gorilla/websocket.(*Conn).NextReader
0 0% 100% 9999 100% github.com/gorilla/websocket.(*Conn).ReadMessage
0 0% 100% 9999 100% github.com/gorilla/websocket.(*Conn).advanceFrame
0 0% 100% 9998 100% github.com/gorilla/websocket.(*Conn).read
0 0% 100% 9999 100% internal/poll.(*FD).Read
0 0% 100% 10001 100% internal/poll.(*pollDesc).wait
0 0% 100% 10001 100% internal/poll.(*pollDesc).waitRead (inline)
(pprof) list flat
Total: 10003
(pprof)
```
douyacun
2021-01-25 11:21:25 +08:00
@airyland 刚才本子打开也恶心到我自己了,都是在外接显示上开发的
krixaar
2021-01-25 11:21:56 +08:00
@jobsofchina 第一,可能会有跨站点 WebSocket 劫持漏洞;第二,同一设备出 bug 导致连接数过多会让服务挂掉 🤣
zxlzy
2021-01-25 11:25:39 +08:00
在线人数这种需求建议还是轮询吧。
douyacun
2021-01-25 11:27:41 +08:00
@krixaar 这几个问题也是这个帖子发布的目的,也是想看看大家是怎么玩的,有什么好的思路,之前有个安卓的同学就这么搞过我~,吐血的经历
douyacun
2021-01-25 11:29:02 +08:00
@zxlzy 自己的站点,当然随意玩耍了,主要是有 wss 使用的场景,如何防护一下
rust
2021-01-25 12:53:43 +08:00
直接把用户登入的状态放在 Redis 里边啊,设置个超时时间,然后没有统计有多少数据存在不就行了
rust
2021-01-25 12:56:04 +08:00
@rust 我的错,没看清标题.
抖音 APP 在使用 WS 传输 Protobuf 编码之后的数据,同时也使用了 token,这也算是一个比较好的解决方案吧
bbao
2021-01-25 13:31:33 +08:00
@rust 登入状态放 redis 里,如何统计有多少数据存在?命令是啥呀?
SaltyLeo
2021-01-25 14:21:32 +08:00
额,不同的语言写法不同。

思路就是丢个唯一值到客户端 cookie,再把这个值丢到 redis 设置个超时,然后每次新请求获取这个值,如果这个值还在 redis 就不做操作,返回当前 redis 总计多少个 key 。

如果这个值不在 redis 里,就再丢一个唯一值到客户端,本地新增一个记录,返回 key 总数。
abersheeran
2021-01-25 14:27:30 +08:00
初次访问你网站的时候,下发一个 cookie. 后续 websocket 携带这个 cookie 去访问. 同一个 cookie 的直接 close 掉. 不带 cookie 的也 close 掉.
learningman
2021-01-25 17:19:17 +08:00
所有用户的这个值都应该是一样的啊,为啥要 ws
直接服务端统计然后直接暴露一个固定的接口轮询不就好了
hantsy
2021-01-25 19:54:40 +08:00
Client 与 Server 之间可以用 RabbitMQ 来缓和压力,这个在 Spring 中很好的支持,通过 STOMP 协议,客户端也用 sockjs 支持。
BBCCBB
2021-01-25 20:28:08 +08:00
设置一个能承受的连接上限, 比如好几十万. 网站最大就显示这么多个数..
BBCCBB
2021-01-25 20:28:26 +08:00
超过就直接连接失败
ihipop
2021-01-25 21:24:09 +08:00
@douyacun 一个端口服务能服务多少用户和服务器本地有多少个端口(也就是你认为的那个常规是 65535 的数值)没关系。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/748054

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX