在写一个 HTTP 服务器,想问一下请求报文中的 Content-Length 该如何验证

2019-08-07 11:38:20 +08:00
 leaflxh

平台是 linux,使用 select 函数来进行 IO 复用

对于每一个已连接的描述符,会有一个缓冲区来存储其发送过来的数据。(存储数据的逻辑在文尾)

由于是来多少数据就往缓冲区里存多少数据,这样如果有两个及以上的报文同时进了缓冲区,需要对他们进行分割。

我打算是先以两个\r\n 来进行分割,取出缓冲区里的第一个报文头,如果报文头里有 Content-Length 字段,就继续从缓冲区里读相应长度的数据。

然后就遇到了问题,假如 Content-Length 是伪造的,数值大于实际发送过来的数据的长度,那么会读到下一个报文的报文。

所以想问一下各位有什么解决办法吗

4124 次点击
所在节点    HTTP
13 条回复
leaflxh
2019-08-07 11:50:36 +08:00
zzzbkl
2019-08-07 12:08:58 +08:00
rfc 里面描述 content-length 时用的是 should 而不是 must,通过它来验证长度确实不靠谱。同好奇
009694
2019-08-07 12:21:29 +08:00
content-length 是用来验证报文完整性而不是用来听之任之长度读取的吧。。
abcbuzhiming
2019-08-07 12:38:30 +08:00
楼主,我觉得你的思路不对,首先 Http 是基于 TCP 的,每个连接的缓冲区都是独立的,现在假设有一个有恶意的人,伪造了 Content-Length,把它变的更长,那么就算你读下去,你读到的仍然是这个人后续发来的包,你就把后续得到的包数据也当成是 request body 的内容好了。这有什么问题呢,你是告诉我有这么长的,我就读这么长,我看过 Nginx 的实现,只有在读到不够长度的数据时才会报错断开连接,但是只要后续能继续读到数据,就会继续读下去,http 的 content-length 就是 body 长度指示器,只要它不超过 http 协议定义的最大长度,你就照着读,没错的
ipwx
2019-08-07 12:40:18 +08:00
@abcbuzhiming 我觉得楼主可能担心客户端伪造了超长 content length
xenme
2019-08-07 12:48:13 +08:00
@ipwx 一段时间没数据或者 idle 很久就可以断开连接了
des
2019-08-07 12:49:22 +08:00
补充一点,仅仅两个\r\n 来进行分割,也是考虑不完全的,因为有可能对方不发这个,然后就挂了
abcbuzhiming
2019-08-07 14:00:12 +08:00
@ipwx 超长的 content length 可以被 http 服务器的最大包长参数限制,主流的 http 服务器实现都带有这个参数,一旦超了直接 close socket
walkman660
2019-08-07 15:16:57 +08:00
觉得楼主可以试下在已有开源的 HTTP SERVER 做修改满足需求
自己写一边太麻烦了
leaflxh
2019-08-07 16:00:49 +08:00
🌚决定直接关闭连接,因为请求者发送的数据长度扰乱了本次连接的缓冲区管理
julyclyde
2019-08-07 16:06:53 +08:00
首先 HTTP 是基于 TCP 的
TCP 不是报文,而是流
只有坚信流式思维才能想明白这个问题
tabris17
2019-08-07 16:10:52 +08:00
根据 content-length 来截断数据包这个思路本身就有问题吧
momocraft
2019-08-30 15:09:28 +08:00
content-length 是用户传的(而且和其他请求一样是可以随便造的)。服务器能处理正确情况,并在出错时继续稳定运行就可。

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

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

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

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

© 2021 V2EX