V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
httpbin - 协议调试工具
httpstatuses - 协议状态码查询
httpie - cURL-like tool for humans
Fiddler
leaflxh
V2EX  ›  HTTP

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

  •  
  •   leaflxh · 2019-08-07 11:38:20 +08:00 · 3914 次点击
    这是一个创建于 1695 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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