惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
T
Threatpost
Latest news
Latest news
N
News | PayPal Newsroom
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
T
Threat Research - Cisco Blogs
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Exploit Database - CXSecurity.com
NISL@THU
NISL@THU
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Securelist
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
AWS News Blog
AWS News Blog
GbyAI
GbyAI
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
美团技术团队
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
博客园 - 聂微东
V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
SecWiki News
SecWiki News
S
Secure Thoughts
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
腾讯CDC
H
Heimdal Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed

博客园 - Nihaorz

告别闪烁,拥抱流畅:在 Windows Terminal 中完美配置 Cygwin 环境 创建 docker ipvlan,让 docke 容器获取独立ip 电犀牛 R68s iStoreOS 2.5G 网口速率优化 解决 openwrt ssh 命令行终端 home、end 键不可用问题 一键添加视频封面脚本 ffmpeg 转码参数 docker save 远程 ssh 主机直接 load,不产生本地文件 AutoHotKey 脚本 - win10 自动连接无线显示器 SSH 登录/退出实时监控脚本 OpenClaw 安装部署,配置 deepseek curl 断点续传下载 debian iso 镜像下载地址 linux 安装 zerotier,加入网络 基于 Fail2ban 的 SSH 入侵自动反制方案 ssh 配置密钥登录,关闭密码登录 memc - 基于 shell 的交互式清理内存脚本 基于 Fail2ban 的 OpenWRT SSH 入侵自动反制方案 Linux Screen 命令速查 使用 ofelia 在 docker 容器中执行计划任务 linux 磁盘挂载示例
Nginx 透明代理 + 自动回源存储:访问即缓存,落盘即文件
Nihaorz · 2026-04-03 · via 博客园 - Nihaorz

项目结构:

root@iStoreOS:/ssd/openwrt-compose/network/example-nginx# tree -L 2
.
├── conf.d
│   └── example-8820.conf
├── html
│   └── www.example.com
├── example_cached.sh
├── logs
│   ├── access.log
│   ├── error.log
│   ├── example.access.log
│   ├── example.error.log
│   └── example_cached.log
├── nginx.conf
└── start.sh

example-8820.conf:

# 在 http 块中定义日志格式,增加 $proxy_target 字段
log_format proxy_detailed '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" '
                          'proxied=$proxied '
                          'proxy_target="$proxy_target"';   # 新增字段

server {
    listen 8820 ssl;
    listen [::]:8820 ssl;
    server_name lfk.java-jar.fun;
    client_max_body_size 0;
    
    ssl_certificate /etc/uhttpd.crt;
    ssl_certificate_key /etc/uhttpd.key;
    
    error_page 497 https://$host:$server_port$request_uri;
    

    # 使用自定义日志格式
    access_log /var/log/nginx/example.access.log proxy_detailed;
    access_log /dev/stdout proxy_detailed;
    error_log  /var/log/nginx/example.error.log error;   # 生产环境可改为 warn
    error_log  /dev/stderr error;

    root "/html/www.example.com";
    index index.html index.htm;

#    resolver 223.5.5.5 223.6.6.6 valid=300s;
#    resolver_timeout 5s;

    location / {
        try_files $uri $uri/ =404;
        sub_filter_types text/html text/css application/javascript;
        sub_filter 'https://www.example.com/' '/';
        sub_filter '<div class="head-lang"' '<div style="display:none;" class="head-lang"';
        sub_filter_once off;
    }

    location /uploads/ {
        set $proxied 0;
        set $proxy_target "";
        try_files $uri @proxy_uploads;
    }

    location @proxy_uploads {
        set $proxied 1;
        # 构造实际代理的目标 URL(包含原始请求 URI 和查询参数)
        set $proxy_target "https://www.example.com$request_uri";

        proxy_pass https://www.example.com;
        proxy_set_header Host www.example.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version 1.1;
        proxy_ssl_server_name on;
        proxy_ssl_protocols TLSv1.2 TLSv1.3;
        proxy_ssl_verify off;          # 调试用,正式环境建议 on

        proxy_connect_timeout 10s;
        proxy_send_timeout 10s;
        proxy_read_timeout 30s;

        proxy_cache_valid 200 302 1h;
        proxy_cache_valid 404 1m;
    }

    error_page 404 /404.html;
    location = /404.html {
        internal;
    }
}

example_cached.sh:

#!/bin/bash

# 配置
LOG_FILE="/var/log/nginx/example.access.log"
LOCAL_ROOT="/html/www.example.com"
ERROR_LOG="/var/log/nginx/example_cached_error.log"

# 确保日志文件存在
touch "$LOG_FILE"

# 函数:从 proxy_target 字段提取完整 URL
extract_url() {
    # 格式:... proxy_target="https://www.example.com/xxxx?params"
    # 使用 grep -oP 提取双引号内的内容(需要 GNU grep 支持 -P)
    echo "$1" | grep -oP 'proxy_target="\K[^"]+' | head -1
}

# 函数:从 URL 中提取 URI(去掉查询参数)
extract_uri() {
    # 去掉协议和域名,只保留路径部分,再去掉 ? 后的参数
    echo "$1" | sed -E 's|https?://[^/]+||' | cut -d'?' -f1
}

# 函数:下载文件
download_file() {
    local url="$1"
    local uri="$2"
    local local_path="${LOCAL_ROOT}${uri}"

    # 如果文件已存在,跳过
    if [ -f "$local_path" ]; then
        return 0
    fi

    # 创建目录
    mkdir -p "$(dirname "$local_path")"

    echo "[$(date)] Downloading: $url"
    # 使用 curl 下载(-s 静默,-L 跟随重定向,-o 输出文件)
    if curl -s -L -o "$local_path" "$url"; then
        echo "[$(date)] Saved to $local_path"
    else
        echo "[$(date)] ERROR: Failed to download $url" >> "$ERROR_LOG"
    fi
}

# 主循环:tail -F 持续跟踪文件(支持日志轮转)
tail -F "$LOG_FILE" | while read line; do
    # 只处理包含 proxied=1 的行
    if echo "$line" | grep -q 'proxied=1'; then
        url=$(extract_url "$line")
        if [ -n "$url" ]; then
            uri=$(extract_uri "$url")
            download_file "$url" "$uri"
        fi
    fi
done

nginx.conf:

user  root;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

start.sh:

#!/bin/bash

# 使用 while 循环保证脚本持续运行
while true; do
    bash /example_cached.sh >> /var/log/nginx/example_cached.log 2>&1
    echo "$(date): example_cached.sh exited, restarting in 5 seconds..." >> /var/log/nginx/example_cached.log
    sleep 5
done &

# 前台运行 nginx
nginx -g "daemon off;"

compose.yml

services:

  example-nginx:
    image: nginx
    container_name: example-nginx
    hostname: example-nginx
    environment:
      - TZ=Asia/Shanghai
    privileged: true
    volumes:
      - ./example-nginx/conf.d/:/etc/nginx/conf.d/
      - ./example-nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./example-nginx/html/:/html/
      - ./example-nginx/start.sh:/start.sh
      - ./example-nginx/example_cached.sh:/example_cached.sh
      - ./example-nginx/logs/:/var/log/nginx/
      - /etc/uhttpd.crt:/etc/uhttpd.crt
      - /etc/uhttpd.key:/etc/uhttpd.key
    ports:
      - 8820:8820
    command: /start.sh
    restart: always

项目原理:

这个项目的核心原理是 “按需缓存 + 动态代理”,具体流程如下:

  1. Nginx 反向代理

    • 监听 8820 端口(HTTPS),当用户访问 /uploads/ 路径时,默认先尝试从本地 html/www.example.com 目录读取文件。

    • 如果本地不存在(try_files 失败),则通过 @proxy_uploads 将请求代理到上游 https://www.example.com

  2. 自定义日志标记代理行为

    • 在代理逻辑中设置两个自定义变量:$proxied=1 和 $proxy_target(记录实际请求的完整 URL)。

    • 使用专用日志格式 proxy_detailed 将这些信息写入 example.access.log

  3. 后台脚本持续处理日志

    • example_cached.sh 使用 tail -F 实时跟踪日志文件。

    • 当检测到 proxied=1 的行时,解析出 $proxy_target 中的 URL,提取 URI 路径。

    • 调用 curl 下载该 URL 的内容,保存到本地 html/www.example.com 对应的路径下。

  4. 缓存生效

    • 下次同样请求到达时,Nginx 的 try_files 会直接命中本地文件,不再触发代理,实现透明加速。

简而言之:通过日志驱动的方式,将首次代理请求的内容自动持久化到本地,后续请求由静态文件直接响应,降低上游带宽和负载。