前言:最近痴迷于追剧,发现一个不错的影视站主打1080/无广/可采, 遗憾的一点是所有资源引用只能海外ip,国内通过扶墙可正常使用,顺便讲讲Nginx反代突破采集站流媒体区域限制,达到国内播放目的。
提示:按本文操作后所有流量经自己服务器,如果你手头正有不限流G口机不妨试试,如何本地搭建+采集过程这里不多说了。
操作需要:
国外小鸡+Nginx环境
本地:127.0.0.1
举例采集地址:https://example.com 简称example采集
举例播放地址:https://m3u8.example.com/xm3u8/f11e97d0da21.m3u8
一、尝试反代m3u8文件的域名
因为example采集站所有资源限制海外ip访问,国外机子反代m3u8文件的域名是个不错的法子。
代码如下:
location ~* \.(m3u8|ts|aac)$ {
proxy_cache off; # 禁用代理缓存
gzip off;
expires -1; # 禁用页面缓存
proxy_pass https://m3u8.example.com; # 反代目标 URL
sub_filter 'https://127.0.0.1/' 'https://$host/'; # 替换 m3u8 文件里的资源链接
sub_filter_last_modified off; # 删除原始响应里的浏览器缓存值
sub_filter_once off; # 替换所有匹配内容
sub_filter_types *; # 匹配任何 MIME 类型
}
配置好反代,本地访问127.0.0.1/xm3u8/f11e97d0da21.m3u8返回502 Bad Gateway,错误信息显示 SSL_do_handshake() failed
返回502 Bad Gateway 是由于网站启用了 SNI , 宝塔Nginx反代默认没有加入 SNI proxy_ssl_server_name on; ,Nginx 无法成功 handshake 上游的 SSL , 导致 502 Bad Gateway. 补充代码加上proxy_ssl_server_name on;
后正常返回m3u8文件
补充后的代码如下:
location ~* \.(m3u8|ts|aac)$ {
proxy_cache off; # 禁用代理缓存
gzip off;
expires -1; # 禁用页面缓存
proxy_pass https://m3u8.example.com; # 反代目标 URL
proxy_ssl_server_name on;
sub_filter 'https://127.0.0.1/' 'https://$host/'; # 替换 m3u8 文件里的资源链接
sub_filter_last_modified off; # 删除原始响应里的浏览器缓存值
sub_filter_once off; # 替换所有匹配内容
sub_filter_types *; # 匹配任何 MIME 类型
}
尝试播放m3u8文件,播放器可正常加载m3u8文件,但所有ts文件403
打开m3u8文件,发现sub_filter
没起作用,nginx反代替换关键字前并不会自动解压缩,所以无法执行替换内容
因为m3u8.example.com域名使用的Brotli压缩,检测Accept-Encoding,如果客户端未设置Content-Encoding或设置为支持br压缩,则强制返回Content-Encoding:br。如果强制指定了只支持gzip,defalte,则Content-Encoding:gizp.defalter。在请求中增加Accept-Encoding "gzip,deflate";
等内容
再次补充后的代码如下
location ~* \.(m3u8|ts|aac)$ {
proxy_cache off; # 禁用代理缓存
proxy_set_header Sec-Fetch-Mode "navigate";
proxy_set_header Sec-Fetch-Site "cross-site";
proxy_set_header Cache-Control "max-age=0";
proxy_set_header Accept-Encoding "gzip,deflate";
gunzip on;
gzip_disable ".";
expires -1; # 禁用页面缓存
proxy_pass https://m3u8.example.com; # 反代目标 URL
proxy_ssl_server_name on;
sub_filter 'https://127.0.0.1/' 'https://$host/'; # 替换 m3u8 文件里的资源链接
sub_filter_last_modified off; # 删除原始响应里的浏览器缓存值
sub_filter_once off; # 替换所有匹配内容
sub_filter_types *; # 匹配任何 MIME 类型
}
到此步常规站基本能正常使用了,最骚点来了,example采集这个站很多剧在更新,除了m3u8文件地址固定,文件内ts文件地址随机变化,如何解决这种情况!
二、来了来了,它来了,反代任意站
顾名思义,它、嗯、对、是的
举例1. 访问 xxx.com/fd/https://www.baidu.com 进入到百度搜索
举例2. 访问xxx.com/fd/https://cdn1.xxx.com/xvod/00db111e97d0da21/eee_0.ts 返回ts文件
举例3. 二哥说了凡事讲三点,举一反三,
代码如下
server {
listen 80;
listen 443 ssl http2;
server_name xxx.com; #改成自己的域名
root "/www/wwwroot/xxx.com"; #改自己的服务器目录
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
ssl_certificate /www/server/panel/vhost/cert/xxx.com/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/xxx.com/privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
set $custom_PATH /iss;
set $custom_host "https://www.baidu.com";
set $custom_host3 "/";
set $custom_host5 "/";
if ($request_uri ~* ^\/(.+)\/((http|https)://(www.)?([\w-]+(\.)?)+)(.*?)$) {
set $custom_host $2;
set $custom_host3 $7;
}
if ($custom_host3 = ""){
set $custom_host3 "/";
}
if ($custom_host3 = " "){
set $custom_host3 "/";
}
if ($request_uri ~* ^\/(.+)\/((http|https)://(www.)?([\w-]+(\.)?)+)(.+)\?(.+)$) {
set $custom_host3 $7;
}
if ($request_uri ~* ^\/(.+)\/((http|https)://)((www.)?(\w+(\.)?)+)$) {
return 301 $custom_PATH/$custom_host/;
}
set $custom_host2 "www.baidu.com";
if ($custom_host ~* ^((http|https)://)((www.)?([\w-]+(\.)?)+)$) {
set $custom_host2 $3;
set $custom_host5 $1;
}
set $referer $custom_host;
if ($http_referer ~* ^((http|https)://)(.*?)\/(.+)\/((http|https)://)(.*?)$) {
set $referer $5$7;
}
set $current "http://";
if ($scheme = https) {
set $current "https://";
}
proxy_hide_header content-security-policy;
location /fd/ {
# proxy_connect_timeout 100s;
# add_header Content-Security-Policy "default-src 'self' https://$host http://$host 'unsafe-inline' 'unsafe-eval' blob: data: ;";
# proxy_set_header x-forwarded-for $remote_addr;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
set $ishttp "http";
if ($custom_host5 = https://) {
set $ishttp "https";
}
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-Proto $ishttp;
proxy_set_header Host $custom_host2;
proxy_cache_key $host$uri$is_args$args;
proxy_headers_hash_max_size 512;
proxy_pass_header Server;
proxy_headers_hash_bucket_size 128;
proxy_buffer_size 64k;
proxy_buffers 32 64k;
proxy_busy_buffers_size 128k;
proxy_set_header Cookie $http_cookie;
proxy_cache_methods GET;
proxy_cache_methods POST;
proxy_cache_methods HEAD;
proxy_redirect $upstream_http_location "$current$host$custom_PATH/$upstream_http_location";
proxy_set_header Referer $referer;
proxy_set_header User-Agent $http_user_agent;
# 防止谷歌返回压缩的内容,因为压缩的内容无法替换字符串
proxy_set_header Accept-Encoding "";
proxy_connect_timeout 15000;
proxy_send_timeout 15000;
proxy_read_timeout 15000;
proxy_cache_valid 200 304 301 1s;
add_header MJJCDN-Cache "$upstream_cache_status";
# proxy_temp_file_write_size 512000k;
resolver 1.1.1.1; #改为自己想要的DNS
proxy_set_header Accept-Encoding "";
sub_filter_types text/plain text/javascript text/xml text/css application/x-javascript application/xml;
sub_filter_once off;
proxy_temp_file_write_size 512000k;
sub_filter "<head" '<base href="$current$host$custom_PATH/$custom_host/" />\n<head';
sub_filter '\'https://' '\'$current$host$custom_PATH/https://';
sub_filter '\'http://' '\'$current$host$custom_PATH/https://';
sub_filter '\"https://' '\"$current$host$custom_PATH/https://';
sub_filter '\"http://' '\"$current$host$custom_PATH/https://';
sub_filter "\"//" '"$current$host$custom_PATH/https://';
sub_filter '"/' '"$current$host$custom_PATH/$custom_host/';
sub_filter "'//" "'$current$host$custom_PATH/https://";
sub_filter "'/" "'$current$host$custom_PATH/$custom_host/";
sub_filter '"/search' '"search';
sub_filter "(http" "($current$host$custom_PATH/http";
sub_filter '"/images' '"images';
sub_tifilter ', /images' ', images';
sub_filter 'integrity' ', kkkk';
sub_filter '../' '$current$host$custom_PATH/$custom_host/../';
sub_filter "'http://$custom_host2" "'$current$host$custom_PATH/$custom_host";
sub_filter "'https://$custom_host2" "'$current$host$custom_PATH/$custom_host";
sub_filter "\"http://$custom_host2" "\"$current$host$custom_PATH/$custom_host";
sub_filter "\"https://$custom_host2" "\"$current$host$custom_PATH/$custom_host";
if ($request_uri ~* ^\/(.+)\/((http|https)://(www.)?([\w-]+(\.)?)+)(.*?)$) {
proxy_pass $custom_host$7$is_args$query_string;
}
# # set $request_uri "qqqq";
# add_header Content-Type "text/plain;charset=utf-8";
# return 200 "Your IP Address:$referer</br>$http_referer";
}
location / {
add_header Content-Type "text/plain;charset=utf-8";
return 200 "这是个正经网站";
}
}
所以怎么应用到m3u8文件里呢?这里需更改以下sub_filter
替换内容http' 'https://xxx.com/fd/http
,详见代码
再再次补充后的代码如下:
location ~* \.(m3u8|ts|aac)$ {
proxy_cache off; # 禁用代理缓存
proxy_set_header Sec-Fetch-Mode "navigate";
proxy_set_header Sec-Fetch-Site "cross-site";
proxy_set_header Cache-Control "max-age=0";
proxy_set_header Accept-Encoding "gzip,deflate";
gunzip on;
gzip_disable ".";
expires -1; # 禁用页面缓存
proxy_pass https://m3u8.example.com; # 反代目标 URL
proxy_ssl_server_name on;
sub_filter 'http' 'https://xxx.com/fd/http'; # 替换 m3u8 文件里的资源链接
sub_filter_last_modified off; # 删除原始响应里的浏览器缓存值
sub_filter_once off; # 替换所有匹配内容
sub_filter_types *; # 匹配任何 MIME 类型
}
完!感谢浏览此文章,感谢提供参考的博主!
参考
https://www.hostarr.com/reverse-proxy-for-hls-stream/
https://blog.samsam123.name.my/articles/bt-nginx-502-bad-gateway-ssl-upstream-handshake-fail
https://www.yeeach.com/post/1541
https://www.yeeach.com/post/1523
https://hostloc.com/thread-1011338-1-1.html