Linux

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > Linux > Apache海量图片防盗链与防下载

Apache配置实现对海量图片资源的深度防盗链与防下载策略

作者:舞夢輝影

本文主要介绍了Apache配置实现对海量图片资源的深度防盗链与防下载策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

针对海量图片资源的防盗链与防下载,需要构建多层防御体系。以下是经过实战验证的 Apache 深度防护策略:

一、基础层:Referer 防盗链(第一层过滤)

<IfModule mod_rewrite.c>
    RewriteEngine On
    # 定义允许的白名单域名(正则匹配,支持子域名)
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?partner-site\.com [NC]
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?cdn\.yourdomain\.com [NC]
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?localhost [NC]
    # 对图片资源应用防盗链
    RewriteRule \.(jpg|jpeg|png|gif|webp|bmp|svg|ico)$ - [F,L]
</IfModule>

说明!^$ 允许空 Referer(部分客户端/邮件客户端),如需严格可移除。[F] 返回 403 Forbidden,[L] 终止后续规则。

二、核心层:Token 签名验证(防直链 + 防篡改)

1. 服务端 Token 生成逻辑(PHP/Python 示例)

<?php
// 密钥必须与服务端一致
$secret = 'YourStrongSecretKey_2024!';
$expire = time() + 300; // 5分钟有效期
function generateImageToken($path, $expire, $secret) {
    $data = $path . '|' . $expire;
    return hash_hmac('sha256', $data, $secret);
}
$imagePath = '/uploads/2024/photo.jpg';
$token = generateImageToken($imagePath, $expire, $secret);
$url = "https://img.yourdomain.com{$imagePath}?t={$token}&e={$expire}";
// 输出: https://img.yourdomain.com/uploads/2024/photo.jpg?t=abc123&e=1715000000
?>

2. Apache 配置(验证 Token + 过期时间)

<IfModule mod_rewrite.c>
    RewriteEngine On
    # 仅对图片目录启用
    <Directory "/var/www/images">
        # 提取 URL 参数
        RewriteCond %{QUERY_STRING} ^(?:.*&)?t=([^&]+)(?:&.*)?$ [NC]
        RewriteRule .* - [E=TOKEN:%1]
        RewriteCond %{QUERY_STRING} ^(?:.*&)?e=([^&]+)(?:&.*)?$ [NC]
        RewriteRule .* - [E=EXPIRE:%1]
        # 构建验证字符串:路径|过期时间
        RewriteRule .* - [E=VERIFY_STRING:%{REQUEST_URI}|%{ENV:EXPIRE}]
        # 计算期望的 HMAC(需要 mod_setenvif 或外部程序,这里用 Lua/外部脚本)
        # 方案A:使用 mod_lua(推荐,高性能)
        <IfModule mod_lua.c>
            LuaHookAccessChecker /etc/apache2/scripts/verify_token.lua verify_token
        </IfModule>
        # 方案B:使用外部程序验证(性能较低,适合低频)
        # RewriteMap token_verify prg:/etc/apache2/scripts/verify_token.py
        # RewriteCond ${token_verify:%{ENV:VERIFY_STRING}|%{ENV:TOKEN}} !^VALID$
        # RewriteRule .* - [F,L]
        # 检查过期时间
        RewriteCond %{TIME} > %{ENV:EXPIRE}
        RewriteRule .* - [F,L]
    </Directory>
</IfModule>

3. Lua 验证脚本(/etc/apache2/scripts/verify_token.lua)

-- 需要安装 libapache2-mod-lua
require "apache2"
require "hash"
require "string"
local secret = "YourStrongSecretKey_2024!"
function verify_token(r)
    local token = r.subprocess_env["TOKEN"]
    local expire = r.subprocess_env["EXPIRE"]
    local path = r.uri
    if not token or not expire then
        return apache2.DECLINED -- 让 Rewrite 规则处理(返回403)
    end
    -- 检查是否过期
    local now = os.time()
    if tonumber(expire) < now then
        return apache2.HTTP_FORBIDDEN
    end
    -- 计算 HMAC
    local data = path .. "|" .. expire
    local expected = hash.hmac_sha256(data, secret)
    -- 安全比较(防时序攻击)
    if not secure_compare(token, expected) then
        return apache2.HTTP_FORBIDDEN
    end
    return apache2.OK
end
function secure_compare(a, b)
    if #a ~= #b then return false end
    local result = 0
    for i = 1, #a do
        result = result | (string.byte(a, i) ~ string.byte(b, i))
    end
    return result == 0
end

三、传输层:防直接下载 + 防右键保存

1. 禁用图片直接保存(Content-Disposition)

<IfModule mod_headers.c>
    # 对图片强制 inline 显示,但阻止"另存为"对话框的默认行为
    <FilesMatch "\.(jpg|jpeg|png|gif|webp)$">
        Header set Content-Disposition "inline"
        # 禁止浏览器缓存图片到本地(减少离线查看)
        Header set Cache-Control "private, no-store, max-age=0"
    </FilesMatch>
</IfModule>

2. 添加水印(通过 mod_pagespeed 或后端处理)

# 使用 mod_pagespeed 自动添加水印(需安装)
<IfModule pagespeed_module>
    ModPagespeedEnableFilters rewrite_images
    ModPagespeedEnableFilters insert_image_dimensions
    # 自定义水印滤镜
    ModPagespeedImageMaxBytes 2097152
</IfModule>

四、行为层:反爬虫与异常检测

1. 频率限制(mod_evasive 或 mod_security)

# 使用 mod_evasive 限制单 IP 图片请求频率
<IfModule mod_evasive24.c>
    DOSHashTableSize    3097
    DOSPageCount        5          # 同一页面5秒内超过5次
    DOSSiteCount        50         # 同一站点5秒内超过50次
    DOSPageInterval     5
    DOSSiteInterval     5
    DOSBlockingPeriod   600        # 封禁10分钟
    DOSEmailNotify      admin@yourdomain.com
    DOSLogDir           "/var/log/mod_evasive"
</IfModule>

2. 使用 ModSecurity 高级防护

<IfModule security2_module>
    # 拦截无 Referer 的批量请求(爬虫特征)
    SecRule REQUEST_FILENAME "@rx \.(jpg|jpeg|png|gif|webp)$" \
        "id:1001,phase:1,block,log,msg:'Image access without referer',\
        chain"
        SecRule REQUEST_HEADERS:Referer "@streq" \
            "setvar:ip.image_requests=+1,expirevar:ip.image_requests=60"
    # 单 IP 60秒内超过100次图片请求则封禁
    SecRule IP:IMAGE_REQUESTS "@gt 100" \
        "id:1002,phase:1,deny,status:403,msg:'Rate limit exceeded for images'"
    # 拦截常见爬虫 User-Agent
    SecRule REQUEST_HEADERS:User-Agent "@pm wget curl python scrapy" \
        "id:1003,phase:1,deny,status:403,msg:'Bot detected'"
</IfModule>

五、应用层:前端 + 后端协同防护

1. 图片通过 Canvas 渲染(防右键保存)

<!-- 前端示例:图片通过 Canvas 绘制,DOM 中不暴露真实 img 标签 -->
<canvas id="protected-img" width="800" height="600"></canvas>
<script>
fetch('/api/get-image-token?path=/uploads/photo.jpg')
    .then(r => r.json())
    .then(data => {
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.onload = function() {
            const canvas = document.getElementById('protected-img');
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            // 添加视觉水印
            ctx.font = '14px Arial';
            ctx.fillStyle = 'rgba(255,255,255,0.5)';
            ctx.fillText('© YourDomain ' + new Date().getFullYear(), 10, 30);
        };
        img.src = data.url; // 带 Token 的 URL
    });
</script>

2. 动态缩略图 + 防盗链(防止原图泄露)

# 使用 mod_rewrite + mod_proxy 将缩略图请求代理到处理服务
RewriteRule ^/thumb/(\d+)x(\d+)/(.*)$ \
    http://localhost:8080/thumbnail?w=$1&h=$2&path=$3 [P,L]

六、完整配置汇总

# ==================== 全局设置 ====================
ServerTokens Prod
ServerSignature Off
# ==================== 模块加载 ====================
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
LoadModule lua_module modules/mod_lua.so
# ==================== 图片目录防护 ====================
<Directory "/var/www/images">
    Options -Indexes -FollowSymLinks
    AllowOverride None
    Require all granted
    RewriteEngine On
    # ---- Layer 1: Referer 白名单 ----
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?cdn\.yourdomain\.com [NC]
    RewriteCond %{HTTP_REFERER} !^https?://(www\.)?localhost [NC]
    RewriteRule \.(jpg|jpeg|png|gif|webp|bmp|svg)$ - [F,L]
    # ---- Layer 2: Token 验证 ----
    RewriteCond %{QUERY_STRING} ^(?:.*&)?t=([^&]+)(?:&.*)?$ [NC]
    RewriteRule .* - [E=TOKEN:%1]
    RewriteCond %{QUERY_STRING} ^(?:.*&)?e=([^&]+)(?:&.*)?$ [NC]
    RewriteRule .* - [E=EXPIRE:%1]
    # 过期检查
    RewriteCond %{TIME} > %{ENV:EXPIRE}
    RewriteRule .* - [F,L]
    # Lua HMAC 验证
    <IfModule mod_lua.c>
        LuaHookAccessChecker /etc/apache2/scripts/verify_token.lua verify_token
    </IfModule>
    # ---- Layer 3: 响应头加固 ----
    <IfModule mod_headers.c>
        Header set Content-Disposition "inline"
        Header set Cache-Control "private, max-age=300"
        Header set X-Content-Type-Options "nosniff"
        # 禁止图片被嵌入 iframe(点击劫持防护)
        Header set X-Frame-Options "DENY"
        # CSP 限制图片加载来源
        Header set Content-Security-Policy "img-src 'self' data:; default-src 'none'"
    </IfModule>
    # ---- Layer 4: 频率限制(需 mod_evasive)----
    <IfModule mod_evasive24.c>
        DOSPageCount        10
        DOSSiteCount        100
        DOSBlockingPeriod   300
    </IfModule>
</Directory>
# ==================== 日志记录 ====================
CustomLog "/var/log/apache2/image_access.log" "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{UNIQUE_ID}e"

防护效果总结

层级防护手段防御目标
Layer 1Referer 白名单阻止第三方网站直接引用
Layer 2Token + HMAC + 过期时间防止 URL 分享、直链访问
Layer 3响应头控制 + CSP防止右键保存、iframe 嵌入
Layer 4频率限制 + WAF阻止爬虫批量抓取
Layer 5Canvas 渲染 + 动态水印前端防保存、溯源追踪

这套方案的核心是 Token 签名机制——即使攻击者获取了图片 URL,Token 会在短时间内过期,且无法伪造签名,从根本上杜绝了盗链和批量下载。

到此这篇关于Apache配置实现对海量图片资源的深度防盗链与防下载策略的文章就介绍到这了,更多相关Apache海量图片防盗链与防下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文