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

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

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

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