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

 更新时间:2026年04月19日 11:37:56   作者:冷炫風刃  
LimitInternalRecursion 是 Apache 限制内部重定向和子请求嵌套深度的熔断指令,本文主要介绍了Apache通过LimitInternalRecursion指令防止重写死循环,感兴趣的可以了解一下

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防止重写死循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • CentOS系统密码重置全流程实战指南(服务器紧急救援)

    CentOS系统密码重置全流程实战指南(服务器紧急救援)

    在企业IT运维实践中,物理服务器密码丢失是典型的"低概率高风险"事件,本文基于笔者处理27台未交接密码的CentOS生产服务器的实战经验,深入解析物理服务器密码重置的完整技术路径,我们将重点探讨两种主流解决方案,需要的朋友可以参考下
    2025-05-05
  • Apache上传文件500错误的解决方法

    Apache上传文件500错误的解决方法

    Apache 2.3.6开始,MaxRequestLen这个参数的默认值从之前的1GB(汗一个)调整到了131072字节(128KB)。于是上传128KB以下的文件不会出问题,但是超过这个值就会报500错误了
    2014-04-04
  • Linux查看和关闭后台运行程序的方法

    Linux查看和关闭后台运行程序的方法

    这篇文章主要介绍了Linux查看和关闭后台运行程序的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • ssh修改超时自动登出时间的方法

    ssh修改超时自动登出时间的方法

    这篇文章主要介绍了关于linux中ssh超时自动登出时间的设置方法,以避免总是被强行退出。需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-02-02
  • Linux实现自动登录的实例讲解

    Linux实现自动登录的实例讲解

    在本篇文章里小编给大家分享的是关于Linux实现自动登录的相关实例以及知识点,需要的朋友们参考学习下。
    2019-10-10
  • 基于Linux系统中查看硬件等信息的方法详解

    基于Linux系统中查看硬件等信息的方法详解

    本篇文章是对Linux系统中查看硬件等信息的方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Linux中使用top命令的技巧

    Linux中使用top命令的技巧

    今天小编就为大家分享一篇关于Linux中使用top命令的技巧,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-09-09
  • centos 7 源码安装openssh的方法

    centos 7 源码安装openssh的方法

    这篇文章主要介绍了centos 7 源码安装openssh的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • 详解CentOS7安装配置vsftp搭建FTP

    详解CentOS7安装配置vsftp搭建FTP

    这篇文章主要介绍了详解CentOS7安装配置vsftp搭建FTP,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Linux 服务器同步 Rsync同步服务器文件

    Linux 服务器同步 Rsync同步服务器文件

    服务器之间常常要保持些文件或目录的一致,比如一些大的软件下载网站,它们通常使用多台服 务器来提供下载服务。
    2009-08-08

最新评论