Allen's 碎碎念

Allen's 碎碎念

emby 服务器反代更新

2
2026-03-23

以前写过一篇 emby反代的帖子,长期的使用下来发现一些问题,更新一些配置。

主要修改点是增加代理特征的清除,由于有些服禁止反代,增加配置以实现在 http 层面的隐身,与正向代理实现同样的特征。

以下所有仍然使用假数据,emby 服务器地址使用 emby.domain 代替,推流地址使用 stream1、stream2、stream3 等代替。

前后端不分离

location / {
    # ---------------- 基础反代目标 ----------------
    proxy_pass $forward_scheme://$server:$port;

    # ---------------- 伪装后端 (防 Emby 识破) ----------------
    # Host 设置为后端服务器实际域名或 IP
    proxy_set_header Host $server;
    
    # HTTPS SNI 设置为后端服务器域名,避免证书警告
    proxy_ssl_server_name on;
    proxy_ssl_name $server;

    # 【关键修复】覆盖并清空 NPM 默认自带的代理特征头
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header X-Forwarded-Port "";
    
    # 彻底清理请求中的 Via 头
    proxy_set_header Via "";

    # ---------------- 流媒体支持 ----------------
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;

    # 超时设置(确保长视频播放不中断)
    proxy_connect_timeout 60s;
    proxy_send_timeout 180s;
    proxy_read_timeout 180s;
    proxy_buffering off; # Emby 官方推荐关闭缓冲,降低延迟

    # ---------------- 伪装客户端 (防客户端识破) ----------------
    # 隐藏后端可能返回的特征
    proxy_hide_header X-Powered-By;
    proxy_hide_header X-Frame-Options;
    proxy_hide_header X-Content-Type-Options;
    
    # 【关键修复】利用 NPM 内置的 OpenResty 彻底清除 Server 头
    more_clear_headers 'Server';
}

前后端分离

# ==========================================
# 核心入口:反代 Emby 主程序
# ==========================================
location / {
    proxy_pass $forward_scheme://$server:$port;
    
    # 【必须修复】伪装 Host,让 Emby 主站以为是原域名直连
    proxy_set_header Host $server;
    proxy_ssl_name $server;
    proxy_ssl_server_name on;
    
    # 【流媒体补全】支持视频拖拽和断点续传(两项缺一不可)
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【核心拦截】将三个推流源分别重定向到我们的 3 个伪装路径
    proxy_redirect http://stream1 https://yourdomain/s1/;
    proxy_redirect http://stream2 https://yourdomain/s2/;
    proxy_redirect http://stream3 https://yourdomain/s3/;

    # 【抹除请求特征】对 Emby 主站隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【抹除响应特征】对客户端(浏览器/APP)隐身,彻底隐藏 Nginx 身份
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

# ==========================================
# 推流节点 1:代理 stream1
# ==========================================
location /s1/ {
    rewrite ^/s1(/.*)$ $1 break;
    # 【必须修复】去掉了结尾的斜杠,防止与 rewrite 产生双斜杠路径冲突
    proxy_pass http://stream1;
    
    proxy_set_header Referer "http://emby.domain/web/index.html";
    proxy_set_header Host $proxy_host;
    # 传递 Range 头,实现视频拖拽
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【流媒体补全】关闭缓冲并增加超时,防断流
    proxy_buffering off;
    proxy_connect_timeout 60s;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    # 【抹除请求特征】对 推流节点 1 隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【抹除响应特征】对客户端隐身
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

# ==========================================
# 推流节点 2:代理 stream2
# ==========================================
location /s2/ {
    rewrite ^/s2(/.*)$ $1 break;
    # 【必须修复】去掉了结尾的斜杠
    proxy_pass http://stream2;
    
    proxy_set_header Referer "http://emby.domain/web/index.html";
    proxy_set_header Host $proxy_host;
    # 传递 Range 头,实现视频拖拽
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【流媒体补全】关闭缓冲并增加超时,防断流
    proxy_buffering off;
    proxy_connect_timeout 60s;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    # 【抹除请求特征】对 推流节点 2 隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【抹除响应特征】对客户端隐身
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

# ==========================================
# 推流节点 3:代理 stream3
# ==========================================
location /s3/ {
    rewrite ^/s3(/.*)$ $1 break;
    # 【必须修复】去掉了结尾的斜杠
    proxy_pass http://stream3;
    
    proxy_set_header Referer "http://emby.domain/web/index.html";
    proxy_set_header Host $proxy_host;
    # 传递 Range 头,实现视频拖拽
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【流媒体补全】关闭缓冲并增加超时,防断流
    proxy_buffering off;
    proxy_connect_timeout 60s;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    # 【抹除请求特征】对 推流节点 3 隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【抹除响应特征】对客户端隐身
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

需要注意,如果推流地址是 https,需要额外增加两条

    # 添加sni信息
    proxy_ssl_server_name on;
    proxy_ssl_name stream.embyplus.org;

举一个例子

# ==========================================
# 核心入口:反代 Emby 主程序
# ==========================================
location / {
    proxy_pass $forward_scheme://$server:$port;
    
    # 【必须补齐 1】伪装 Host,让 Emby 主站以为请求来自其原生域名
    proxy_set_header Host $server;
    proxy_ssl_name $server;
    proxy_ssl_server_name on;
    
    # 【必须补齐 2】完善流媒体支持,Range 和 If-Range 成对出现,保证视频丝滑拖拽
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【核心拦截】将推流地址重定向到伪装路径
    proxy_redirect https://stream.domain https://yourdomain/s1/;

    # 【抹除请求特征】对 Emby 主程序隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【必须补齐 3】抹除响应特征,对客户端隐藏 Nginx 身份
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

# ==========================================
# 推流节点:代理 stream.domain
# ==========================================
location /s1/ {
    # 路径匹配规范化,加上结尾的斜杠更安全
    rewrite ^/s1(/.*)$ $1 break;
    
    # 真实推流地址(明文 http,已去掉下面冗余的 proxy_ssl_server_name 指令)
    proxy_pass https://stream.domain;
    # 添加sni信息
    proxy_ssl_server_name on;
    proxy_ssl_name stream.domain;
    # 传递 Range 头,实现视频拖拽
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    proxy_set_header Referer "https://emby.domain/web/index.html";
    proxy_set_header Host $proxy_host;
    
    # 【必须补齐 4】关闭缓冲并增加超时时间,彻底解决看长视频中途断开的问题
    proxy_buffering off;
    proxy_connect_timeout 60s;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    # 【抹除请求特征】对 推流服务器 隐身
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【必须补齐 5】抹除响应特征,对客户端隐藏身份
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

lily服反代

lily 服更改了后段配置,在以上面前后端分离的方式进行反代后,发现播放器行为不一致。在小幻、forward上能正常反代,但是在 senplayer 上仍然走了原推流,未达到反代的目的。原因是在返回值中写死了路径,而非像普通服返回相对路径。

解决方式是使用 nginx 中的 sub_filter 功能。

# ==========================================
# 核心入口:反代 Emby 主站
# ==========================================
location / {
    proxy_pass $forward_scheme://$server:$port;
    
    # 【伪装 1】伪装客户端 Host
    proxy_set_header Host $server;
    proxy_ssl_name $server;
    proxy_ssl_server_name on;
    
    # 【流媒体优化】支持视频拖拽和断点续传
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    
    # 【核心拦截 - 重定向头】处理 302 重定向
    proxy_redirect https://stream.domain https://yourdomain/s1;
    proxy_redirect https://emby.domain https://yourdomain;

    # =============================================
    # 【核心新增 - 响应体替换】修改 JSON Body 中的绝对路径
    # =============================================
    
    # ❶ 强制上游返回未压缩内容,否则 sub_filter 无法工作!
    proxy_set_header Accept-Encoding "";
    
    # ❷ 指定需要替换的 Content-Type(默认只处理 text/html)
    sub_filter_types application/json text/xml text/plain;
    
    # ❸ 替换所有匹配项,而不是只替换第一个
    sub_filter_once off;
    
    # ❹ 替换响应体中的真实域名 → 反代域名
    #    将 Emby 主站域名替换
    sub_filter 'https://emby.domain' 'https://yourdomain';
    #    将推流 CDN 域名替换(以防某些接口直接返回推流地址)
    sub_filter 'https://stream.domain' 'https://yourdomain/s1';

    # 【抹除特征】
    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    # 【抹除响应头】
    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}

# ==========================================
# 视频推流入口:代理真实的 CDN / 推流节点
# ==========================================
location /s1/ {
    rewrite ^/s1(/.*)$ $1 break;
    proxy_pass https://stream.domain;
    
    proxy_ssl_server_name on;
    proxy_ssl_name stream.domain;
    
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    proxy_set_header Host $proxy_host;
    proxy_set_header Referer "https://emby.domain/web/index.html";
    
    proxy_buffering off;
    proxy_connect_timeout 60s;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    proxy_set_header X-Real-IP "";
    proxy_set_header X-Forwarded-For "";
    proxy_set_header X-Forwarded-Proto "";
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header Forwarded "";
    proxy_set_header Via "";

    more_clear_headers 'Server';
    proxy_hide_header X-Powered-By;
}