当前位置: 代码网 > it编程>数据库>mongodb > Apache通过LimitInternalRecursion指令防止重写死循环

Apache通过LimitInternalRecursion指令防止重写死循环

2026年04月19日 mongodb 我要评论
limitinternalrecursion 不能防止重写死循环,它只在死循环发生后强制中断并报错。它是 apache 的安全熔断机制,不是预防手段。真正要防死循环,得靠规则设计和日志观测。limit

limitinternalrecursion 不能防止重写死循环,它只在死循环发生后强制中断并报错。 它是 apache 的安全熔断机制,不是预防手段。真正要防死循环,得靠规则设计和日志观测。

limitinternalrecursion 是什么,为什么它不“防止”循环

这个指令设置的是内部重定向(internal redirect)和子请求(subrequest)的嵌套深度上限,默认值是 10。当 mod_rewrite 触发的重写链超过该次数,apache 就会中止处理,并记录类似 [alert] mod_rewrite: maximum number of internal redirects reached 的错误——这说明循环已经发生了,只是被拦下了。

它不分析规则逻辑,也不提前拦截;就像汽车的安全气囊,撞上了才弹出来。

  • 它控制两个维度:第一个数字是内部重定向链长度(即重写跳转次数),第二个是子请求嵌套深度(如 mod_dir 查 directoryindex 时的递归)
  • 只写一个数字(如 limitinternalrecursion 20)会同时设为两者
  • 该指令作用域为 server config、virtual host 或 directory,不能在 .htaccess 中使用
  • 调高它(比如设成 20)仅用于临时定位问题,绝不能作为“解决死循环”的方案

死循环场景示例

# ❌ 危险配置:无条件重写导致无限循环
rewriteengine on
rewriterule ^(.*)$ /index.php?page=$1 [l]
# 问题:/index.php 匹配 ^(.*)$,再次重写 → 死循环

limitinternalrecursion 指令详解

# 默认配置(apache 2.4+)
limitinternalrecursion 10
# 生产环境建议(根据应用复杂度调整)
limitinternalrecursion 5
# 调试时临时增大(配合 rewriteloglevel)
<ifdefine debug>
    limitinternalrecursion 20
</ifdefine>
参数值行为适用场景
0禁用重写(不推荐)仅静态资源服务器
1-3严格限制简单路由,无嵌套重写
5-10平衡配置(默认)现代 cms/框架(wordpress/laravel)
20+宽松限制复杂多级代理/遗留系统

与 mod_rewrite 协同的完整方案

1. 基础防护配置

<virtualhost *:80>
    servername example.com
    documentroot /var/www/html
    # 核心:限制内部递归深度
    limitinternalrecursion 5
    # 辅助:限制单请求子请求数(防止间接循环)
    limitrequestfields 50
    limitrequestfieldsize 8190
    <directory /var/www/html>
        rewriteengine on
        # 关键:使用 [end] 标志(apache 2.4+)替代 [l]
        # [l] 仅停止当前轮,[end] 完全终止重写处理
        rewriterule ^api/(.*)$ /api/index.php?path=$1 [end]
        # 传统 [l] 需配合条件避免循环
        rewritecond %{env:redirect_status} ^$
        rewriterule ^(.*)$ /index.php [l]
    </rewritecond>
    </directory>
</virtualhost>

2. 复杂路由的安全模式

<directory /var/www/app>
    rewriteengine on
    # 防御层1:严格递归限制
    limitinternalrecursion 3
    # 防御层2:标记已重写请求(双重保险)
    rewritecond %{env:redirect_status} 200
    rewriterule ^ - [l]
    # 防御层3:排除已处理 uri 模式
    rewritecond %{request_uri} !\.php$
    rewritecond %{request_uri} !^/(assets|uploads)/
    rewriterule ^(.*)$ /router.php?uri=$1 [qsa,l]
    # 错误处理:递归超限返回 500
    errordocument 500 /error/loop-detected.html
</directory>

3. 与 proxy 组合时的特殊处理

# 反向代理场景易触发多级重写
<virtualhost *:443>
    sslengine on
    # 代理场景需更大递归深度(子请求+重写)
    limitinternalrecursion 10
    rewriteengine on
    # 关键:排除代理目标路径,防止回环
    rewritecond %{request_uri} !^/proxy-backend/
    rewriterule ^/api/(.*)$ /proxy-backend/api/$1 [p,l]
    proxypass /proxy-backend/ http://localhost:8080/
    proxypassreverse /proxy-backend/ http://localhost:8080/
    # 代理错误时停止递归
    rewritecond %{http:upgrade} websocket [nc]
    rewriterule ^/ws/(.*)$ ws://localhost:8081/$1 [p,l]
</virtualhost>

关键关联指令对比

指令作用层级防护目标与 limitinternalrecursion 关系
limitinternalrecursion服务器/虚拟主机/目录重写/映射死循环核心防线
limitrequestfields服务器http 头溢出辅助防护
rewriteoptions maxredirects目录外部重定向次数仅限制外部 301/302,不防内部重写
limitrequestbody服务器/目录请求体大小防止大请求导致的间接递归

死循环检测与调试

日志分析配置

# 开发/调试环境启用详细重写日志
<ifdefine debug_rewrite>
    loglevel rewrite:trace8
    # 自定义日志格式包含递归深度
    logformat "%h %l %u %t \"%r\" %>s %b \"%{redirect_status}e\" %{rewrite_uri}n" rewrite_log
    customlog logs/rewrite.log rewrite_log
</ifdefine>

典型死循环特征

# 错误日志中的循环迹象
[rewrite:trace4] ... (1) init rewrite engine
[rewrite:trace4] ... (1) applying pattern '^/(.*)$' to uri 'index.php'
[rewrite:trace4] ... (2) init rewrite engine  <-- 数字递增表示递归
[rewrite:trace4] ... (2) applying pattern '^/(.*)$' to uri 'index.php'
...
[rewrite:trace1] ... (11) init rewrite engine  <-- 超过 limitinternalrecursion
[core:error] ... request exceeded the limit of 10 internal redirects 
              due to probable configuration error. use 'limitinternalrecursion' 
              to increase the limit if necessary.

现代框架的安全模板

# laravel / symfony / 类似 mvc 框架
<directory /var/www/laravel/public>
    rewriteengine on
    # 严格递归限制(框架路由已处理多级逻辑)
    limitinternalrecursion 2
    # 发送所有请求到 index.php(单次重写)
    rewritecond %{http:authorization} .
    rewriterule .* - [e=http_authorization:%{http:authorization}]
    rewritecond %{request_filename} !-d
    rewritecond %{request_filename} !-f
    rewriterule ^ index.php [end]  # [end] 完全终止,比 [l] 更安全
</directory>
# wordpress 典型配置
<directory /var/www/wordpress>
    rewriteengine on
    limitinternalrecursion 3
    rewritebase /
    rewriterule ^index\.php$ - [l]
    rewritecond %{request_filename} !-f
    rewritecond %{request_filename} !-d
    rewriterule . /index.php [l]
</directory>

关键最佳实践

  • 优先使用 [end] 标志(apache 2.4+):完全终止重写处理,比 [l] 更防循环
  • 始终设置 rewritecond %{env:redirect_status} ^$:排除已重写请求
  • 递归深度宁小勿大:生产环境建议 3-5,异常时增大而非默认无限
  • 配合 rewritemap 复杂逻辑:避免在 rewriterule 中堆砌条件导致隐性循环

核心要点:limitinternalrecursion 是最后防线,良好设计的重写规则应通过 [end] 标志和 redirect_status 条件自我防循环,而非依赖递归限制。

 到此这篇关于apache通过limitinternalrecursion指令防止重写死循环的文章就介绍到这了,更多相关apache limitinternalrecursion防止重写死循环内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com