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

Apache+mod_wsgi/Nginx+uWSGI环境下类X-Sendfile的内网大文件代理授权配置

Alright, let's break down how to set up this proxy-based file delivery (similar to X-Sendfile) for both Apache + mod_wsgi and Nginx + uWSGI environments. The core idea is: your WSGI app handles all auth/permission checks first, then tells the web server to fetch the internal file URL and forward it to the client—without ever exposing that internal address to the end user.

Apache + mod_wsgi Configuration

Step 1: Enable Required Modules

First, make sure you have the necessary Apache modules installed and enabled. These let you run the WSGI app and proxy requests to internal servers:

a2enmod wsgi proxy proxy_http
systemctl restart apache2

Step 2: WSGI App Logic (Auth + Permission Checks)

Your app is responsible for validating the user's identity and permissions before allowing access to the file. Here's a quick Flask example:

from flask import Flask, abort, request

app = Flask(__name__)

def is_authenticated():
    # Replace with your actual auth logic (e.g., session checks, JWT validation)
    return request.headers.get('Authorization') == 'ValidToken123'

def has_file_access(user_id, file_id):
    # Replace with your permission check (e.g., database lookup)
    return True  # Simplified for demo

@app.route('/download/<file_id>')
def initiate_download(file_id):
    # 1. Check if user is authenticated
    if not is_authenticated():
        abort(401, description="Unauthorized: Please log in")
    
    # 2. Verify user has permission to access this file
    user_id = "current_user_id"  # Get from your auth system
    if not has_file_access(user_id, file_id):
        abort(403, description="Forbidden: No access to this file")
    
    # 3. Return a custom header with the internal file URL
    internal_file_url = f"http://internal-fileserver:8080/secure-files/{file_id}"
    return '', 200, {'X-Proxy-Internal-URL': internal_file_url}

Step 3: Apache Virtual Host Configuration

Configure Apache to intercept the custom header, proxy the internal URL, and hide the header from clients. Here's a full virtual host example:

<VirtualHost *:80>
    ServerName your-public-domain.com

    # Mount your WSGI application
    WSGIScriptAlias / /var/www/your-app/wsgi.py
    <Directory /var/www/your-app>
        Require all granted
    </Directory>

    # Enable rewrite engine to handle internal proxying
    RewriteEngine On
    # Capture the internal URL from the WSGI response header
    RewriteCond %{LA-U:RESPONSE_X_Proxy_Internal_URL} (.+)
    # Proxy the request to the internal URL (P flag uses mod_proxy)
    RewriteRule ^(.*)$ %1 [P,L]

    # Ensure the custom header never reaches the client
    Header always unset X-Proxy-Internal-URL

    # Optimize for large file transfers
    ProxyTimeout 3600  # 1 hour timeout for big files
    ProxyBufferSize 64k
    ProxyBuffers 4 64k
    ProxyMaxForwards 10

    # Restrict Apache to only proxy your internal server (security measure)
    <Proxy http://internal-fileserver:8080/*>
        Require ip 192.168.0.0/24  # Your internal subnet
    </Proxy>
</VirtualHost>

Nginx + uWSGI Configuration

Step 1: Ensure uWSGI-Nginx Connection is Working

First, confirm your WSGI app is running via uWSGI (e.g., using a Unix socket or TCP port) and Nginx can reach it.

Step 2: WSGI App Logic (Same as Apache)

The auth/permission logic is identical—your app returns the X-Proxy-Internal-URL header only after validating the user. Here's a Django example:

from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied

@login_required
def download_file(request, file_id):
    # Check if user has permission to access this file
    if not request.user.has_perm('myapp.access_file', file_id):
        raise PermissionDenied("You don't have access to this file")
    
    # Get internal file URL from your database/config
    internal_url = f"http://internal-fileserver:8080/secure-files/{file_id}"
    response = HttpResponse(status=200)
    response['X-Proxy-Internal-URL'] = internal_url
    return response

Step 3: Nginx Server Block Configuration

Nginx needs to capture the custom header, proxy the internal request, and hide the header. We'll use Lua (via ngx_http_lua_module) for flexible header handling (if you don't have Lua, see alternative notes below):

server {
    listen 80;
    server_name your-public-domain.com;

    client_max_body_size 0;  # Disable body size limit for large files

    # Handle dynamic requests and forward to uWSGI
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/var/run/uwsgi/your-app.sock;  # Or tcp://127.0.0.1:5000

        # Use Lua to capture and remove the custom header
        set $internal_url "";
        header_filter_by_lua_block {
            local url = ngx.resp.get_header("X-Proxy-Internal-URL")
            if url then
                ngx.var.internal_url = url
                ngx.resp.delete_header("X-Proxy-Internal-URL")
            end
        }

        # If internal URL is set, proxy to it
        if ($internal_url != "") {
            rewrite ^(.*)$ $internal_url break;
            proxy_pass $internal_url;
            
            # Pass client info to internal server (optional)
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # Optimize for large files
            proxy_buffering off;
            proxy_cache off;
            proxy_max_temp_file_size 0;
            sendfile on;
            tcp_nopush on;
            proxy_timeout 3600s;
        }
    }

    # Security: Restrict proxy access to internal servers only
    location ~* ^http://internal-fileserver:8080/ {
        allow 192.168.0.0/24;
        deny all;
    }
}

Alternative Without Lua

If you don't have the Lua module installed, you can use proxy_hide_header to hide the custom header, and rely on $sent_http_x_proxy_internal_url to capture the value. However, this is less flexible—here's a simplified snippet:

proxy_hide_header X-Proxy-Internal-URL;

if ($sent_http_x_proxy_internal_url != "") {
    proxy_pass $sent_http_x_proxy_internal_url;
    # Add the same large file optimizations here
}

Key Universal Notes

  • Auth/Permissions First: Always handle authentication and permission checks in your WSGI app—web servers can't enforce application-specific access rules.
  • Internal Network Security: Make sure your web server can only reach the internal file server (use subnet restrictions, firewall rules, or VPNs if needed).
  • Large File Optimizations: Disable buffering, set long timeouts, and use sendfile to avoid memory issues during large transfers.
  • Error Handling: Your app should return 401/403 errors if auth/permission checks fail—these will be passed directly to the client without triggering proxy logic.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:19:08