无成本反向代理Jsdelivr
|字数总计:2.3k|阅读时长:9分钟|阅读量:|
前言
自从去年底 jsdelivr 的备案被吊销后,其在我国大陆地区的速度相较于此前慢了非常多,幸亏有大佬无私分享了他反代的 jsd ,所以我的博客并没有受到太大的影响。
但是我尝试反代 jsd 的原因说起来也很无奈,一是因为重庆三大运营商对 jsd 有不同程度的 DNS 污染(2022年2月15日,重庆电信和移动恢复正常),另一个是大佬无私分享的反代链接有白名单机制,因此我在本地测试的时候往往得手动把链接换回成 jsd ,然后再代理一下才能测试效果。
反代 jsd 的方案应该有很多,nginx 很轻松就能做到。但是想要低成本或者无成本反代,我做出了比较多的尝试,最终总结出两个我个人实践后可行的办法。
虚拟主机反代
虚拟主机相较于服务器而言成本更低,但是往往存在很多限制。我去年白嫖了蓝队云的免费不限带宽不限流量虚拟主机,详见《这可能是国内最好用的虚拟主机》,并且今年也成功续期了,不得不说蓝队云还是非常大方的。
但是我们今天的主角不是它,因为蓝队云的虚拟主机存在诸多限制,所以我此前尝试部署一个 php 网盘程序失败,今天尝试部署反代同样失败。所以今天的主角是来自灰狼云的免费虚拟主机。
相较于蓝队云,灰狼云每次只能续期一个月,一月一续,如果要免除续期可以交一点点钱,或者购买付费虚拟主机(说实话,付费的价格也非常非常实惠)。
免费空间300MB,并发数100,流量15G/月,如果是为了反代个人使用的话,应该是完全够用的。这里省去领取和部署方法(直观并且确实无套路)。
关于反代的方法我在 github 上找到了好几个,但是实测下来有两个可用,其它的要么返回404,要么就是只能反代单页面(可能问题还是在于虚拟主机的限制)。
另外,如下两种虚拟主机反代的方法并未缓存对应文件到虚拟主机上,所以加载速度相对较慢。
第一种方法
①新建一个 php 文件,粘贴下面的代码,保存任意名称即可:
<?php if(isset($_GET['url'])==false){die("请将参数填写完整,在当前路径后加上?url=反代的链接");} $token=(string)rand(100,99999); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $_GET['url']); curl_setopt($ch, CURLOPT_HEADER,false); curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,1); if(isset($_SERVER['HTTP_REFERER'])==true){curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']);} $data_down = curl_exec($ch); if($data_down === FALSE){die("代理时发生错误");} curl_close($ch); file_put_contents($token, $data_down); header('Content-Type: '.mime_content_type($token)); unlink($token); echo $data_down; ?>
|
②将该文件上传到虚拟主机,然后访问你解析的域名+该文件名,在后面输入要反代的链接即可。
比如我下面这个链接:
https://w.hin.cool/proxy.php?url=https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css
|
速度通常在几百毫秒以上,如果一次引入较多可能会拖慢速度,有更高速的需求可以尝试付费虚拟主机:
第二种方法
如果你觉得上面的方式中,链接太过于冗长,想要类似于xxx.coml/npm/@fancyapps/ui/dist/fancybox.css
这样的链接,在全局替换的时候也可以更简单,那么你可以尝试使用这个代码:
<?php
$target_host="https://cdn.jsdelivr.net";
$protocal_host=parse_url($target_host);
$Agent = $_SERVER['HTTP_USER_AGENT'];
$rootdomain=explode(".",$_SERVER["SERVER_NAME"]);
$lenth=count($rootdomain);
$top=".".$rootdomain[$lenth-1];
$root=".".$rootdomain[$lenth-2];
function get_request_params() { $url = $_SERVER["REQUEST_URI"]; $refer_url = parse_url($url); $params = $refer_url['query']; $arr = array(); if(!empty($params)) { $paramsArr = explode('&',$params); foreach($paramsArr as $k=>$v) { $a = explode('=',$v); $arr[$a[0]] = $a[1]; } } return $arr; }
function parse_headers($headers) { global $root,$top; foreach( $headers as $k=>$v ) { $t = explode( ':', $v, 2 ); if( isset( $t[1] ) ) { if(strcasecmp('Set-Cookie',trim($t[0]))==0) { $targetcookie=trim( $t[1] ).";"; $res_cookie=preg_replace("/domain=.*?;/","domain=".$root.$top.";",$targetcookie); $res_cookie=substr($res_cookie,0,strlen($res_cookie)-1); header("Set-Cookie: ".$res_cookie); } elseif(strcasecmp('Content-Type',trim($t[0]))==0) { header("Content-Type: ".trim( $t[1] )); } elseif(strcasecmp('Location',trim( $t[0] ))==0) { $relocation=str_replace($protocal_host['host'],$_SERVER["SERVER_NAME"],trim( $t[1] )); header("Location: ".$relocation); } elseif(strcasecmp('cache-control',trim( $t[0] ))==0) header("cache-control: ".trim( $t[1] )); else continue; } } return; }
function array_to_str($array) { $string=""; if (is_array($array)) { foreach ($array as $key => $value) { if(!empty($string)) $string.="; ".$key."=".$value; else $string.=$key."=".$value; } } else { $string = $array; } return $string; }
function debug_to_console($data) { if(is_array($data) || is_object($data)) { echo("<script>console.log('PHP: ".json_encode($data)."');</script>"); } else { echo("<script>console.log('PHP: ".$data."');</script>"); } }
$opts=""; if($_SERVER['REQUEST_METHOD']=='POST') { $postdata=file_get_contents("php://input"); $opts = array( 'http'=>array( 'method'=>$_SERVER['REQUEST_METHOD'], 'content'=>$postdata, 'header'=>"Accept-language: zh-CN\r\n" . "user-agent: '$Agent'"."\r\n". "Cookie: ".array_to_str($_COOKIE)."\r\n". "Content-Type: ".$_SERVER['CONTENT_TYPE'] ) ); } else { $opts = array( 'http'=>array( 'method'=>$_SERVER['REQUEST_METHOD'], 'header'=>"Accept-language: zh-CN\r\n" . "user-agent: '$Agent'"."\r\n". "Cookie: ".array_to_str($_COOKIE) ) ); }
$context = stream_context_create($opts);
$new_request_uri = ""; $path_script = pathinfo($_SERVER["PHP_SELF"]);
if ($path_script['dirname']!="/") { $new_request_uri = substr_replace($_SERVER["REQUEST_URI"],"",strpos($_SERVER["REQUEST_URI"],$path_script['dirname']),strlen($path_script['dirname'])); } else { $new_request_uri = $_SERVER["REQUEST_URI"]; } $homepage = file_get_contents($protocal_host['scheme']."://".$protocal_host['host'].$new_request_uri,false,$context);
parse_headers($http_response_header);
$homepage=str_replace($protocal_host['host'],$_SERVER["SERVER_NAME"],$homepage);
echo $homepage; ?>
|
并且需要额外配置伪静态,apache 的示例如下:
RewriteEngine on RewriteBase / RewriteCond $1 ^(index\.php)?$ [OR] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} ^index\.php?$ RewriteRule ^(.*)$ - [S=1] RewriteRule . /index.php [L]
|
CDN 反代
在折腾了多个 PHP 反代之后,我想,难道就没有更简便的方法了吗,或者速度更快的?联想到 jsd 本质上就是一个 CDN ,没有缓存的内容都会回源去取,所以我想到了其它 CDN !
关于 CDN 我此前也写过一篇《国内免费CDN和云存储测评分享》,除了又拍云我不建议使用外,其它的看你自己的喜好。如果你没有备案域名,那你或许也可以尝试一下 cloudflare (当然仅在你无法直接访问jsd的时候,因为速度不一定比 jsd 本身快)
方法也非常简单,新建一个 CDN ,域名输入你自己要解析的域名,源站域名和回源 Host 都填写cdn.jsdelivr.net
,回源协议选择“协议跟随”,为了避免 CDN 节点所在的运营商也屏蔽了 jsd ,热备源站或许可以试试套娃。
此外,记得开启回源跟随301、302。
那么反代后的链接应该就是:
https://xxx.com/npm/@fancyapps/ui/dist/fancybox.css
|
速度大概就是这个样子,第一次访问因为要回源所以比较慢,CDN 节点有缓存之后速度会快很多:
此外就是配置防盗链和设置流量阈值什么的了,请参考我曾经被刷流量的教训。
经测试,腾讯云 CDN 同样可以!
总结
昨天听群里有人说北京也出现了 jsd 无法访问的情况,不知道未来这个现象会不会扩大。自己反代 jsd 建议在无法访问或者访问速度奇慢的情况下使用。以上两种方法各有优劣,大家可以根据自己的需求来选择。
最后还是要提醒一下各位,遵纪守法,也要懂得保护自己,不要为任何违法犯罪的行为提供机会和帮助。