v2user

维护机场的经验,从入门到入狱

攻击起因

11月因为日常流量已经到了1G,之前一直用三方的转发,流量成本核算下来,还是自建面板更划算。
4c的aws租机,一个月也就100U,而三方的转发面板,市场价的价格也10CNY/T,也就是只要一个月跑的超过70T,自建转发面板和出口就更划算,而当时我们的月流量超不多已经到了一天6T多。

转发面板没啥好说的,就是用三方的软件,按照教程一步步搭建就可以了。

面板如图,看着是不是特眼熟,面板管理员才能看到哦。

然后就被人盯上了,态度就是打钱,不然打你。不给钱就是持续不断地各种针对机场的攻击。

第一波攻击

第一波很简单,网站的cc攻击。

机场的网站中有一个漏洞一样的请求,那就是订阅连接。

之所以说是漏洞一样,第一是访问这个连接不需要鉴权,说人话就是不需要登录验证。
第二就是,它非常需要算力。

默认订阅连接格式是:

https://yoursite.com/api/v1/client/subscribe?token=b8bd02d153ef63b049a89499b27ae96d

那么,攻击者大批量发送随机token的请求,数据库压力变大,服务器负载直接拉满,造成的结果就是,网站停止响应。普通用户无法正常使用。

比如像这样。

最后统计得到如下的结果。

加一起差不多18万的请求,一般的服务器根本扛不住。

第一波攻击很容易防御,加上cdn,哪怕套个cloudflare就可以轻松解决。

第二波攻击

做机场的最怕的是什么,就是国内的转发入口。

因为绝大多数做机场业务的,都不接受攻击,一旦发现攻击,直接清退。

在第一波攻击之后,平静了一晚上,第二天下午,入口一个挨着一个崩了。

第一个是黑洞,黑洞时间12个小时,第二个是直接被清退,第二个idc号称是50G的ddos防御,就真实感受而言,50G肯定没有,一打基就死。

第二波攻击攻击者完胜。

应对的方法说实话不复杂,就是花钱,找能抗的IDC。

然后就是类似这样的画面。

以为就这样,现实是第一天升级防御之后,攻击消停了之后,攻击方继续升级。

第三波攻击

从下图可以很明显的看到,我们升级到100G,对方打100G,我们升级到300G,对方打300G。

在12月5号的时候,在300G流量打过来的时候,老板已经开始略微绝望了。

因为idc能升级的最大只有300G,对方可以搞到300G,就能继续调流量,继续扩大攻击的流量。(因为对方攻击的都会间隔24小时左右,我们盲猜是他需要调肉鸡凑流量)

而目前来看,对方已经打不来了。

至于防御的方法,也是针对攻击方的攻击方式。

首先的攻击方式还是cc攻击,不过不是针对网站,而是针对转发入口。

看下图就可以看到,在同一个时间点有批量的IP通过TCP连接转发入口。

当时做了一个脚本,把一些高连接的TCP连接全部禁掉,很快对方就改变了攻击方式。

很快对方就改变了攻击策略,使用了UDP攻击方法。

无连接:不需要握手过程,直接发送数据包。
无确认:发送方不需要等待接收方确认,降低了延迟。
没有流量控制:发送数据包时不需要考虑网络的拥塞情况。

UDP攻击太适合做ddos攻击了。反正就是可了劲发UDP数据。

于是,当时直接上防御手段,把IP升级成上层阻断UDP的IP。在运营商层面直接封禁IP,来100G过滤100G,来300G过滤300G。

防是防住了,但是同样也出来了一个很尴尬的事情。

我本地国内IP连接入口节点,最大速度只有1M,800M的入口节点,只能跑到1M。

目前来说,攻击者没有再继续,流量也开始稳定,但是悲痛的说,虽然是防住了,但是持续快5天的攻击,随机的掉线,造成了稳定带宽从500M到了200多M,少了将近1/2的流量,大量用户流失。

如果你有一些自己解决不了的问题,可以添加我的频道telegram

机场运营上,最最最最烦人的就是,中转崩了,群里就直接炸了。

这个时候就需要快速接入其他的中转,正常的转发规则都是一条条添加,需要分别输入,转发绑定的端口,落地的IP,落地的端口。

要是几个落地机倒也不繁琐,要是几十个国家,加能加到人崩溃。

所以,就需要一个快速生成规则的方法,通过中转的批量添加,快速替换崩溃的中转。

使用方法。

1,chrome打开v2board的后台,找到节点管理,F12,有一个getNodes的请求。

v2board的节点信息。复制保存这个文件,以json文件结尾。

2,复制这个php代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php

define('BASE_DIR',__DIR__);

class V2board {

//转发规则
const MODE_ZF_RULE = 'MODE_ZF_RULE';


protected $name ;

public function log($str){
echo $str . PHP_EOL;
}

/**
* 生成转发格式
*/
public function jsonFileTozfRule($srcFile){

$this->name = $this->_getName($srcFile);

$srcFile = BASE_DIR . DIRECTORY_SEPARATOR .'json' . DIRECTORY_SEPARATOR . $srcFile;
$rawContent = $this->_getNodeInfoFromJsonFile($srcFile);
$ruleContent = $this->filterNodeInfo($rawContent,self::MODE_ZF_RULE);

$this->saveToFile(
$ruleContent,
$fileName = sprintf('%s/rules/%s2sc.csv',BASE_DIR,$this->name)
);

$this->log( "file name is " . $fileName);
}

public function _getName($srcFileName){
$_t = explode('.',$srcFileName);
return current($_t);
}


//get v2board node from json file
public function _getNodeInfoFromJsonFile($srcFile){
$content = file_get_contents($srcFile);
$obj = json_decode($content);
return $obj->data;
}

public function filterNodeInfo($nodeObj,$mode = 'default'){

switch($mode){

case self::MODE_ZF_RULE:
return $this->_modeZfRule($nodeObj);
break;
default:
return $this->_modeDefault($nodeObj);
break;
}

}

public function _modeDefault($nodeObj){
$tmp = "";
foreach($nodeObj as $item){
if($item -> show != 0 && $item->parent_id != null){
// if(preg_match("/01/",$item->name) || preg_match("/02/",$item->name)){
// $tmp .= sprintf("%s,%s,%s",$item->name,$item->host,$item->port).PHP_EOL;
// }
$tmp .= sprintf("%s,%s,%s",$item->name,$item->host,$item->port).PHP_EOL;
}
}
return $tmp;
}

public function _modeZfRule($nodeObj){
$tmp = "";
$_t_Arr = [];
foreach($nodeObj as $item){
if($item->parent_id == null){
$_t_Arr[$item->id] = [
'host' => $item->host,
'port' => $item->server_port
];
}
}

foreach($nodeObj as $item){

if($item->show != 0 && $item->parent_id != null){
$tmp .= sprintf(
"%s#%s#%s#%s",
$this->_buildRuleName($item),
$item->port,
$_t_Arr[$item->parent_id]['host'],
$_t_Arr[$item->parent_id]['port']
).PHP_EOL;

}
}
return $tmp;
}

public function _buildRuleName($item){
$_t = explode('.',$item->host);
return sprintf("%s-%s",$this->name,current($_t));
}

public function saveToFile($content,$file){
file_put_contents($file,$content);
}


}


//使用方法,首先保存V2的node信息
(new V2board()) -> jsonFileTozfRule('mk.json');

两个文件放到一个目录下,修改代码的最后一行,替换mk.json成你自己的文件名。

最后,执行命令 php V2board.php

本来打算做个页面,这样就不需要下载文件,上传文件就可以批量生成规则,考虑到这个文件敏感信息太多了,就直接放源码了。

曾经遇到过一个很诡异的现象,v2board密码都是对的,也提示了登录成功,但是就是登录失败,进入不了后台,有的用户不信邪,多次登录中会有一次成功。

开始以为是用户的账号密码错误,尝试过后台重置密码,还是一样的结果。

翻了翻对应的代码

AuthController.php 中的 login 方法。

常见的登录验证代码流程,只是其中最后一段,

1
2
3
4
$authService = new AuthService($user);
return response([
'data' => $authService->generateAuthData($request)
]);

跟着查看 generateAuthData方法,其中有一个 self::addSession方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function generateAuthData(Request $request)
{
$guid = Helper::guid();
$authData = JWT::encode([
'id' => $this->user->id,
'session' => $guid,
], config('app.key'), 'HS256');
self::addSession($this->user->id, $guid, [
'ip' => $request->ip(),
'login_at' => time(),
'ua' => $request->userAgent()
]);
return [
'token' => $this->user->token,
'is_admin' => $this->user->is_admin,
'auth_data' => $authData
];
}

继续追代码,找到 addSession方法。

1
2
3
4
5
6
7
8
9
10
11
private static function addSession($userId, $guid, $meta)
{
$cacheKey = CacheKey::get("USER_SESSIONS", $userId);
$sessions = (array)Cache::get($cacheKey, []);
$sessions[$guid] = $meta;
if (!Cache::put(
$cacheKey,
$sessions
)) return false;
return true;
}

其中的Cacheget/put操作看起来是那么醒目,有编程基础的人,看到这里,想必已经能猜到原因了,权限问题。

找到缓存目录storage/framework/cache/data,果然是这个原因。

清一色的www权限,莫名出现了一个root权限目录。

这就造成了Session文件无法写入,也就造成了,明明登录成功了,但是却进入不了后台。

知道了问题,解决也就很容易了。

修改对应的cache文件目录权限。

chown www:www cache -R

再次登录,恢复正常。

开发app时遇到的一个问题,v2board官方默认的前端支持快捷登录(不需要输入账号密码的登录方式),后端代码用的是token2Login方法。

而大部分的三方主题是不带这个功能,好不容易找到一个支持的v2board前端主题,结果要价 200U

有一说一,这个代码值这个价,为了防墙,前端是独立站点,利用配置文件的api_base值,向v2board的真实站点请求数据。

哪怕后端域名墙了,改一下对应的api_base对应值就满血复活了。

源码地址:https://github.com/amyouran/v2board-Zero-Theme

有钱的朋友可以去支持,反正我没钱,何况甲方也不出这个钱。

如下就是破解这个200U的付费前端主题的过程。

主题破解原理

根据计算机原理,所有的网页的交互功能都是js实现的。

而网页的前端代码都是会下载到本地上,不像其他exe,apk这类字节执行文件,而js的本地代码是可以自行修改的。

破解过程

第一步,首先是下载代码到本地。

这个很简单,本地配置一个web的开发环境,chrome,F12,把对应的网页文件下载到本地对应的目录。

修改了对应的配置文件之后,出错了。

下面就是要一步步的去掉对应的验证功能。

首先肯定是先F12,看看代码的执行过程。

不出意外的是,肯定就出意外了。强制循环跳出debug,跟个小姑娘一样,不给看。

不给看,那就强行看呗。

跳出debug的地方是在对应的代码,可以看到是什么代码调用了这个循环的debug

而对应的代码是

1
constructor(I.MEtYM + V(-188 * -17 + 9290 + 6197 * -2, 9206 + 6327 + -15443, 73 * 37 + 8779 + -11350, 6826 + -15 * -255 + -10512, -9557 + 6190 + 3562)).call(I.PyYEW);

在对应的 index.9ea5738c.js 直接把 I.PyYEWI.MEtYM + V(-188 * -17 + 9290 + 6197 * -2, 9206 + 6327 + -15443, 73 * 37 + 8779 + -11350, 6826 + -15 * -255 + -10512, -9557 + 6190 + 3562) 在源代码里删除掉,代码就无法调用对应的函数,无法调用不就可以看代码执行了呗。

至于它是干什么用的,略微的功能猜也能猜出来,是构造了一个方法并且调用这个方法。

删除之后是这样的。

1
constructor().call();

再次刷新页面,还是出现了debug,不过是在另外一个位置,既然说明了有效果,那就按照刚刚的操作,继续删代码。

处理掉浏览器的debug方法,终于到了错误提醒框。

然后就很尴尬,不点击这个弹窗,无法操作chrome,点击这个弹窗,会立马清空chrome的url。这就造成了,还没看到对应的代码,chrome就更新了,开发编辑器的内容也被一起清空了。

就在被这个操作搞的无语的时候,忽然灵光一闪,弹窗就一定有对应的代码。

然后在对应的代码里,搜索 alert,也就是js的弹窗代码。

一一分辨对应的执行代码。

只有一个alert代码后面紧跟着一个 window.location.href,也就是刚好满足提到的操作实现(弹窗之后修改当前chrome的url)。

二话不说,继续删。

再次刷新,终于没有付费的弹窗。

破解之后

破解之后,部署上线,还需要对nginx做一个配置。

1
2
3
location / {
try_files $uri $uri/ /index.html;
}

为了安全考虑,毕竟是混淆的代码,谁知道在哪里加了点上传的功能,毕竟自己都是破解的,也没付钱,所以,就还需要在当前站点的nginx配置中,丢弃所有post请求。

1
2
3
if ($request_method = 'POST') {
return 403;
}

最后给原作者的建议

想要完全不被破解,还有个办法,那就是加一个中转接口。

这样的好处,第一是,防封,可以把官方的接口命名规则全部改掉了,所有的json请求做二次加密,彻底去掉特征码,没错,开发app的时候,本人做了一套现成的中转接口。

第二则是,静态文件很难做验证,就像上文一样,把文件拖到本地,就很容易强行破解,破坏肯定比建设来的更容易。

但是,在接口里做动态验证,数据库里没有就是不给用。

第三则是,这样才能持续不断的收费啊,卖的是防封服务,大兄弟。

所以,大兄弟,如果看到了,尽快联系我,不然就公开代码了。

最后,我的联系方式,可以添加我的频道telegram

估摸着很多多年运营的机场主都不知道的技巧,那就是如何设置公告弹窗。

类似这样。

其实设置起来很简单。

只需要在后台公告设置当中,公告标签当中,添加“弹窗”就可以实现。

算是v2board的一个代码小彩蛋了。

umi.js 当中有这么一段代码:

1
2
3
4
5
6
7
8
9
10
this.props.dispatch({
type: "notice/fetch",
complete: ()=>{
var e, t = (null === (e = this.props.notice) || void 0 === e ? void 0 : e.notices) || [];
if (t.length) {
var n = t.find(e=>-1 !== e.tags.indexOf("\u5f39\u7a97"));
console.log(n),
n && this.modalVisible(n)
}
}

在执行获取公告之后,会做一个判断,

如果e.tags.indexOf 包含 \u5f39\u7a97this.modalVisible(n)

而这个unicode\u5f39\u7a97编码之后的中文,就是弹窗。

那么,只要在公告编辑的标签当中,包含关键词 弹窗,就实现了公告弹窗。

又是收获满满的一天,又刑了。

如果你有一些自己解决不了的问题,欢迎加入我的频道telegram

上面提到的dnsmasq解锁也好,cloudflare解锁也好,前提都是需要安装额外的软件,说实话,繁琐,而且节点可能由于各种原因更换,比如,流量不够,到期,那么下一次就要重新再配置一次,相当的繁琐。

那么,就要重点推荐这个方法,用xrayr自带的功能。

准备工作

这里还是需要两台落地vps,一台可以正常访问流媒体,就叫做YES机器,一台不能访问,就叫做NO机。

现在啥也不安装,就通过xrayr自带的功能,就可以实现,NO机的解锁流媒体。

配置YES机

首先,登录到yes机,进入到xrayr的配置目录,一般是 /etc/XrayR

首先,修改 config.yml 第7行,类似如下内容:

1
InboundConfigPath: # /etc/XrayR/custom_inbound.json

取消掉注释,准许自定义进入规则。

其次,修改 custom_inbound.josn

修改
listen: "127.0.0.1"listen: "0.0.0.0"

port 可以自定义,这里例子用的是40001。

修改之后大概是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  {
"listen": "0.0.0.0",
"port": 40001,
"protocol": "socks",
"settings": {
"auth": "noauth",
"accounts": [
{
"user": "my-username",
"pass": "my-password"
}
],
"udp": false,
"ip": "127.0.0.1",
"userLevel": 0
}
}
]

这么修改的意义,就是在YES机开放40001端口,准许其他进行访问。

当然,需要准许防火前的端口访问。

ubuntu下的命令是

1
2
ufw allow 40001/tcp
ufw reload

最后一步,当然是重启 xrayr restart

配置NO机

首先,修改 config.yml

取消 第6行

RouteConfigPath: /etc/XrayR/route.json

和 第8行 的 #注释。

OutboundConfigPath: /etc/XrayR/custom_outbound.json

然后,修改custom_outbound.json

添加规则,大致如下,规则需要符合json格式。

1
2
3
4
5
6
7
8
9
10
11
12
{
"tag": "chatgpt_relay",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "YOUR_YES_VPS_IP(你的YES机器IP)",
"port": 40001
}
]
}
},

这里就是新建一个规则名称为 chatgpt_relay,转发给YES机对应的端口,40001

然后,修改 route.json

添加规则,大致如下,需要满足json格式要求。

1
2
3
4
5
6
7
8
9
{
"type": "field",
"outboundTag": "chatgpt_relay",
"domain": [
"chatgpt.com",
"openai.com"
]
},

这条规则,就是满足域名为chatgpt.comopenai.com 的请求,都转发给 chatgpt_relay规则。

而在custom_outbond.json文件里,恰好定义了具体的路径,就是转发给你的YES机的40001端口。

最后一步,重启xrayr xrayr restart

至此,什么软件都不需要,就完成了对 chatgpt 的解锁,对其他的流媒体一样有效。

又是进步的一天,真刑。

如果你有一些自己解决不了的问题,可以添加我的频道telegram

之前的流媒体解锁之dns解锁中提到的方法,前提是必须有一个可以正常访问的落地机节点。

那要是没有这种节点怎么办?简单,用cloudflare解锁。

安装脚本

首先下载安装脚本。

1
wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh

给文件执行权限。

1
chmod +x menu.sh

执行脚本

1
./menu.sh

默认中文语言,选择13. 安装 wireproxy,让 WARP 在本地创建一个 socks5 代理 (bash menu.sh w)

端口这里是40000

安装成功之后是这样的:

到此,已经在本地的40000端口开启了cf的sock代理服务。

配置xrayr

首先,编辑 custom_outbound.json

修改文件的第22行代码左右。

注意是 "tag::"socks5-warp"

1
"port":40000

其次,编辑 route.json
修改文件的第21行左右。

1
"domain":["geosite:netflix"]

同样需要注意的是 "outboundTag":"socks5-wwarp"

最后,修改config.yml

在文件的第6行

取消 RouteConfigPath的注释

在文件的第8行

取消OutBoundConfigPath的注释

如上的配置修改,是告诉xrayr这个软件。

凡是符合netflix的请求,全部转发给socks-wrap,也是本地的40000端口。

最后还需要重启xrayr

1
xrayr restart

优劣处

至此,完成对流媒体的解锁。

这个方法的好处是,不需要已有节点的支持,但是大家都知道,毕竟是免费的流量,速度会跟不上,更适合类似chagGPT这类的网页解锁。

当然还有其他问题,就是有些地区没有cf的节点。

又是刑的一天。

如果你有一些自己解决不了的问题,可以添加我的频道telegram

机场运营的痛楚

在v2board机场运行中,其中有机场主最头疼的问题,那就是域名被封。

有没有域名不被封的方法,有,没办法公开,第一是成本高,其次是,一旦公开就无效了。

一旦域名被reset之后,不仅用户会出现大面积的流失,更关键的是会极大挫伤推广人员的积极性。

弟兄们寒了心,队伍就不好带了。

解决的思路就是,做一个稳定的对外推广链接。

不好理解,那么就形象一点。

比如,现在有一个对外的邀请连接,假定是,a.com。

这个域名啥也不做,就只负责做跳转。

用户打开 a.com 会自动跳转到另外一个域名,比如,sitea.com。

而sitea.com是真实的注册页面。

如果sitea.com被封,那么a.com再跳转到siteb.com。

而 a.com 上没有任何内容,只是做了一个跳转,没有特征,就不会触发墙的自动屏蔽。

当然,人工封禁除外。

具体的实现

首先,修改代码。

原生默认的主题中,路径是 public/v2board/theme/assets/ 找到umi.js。

搜索关键词

?code=

找到类似的代码:

1
window.location.origin+window.location.pathname+"#/register?code="+

替换 window.location.origin 成你自己的跳转域名,比如 https://a.com

保存之后,邀请连接就由之前的 默认邀请连接,变成了 https://a.com/#/register?code=xxxxxx

其他主题默认是一样的,都是替换掉默认的邀请域名,改成一个跳转域名。

跳转代码

最有一步,做一个301跳转页面。

301跳转的方法有很多。

请注意的是,跳转时要带上注册的邀请码,也就是后面的参数 /#/register?code=xxxxxx

放上php的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php 

class RelayService {

private $inviteDomain = 'a.com';

public function inviteRelay(){
$params = $this->_inviteParam();
$inviteUrl = $this->_getInviteDomain($params);
$this->_redirect($inviteUrl);
}

public function _inviteParam(){
if(isset($_GET['code'])){
return sprintf(
"#/register?code=%s",$_GET['code']
);
}
return '';
}

public function _getInviteDomain($params){
return sprintf(
"https://%s,%s",
$this->inviteDomain,
$params
);
}

public function _redirect($relayUrl){
header('HTTP/1.1 301 Move Permanently');
header('Location: $relayUrl');
}

}


(new RelayService())->inviteRelay();

当然,这个是基础版功能,已经足够保证邀请链接的稳定性。

一旦域名被封,就换个新域名。对推广人员来说,推广链接一直有效。

如果各位老板搞不定,可以联系我解决(不免费,收费标准查看关于我)。

今天又是进步的一天,又刑了一点点。

如果你有一些自己解决不了的问题,可以添加我的频道telegram

具体使用

为了方便理解,如下操作,除非特别指明,默认是在已经可以正常观看奈飞服务的vps,暂叫做解锁机,例子中的IP是:23.142.200.1*

安装前需要注意

在安装之前,确保53,80,443端口没有被占用。

在实际的操作过程中,53端口由systemd-resolv占用,需进行如下操作。

  1. 修改 /etc/systemd/resolved.conf
1
2
3
4
5
6
7
8
9
[Resolve]
DNS=8.8.8.8 1.1.1.1 #取消注释,增加dns
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#Cache=yes
DNSStubListener=no #取消注释,把yes改为no
  1. 重新链接解析配置文件

ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

在执行如上操作之前,更建议先备份当前resolv.conf文件。

1
2
lrwxrwxrwx   1 root root         39 Feb 10  2023 resolv.back.conf -> ../run/systemd/resolve/stub-resolv.conf
lrwxrwxrwx 1 root root 32 Jul 31 09:05 resolv.conf -> /run/systemd/resolve/resolv.conf

清晰对比出两个配置文件的区别。

  1. 重启systemd-resolved

systemctrl restart systemd-resolved

安装过程

快速安装

1
wget --no-check-certificate -O dnsmasq_sniproxy.sh https://raw.githubusercontent.com/myxuchangbin/dnsmasq_sniproxy_install/master/dnsmasq_sniproxy.sh && bash dnsmasq_sniproxy.sh -f

卸载命令

1
wget --no-check-certificate -O dnsmasq_sniproxy.sh https://raw.githubusercontent.com/myxuchangbin/dnsmasq_sniproxy_install/master/dnsmasq_sniproxy.sh && bash dnsmasq_sniproxy.sh -u

验证效果

dns解析

在不能观看奈飞的vps上执行如下命令。

指定ip为23.142.200.1*的dns服务器解析www.netflix.com域名。

nslookup www.netflix.com 23.142.200.1*

这里得到的效果

1
2
3
4
5
6
nslookup www.netflix.com 23.142.200.1*
Server: 23.142.200.1*
Address: 23.142.200.1*#53

Name: www.netflix.com
Address: 23.142.200.1*

正确的情况下,解析 www.netflix.com 对应的IP应该就是解锁机的IP。

访问页面

上一步是通过强行指定dns服务器,下一步验证访问。

在不能访问奈飞的vps,修改 /etc/resolv.conf

添加nameserver 之后

1
2
nameserver 23.142.200.1*
nameserver 127.0.0.53

再执行

1
curl https://www.netflix.com -vvv

不能访问奈飞的vps也可以正常访问奈飞了。

问题

1
2
3
4
5
nslookup netflix.com 23.142.200.1*
;; communications error to 23.142.200.1*#53: timed out
;; communications error to 23.142.200.1*#53: timed out
;; communications error to 23.142.200.1*#53: timed out
;; no servers could be reached

除了开放53/tcp,还需要开放53/udp,dns的请求解析协议是udp。

ubuntu命令如下

1
2
3
ufw allow 53/tcp 
ufw allow 53/udp
ufw reload

如果就这么设置,很快这个解锁机也无法访问奈飞,因为你能访问的同时,其他人也可以访问,解决下拉到 安全。

其次,如果无法访问指定的域名,比如flixnet.com,在dnsmasq中添加需要指向的域名。

配置文件目录为 /etc/dnsmasq.d/custom_netflix.conf ,添加需要指向的域名。

格式为 address=/primevideo.com/156.x.x.x

只有这样,其他机器通过53请求dns指向时,才会返回你指定的ip地址,修改后重启,命令为 systemctl restart dnsmasq

最后,如果dns域名指向已经改变了,但是还是会遇到打开的网站出现证书错误,需要调整sniproxy的配置,比如在访问 chatgpt.com这个域名时,默认的网页配置并没有这个域名,就需要修改配置文件。

默认配置文件在/etc/sniproxy.conf,按照格式添加需要的域名,比如chatgpt.com就是.*chatgpt\.com$ *

重启sniproxy ,命令是 systemctl restart sniproxy

安全

更建议的设置是:

1
2
3
ufw delete allow 53/tcp
ufw delete allow 53/udp
ufw allow from ip(不能解锁奈飞的vps)

设置访问白名单。

自动化脚本

自动化脚本出处:https://github.com/myxuchangbin/dnsmasq_sniproxy_install

如果你有一些自己解决不了的问题,可以添加我的频道telegram

如果是机场主,你要不是不解锁奈飞,你都不好意思出门见人。

这篇文章就从原理开始,一步步告诉你如何实现,让一部分无法访问奈飞的落地机vps,能够访问netflix,主打一个从入门到入狱,每天又刑了一点点。

dns解锁原理

首先,比如你现在手里有台vps,比如我这台vultr的新加坡机器,不知道是否能够访问netflix。

只需要输入如下命令:

curl https://www.netflix.com -vvv

得到如下的结果:

403状态码就是无权限访问,就暂定叫做NO机。

而另外一台机器(暂定叫做YES机),输入同样的命令,得到的结果却是:

不仅是200的正常http码,而且还能看到对应的html代码。

看这里,看这里,请注意,要施展魔法了。

如上的NO机一样可以正常访问netflix,请看图。

实现原理

使用Dnsmasq的DNS将网站解析劫持到SNIproxy反向代理的页面上。

正常的网络请求是这样:

  1. NO机 -> dns请求www.netflix.com的ip
  2. NO机 -> 向解析后的ip发送网页请求。

NO机在第二步会出错,因为NO机的IP会被netflix屏蔽掉。

可是,dns请求获取的IP是可以访问netflix.com的YES机,然后再由YES机代请求呢。

执行的流程就类似这样:

  1. NO机 -> dns请求www.netflix.com -> 得到YES机IP (dns为自定义的dnsmasq服务)
  2. NO机 -> 向YES机发送网页请求 -> YES机代为转发请求

于是就通过虚构dns,再转发请求的方式完成了奈飞解锁。

具体实现

那这里就需要用到一款工具,具体的操作可以查看这个文章。

dnsmasq解锁奈飞

xrayr配置

如上已经完成了NO机对奈飞的解锁,如何配置到xrayr上。

进入到xrayr的配置目录,/etc/XrayR

  1. 首先配置 DNS.json
1
vim dns.json

修改成如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"servers": [
"1.1.1.1",
"8.8.8.8",
{
"address": "unlook.your.yes.vps",
"port": 53,
"domains": [
"geosite:netflix",
"geosite:disney",
"bamgrid.com",
]
}
]
}

如上配置是告诉xrayr,当域名为netflix,disney,bamgrid.com时,向unlook.your.yes.vps发送dns请求。

  1. 修改成XrayR配置文件
1
vim config.yml

第5行去掉#号,开启dns

1
DnsConfigPath:  /etc/XrayR/dns.json

第35行左右

1
2
EnableDNS: true
DNSType: UseIP
  1. 重启
1
xrayr restart

按照这个过程搭建一个服务器,就比如之前的主机评测当中,主机评测-polocloud,用一台9.9人民币的美国服务器作为解锁机,这样就可以解锁其他所有的节点。

只是2T的流量会略微少了一些,不过对刚开始的机场也足够了。

毕竟,专门的

如果你有一些自己解决不了的问题,可以添加我的频道telegram

0%