Livid
284.65D
539.49D

20260526 - 关于已经修复的 404 bug 的具体原因

  •  1
     
  •   Livid ·
    PRO
    · May 26 · 5312 views

    假设有恶意程序写一个简单的循环,持续访问不存在的 topic id ,那么每次 V2EX 接收到这样的请求,还需要从数据库里查了之后,才知道是无效的 topic id ,这个查询过程就会很浪费资源。

    所以程序中有这样的一种机制,如果 topic id 明显大于某个值,那么就不用查任何数据库资源,直接返回 404 。

    这个值应该是被定期更新并且加上一个足够大的安全值。

    但是由于最近测试服里的一个 bug ,导致这个值自从测试服上线之后,就一直没有被正确更新。因此当 topic id 持续增长,终于来到旧值 + 安全值的边界时,所有新的 topic id 就都 404 跳转了。

    这个问题的根源是测试服上更新全站统计数据进 Memcached Key 时的 bug ,这个 bug 现在已经修复(测试服在这个地方现在使用了单独的 Memcached Key )。

    35 replies    2026-05-29 13:56:37 +08:00
    aheadlead
        1
    aheadlead  
       May 26
    没想到竟然是一个这样简单的问题..
    InDom
        2
    InDom  
       May 26
    啊?
    povsister
        3
    povsister  
       May 26
    我这类似用途是靠 id 算法,全局时间+safe margin 搞的。通过当前时间+id 编码规则就能很容易初步判定 id 是不是伪造的。后面被枚举刷太狠了就又在回源套了层布隆,也是时间校验,安全值范围内允许回源否则一律拦截。

    最开始考虑过全局通过有状态存储维护这个上限,但组件太多依赖一个单点就很麻烦。
    Pipecraft
        4
    Pipecraft  
       May 26
    那现在已经公开秘密了,这个机制似乎不能防止恶意程序了。
    ByteRan
        5
    ByteRan  
       May 26
    有点像千年虫的 BUG
    zhouzoki
        6
    zhouzoki  
       May 26
    现在应该有更好的方法了吧
    MFWT
        7
    MFWT  
       May 26
    @Pipecraft 应该也不追求完全拦住吧,至少抬高一点门槛
    Livid
        8
    Livid  
    MOD
    OP
    PRO
       May 26
    @Pipecraft 很可能这个机制现在也是不需要的。

    一些这样的逻辑都是当年应对某些恶意访问时写的。

    然后年复一年这样的逻辑堆太多,本身也是一种问题。
    itechify
        9
    itechify  
    PRO
       May 26
    哈哈哈哈哈,这也能宕机一天。历史遗留的 feature ,堆积的临时性代码,可以考虑做下减法了🤣
    tty0
        10
    tty0  
       May 26
    可不可以将 ID 改为编码?
    先校验自定义编码是否有效, 有效再去查询数据库.
    JoeJoeJoe
        11
    JoeJoeJoe  
    PRO
       May 26 via iPhone
    哈哈哈哈 这是有历史沉淀的站点才能出现的问题😂
    Tink
        12
    Tink  
    PRO
       May 26
    这个机制感觉可以考虑用别的算法替代掉
    GeorgeV
        13
    GeorgeV  
       May 26   ❤️ 1
    v 站的这个 feature 很有趣,时不时来一下也蛮好的
    Ketteiron
        14
    Ketteiron  
       May 27
    @zhouzoki #6 可以借鉴 b 站当初从数字改成数字字母,或者用算法,或者给数字加个 token ,例如 /t/12345 -> /t/12345/fuawf67adafjmaiowf 。不过对于 V2EX 这种有年头的网站,重构的收益有些低。
    CEBBCAT
        15
    CEBBCAT  
       May 27
    > 假设有恶意程序写一个简单的循环,持续访问不存在的 topic id
    似乎是缓存穿透,如果是恶意请求,那就是 CC 攻击?

    听起来似乎是判定逻辑直接使用了缓存中存储的 topic count 作为 max id ?也许可以在新发帖时主动向 Cache 推送 max id ,记得使用 CAS 原子操作

    BTW Livid 你最后一段似乎语序有些模糊,是这个 bug 让你措手不及吗?注意休息
    ryd994
        16
    ryd994  
       May 27 via Android
    @CEBBCAT #15 不用 CAS ,因为这个值不需要太精确。加个安全余量即可。同一时间生成的新帖 ID 应该差不了多少。
    tf2
        17
    tf2  
       May 27   ❤️ 1
    这个 idea 其实很好。不过可以做得细致一点

    故意设置一些不存在的但是红线主题 id

    谁访问,封谁的 IP
    diudiuu
        18
    diudiuu  
       May 27
    挺好的这个想法
    现在换个算法,可能以前的数据就难受了,最后全是补丁
    yougg
        19
    yougg  
       May 27
    可以通过 ULID 或者 UUID v7 判断时间戳
    ovtfkw
        20
    ovtfkw  
       May 27
    缓存穿透吗,但是现在的主题 id 都是线性增加的,很容易被猜到把,那直接恶意大量访问已经存在的主题呢
    8888888888
        21
    8888888888  
       May 27
    开始还以为是在治理那些中转站或者疑似广告贴,后来发现新帖全 404
    yelog
        22
    yelog  
       May 27
    这个场景感觉使用缓存比较好,max_topic_id 在新增帖子的更新一下缓存。查询帖子判断大于这个 max_topic_id 就 404 。
    keyfunc
        23
    keyfunc  
       May 27
    可以对 ID 额外增加校验位,校验失败就不去查数据库了。
    rrubick
        24
    rrubick  
       May 27 via iPhone
    但是,有的帖子当时是有新增回复的,也就是有人是可以打开的,这又是为啥?
    penisulaS
        25
    penisulaS  
       May 27
    作为站长真不容易啊
    dudu2017
        26
    dudu2017  
       May 27
    昨晚用 chat 分析了一下,也定位到是数据库响应问题
    leekoho
        27
    leekoho  
       May 27
    @dudu2017 V2EX 源码开源了吗? 你这咋能通过 chat 去定位... 而且不是说不是数据库响应的问题吗,是程序设计导致的,是我理解错了吗
    CEBBCAT
        28
    CEBBCAT  
       May 27 via iPhone
    @ryd994 make sense ,想的是既然存了就维护好这个数据,不然以后如果复用没注意到竟态可能会造成别的问题,但如果存的时候写明白,应该也行
    dudu2017
        29
    dudu2017  
       May 27
    @leekoho 重新看了一遍站长的发文,是我理解错了。可能被 AI 的幻觉误导了
    InDom
        30
    InDom  
       May 27
    @rrubick #24 也打不开, 读 404 但可以写, 所以直接 post 即可.

    还有一些是通过 api 查看的, api 没有这个检查所以不会 404.
    mywaiting
        31
    mywaiting  
       May 27   ❤️ 1
    从我过去的维护经验来说,最好把基础定义 API 和反垃圾 AntiSpam 的实现分离比较好

    一来可以保证 AntiSpam 不会影响基础 API 运行,二来方便在 AntiSpam 执行各种试验

    大概过程如下:

    所有流量从 gateway 进入到 webapp 后会有系列分离/分流机制推送到 AntiSpam 离线检测,检测后会自动标识 IP/User/Fingerprint 等标识的风险值,然后反馈到 webapp gateway 自动拉黑/喂假数据

    举个例子:正常访问的流量都会访问 /favicon.ico 这个请求进入 gateway 后会推送到 AntiSpam 离线检测后会适当降低当前访问 IP 的风险值
    CEBBCAT
        32
    CEBBCAT  
       May 28
    @mywaiting 哦老天,这让我想到某 Firewall ,原来工业竟是这样异曲同工
    mywaiting
        33
    mywaiting  
       May 29
    @CEBBCAT 旁路方式处理风控类业务也是很常见的架构套路了,确实很多地方都能见到
    dode
        34
    dode  
       May 29
    所有还是搞一个位运算服务吧,查询性能更好
    dode
        35
    dode  
       May 29
    redis ID 自增 读取和查询性能怎么样
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2527 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 98ms · UTC 00:24 · PVG 08:24 · LAX 17:24 · JFK 20:24
    ♥ Do have faith in what you're doing.