You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache2反向代理:配置每次请求触发脚本进行请求校验

解决Apache反向代理前置CGI检查的问题

1. 先修复CGI脚本不执行的问题

你当前配置直接Rewrite到本地文件路径/usr/local/bin/throttle.cgi,Apache会把它当作静态文件返回内容,而非执行脚本。需要利用ScriptAlias映射的路径触发CGI执行:

修改Rewrite规则

将原RewriteRule改为指向/cgi-bin/throttle.cgi,同时保留原始请求的路径和查询参数:

RewriteEngine On
RewriteRule ^(.*)$ /cgi-bin/throttle.cgi?$1 [QSA,L]
  • QSA:保留原始请求的查询字符串,传递给CGI脚本
  • L:停止后续Rewrite规则处理

确保脚本满足执行条件

  • 脚本开头添加正确的shebang,示例:
    #!/usr/bin/env python3
    
  • 给脚本添加可执行权限:
    chmod +x /usr/local/bin/throttle.cgi
    
  • 确保Apache已启用mod_cgi或mod_cgid模块(容器内执行a2enmod cgi后重启httpd)

2. 调整代理逻辑,让CGI脚本控制转发

脚本需要完成两个核心动作:检查请求合法性,通过则转发到后端,否则返回拒绝响应。以下是Python脚本示例:

#!/usr/bin/env python3
import os
import sys
import requests

# 获取原始请求信息
request_method = os.environ.get('REQUEST_METHOD')
request_path = os.environ.get('PATH_INFO', '')
query_string = os.environ.get('QUERY_STRING', '')
full_backend_url = f"https://www.example.com{request_path}"
if query_string:
    full_backend_url += f"?{query_string}"

# 提取请求头(Apache将请求头转为HTTP_*格式的环境变量)
request_headers = {}
for key, value in os.environ.items():
    if key.startswith('HTTP_'):
        header_name = key[5:].replace('_', '-').title()
        request_headers[header_name] = value

# 读取请求体(仅POST/PUT等方法需要)
request_body = sys.stdin.read() if request_method in ['POST', 'PUT'] else None

# 自定义检查逻辑,根据需求修改
def validate_request():
    # 示例:检查特定请求头是否存在
    if 'X-Auth-Token' not in request_headers:
        return False
    # 可添加查询参数、请求体内容等检查逻辑
    return True

# 执行检查
if not validate_request():
    print("Status: 403 Forbidden")
    print("Content-Type: text/plain")
    print()
    print("Request rejected by validation check")
    sys.exit()

# 检查通过,转发请求到后端
try:
    backend_response = requests.request(
        method=request_method,
        url=full_backend_url,
        headers=request_headers,
        data=request_body,
        allow_redirects=False
    )

    # 将后端响应返回给客户端
    print(f"Status: {backend_response.status_code} {backend_response.reason}")
    for key, value in backend_response.headers.items():
        print(f"{key}: {value}")
    print()
    sys.stdout.write(backend_response.content)
except Exception as e:
    print("Status: 500 Internal Server Error")
    print("Content-Type: text/plain")
    print()
    print(f"Failed to forward request: {str(e)}")

注意事项

  • 容器内需要安装requests库:pip install requests(可在Dockerfile中添加该安装步骤)

3. 最终Apache配置

<VirtualHost *:80>
    ErrorLog "/var/log/apache2/proxy-error.log"
    CustomLog "/var/log/apache2/proxy-access.log" common

    ScriptAlias /cgi-bin/ /usr/local/bin/
    ProxyRequests Off
    SSLProxyEngine On
    SSLProxyCheckPeerCN on
    SSLProxyCheckPeerExpire on

    # 注释原直接代理规则,由CGI脚本负责转发
    # ProxyPass "/" "https://www.example.com/"
    # ProxyPassReverse "/" "https://www.example.com/"
    
    RewriteEngine On
    RewriteRule ^(.*)$ /cgi-bin/throttle.cgi?$1 [QSA,L]

    <Location "/cgi-bin/">
        AllowOverride None
        Options +ExecCGI
        Require all granted
    </Location>
</VirtualHost>

内容的提问来源于stack exchange,提问作者mhaken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:01:05