From 954cfe03462101763a87326246db243c5ae23b91 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 14 Nov 2024 14:32:49 +0400 Subject: [PATCH 01/58] improve ip ban --- app/bot.php | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/app/bot.php b/app/bot.php index 4421ea8..340b4a0 100644 --- a/app/bot.php +++ b/app/bot.php @@ -149,6 +149,9 @@ class Bot case preg_match('~^/switchBanIp$~', $this->input['callback'], $m): $this->switchBanIp(); break; + case preg_match('~^/switchSilence$~', $this->input['callback'], $m): + $this->switchSilence(); + break; case preg_match('~^/switchScanIp$~', $this->input['callback'], $m): $this->switchScanIp(); break; @@ -1179,13 +1182,15 @@ class Bot ]]; } } - foreach ($c['admin'] as $k => $v) { - $this->send($v, "suspicious ips found: $text" . ($ban ? "\nbanned:$ban" : ''), button: $ips ?: [[ - [ - 'text' => $this->i18n('analyze'), - 'callback_data' => '/analysisIp', - ], - ]]); + if (empty($pac['silence'])) { + foreach ($c['admin'] as $k => $v) { + $this->send($v, "suspicious ips found: $text" . ($ban ? "\nbanned:$ban" : ''), button: $ips ?: [[ + [ + 'text' => $this->i18n('analyze'), + 'callback_data' => '/analysisIp', + ], + ]]); + } } } } @@ -4173,6 +4178,14 @@ DNS-over-HTTPS with IP: $this->ipMenu(); } + public function switchSilence() + { + $c = $this->getPacConf(); + $c['silence'] = $c['silence'] ? 0 : 1; + $this->setPacConf($c); + $this->ipMenu(); + } + public function ipMenu() { $text = 'Menu -> IP'; @@ -4188,20 +4201,26 @@ DNS-over-HTTPS with IP: if (!empty($pac['autoscan'])) { $data[] = [ [ - 'text' => $this->i18n('autodeny') . ': ' . $this->i18n($pac['autodeny'] ? 'on' : 'off'), + 'text' => $this->i18n('autoblock') . ': ' . $this->i18n($pac['autodeny'] ? 'on' : 'off'), 'callback_data' => '/switchBanIp', ], ]; + $data[] = [ + [ + 'text' => $this->i18n('silence') . ': ' . $this->i18n($pac['silence'] ? 'on' : 'off'), + 'callback_data' => '/switchSilence', + ], + ]; } $data[] = [ [ - 'text' => $this->i18n('allow list') . ": $w", + 'text' => $this->i18n('ignorelist') . ": $w", 'callback_data' => '/denyList 0 1', ], ]; $data[] = [ [ - 'text' => $this->i18n('deny list') . ": $d", + 'text' => $this->i18n('blocklist') . ": $d", 'callback_data' => '/denyList 0 0', ], ]; @@ -4319,11 +4338,11 @@ DNS-over-HTTPS with IP: } else { $this->send($this->input['from'], "$k $comment\n", button: [[ [ - 'text' => $this->i18n('deny'), + 'text' => $this->i18n('block'), 'callback_data' => "/denyIp $k", ], [ - 'text' => $this->i18n('allow'), + 'text' => $this->i18n('ignore'), 'callback_data' => "/whiteIp $k", ], [ @@ -4393,7 +4412,7 @@ DNS-over-HTTPS with IP: 'callback_data' => "/allowIp $v $page" . ($white ? " 1" : ''), ], [ - 'text' => $this->i18n($white ? 'deny' : 'allow'), + 'text' => $this->i18n($white ? 'block' : 'ignore'), 'callback_data' => ($white ? "/denyIp" : "/whiteIp") . " $v 1 $page $white", ], [ From 9eb15b9b4506b9aff6e8fbc42550459d8f587ebb Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 14 Nov 2024 15:37:06 +0400 Subject: [PATCH 02/58] update version --- version | 2 ++ 1 file changed, 2 insertions(+) diff --git a/version b/version index a3a82ff..620b6e9 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +14.11.2024 v1.99.1 +- анализ логов и бан айпишников, фиксы 14.11.2024 v1.99 - анализ логов и бан айпишников 11.11.2024 v1.98 From f29d366aef5f2b4fe9f4e258e288ea49d87a6250 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 14 Nov 2024 16:47:55 +0400 Subject: [PATCH 03/58] scaner: fix regex --- app/bot.php | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/app/bot.php b/app/bot.php index 340b4a0..94787de 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4247,7 +4247,23 @@ DNS-over-HTTPS with IP: public function analysisIp($return = false) { $pac = $this->getPacConf(); - foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], ['10.10.0.10']) as $v) { + foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], [ + '10.10.0.1' ,'10.10.1.1' , + '10.10.0.2' ,'10.10.1.2' , + '10.10.0.3' ,'10.10.1.3' , + '10.10.0.4' ,'10.10.1.4' , + '10.10.0.5' ,'10.10.1.5' , + '10.10.0.6' ,'10.10.1.6' , + '10.10.0.7' ,'10.10.1.7' , + '10.10.0.8' ,'10.10.1.8' , + '10.10.0.9' ,'10.10.1.9' , + '10.10.0.10','10.10.1.10', + '10.10.0.11','10.10.1.11', + '10.10.0.12','10.10.1.12', + '10.10.0.13','10.10.1.13', + '10.10.0.14','10.10.1.14', + '10.10.0.15','10.10.1.15', + ]) as $v) { $xr[$v] = true; } if ($r = fopen('/logs/nginx_tlgrm_access', 'r')) { @@ -4282,15 +4298,15 @@ DNS-over-HTTPS with IP: } $reg = [ - 'GET /ws.+ HTTP', - 'GET /adguard/.+ HTTP', - 'GET /webapp.+ HTTP', - 'GET /pac.+ HTTP', - 'GET \.well-known.+ HTTP', - 'GET /v2ray.+ HTTP', - 'GET /dns-query.+ HTTP', + 'GET /ws(?:.+)? HTTP', + 'GET /adguard/(?:.+)? HTTP', + 'GET /webapp(?:.+)? HTTP', + 'GET /pac(?:.+)? HTTP', + 'GET \.well-known(?:.+)? HTTP', + 'GET /v2ray(?:.+)? HTTP', + 'GET /dns-query(?:.+)? HTTP', 'GET / HTTP', - 'GET /tlgrm.+ HTTP', + 'GET /tlgrm(?:.+)? HTTP', 'GET /jsoneditor.min.css HTTP', 'GET /jsoneditor.min.js HTTP', 'GET /jquery-3.7.1.min.js HTTP', From b0e6835ac9ef18be5bc0c2ec59a0b3ab83f48af1 Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 15 Nov 2024 01:04:06 +0400 Subject: [PATCH 04/58] improve scanner --- app/bot.php | 108 +++++++++++++++++++++++++---------------------- update/update.sh | 12 +++--- version | 6 +++ 3 files changed, 70 insertions(+), 56 deletions(-) diff --git a/app/bot.php b/app/bot.php index 94787de..82c7397 100644 --- a/app/bot.php +++ b/app/bot.php @@ -149,6 +149,9 @@ class Bot case preg_match('~^/switchBanIp$~', $this->input['callback'], $m): $this->switchBanIp(); break; + case preg_match('~^/searchLogs (.+)$~', $this->input['message'], $m): + $this->searchLogs($m[1]); + break; case preg_match('~^/switchSilence$~', $this->input['callback'], $m): $this->switchSilence(); break; @@ -1182,14 +1185,14 @@ class Bot ]]; } } - if (empty($pac['silence'])) { + if ($pac['silence'] == 0 || $pac['silence'] == 1) { foreach ($c['admin'] as $k => $v) { $this->send($v, "suspicious ips found: $text" . ($ban ? "\nbanned:$ban" : ''), button: $ips ?: [[ [ 'text' => $this->i18n('analyze'), 'callback_data' => '/analysisIp', ], - ]]); + ]], disable_notification: $pac['silence'] ? true : false); } } } @@ -4100,7 +4103,7 @@ DNS-over-HTTPS with IP: ], [ [ - 'text' => $this->i18n('IP ban'), + 'text' => $this->i18n('IP ban & Logs'), 'callback_data' => "/ipMenu", ], ], @@ -4181,7 +4184,7 @@ DNS-over-HTTPS with IP: public function switchSilence() { $c = $this->getPacConf(); - $c['silence'] = $c['silence'] ? 0 : 1; + $c['silence'] = (($c['silence'] ?: 0) + 1) % 3; $this->setPacConf($c); $this->ipMenu(); } @@ -4192,6 +4195,12 @@ DNS-over-HTTPS with IP: $pac = $this->getPacConf(); $d = count($pac['deny'] ?: []); $w = count($pac['white'] ?: []); + $data[] = [ + [ + 'text' => $this->i18n('logs'), + 'callback_data' => "/logs", + ], + ]; $data[] = [ [ 'text' => $this->i18n('autoscan') . ': ' . ($pac['autoscan'] ? $this->getTime(strtotime(($pac['autoscan_timeout'] ?: 3600) . ' seconds')) : $this->i18n('off')), @@ -4204,10 +4213,17 @@ DNS-over-HTTPS with IP: 'text' => $this->i18n('autoblock') . ': ' . $this->i18n($pac['autodeny'] ? 'on' : 'off'), 'callback_data' => '/switchBanIp', ], - ]; - $data[] = [ [ - 'text' => $this->i18n('silence') . ': ' . $this->i18n($pac['silence'] ? 'on' : 'off'), + 'text' => $this->i18n('silence') . ': ' . ((function ($pac) { + switch ($pac['silence']) { + case 0: + return $this->i18n('off'); + case 1: + return '🟡'; + case 2: + return $this->i18n('on'); + } + })($pac)), 'callback_data' => '/switchSilence', ], ]; @@ -4217,8 +4233,6 @@ DNS-over-HTTPS with IP: 'text' => $this->i18n('ignorelist') . ": $w", 'callback_data' => '/denyList 0 1', ], - ]; - $data[] = [ [ 'text' => $this->i18n('blocklist') . ": $d", 'callback_data' => '/denyList 0 0', @@ -4342,45 +4356,43 @@ DNS-over-HTTPS with IP: fclose($r); } - $i = 0; if (!empty($ip)) { - foreach ($ip as $k => $v) { - if ($i > 10) { - break; - } - $comment = implode(', ', array_unique($v)); - if (!empty($return)) { - $ret[$k] = $v; - } else { - $this->send($this->input['from'], "$k $comment\n", button: [[ - [ - 'text' => $this->i18n('block'), - 'callback_data' => "/denyIp $k", - ], - [ - 'text' => $this->i18n('ignore'), - 'callback_data' => "/whiteIp $k", - ], - [ - 'text' => $this->i18n('logs'), - 'callback_data' => "/searchIp $k", - ], - [ - 'text' => $this->i18n('clean logs'), - 'callback_data' => "/cleanLogs $k", - ], - ]]); - $i++; - } - } if (!empty($return)) { - return $ret; + return $ip; } + foreach ($ip as $k => $v) { + $file .= "/searchLogs $k\n"; + } + $this->sendFile($this->input['from'], new CURLStringFile($file, 'analyze_ip_' . date('Y_m_d_H_i_s'))); } else { $this->answer($this->input['callback_id'], 'empty'); } } + public function searchLogs($search) + { + if (preg_match('~^\d+\.\d+\.\d+\.\d+$~', $search)) { + $this->send($this->input['from'], $search, button: [[ + [ + 'text' => $this->i18n('block'), + 'callback_data' => "/denyIp $search", + ], + [ + 'text' => $this->i18n('ignore'), + 'callback_data' => "/whiteIp $search", + ], + [ + 'text' => $this->i18n('logs'), + 'callback_data' => "/searchIp $search", + ], + [ + 'text' => $this->i18n('clean logs'), + 'callback_data' => "/cleanLogs $search", + ], + ]]); + } + } + public function searchIp($ip) { foreach ($this->logs as $v) { @@ -4951,9 +4963,9 @@ DNS-over-HTTPS with IP: { $r = $this->send( $this->input['chat'], - "@{$this->input['username']} send time:", + "@{$this->input['username']} send time like 1 hour or 1 day etc", $this->input['message_id'], - reply: 'send time:', + reply: 'send time like 1 hour or 1 day etc', ); $_SESSION['reply'][$r['result']['message_id']] = [ 'start_message' => $this->input['message_id'], @@ -6397,10 +6409,6 @@ DNS-over-HTTPS with IP: ], ]; $data[] = [ - [ - 'text' => $this->i18n('logs'), - 'callback_data' => "/logs", - ], [ 'text' => $this->i18n('debug') . ': ' . $this->i18n($c['debug'] ? 'on' : 'off'), 'callback_data' => "/debug", @@ -6550,7 +6558,7 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => $this->i18n('back'), - 'callback_data' => "/menu config", + 'callback_data' => "/ipMenu", ], ]; $this->update( @@ -7162,7 +7170,7 @@ DNS-over-HTTPS with IP: var_dump($this->request('setMyCommands', json_encode($data), 1)); } - public function send($chat, $text, ?int $to = 0, $button = false, $reply = false, $mode = 'HTML') + public function send($chat, $text, ?int $to = 0, $button = false, $reply = false, $mode = 'HTML', $disable_notification = false) { if ($button) { $extra = ['inline_keyboard' => $button]; @@ -7183,7 +7191,7 @@ DNS-over-HTTPS with IP: 'text' => "$v\n", 'parse_mode' => $mode, // 'disable_web_page_preview' => true, - // 'disable_notification' => !empty($to) && 0 == $k, + 'disable_notification' => $disable_notification, 'reply_to_message_id' => 0 == $k && $to > 0 ? $to : false, ]; if ($k == array_key_last($tails)) { @@ -7199,7 +7207,7 @@ DNS-over-HTTPS with IP: 'text' => $text, 'parse_mode' => $mode, // 'disable_web_page_preview' => true, - // 'disable_notification' => !empty($to), + 'disable_notification' => $disable_notification, 'reply_to_message_id' => $to, ]; if (!empty($extra)) { diff --git a/update/update.sh b/update/update.sh index 34b5036..0aed283 100755 --- a/update/update.sh +++ b/update/update.sh @@ -10,23 +10,23 @@ do if [[ -n "$cmd" ]] then key=$(cat $pwd/update/key) - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "останавливаю бота"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "stopping the bot"/')" docker compose down --remove-orphans if [[ "$cmd" == "1" ]] then - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "очищаю директорию"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "clearing the directory"/')" git reset --hard && git clean -fd - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "скачиваю обновление"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "downloading the update"/')" git fetch if [[ -n "$branch" ]] then - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "меняю ветку"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "changing branch"/')" git checkout -t origin/$branch || git checkout $branch fi - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "применяю обновления"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "applying updates"/')" git pull > ./update/message fi - curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "запускаю бота"/')" + curl -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$key/editMessageText -d "$(cat $pwd/update/curl | sed 's/"text":"~t~"/"text": "launching the bot"/')" IP=$(curl ipinfo.io/ip) VER=$(git describe --tags) docker compose --env-file ./.env --env-file ./override.env up -d --force-recreate bash $pwd/update/update.sh & > $pwd/update/key diff --git a/version b/version index 620b6e9..080ef20 100644 --- a/version +++ b/version @@ -1,3 +1,9 @@ +15.11.2024 v1.100 +- несколько режимов silence для сканера +- анализ сканера скидывает файл всех найденных айпи +- команда /searchLogs (пока только для айпи) +- логи переехали в меню сканера +- обновление текстов и подсказок 14.11.2024 v1.99.1 - анализ логов и бан айпишников, фиксы 14.11.2024 v1.99 From c56fe4ff78e764ef3c84d72f2070cf1c018fa004 Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 15 Nov 2024 11:49:20 +0400 Subject: [PATCH 05/58] blocklist improve add https://github.com/legiz-ru/sb-rule-sets/raw/main/ru-bundle.lst button --- app/bot.php | 44 ++++++++++++++++++++++++++++++-------------- version | 3 +++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/app/bot.php b/app/bot.php index 82c7397..3a17a08 100644 --- a/app/bot.php +++ b/app/bot.php @@ -150,6 +150,7 @@ class Bot $this->switchBanIp(); break; case preg_match('~^/searchLogs (.+)$~', $this->input['message'], $m): + case preg_match('~^/searchLogs (.+)$~', $this->input['callback'], $m): $this->searchLogs($m[1]); break; case preg_match('~^/switchSilence$~', $this->input['callback'], $m): @@ -243,6 +244,9 @@ class Bot case preg_match('~^/addCommunityFilter$~', $this->input['callback'], $m): $this->addCommunityFilter(); break; + case preg_match('~^/addLegizFilter$~', $this->input['callback'], $m): + $this->addLegizFilter(); + break; case preg_match('~^/pacMenu (\d+)$~', $this->input['callback'], $m): $this->pacMenu($m[1]); break; @@ -3479,6 +3483,19 @@ DNS-over-HTTPS with IP: $this->pacUpdate(); } + public function addLegizFilter() + { + $pac = $this->getPacConf(); + $l = array_filter(array_map(fn($e) => trim($e), explode("\n", file_get_contents('https://github.com/legiz-ru/sb-rule-sets/raw/main/ru-bundle.lst')))); + if (!empty($l)) { + foreach ($l as $k => $v) { + $pac['includelist'][$v] = true; + } + } + $this->setPacConf($pac); + $this->pacUpdate(); + } + public function pacMenu($page = 0) { unset($_SESSION['proxylistentry']); @@ -3562,6 +3579,12 @@ DNS-over-HTTPS with IP: 'callback_data' => "/addCommunityFilter", ], ]; + $data[] = [ + [ + 'text' => $this->i18n('add') . ' ru-bundle', + 'callback_data' => "/addLegizFilter", + ], + ]; $data = array_merge($data, $this->listPac('includelist', $page, 'pacMenu')[0]); $data[] = [ [ @@ -4372,7 +4395,8 @@ DNS-over-HTTPS with IP: public function searchLogs($search) { if (preg_match('~^\d+\.\d+\.\d+\.\d+$~', $search)) { - $this->send($this->input['from'], $search, button: [[ + $info = file_get_contents("https://ipinfo.io/$search/json", context: stream_context_create(['http' => ['timeout' => 2]])); + $this->send($this->input['from'], "$search\n
$info
", button: [[ [ 'text' => $this->i18n('block'), 'callback_data' => "/denyIp $search", @@ -4436,21 +4460,13 @@ DNS-over-HTTPS with IP: foreach (array_slice($domains, $page * $this->limit, $this->limit) as $v) { $data[] = [ [ - 'text' => $this->i18n('delete') . " $v", + 'text' => $v, + 'callback_data' => "/searchLogs $v", + ], + [ + 'text' => $this->i18n('delete'), 'callback_data' => "/allowIp $v $page" . ($white ? " 1" : ''), ], - [ - 'text' => $this->i18n($white ? 'block' : 'ignore'), - 'callback_data' => ($white ? "/denyIp" : "/whiteIp") . " $v 1 $page $white", - ], - [ - 'text' => $this->i18n('logs'), - 'callback_data' => "/searchIp $v", - ], - [ - 'text' => $this->i18n('clean logs'), - 'callback_data' => "/cleanLogs $v 1", - ], ]; } if ($all > 1) { diff --git a/version b/version index 080ef20..156faaf 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +15.11.2024 v1.101 +- кнопка добавления https://github.com/legiz-ru/sb-rule-sets/raw/main/ru-bundle.lst +- переделан раздел списка ip для читаемости 15.11.2024 v1.100 - несколько режимов silence для сканера - анализ сканера скидывает файл всех найденных айпи From 0d7426e78537d0341d740e6fc8dd80ce9957d06b Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 00:11:19 +0400 Subject: [PATCH 06/58] improve analyze ip --- app/bot.php | 264 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 176 insertions(+), 88 deletions(-) diff --git a/app/bot.php b/app/bot.php index 3a17a08..9ce0b2c 100644 --- a/app/bot.php +++ b/app/bot.php @@ -12,6 +12,7 @@ class Bot public $dns; public $mtu; public $logs; + public $reg; public function __construct($key, $i18n) { @@ -35,6 +36,22 @@ class Bot 'upstream_access', 'xray', ]; + $this->reg = '~' . implode('|', [ + 'GET /ws(?:.+)? HTTP', + 'GET /adguard/(?:.+)? HTTP', + 'GET /webapp(?:.+)? HTTP', + 'GET /pac(?:.+)? HTTP', + 'GET \.well-known(?:.+)? HTTP', + 'GET /v2ray(?:.+)? HTTP', + 'GET /dns-query(?:.+)? HTTP', + 'GET / HTTP', + 'GET /tlgrm(?:.+)? HTTP', + 'GET /jsoneditor.min.css HTTP', + 'GET /jsoneditor.min.js HTTP', + 'GET /jquery-3.7.1.min.js HTTP', + 'GET /img/jsoneditor-icons.svg HTTP', + 'GET /favicon.ico HTTP', + ]) . '~'; } public function input() @@ -150,9 +167,11 @@ class Bot $this->switchBanIp(); break; case preg_match('~^/searchLogs (.+)$~', $this->input['message'], $m): - case preg_match('~^/searchLogs (.+)$~', $this->input['callback'], $m): $this->searchLogs($m[1]); break; + case preg_match('~^/searchLogs (.+?)(?:\s(.+?))?(?:\s(.+?))?(?:\s(.+?))?$~', $this->input['callback'], $m): + $this->searchLogs($m[1], $m[2], $m[3], $m[4]); + break; case preg_match('~^/switchSilence$~', $this->input['callback'], $m): $this->switchSilence(); break; @@ -168,9 +187,8 @@ class Bot case preg_match('~^/ports$~', $this->input['callback'], $m): $this->ports(); break; - case preg_match('~^/ip$~', $this->input['message'], $m): - case preg_match('~^/analysisIp$~', $this->input['callback'], $m): - $this->analysisIp(); + case preg_match('~^/analysisIp(?:\s(\d+))?$~', $this->input['callback'], $m): + $this->analysisIp($m[1] ?: 0); break; case preg_match('~^/ipMenu$~', $this->input['callback'], $m): $this->ipMenu(); @@ -190,10 +208,13 @@ class Bot case preg_match('~^/searchIp (.+)$~', $this->input['callback'], $m): $this->searchIp($m[1]); break; - case preg_match('~^/denyIp (.+?)(?:\s(\d)\s(\d+?)\s(\d))?$~', $this->input['callback'], $m): + case preg_match('~^/searchSuspiciousIp (.+)$~', $this->input['callback'], $m): + $this->searchSuspiciousIp($m[1]); + break; + case preg_match('~^/denyIp (.+?)(?:\s(.+?)\s(\d+?)\s(\d))?$~', $this->input['callback'], $m): $this->denyIp($m[1], $m[2], $m[3], $m[4]); break; - case preg_match('~^/whiteIp (.+?)(?:\s(\d)\s(\d+?)\s(\d))?$~', $this->input['callback'], $m): + case preg_match('~^/whiteIp (.+?)(?:\s(.+?)\s(\d+?)\s(\d))?$~', $this->input['callback'], $m): $this->whiteIp($m[1], $m[2], $m[3], $m[4]); break; case preg_match('~^/adgFillAllowedClients(?: (\d+))?$~', $this->input['callback'], $m): @@ -1165,27 +1186,26 @@ class Bot try { $pac = $this->getPacConf(); if (!empty($pac['autoscan'])) { - $r = $this->analysisIp(1); + $r = $this->analysisIp(return: 1); require __DIR__ . '/config.php'; if (!empty($c['admin']) && (empty($this->time3) || ((time() - $this->time3) > $pac['autoscan_timeout']))) { $this->time3 = time(); if (!empty($r)) { foreach ($r as $k => $v) { - $tmp = array_unique($v); - foreach ($tmp as $i) { - $t[$i]++; + foreach ($v as $i) { + $t[$i['title']][$k] = 1; } } foreach ($t as $k => $v) { - $text .= "\n$v $k"; + $text .= "\n" . count($v) . " $k"; } if (!empty($pac['autodeny'])) { $this->denyIp(array_keys($r)); $ban = count(array_keys($r)); foreach (array_keys($r) as $v) { $ips[] = [[ - 'text' => "logs $v", - 'callback_data' => "/searchIp $v", + 'text' => $v, + 'callback_data' => "/searchLogs $v", ]]; } } @@ -4281,7 +4301,37 @@ DNS-over-HTTPS with IP: ); } - public function analysisIp($return = false) + public function suspicious($regexp, $file, $ip, $title, $reverse = false) + { + if ($r = fopen($file, 'r')) { + while (feof($r) === false) { + $l = fgets($r); + if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { + if ($reverse xor preg_match($regexp, $l)) { + if (is_array($ip)) { + if (empty($ip[$m[1]])) { + $ret[$m[1]][] = [ + 'title' => $title, + 'log' => $l, + ]; + } + } else { + if ($ip == $m[1]) { + $ret[$m[1]][] = [ + 'title' => $title, + 'log' => $l, + ]; + } + } + } + } + } + fclose($r); + } + return $ret ?: []; + } + + public function analysisIp(int $page = 0, $return = false) { $pac = $this->getPacConf(); foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], [ @@ -4322,98 +4372,102 @@ DNS-over-HTTPS with IP: fclose($r); } - if ($r = fopen('/logs/upstream_access', 'r')) { - while (feof($r) === false) { - $l = fgets($r); - if (preg_match('~(\d+\.\d+\.\d+\.\d+).+200\s\d+\s0$~', $l, $m)) { - if (empty($xr[$m[1]])) { - $ip[$m[1]][] = 'possibly a Reality Degenerate'; - } - } - } - fclose($r); - } - - $reg = [ - 'GET /ws(?:.+)? HTTP', - 'GET /adguard/(?:.+)? HTTP', - 'GET /webapp(?:.+)? HTTP', - 'GET /pac(?:.+)? HTTP', - 'GET \.well-known(?:.+)? HTTP', - 'GET /v2ray(?:.+)? HTTP', - 'GET /dns-query(?:.+)? HTTP', - 'GET / HTTP', - 'GET /tlgrm(?:.+)? HTTP', - 'GET /jsoneditor.min.css HTTP', - 'GET /jsoneditor.min.js HTTP', - 'GET /jquery-3.7.1.min.js HTTP', - 'GET /img/jsoneditor-icons.svg HTTP', - 'GET /favicon.ico HTTP', + $t = [ + $this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', $xr, 'possibly a Reality Degenerate'), + $this->suspicious($this->reg, '/logs/nginx_default_access', $xr, 'possibly a scanner', true), + $this->suspicious($this->reg, '/logs/nginx_domain_access', $xr, 'possibly a scanner', true), ]; - if ($r = fopen('/logs/nginx_default_access', 'r')) { - while (feof($r) === false) { - $l = fgets($r); - if (!preg_match('~' . implode('|', $reg) . '~', $l)) { - if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { - if (empty($xr[$m[1]])) { - $ip[$m[1]][] = 'possibly a scanner'; - } - } - } + $ip = []; + foreach ($t as $r) { + foreach ($r as $k => $v) { + $ip[$k] = $v; } - fclose($r); } - if ($r = fopen('/logs/nginx_domain_access', 'r')) { - while (feof($r) === false) { - $l = fgets($r); - if (!preg_match('~' . implode('|', $reg) . '~', $l)) { - if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { - if (empty($xr[$m[1]])) { - $ip[$m[1]][] = 'possibly a scanner'; - } - } - } - } - fclose($r); + if (!empty($return)) { + return $ip; } - if (!empty($ip)) { - if (!empty($return)) { - return $ip; - } foreach ($ip as $k => $v) { - $file .= "/searchLogs $k\n"; + $data[] = [ + [ + 'text' => $k, + 'callback_data' => "/searchLogs $k analysisIp $page 0", + ] + ]; + } + $all = (int) ceil(count($data) / $this->limit); + $page = min($page, $all - 1); + $page = $page < 0 ? $all - 1 : $page; + $data = array_slice($data ?: [], $page * $this->limit, $this->limit); + if ($all > 1) { + $data[] = [ + [ + 'text' => '<<', + 'callback_data' => "/analysisIp " . ($page - 1 >= 0 ? $page - 1 : $all - 1), + ], + [ + 'text' => '>>', + 'callback_data' => "/analysisIp " . ($page < $all - 1 ? $page + 1 : 0), + ] + ]; } - $this->sendFile($this->input['from'], new CURLStringFile($file, 'analyze_ip_' . date('Y_m_d_H_i_s'))); - } else { - $this->answer($this->input['callback_id'], 'empty'); } + $data[] = [ + [ + 'text' => $this->i18n('back'), + 'callback_data' => "/ipMenu", + ], + ]; + $this->update($this->input['from'], $this->input['message_id'], count($ip) ?: 'empty', $data); } - public function searchLogs($search) + public function searchLogs($search, $fun = false, $page = 0, $white = 0) { if (preg_match('~^\d+\.\d+\.\d+\.\d+$~', $search)) { $info = file_get_contents("https://ipinfo.io/$search/json", context: stream_context_create(['http' => ['timeout' => 2]])); - $this->send($this->input['from'], "$search\n
$info
", button: [[ + $text = "$search\n
$info
"; + $data[] = [ [ 'text' => $this->i18n('block'), - 'callback_data' => "/denyIp $search", + 'callback_data' => "/denyIp $search" . ($fun ? " $fun $page $white" : ''), ], [ 'text' => $this->i18n('ignore'), - 'callback_data' => "/whiteIp $search", + 'callback_data' => "/whiteIp $search" . ($fun ? " $fun $page $white" : ''), ], + ]; + $data[] = [ [ - 'text' => $this->i18n('logs'), + 'text' => $this->i18n('all logs'), 'callback_data' => "/searchIp $search", ], [ - 'text' => $this->i18n('clean logs'), + 'text' => $this->i18n('suspicious log'), + 'callback_data' => "/searchSuspiciousIp $search", + ], + ]; + $data[] = [ + [ + 'text' => $this->i18n("clean logs $search"), 'callback_data' => "/cleanLogs $search", ], - ]]); + ]; + if (!empty($fun)) { + $data[] = [ + [ + 'text' => $this->i18n('back'), + 'callback_data' => "/$fun $page" . ($white ? " $white" : ''), + ], + ]; + $this->update($this->input['from'], $this->input['message_id'], $text, button: $data); + } else { + if (empty($this->input['callback_id'])) { + $this->delete($this->input['from'], $this->input['message_id']); + } + $this->send($this->input['from'], $text, button: $data); + } } } @@ -4448,6 +4502,40 @@ DNS-over-HTTPS with IP: } } + public function searchSuspiciousIp($ip) + { + $t = [ + $this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', $ip, 'possibly a Reality Degenerate'), + $this->suspicious($this->reg, '/logs/nginx_default_access', $ip, 'possibly a scanner', true), + $this->suspicious($this->reg, '/logs/nginx_domain_access', $ip, 'possibly a scanner', true), + ]; + foreach ($t as $r) { + if (!empty($r)) { + foreach ($r as $v) { + foreach ($v as $k) { + $logs[$k['title']][] = $k['log']; + } + } + } + } + if (!empty($logs)) { + foreach ($logs as $k => $v) { + $head= "$k:\n"; + $t = array_chunk($v, 10); + foreach ($t as $j) { + $text = "$head
";
+                    foreach ($j as $i) {
+                        $text .= htmlspecialchars($i, ENT_HTML5, 'UTF-8');
+                    }
+                    $text .= '
'; + $this->send($this->input['from'], $text, $this->input['message_id']); + } + } + } else { + $this->answer($this->input['callback_id'], 'empty'); + } + } + public function denyList($page = 0, $white = 0) { $text = 'Menu -> IP -> ' . ($white ? 'white' : 'deny') . ' list'; @@ -4461,7 +4549,7 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => $v, - 'callback_data' => "/searchLogs $v", + 'callback_data' => "/searchLogs $v denyList $page $white", ], [ 'text' => $this->i18n('delete'), @@ -4512,7 +4600,7 @@ DNS-over-HTTPS with IP: $this->ipMenu(); } - public function denyIp($ip, $nodelete = false, $page = 0, $white = 0) + public function denyIp($ip, $fun = false, $page = 0, $white = 0) { $pac = $this->getPacConf(); if (is_array($ip)) { @@ -4529,16 +4617,16 @@ DNS-over-HTTPS with IP: } } $this->setPacConf($pac); - if (empty($nodelete)) { + if (empty($fun)) { $this->delete($this->input['from'], $this->input['message_id']); } $this->syncDeny(); - if (!empty($nodelete)) { - $this->denyList($page, $white); + if (!empty($fun)) { + $this->{$fun}($page, $white); } } - public function whiteIp($ip, $nodelete = false, $page = 0, $white = 0) + public function whiteIp($ip, $fun = false, $page = 0, $white = 0) { $pac = $this->getPacConf(); if (is_array($ip)) { @@ -4555,12 +4643,12 @@ DNS-over-HTTPS with IP: } } $this->setPacConf($pac); - if (empty($nodelete)) { + if (empty($fun)) { $this->delete($this->input['from'], $this->input['message_id']); } $this->syncDeny(); - if (!empty($nodelete)) { - $this->denyList($page, $white); + if (!empty($fun)) { + $this->{$fun}($page, $white); } } From c2219e3657946012f5740e6aeecb70fbc8ac028b Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 00:34:22 +0400 Subject: [PATCH 07/58] ability to add your IPs to blocklist/whitelist --- app/bot.php | 21 ++++++++++++++++++--- version | 3 +++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/bot.php b/app/bot.php index 9ce0b2c..daf4e57 100644 --- a/app/bot.php +++ b/app/bot.php @@ -2584,9 +2584,9 @@ DNS-over-HTTPS with IP: default: $r = $this->send( $this->input['chat'], - "@{$this->input['username']} list domains separated by commas", + "@{$this->input['username']} list separated by commas", $this->input['message_id'], - reply: 'list domains separated by commas', + reply: 'list separated by commas', ); break; } @@ -2608,7 +2608,11 @@ DNS-over-HTTPS with IP: if (!empty($domains)) { $conf = $this->getPacConf(); foreach ($domains as $k => $v) { - $conf[$type][in_array($type, ['rulessetlist', 'packagelist', 'processlist']) ? trim($v) : idn_to_ascii(trim($v))] = true; + if (in_array($type, ['white', 'deny'])) { + $conf[$type][] = $v; + } else { + $conf[$type][in_array($type, ['rulessetlist', 'packagelist', 'processlist']) ? trim($v) : idn_to_ascii(trim($v))] = true; + } } ksort($conf[$type]); $this->setPacConf($conf); @@ -2647,6 +2651,11 @@ DNS-over-HTTPS with IP: $this->xrayUpdateRules(); $this->xtlsrulesset(); break; + case 'white': + case 'deny': + $this->syncDeny(); + $this->denyList(0, $type == 'white' ? 1 : 0); + break; } } @@ -4544,6 +4553,12 @@ DNS-over-HTTPS with IP: $page = min($page, $all - 1); $page = $page < 0 ? $all - 1 : $page; + $data[] = [ + [ + 'text' => $this->i18n('add'), + 'callback_data' => "/include " . ($white ? 'white' : 'deny'), + ], + ]; if (!empty($domains)) { foreach (array_slice($domains, $page * $this->limit, $this->limit) as $v) { $data[] = [ diff --git a/version b/version index 156faaf..8c39fef 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +16.11.2024 v1.102 +- переделан раздел списка ip под управление кнопками +- возможность добавить свои айпи в blocklist/whitelist 15.11.2024 v1.101 - кнопка добавления https://github.com/legiz-ru/sb-rule-sets/raw/main/ru-bundle.lst - переделан раздел списка ip для читаемости From f34427c13c429bb3c3f9fbad26fe65c50b6465fa Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 00:42:22 +0400 Subject: [PATCH 08/58] fix notification about new version --- docker-compose.yml | 1 + version | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 84c6172..d0dd24c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -161,6 +161,7 @@ services: - ./app:/app - ./logs/:/logs/ - ./update:/update + - ./.git:/.git - ./scripts/start_service.sh:/start_service.sh - /var/run/docker.sock:/var/run/docker.sock:ro environment: diff --git a/version b/version index 8c39fef..fac66e4 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +16.11.2024 v1.103 +- фикс уведомления о новой версии 16.11.2024 v1.102 - переделан раздел списка ip под управление кнопками - возможность добавить свои айпи в blocklist/whitelist From 3813f43b92d81a8c7c796cb0d2ecde9d4bc79f5b Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 00:45:30 +0400 Subject: [PATCH 09/58] update bot from notify --- app/bot.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/bot.php b/app/bot.php index daf4e57..52c597d 100644 --- a/app/bot.php +++ b/app/bot.php @@ -1293,9 +1293,13 @@ class Bot $this->send($v, implode("\n", $diff), 0, [ [ [ - 'text' => 'changelog', + 'text' => 'changelog', 'web_app' => ['url' => "https://raw.githubusercontent.com/mercurykd/vpnbot/$b/version"], - ] + ], + [ + 'text' => $this->i18n('update bot'), + 'callback_data' => "/applyupdatebot", + ], ] ]); } From 565573cfc22b1b8d21bf7419e15359b6b74bbdc8 Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 00:51:09 +0400 Subject: [PATCH 10/58] fix notify update --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index d0dd24c..8b737d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -160,6 +160,7 @@ services: - ./ssh:/ssh - ./app:/app - ./logs/:/logs/ + - ./version:/version - ./update:/update - ./.git:/.git - ./scripts/start_service.sh:/start_service.sh From 37d392a2404e82ff1f5ca54b89a439d2d98a3c8f Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 01:10:47 +0400 Subject: [PATCH 11/58] update backup --- app/bot.php | 34 ++++++++++++++-------------------- scripts/dns_close_53_port.sh | 5 ----- scripts/dns_open_53_port.sh | 8 -------- 3 files changed, 14 insertions(+), 33 deletions(-) delete mode 100755 scripts/dns_close_53_port.sh delete mode 100755 scripts/dns_open_53_port.sh diff --git a/app/bot.php b/app/bot.php index 52c597d..9b89e02 100644 --- a/app/bot.php +++ b/app/bot.php @@ -600,7 +600,7 @@ class Bot $this->addOverrideHtml(); break; case preg_match('~^/export$~', $this->input['callback'], $m): - $this->exportManual(); + $this->pinBackup(); break; case preg_match('~^/import$~', $this->input['callback'], $m): $this->import(); @@ -1228,7 +1228,7 @@ class Bot public function checkBackup($delta) { - $c = $this->getPacConf(); + $c = $this->getPacConf(); if (!empty($c['backup'])) { $now = strtotime(date('Y-m-d H:i:s')); [$start, $period] = explode('/', $c['backup']); @@ -1241,9 +1241,6 @@ class Bot && $now - $start >= 0 && (($now - $start) % $period < $delta) ) { - if (!empty($c['pinbackup'])) { - $this->pinAdmin($c['pinbackup'], 1); - } $this->pinBackup(); } } @@ -1265,12 +1262,19 @@ class Bot } } - public function pinBackup() + public function pinBackup($file = false) { require __DIR__ . '/config.php'; - $conf = $this->getPacConf(); - $bot = preg_replace('~[\W]~iu', '_', $this->request('getMyName', [])['result']['name']); - $conf['pinbackup'] = $this->upload("{$bot}_export_" . date('d_m_Y_H_i') . '.json', $this->export(), $c['admin'][0])['result']['message_id']; + $conf = $this->getPacConf(); + $bot = preg_replace('~[\W]~iu', '_', $this->request('getMyName', [])['result']['name']); + $json = $this->export(); + if (!empty($file)) { + file_put_contents($file, $json); + } + if (!empty($conf['pinbackup'])) { + $this->pinAdmin($conf['pinbackup'], 1); + } + $conf['pinbackup'] = $this->upload("{$bot}_export_" . date('d_m_Y_H_i') . '.json', $json, $c['admin'][0])['result']['message_id']; $this->setPacConf($conf); $this->pinAdmin($conf['pinbackup']); } @@ -1458,16 +1462,6 @@ class Bot return json_encode($conf, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } - public function exportManual($file = false) - { - $json = $this->export(); - if (!empty($file)) { - file_put_contents($file, $json); - } - $bot = preg_replace('~[\W]~iu', '_', $this->request('getMyName', [])['result']['name']); - return $this->upload("{$bot}_export_" . date('d_m_Y_H_i') . '.json', $json); - } - public function import() { $r = $this->send( @@ -6372,7 +6366,7 @@ DNS-over-HTTPS with IP: public function applyupdatebot() { - $this->exportManual($this->update); + $this->pinBackup($this->update); $r = $this->send($this->input['from'], 'update...'); file_put_contents('/update/reload_message', "{$this->input['from']}:{$r['result']['message_id']}"); file_put_contents('/update/key', $this->key); diff --git a/scripts/dns_close_53_port.sh b/scripts/dns_close_53_port.sh deleted file mode 100755 index ea175d4..0000000 --- a/scripts/dns_close_53_port.sh +++ /dev/null @@ -1,5 +0,0 @@ -make d -rm /etc/systemd/resolved.conf.d/adguardhome.conf -mv /etc/resolv.conf.backup /etc/resolv.conf -systemctl reload-or-restart systemd-resolved -make u diff --git a/scripts/dns_open_53_port.sh b/scripts/dns_open_53_port.sh deleted file mode 100755 index 785e6bd..0000000 --- a/scripts/dns_open_53_port.sh +++ /dev/null @@ -1,8 +0,0 @@ -mkdir /etc/systemd/resolved.conf.d -echo "[Resolve] -DNS=127.0.0.1 -DNSStubListener=no" > /etc/systemd/resolved.conf.d/adguardhome.conf -mv /etc/resolv.conf /etc/resolv.conf.backup -ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf -systemctl reload-or-restart systemd-resolved -make d u From be227f6a3314a62d0006c9f8bf1d598406c4219a Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 01:13:53 +0400 Subject: [PATCH 12/58] update version --- version | 3 +++ 1 file changed, 3 insertions(+) diff --git a/version b/version index fac66e4..c326328 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +16.11.2024 v1.104 +- единая механика закрепления бэкапа +- фикс текста уведомления о новой версии 16.11.2024 v1.103 - фикс уведомления о новой версии 16.11.2024 v1.102 From 66225917fee060abbda3a058cfacd6f5ac1c0fd3 Mon Sep 17 00:00:00 2001 From: mercury Date: Sat, 16 Nov 2024 16:45:36 +0400 Subject: [PATCH 13/58] fix ip menu --- app/bot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 9b89e02..b160697 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4545,7 +4545,7 @@ DNS-over-HTTPS with IP: public function denyList($page = 0, $white = 0) { - $text = 'Menu -> IP -> ' . ($white ? 'white' : 'deny') . ' list'; + $text = 'Menu -> IP -> ' . ($white ? 'ignore' : 'block') . 'list'; $domains = $this->getPacConf()[$white ? 'white' : 'deny'] ?: []; $all = (int) ceil(count($domains) / $this->limit); $page = min($page, $all - 1); From 66cee61d41ea7015858b0fae4e328b319a4aa949 Mon Sep 17 00:00:00 2001 From: mercury Date: Sun, 17 Nov 2024 15:08:01 +0400 Subject: [PATCH 14/58] allow telegram ip --- app/bot.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/bot.php b/app/bot.php index b160697..cfbc23e 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4687,6 +4687,18 @@ DNS-over-HTTPS with IP: public function syncDeny() { $pac = $this->getPacConf(); + if ($r = fopen('/logs/nginx_tlgrm_access', 'r')) { + while (feof($r) === false) { + $l = fgets($r); + if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { + $xr[$m[1]] = true; + } + } + fclose($r); + } + foreach (array_keys($xr) as $v) { + $text .= "allow $v;\n"; + } if (!empty($pac['white'])) { $pac['white'] = array_unique($pac['white']); sort($pac['white']); From 51ecb815bac3932dd18011f4d1ed95042971f774 Mon Sep 17 00:00:00 2001 From: mercury Date: Sun, 17 Nov 2024 19:32:54 +0400 Subject: [PATCH 15/58] fix domain installation on first launch --- app/service.php | 2 +- version | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/service.php b/app/service.php index 6f962ca..63e9cc1 100644 --- a/app/service.php +++ b/app/service.php @@ -18,7 +18,7 @@ if (!empty($bot->selfupdate)) { $bot->offWarp(); } $bot->dontshowcron = 1; -$bot->adguardSync(); $bot->sslip(); +$bot->adguardSync(); $bot->syncDeny(); $bot->cleanDocker(); diff --git a/version b/version index c326328..909b57a 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +17.11.2024 v1.105 +- фикс установки домена при первом запуске 16.11.2024 v1.104 - единая механика закрепления бэкапа - фикс текста уведомления о новой версии From 21b7a4816f5594355cc3d78bb3e0a012294f86c0 Mon Sep 17 00:00:00 2001 From: mercury Date: Mon, 18 Nov 2024 00:31:53 +0400 Subject: [PATCH 16/58] fix bot dump when telegram logs are empty --- app/bot.php | 7 +++++-- version | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/bot.php b/app/bot.php index cfbc23e..3c64e88 100644 --- a/app/bot.php +++ b/app/bot.php @@ -1223,6 +1223,7 @@ class Bot } } } catch (Exception $e) { + file_put_contents('/logs/php_error', $e->getMessage()); } } @@ -4696,8 +4697,10 @@ DNS-over-HTTPS with IP: } fclose($r); } - foreach (array_keys($xr) as $v) { - $text .= "allow $v;\n"; + if (!empty($xr)) { + foreach (array_keys($xr) as $v) { + $text .= "allow $v;\n"; + } } if (!empty($pac['white'])) { $pac['white'] = array_unique($pac['white']); diff --git a/version b/version index 909b57a..e9ba205 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +18.11.2024 v1.106 +- фикс отвала бота при пустых логах телеги 17.11.2024 v1.105 - фикс установки домена при первом запуске 16.11.2024 v1.104 From b56b48e08072b87f0666c36402ee1af848dd6e4b Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 15:45:02 +0400 Subject: [PATCH 17/58] override ignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c8cd08e..b37bf23 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ update/* override.env override.html override.php -docker-compose.override.yml \ No newline at end of file +docker-compose.override.yml +backup.json +app/webapp/override/ \ No newline at end of file From dbe3f290ea031cdbbe7213069223bd890da3159d Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 15:46:03 +0400 Subject: [PATCH 18/58] commands reset and backup --- app/backup.php | 13 +++++++++++++ makefile | 10 +++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 app/backup.php diff --git a/app/backup.php b/app/backup.php new file mode 100644 index 0000000..044e133 --- /dev/null +++ b/app/backup.php @@ -0,0 +1,13 @@ +export(); diff --git a/makefile b/makefile index 311c4db..a056eec 100644 --- a/makefile +++ b/makefile @@ -59,4 +59,12 @@ c: git checkout . git reset webhook: - docker compose exec php php checkwebhook.php \ No newline at end of file + docker compose exec php php checkwebhook.php +reset: + make d + git reset --hard + git clean -fd + docker volume rm vpnbot_adguard vpnbot_warp + make u +backup: + docker compose exec php php backup.php > backup.json \ No newline at end of file From c3d90ada83569149af6b10f38e004fa7326486c8 Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 15:55:10 +0400 Subject: [PATCH 19/58] addruleset and additional tags --- app/bot.php | 107 ++++++++++++++++++++++++++++++++++++++--------- config/sing.json | 5 +++ 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/app/bot.php b/app/bot.php index 3c64e88..032ca81 100644 --- a/app/bot.php +++ b/app/bot.php @@ -163,6 +163,9 @@ class Bot case preg_match('~^/mirror$~', $this->input['message'], $m): $this->menu('mirror'); break; + case preg_match('~^/mainOutbound$~', $this->input['callback'], $m): + $this->mainOutbound(); + break; case preg_match('~^/switchBanIp$~', $this->input['callback'], $m): $this->switchBanIp(); break; @@ -5235,6 +5238,23 @@ DNS-over-HTTPS with IP: $domain = $this->getDomain(); $hash = substr(md5($this->key), 0, 8); $text[] = "Menu -> " . $this->i18n('xray') . " -> $type templates"; + $text[] = <<~outbound~ + "~pac~" + ~dns~ + ~uid~ + ~domain~ + ~directdomain~ + ~cdndomain~ + ~short_id~ + ~public_key~ + ~server_name~ + ~app_outbound~ + ~process_outbound~ + ~domains_outbound~ + ~final_outbound~ + ~ip~ + TEXT; $templates = $pac["{$type}templates"]; $data[] = [ @@ -5296,6 +5316,34 @@ DNS-over-HTTPS with IP: ); } + public function mainOutbound() + { + $r = $this->send( + $this->input['chat'], + "@{$this->input['username']} send name", + $this->input['message_id'], + reply: 'send name', + ); + $_SESSION['reply'][$r['result']['message_id']] = [ + 'start_message' => $this->input['message_id'], + 'start_callback' => $this->input['callback_id'], + 'callback' => 'setMainOutbound', + 'args' => [], + ]; + } + + public function setMainOutbound($text) + { + $pac = $this->getPacConf(); + if (!empty($text)) { + $pac['outbound'] = $text; + } else { + unset($pac['outbound']); + } + $this->setPacConf($pac); + $this->xray(); + } + public function xray($page = 0) { if (!$this->ssh('pgrep xray', 'xr')) { @@ -5308,6 +5356,12 @@ DNS-over-HTTPS with IP: $text[] = "fake domain: $fake"; } $text[] = 'transport: ' . ($p['transport'] ?: 'Reality'); + $data[] = [ + [ + 'text' => $this->i18n('main outbound: ') . ($p['outbound'] ?: 'proxy'), + 'callback_data' => '/mainOutbound', + ], + ]; $data[] = [ [ 'text' => $p['linkdomain'] ?: $this->i18n('cdn'), @@ -5888,7 +5942,6 @@ DNS-over-HTTPS with IP: $c['outbounds'][$index]['tls']['reality']['short_id'] = '~short_id~'; } - $c['route'] = $this->addRuleSet($c['route']); $c['route'] = $this->createRuleSet($c['route'], $uid, $domain); break; } @@ -5898,6 +5951,8 @@ DNS-over-HTTPS with IP: '~dns~' => "https://$domain/dns-query/$uid", '~uid~' => $uid, '~domain~' => $domain, + '~directdomain~' => $pac['domain'], + '~cdndomain~' => $pac['linkdomain'], '~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0], '~public_key~' => $pac['xray'], '~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0], @@ -5907,6 +5962,7 @@ DNS-over-HTTPS with IP: '~final_outbound~' => $pac['final_outbound'] ? $outbound : 'direct', '~ip~' => $this->ip, ]); + $json = $this->addRuleSet($json); $json = $this->clearEmptyRules($json); header('Content-type: application/json'); @@ -5940,29 +5996,40 @@ DNS-over-HTTPS with IP: return json_encode($json); } - public function addRuleSet($route) + public function addRuleSet($json) { - foreach ($route['rules'] as $k => $v) { - $t[$v['outbound']] = $k; - } - $p = $this->getPacConf(); - if (!empty($p['rulessetlist'])) { - foreach ($p['rulessetlist'] as $k => $v) { - if (!empty($v)) { - [$type, $time, $url] = explode(':', $k, 3); - $route['rule_set'][] = [ - "tag" => $k, - "type" => "remote", - "format" => "binary", - "url" => $url, - "download_detour" => "direct", - "update_interval" => $time - ]; - $route['rules'][$t[$type]]['rule_set'][] = $k; + $json = json_decode($json, 1); + if (!empty($json['route']['rules'])) { + foreach ($json['route']['rules'] as $k => $v) { + if (!empty($v['addruleset'])) { + $t[$v['outbound']] = $k; } } + $this->sd($t, 1); + $p = $this->getPacConf(); + if (!empty($p['rulessetlist'])) { + foreach ($p['rulessetlist'] as $k => $v) { + if (!empty($v)) { + [$type, $time, $url] = explode(':', $k, 3); + if (!empty($json['route']['rules'][$t[$type]])) { + $json['route']['rule_set'][] = [ + "tag" => $k, + "type" => "remote", + "format" => "binary", + "url" => $url, + "download_detour" => "direct", + "update_interval" => $time + ]; + $json['route']['rules'][$t[$type]]['rule_set'][] = $k; + } + } + } + } + foreach ($json['route']['rules'] as $k => $v) { + unset($json['route']['rules'][$k]['addruleset']); + } } - return $route; + return json_encode($json); } public function createRuleSet($route, $uid, $domain) diff --git a/config/sing.json b/config/sing.json index 26af880..9e4577f 100644 --- a/config/sing.json +++ b/config/sing.json @@ -111,6 +111,7 @@ "outbound": "dns-out" }, { + "addruleset": true, "createruleset": [ { "name": "pac", @@ -125,6 +126,7 @@ "outbound": "~domains_outbound~" }, { + "addruleset": true, "createruleset": [ { "name": "package", @@ -139,6 +141,7 @@ "outbound": "~app_outbound~" }, { + "addruleset": true, "createruleset": [ { "name": "process", @@ -153,6 +156,7 @@ "outbound": "~process_outbound~" }, { + "addruleset": true, "createruleset": [ { "name": "block", @@ -167,6 +171,7 @@ "outbound": "block" }, { + "addruleset": true, "createruleset": [ { "name": "warp", From 12b5d84afc71b71e84be5014ec768839745af6a5 Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 17:12:08 +0400 Subject: [PATCH 20/58] IP analyzer takes into account subnets --- app/bot.php | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/app/bot.php b/app/bot.php index 032ca81..2f6854a 100644 --- a/app/bot.php +++ b/app/bot.php @@ -205,7 +205,7 @@ class Bot case preg_match('~^/cleanLogs (.+?)(?:\s(1))?$~', $this->input['callback'], $m): $this->cleanLogs($m[1], $m[2]); break; - case preg_match('~^/allowIp (\d+\.\d+\.\d+\.\d+) (\d+)(?:\s(\d+))?$~', $this->input['callback'], $m): + case preg_match('~^/allowIp (.+?) (\d+)(?:\s(\d+))?$~', $this->input['callback'], $m): $this->allowIp($m[1], $m[2], $m[3]); break; case preg_match('~^/searchIp (.+)$~', $this->input['callback'], $m): @@ -4345,24 +4345,14 @@ DNS-over-HTTPS with IP: public function analysisIp(int $page = 0, $return = false) { $pac = $this->getPacConf(); - foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], [ - '10.10.0.1' ,'10.10.1.1' , - '10.10.0.2' ,'10.10.1.2' , - '10.10.0.3' ,'10.10.1.3' , - '10.10.0.4' ,'10.10.1.4' , - '10.10.0.5' ,'10.10.1.5' , - '10.10.0.6' ,'10.10.1.6' , - '10.10.0.7' ,'10.10.1.7' , - '10.10.0.8' ,'10.10.1.8' , - '10.10.0.9' ,'10.10.1.9' , - '10.10.0.10','10.10.1.10', - '10.10.0.11','10.10.1.11', - '10.10.0.12','10.10.1.12', - '10.10.0.13','10.10.1.13', - '10.10.0.14','10.10.1.14', - '10.10.0.15','10.10.1.15', - ]) as $v) { - $xr[$v] = true; + foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], ['10.10.0.0/23']) as $v) { + if (!empty(preg_match('~^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(\d{1,2})~', $v, $m))) { + for ($i = ip2long($m[1]); $i < ip2long($m[1]) + pow(2, 32 - $m[2]) - 1; $i++) { + $xr[long2ip($i)] = true; + } + } else { + $xr[$v] = true; + } } if ($r = fopen('/logs/nginx_tlgrm_access', 'r')) { while (feof($r) === false) { @@ -4715,8 +4705,12 @@ DNS-over-HTTPS with IP: if (!empty($pac['deny'])) { $pac['deny'] = array_unique($pac['deny']); sort($pac['deny']); - foreach ($pac['deny'] as $v) { - $text .= "deny $v;\n"; + foreach ($pac['deny'] as $k => $v) { + if (!in_array($v, $pac['white'] ?: []) && !in_array($v, array_keys($xr ?: []))) { + $text .= "deny $v;\n"; + } else { + unset($pac['deny'][$k]); + } } } $this->setPacConf($pac); @@ -5358,7 +5352,7 @@ DNS-over-HTTPS with IP: $text[] = 'transport: ' . ($p['transport'] ?: 'Reality'); $data[] = [ [ - 'text' => $this->i18n('main outbound: ') . ($p['outbound'] ?: 'proxy'), + 'text' => $this->i18n('main outbound name: ') . ($p['outbound'] ?: 'proxy'), 'callback_data' => '/mainOutbound', ], ]; From 34b1de513255309201e8ec4c1ecc8420c4be554f Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 20:58:17 +0400 Subject: [PATCH 21/58] import telegram, gcore, cloudflare ip --- app/bot.php | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/app/bot.php b/app/bot.php index 2f6854a..5b656e0 100644 --- a/app/bot.php +++ b/app/bot.php @@ -166,6 +166,9 @@ class Bot case preg_match('~^/mainOutbound$~', $this->input['callback'], $m): $this->mainOutbound(); break; + case preg_match('~^/importIps (.+)$~', $this->input['callback'], $m): + $this->importIps($m[1]); + break; case preg_match('~^/switchBanIp$~', $this->input['callback'], $m): $this->switchBanIp(); break; @@ -3797,7 +3800,7 @@ DNS-over-HTTPS with IP: [$data] = $this->listPac('includelist', $page, 'xtlsproxy'); $data[] = [ [ - 'text' => 'set to ' . ($p['domains_outbound'] ? 'proxy' : 'direct'), + 'text' => 'set to ' . ($p['domains_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), 'callback_data' => "/domainsOutbound", ], ]; @@ -3855,7 +3858,7 @@ DNS-over-HTTPS with IP: $p = $this->getPacConf(); $data[] = [ [ - 'text' => 'set to ' . ($p['app_outbound'] ? 'proxy' : 'direct'), + 'text' => 'set to ' . ($p['app_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), 'callback_data' => "/appOutbound", ], ]; @@ -3881,7 +3884,7 @@ DNS-over-HTTPS with IP: $p = $this->getPacConf(); $data[] = [ [ - 'text' => 'set to ' . ($p['process_outbound'] ? 'proxy' : 'direct'), + 'text' => 'set to ' . ($p['process_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), 'callback_data' => "/processOutbound", ], ]; @@ -4537,6 +4540,33 @@ DNS-over-HTTPS with IP: } } + public function importIps($type) + { + switch ($type) { + case 'telegram': + $r = file_get_contents('https://core.telegram.org/resources/cidr.txt'); + if (!empty($r)) { + $domains = explode("\n", $r); + } + break; + case 'gcore': + $r = json_decode(file_get_contents('https://api.gcore.com/cdn/public-ip-list'), true); + if (!empty($r['addresses'])) { + $domains = $r['addresses']; + } + break; + case 'cloudflare': + $r = json_decode(file_get_contents('https://api.cloudflare.com/client/v4/ips'), true); + if (!empty($r['result']['ipv4_cidrs'])) { + $domains = $r['result']['ipv4_cidrs']; + } + break; + } + if (!empty($domains = array_filter($domains ?: [], fn($e) => preg_match('~^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}~', $e)))) { + $this->addInclude(implode(',', $domains), 'white'); + } + } + public function denyList($page = 0, $white = 0) { $text = 'Menu -> IP -> ' . ($white ? 'ignore' : 'block') . 'list'; @@ -4545,6 +4575,24 @@ DNS-over-HTTPS with IP: $page = min($page, $all - 1); $page = $page < 0 ? $all - 1 : $page; + $data[] = [ + [ + 'text' => $this->i18n('telegram IPs'), + 'callback_data' => "/importIps telegram", + ], + ]; + $data[] = [ + [ + 'text' => $this->i18n('gcore IPs'), + 'callback_data' => "/importIps gcore", + ], + ]; + $data[] = [ + [ + 'text' => $this->i18n('cloudflare IPs'), + 'callback_data' => "/importIps cloudflare", + ], + ]; $data[] = [ [ 'text' => $this->i18n('add'), From 7d8dc1dd2daf95839e5919f10e88a26de3450704 Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 20 Nov 2024 20:59:25 +0400 Subject: [PATCH 22/58] duplicating the list of subnets for openconnect --- app/bot.php | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/bot.php b/app/bot.php index 5b656e0..4a5f6e7 100644 --- a/app/bot.php +++ b/app/bot.php @@ -325,13 +325,13 @@ class Bot case preg_match('~^/defaultMTU (?P\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m): $this->defaultMTU(...explode('_', $m['arg'])); break; - case preg_match('~^/subnet (?P-?\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m): + case preg_match('~^/subnet (?P-?\d+(?:_-?\d+)?(?:_\d)?)$~', $this->input['callback'], $m): $this->subnet(...explode('_', $m['arg'])); break; - case preg_match('~^/subnetAdd (?P-?\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m): + case preg_match('~^/subnetAdd (?P-?\d+(?:_-?\d+)?(?:_-?\d+)?)$~', $this->input['callback'], $m): $this->subnetAdd(...explode('_', $m['arg'])); break; - case preg_match('~^/subnetDelete (?P-?\d+(?:_-?\d+)?(?:_-?\d+)?)$~', $this->input['callback'], $m): + case preg_match('~^/subnetDelete (?P-?\d+(?:_-?\d+)?(?:_-?\d+)?(?:_-?\d+)?)$~', $this->input['callback'], $m): $this->subnetDelete(...explode('_', $m['arg'])); break; case preg_match('~^/addSubnets (?P-?\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m): @@ -3112,7 +3112,7 @@ DNS-over-HTTPS with IP: $this->menu('client', "{$client}_$page"); } - public function subnetAdd($wgpage, $page) + public function subnetAdd($wgpage, $page, $openconnect) { $r = $this->send( $this->input['chat'], @@ -3124,11 +3124,11 @@ DNS-over-HTTPS with IP: 'start_message' => $this->input['message_id'], 'start_callback' => $this->input['callback_id'], 'callback' => 'subnetSave', - 'args' => [$wgpage, $page], + 'args' => [$wgpage, $page, $openconnect], ]; } - public function subnetSave($text, $wgpage, $page) + public function subnetSave($text, $wgpage, $page, $openconnect) { $c = $this->getPacConf(); $subnets = explode(',', $text); @@ -3137,15 +3137,15 @@ DNS-over-HTTPS with IP: $this->setPacConf($c); $page = floor(count($c['subnets']) / $this->limit); } - $this->subnet($wgpage, $page); + $this->subnet($wgpage, $page, $openconnect); } - public function subnetDelete($wgpage, $k, $page = 0) + public function subnetDelete($wgpage, $k, $page = 0, $openconnect = 0) { $c = $this->getPacConf(); unset($c['subnets'][$k]); $this->setPacConf($c); - $this->subnet($wgpage, $page); + $this->subnet($wgpage, $page, $openconnect); } public function calc() @@ -3201,10 +3201,10 @@ DNS-over-HTTPS with IP: } } - public function subnet($wgpage = 0, $page = 0, $count = 5) + public function subnet($wgpage = 0, $page = 0, $openconnect = 0) { $count = $this->limit; - $text = "Menu -> Wireguard -> " . $this->i18n('listSubnet') . "\n"; + $text = 'Menu -> ' . ($openconnect ? 'Openconnect' : 'Wireguard') . ' -> ' . $this->i18n('listSubnet') . "\n"; $data[] = [ [ 'text' => $this->i18n('calc'), @@ -3214,7 +3214,7 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => $this->i18n('add'), - 'callback_data' => "/subnetAdd {$wgpage}_$page", + 'callback_data' => "/subnetAdd {$wgpage}_{$page}_$openconnect", ], ]; $subnets = $this->getPacConf()['subnets']; @@ -3227,7 +3227,7 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => $this->i18n('delete') . " $v", - 'callback_data' => "/subnetDelete {$wgpage}_{$k}_$page", + 'callback_data' => "/subnetDelete {$wgpage}_{$k}_{$page}_$openconnect", ], ]; } @@ -3235,11 +3235,11 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => '<<', - 'callback_data' => "/subnet {$wgpage}_" . ($page - 1 >= 0 ? $page - 1 : $all - 1), + 'callback_data' => "/subnet {$wgpage}_" . ($page - 1 >= 0 ? $page - 1 : $all - 1) . ($openconnect ? '_1' : ''), ], [ 'text' => '>>', - 'callback_data' => "/subnet {$wgpage}_" . ($page < $all - 1 ? $page + 1 : 0), + 'callback_data' => "/subnet {$wgpage}_" . ($page < $all - 1 ? $page + 1 : 0) . ($openconnect ? '_1' : ''), ] ]; } @@ -3247,7 +3247,7 @@ DNS-over-HTTPS with IP: $data[] = [ [ 'text' => $this->i18n('back'), - 'callback_data' => "/menu wg $wgpage", + 'callback_data' => $openconnect ? '/menu oc' : "/menu wg $wgpage", ], ]; $this->update( @@ -4961,11 +4961,19 @@ DNS-over-HTTPS with IP: 'text' => $this->i18n('change password'), 'callback_data' => "/changeOcPass", ], + ]; + $data[] = [ [ 'text' => $this->i18n('dns') . ": $dns", 'callback_data' => "/changeOcDns", ], ]; + $data[] = [ + [ + 'text' => $this->i18n('listSubnet'), + 'callback_data' => "/subnet 0_0_1", + ], + ]; $data[] = [ [ 'text' => $this->i18n('expose-iroutes') . ' ' . $this->i18n($expose ? 'on' : 'off'), From b394e769c62957a4baf2e3910257f783806cdf46 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 00:24:50 +0400 Subject: [PATCH 23/58] =?UTF-8?q?=D1=80=D0=BE=D1=83=D1=82=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=20=D0=B4=D0=BB=D1=8F=20openconnect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- app/bot.php | 27 +++++++++++++++++++++++++++ config/ocserv.conf | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b37bf23..6a8d037 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ override.html override.php docker-compose.override.yml backup.json -app/webapp/override/ \ No newline at end of file +app/webapp/override/ +.rest diff --git a/app/bot.php b/app/bot.php index 4a5f6e7..ac34ef2 100644 --- a/app/bot.php +++ b/app/bot.php @@ -3137,6 +3137,9 @@ DNS-over-HTTPS with IP: $this->setPacConf($c); $page = floor(count($c['subnets']) / $this->limit); } + if (!empty($openconnect)) { + $this->ocservRoute(); + } $this->subnet($wgpage, $page, $openconnect); } @@ -3145,9 +3148,33 @@ DNS-over-HTTPS with IP: $c = $this->getPacConf(); unset($c['subnets'][$k]); $this->setPacConf($c); + if (!empty($openconnect)) { + $this->ocservRoute(); + } $this->subnet($wgpage, $page, $openconnect); } + public function ocservRoute() + { + $p = $this->getPacConf(); + $c = file_get_contents('/config/ocserv.conf'); + $t = preg_replace('~^route[^\n]+~sm', '', $c); + if (!empty($p['subnets'])) { + foreach ($p['subnets'] as $v) { + if (preg_match('~^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}~', $v)) { + $t .= "route = $v"; + $flag = true; + } + } + if (empty($flag)) { + $t .= 'route = default'; + } + } else { + $t .= 'route = default'; + } + $this->restartOcserv($t); + } + public function calc() { $r = $this->send( diff --git a/config/ocserv.conf b/config/ocserv.conf index f9f2b09..3455ab7 100644 --- a/config/ocserv.conf +++ b/config/ocserv.conf @@ -505,7 +505,7 @@ ipv4-netmask = 255.255.255.0 # Whether to tunnel all DNS queries via the VPN. This is the default # when a default route is set. -#tunnel-all-dns = true +tunnel-all-dns = true # The advertised DNS server. Use multiple lines for # multiple servers. From e2f84b0ee7a74f261d89db1cfc2bf1cdf419778f Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 00:39:07 +0400 Subject: [PATCH 24/58] update version --- version | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/version b/version index e9ba205..268f97a 100644 --- a/version +++ b/version @@ -1,3 +1,13 @@ +21.11.2024 v1.107 +- xray: добавлены теги ~cdndomain~, ~directdomain~ +- xray: возможность менять имя главного аутбаунда(тот аутбаунд который заполняет бот, в шаблонах идет как ~outbound~) для клиентских конфигов +- xray: в шаблонах теперь надо явно указывать ключ addruleset в route -> rules, чтобы бот заполнил их правилами из списка ruleset (см origin шаблон) +- openconnect: добавлена маршрутизация (список подсетей общий с wireguard) +- ip ban: фикс обработки подсетей в белом/черном списках +- ip ban: в белый список можно импортировать адреса от telegram, gcore, cloudflare +- добавлена в игнор папка app/webapp/override. она не будет перезатираться после обновления, туда можно положить ваши ресурсы к override.html +- make backup - сохранит в корень backup.json +- make reset - обнуляет все настройки 18.11.2024 v1.106 - фикс отвала бота при пустых логах телеги 17.11.2024 v1.105 From 550a8ad3b7466cc6ee617d18a3000418f8345794 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 01:37:22 +0400 Subject: [PATCH 25/58] fix ip/32 analyze --- app/bot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index ac34ef2..76aa3ed 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4377,7 +4377,7 @@ DNS-over-HTTPS with IP: $pac = $this->getPacConf(); foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], ['10.10.0.0/23']) as $v) { if (!empty(preg_match('~^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(\d{1,2})~', $v, $m))) { - for ($i = ip2long($m[1]); $i < ip2long($m[1]) + pow(2, 32 - $m[2]) - 1; $i++) { + for ($i = ip2long($m[1]); $i <= ip2long($m[1]) + pow(2, 32 - $m[2]) - 1; $i++) { $xr[long2ip($i)] = true; } } else { From 9d53f2896c22b05ee82219f250c9074960b3d75d Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 11:49:29 +0400 Subject: [PATCH 26/58] fix analyze memory --- app/bot.php | 103 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/app/bot.php b/app/bot.php index 76aa3ed..8f355dd 100644 --- a/app/bot.php +++ b/app/bot.php @@ -3130,6 +3130,9 @@ DNS-over-HTTPS with IP: public function subnetSave($text, $wgpage, $page, $openconnect) { + if (!preg_match('~^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$~', $text)) { + return $this->send($this->input['chat'], "wrong format: $text", $this->input['message_id']); + } $c = $this->getPacConf(); $subnets = explode(',', $text); if ($subnets) { @@ -4342,22 +4345,34 @@ DNS-over-HTTPS with IP: ); } - public function suspicious($regexp, $file, $ip, $title, $reverse = false) + public function ipInRange($ip, $range) { + [$range, $netmask] = explode('/', $range, 2); + $rangeDecimal = ip2long($range); + $ipDecimal = ip2long($ip); + $wildcardDecimal = pow(2, 32 - $netmask) - 1; + $netmaskDecimal = ~$wildcardDecimal; + return ($ipDecimal & $netmaskDecimal) == ($rangeDecimal & $netmaskDecimal); + } + + public function suspicious($regexp, $file, $ranges, $title, $reverse = false) { if ($r = fopen($file, 'r')) { while (feof($r) === false) { $l = fgets($r); if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { if ($reverse xor preg_match($regexp, $l)) { - if (is_array($ip)) { - if (empty($ip[$m[1]])) { - $ret[$m[1]][] = [ - 'title' => $title, - 'log' => $l, - ]; + if (is_array($ranges)) { + foreach ($ranges as $range) { + if (!$this->ipInRange($m[1], $range)) { + $ret[$m[1]][] = [ + 'title' => $title, + 'log' => $l, + ]; + break; + } } } else { - if ($ip == $m[1]) { + if ($this->ipInRange($m[1], $ranges)) { $ret[$m[1]][] = [ 'title' => $title, 'log' => $l, @@ -4375,20 +4390,21 @@ DNS-over-HTTPS with IP: public function analysisIp(int $page = 0, $return = false) { $pac = $this->getPacConf(); + $xr = []; foreach (array_merge($pac['white'] ?: [], $pac['deny'] ?: [], ['10.10.0.0/23']) as $v) { - if (!empty(preg_match('~^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(\d{1,2})~', $v, $m))) { - for ($i = ip2long($m[1]); $i <= ip2long($m[1]) + pow(2, 32 - $m[2]) - 1; $i++) { - $xr[long2ip($i)] = true; + if (preg_match('~^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:(/\d{1,2}))?$~', $v, $m)) { + if (!in_array($m[1] . ($m[2] ?: '/32'), $xr)) { + $xr[] = $m[1] . ($m[2] ?: '/32'); } - } else { - $xr[$v] = true; } } if ($r = fopen('/logs/nginx_tlgrm_access', 'r')) { while (feof($r) === false) { $l = fgets($r); if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { - $xr[$m[1]] = true; + if (!in_array("{$m[1]}/32", $xr)) { + $xr[] = "{$m[1]}/32"; + } } } fclose($r); @@ -4397,7 +4413,9 @@ DNS-over-HTTPS with IP: while (feof($r) === false) { $l = fgets($r); if (preg_match('~(\d+\.\d+\.\d+\.\d+)(?=.+accepted)~', $l, $m)) { - $xr[$m[1]] = true; + if (!in_array("{$m[1]}/32", $xr)) { + $xr[] = "{$m[1]}/32"; + } } } fclose($r); @@ -4536,9 +4554,9 @@ DNS-over-HTTPS with IP: public function searchSuspiciousIp($ip) { $t = [ - $this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', $ip, 'possibly a Reality Degenerate'), - $this->suspicious($this->reg, '/logs/nginx_default_access', $ip, 'possibly a scanner', true), - $this->suspicious($this->reg, '/logs/nginx_domain_access', $ip, 'possibly a scanner', true), + $this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', "$ip/32", 'possibly a Reality Degenerate'), + $this->suspicious($this->reg, '/logs/nginx_default_access', "$ip/32", 'possibly a scanner', true), + $this->suspicious($this->reg, '/logs/nginx_domain_access', "$ip/32", 'possibly a scanner', true), ]; foreach ($t as $r) { if (!empty($r)) { @@ -4602,24 +4620,26 @@ DNS-over-HTTPS with IP: $page = min($page, $all - 1); $page = $page < 0 ? $all - 1 : $page; - $data[] = [ - [ - 'text' => $this->i18n('telegram IPs'), - 'callback_data' => "/importIps telegram", - ], - ]; - $data[] = [ - [ - 'text' => $this->i18n('gcore IPs'), - 'callback_data' => "/importIps gcore", - ], - ]; - $data[] = [ - [ - 'text' => $this->i18n('cloudflare IPs'), - 'callback_data' => "/importIps cloudflare", - ], - ]; + if (!empty($white)) { + $data[] = [ + [ + 'text' => $this->i18n('telegram IPs'), + 'callback_data' => "/importIps telegram", + ], + ]; + $data[] = [ + [ + 'text' => $this->i18n('gcore IPs'), + 'callback_data' => "/importIps gcore", + ], + ]; + $data[] = [ + [ + 'text' => $this->i18n('cloudflare IPs'), + 'callback_data' => "/importIps cloudflare", + ], + ]; + } $data[] = [ [ 'text' => $this->i18n('add'), @@ -5766,12 +5786,11 @@ DNS-over-HTTPS with IP: $text[] = "Menu -> " . $this->i18n('xray') . " -> {$c['email']}\n"; $text[] = "
{$this->linkXray($i)}
\n"; - $text[] = "import subscribe:"; - $text[] = "v2rayng"; - $text[] = "sing-box"; - $text[] = "streisand"; - $text[] = "hiddify"; - $text[] = "karing"; + $text[] = "import://v2rayng"; + $text[] = "import://sing-box"; + $text[] = "import://streisand"; + $text[] = "import://hiddify"; + $text[] = "import://karing"; $si = "$scheme://{$domain}/pac/" . base64_encode(serialize([ 'h' => $hash, From 253cceb44c24318e179e5ea5d1934b23120491dd Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 12:13:02 +0400 Subject: [PATCH 27/58] fix analyze ip autoban --- app/bot.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/bot.php b/app/bot.php index 8f355dd..277cb89 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4362,15 +4362,19 @@ DNS-over-HTTPS with IP: if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { if ($reverse xor preg_match($regexp, $l)) { if (is_array($ranges)) { + $flag = true; foreach ($ranges as $range) { - if (!$this->ipInRange($m[1], $range)) { - $ret[$m[1]][] = [ - 'title' => $title, - 'log' => $l, - ]; + if ($this->ipInRange($m[1], $range)) { + $flag = false; break; } } + if ($flag) { + $ret[$m[1]][] = [ + 'title' => $title, + 'log' => $l, + ]; + } } else { if ($this->ipInRange($m[1], $ranges)) { $ret[$m[1]][] = [ From 4902eb53ce19754b836ca96633d0f9c4668ced2c Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 16:04:09 +0400 Subject: [PATCH 28/58] fix addruleset for direct --- config/sing.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/sing.json b/config/sing.json index 9e4577f..b6e5d4a 100644 --- a/config/sing.json +++ b/config/sing.json @@ -186,6 +186,7 @@ "outbound": "~outbound~" }, { + "addruleset": true, "outbound": "direct" } ], From 8ad00bc47ae511f15e72100e89cc8a1170fbf0f8 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 21 Nov 2024 18:09:25 +0400 Subject: [PATCH 29/58] update version --- app/bot.php | 1 - version | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 277cb89..e9eda1c 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6105,7 +6105,6 @@ DNS-over-HTTPS with IP: $t[$v['outbound']] = $k; } } - $this->sd($t, 1); $p = $this->getPacConf(); if (!empty($p['rulessetlist'])) { foreach ($p['rulessetlist'] as $k => $v) { diff --git a/version b/version index 268f97a..6e0819a 100644 --- a/version +++ b/version @@ -1,3 +1,8 @@ +21.11.2024 v1.108 +- xray: addruleset для direct +- openconnect:ограничение формата при добавлении подсети +- новый механизм сверки ip для анализатора айпи +- мелкие фиксы меню и текста 21.11.2024 v1.107 - xray: добавлены теги ~cdndomain~, ~directdomain~ - xray: возможность менять имя главного аутбаунда(тот аутбаунд который заполняет бот, в шаблонах идет как ~outbound~) для клиентских конфигов From cdc20adccdda04bd4fe00f9cced3a357884aad31 Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 27 Nov 2024 16:52:30 +0400 Subject: [PATCH 30/58] consistent template logic --- app/bot.php | 46 ++++++++++------------------------------------ config/sing.json | 12 ++++-------- 2 files changed, 14 insertions(+), 44 deletions(-) diff --git a/app/bot.php b/app/bot.php index e9eda1c..28381fc 100644 --- a/app/bot.php +++ b/app/bot.php @@ -37,7 +37,7 @@ class Bot 'xray', ]; $this->reg = '~' . implode('|', [ - 'GET /ws(?:.+)? HTTP', + 'GET /ws HTTP', 'GET /adguard/(?:.+)? HTTP', 'GET /webapp(?:.+)? HTTP', 'GET /pac(?:.+)? HTTP', @@ -3828,12 +3828,6 @@ DNS-over-HTTPS with IP: $p = $this->getPacConf(); $text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> proxy list'; [$data] = $this->listPac('includelist', $page, 'xtlsproxy'); - $data[] = [ - [ - 'text' => 'set to ' . ($p['domains_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), - 'callback_data' => "/domainsOutbound", - ], - ]; $data[] = [ [ 'text' => $this->i18n('back'), @@ -3886,12 +3880,6 @@ DNS-over-HTTPS with IP: [$data] = $this->listPac('packagelist', $page, 'xtlsapp'); $p = $this->getPacConf(); - $data[] = [ - [ - 'text' => 'set to ' . ($p['app_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), - 'callback_data' => "/appOutbound", - ], - ]; $data[] = [ [ 'text' => $this->i18n('back'), @@ -3912,12 +3900,6 @@ DNS-over-HTTPS with IP: [$data] = $this->listPac('processlist', $page, 'xtlsprocess'); $p = $this->getPacConf(); - $data[] = [ - [ - 'text' => 'set to ' . ($p['process_outbound'] ? ($p['outbound'] ?: 'proxy') : 'direct'), - 'callback_data' => "/processOutbound", - ], - ]; $data[] = [ [ 'text' => $this->i18n('back'), @@ -5342,6 +5324,10 @@ DNS-over-HTTPS with IP: $text[] = <<~outbound~ "~pac~" + ~package~ + ~process~ + ~block~ + ~warp~ ~dns~ ~uid~ ~domain~ @@ -5350,10 +5336,6 @@ DNS-over-HTTPS with IP: ~short_id~ ~public_key~ ~server_name~ - ~app_outbound~ - ~process_outbound~ - ~domains_outbound~ - ~final_outbound~ ~ip~ TEXT; $templates = $pac["{$type}templates"]; @@ -5589,24 +5571,20 @@ DNS-over-HTTPS with IP: 'callback_data' => "/xtlswarp", ]], [[ - 'text' => $this->i18n('rulesset'), - 'callback_data' => "/xtlsrulesset", - ]], - [[ - 'text' => 'domains: ' . ($p['domains_outbound'] ? 'direct' : $outbound), + 'text' => 'domains', 'callback_data' => "/xtlsproxy", ]], [[ - 'text' => 'process: ' . ($p['process_outbound'] ? 'direct' : $outbound), + 'text' => 'process', 'callback_data' => "/xtlsprocess", ]], [[ - 'text' => 'package: ' . ($p['app_outbound'] ? 'direct' : $outbound), + 'text' => 'package', 'callback_data' => "/xtlsapp", ]], [[ - 'text' => 'final: ' . ($p['final_outbound'] ? $outbound : 'direct'), - 'callback_data' => "/finalOutbound", + 'text' => $this->i18n('rulesset'), + 'callback_data' => "/xtlsrulesset", ]], ]; $data[] = [ @@ -6056,10 +6034,6 @@ DNS-over-HTTPS with IP: '~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0], '~public_key~' => $pac['xray'], '~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0], - '~app_outbound~' => $pac['app_outbound'] ? 'direct' : $outbound, - '~process_outbound~' => $pac['process_outbound'] ? 'direct' : $outbound, - '~domains_outbound~' => $pac['domains_outbound'] ? 'direct' : $outbound, - '~final_outbound~' => $pac['final_outbound'] ? $outbound : 'direct', '~ip~' => $this->ip, ]); $json = $this->addRuleSet($json); diff --git a/config/sing.json b/config/sing.json index b6e5d4a..f4e53fd 100644 --- a/config/sing.json +++ b/config/sing.json @@ -123,7 +123,7 @@ ] } ], - "outbound": "~domains_outbound~" + "outbound": "~outbound~" }, { "addruleset": true, @@ -138,7 +138,7 @@ ] } ], - "outbound": "~app_outbound~" + "outbound": "~outbound~" }, { "addruleset": true, @@ -153,7 +153,7 @@ ] } ], - "outbound": "~process_outbound~" + "outbound": "~outbound~" }, { "addruleset": true, @@ -184,12 +184,8 @@ } ], "outbound": "~outbound~" - }, - { - "addruleset": true, - "outbound": "direct" } ], - "final": "~final_outbound~" + "final": "direct" } } \ No newline at end of file From 36e8acd2aaf399e990f2193b3760d482433f10af Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 27 Nov 2024 22:00:30 +0400 Subject: [PATCH 31/58] xray: template for clash --- app/bot.php | 220 +++++++++++++++++++++++++++++----------------- app/index.php | 1 + config/clash.json | 119 +++++++++++++++++++++++++ 3 files changed, 259 insertions(+), 81 deletions(-) create mode 100644 config/clash.json diff --git a/app/bot.php b/app/bot.php index 28381fc..6e9c141 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5482,6 +5482,10 @@ DNS-over-HTTPS with IP: 'text' => $this->i18n('sing-box templates'), 'callback_data' => "/templates sing", ], + [ + 'text' => $this->i18n('clash templates'), + 'callback_data' => "/templates clash", + ], ]; $data[] = [ [ @@ -5784,9 +5788,15 @@ DNS-over-HTTPS with IP: 't' => 's', 's' => $c['id'], ])); + $cl = "$scheme://{$domain}/pac/" . base64_encode(serialize([ + 'h' => $hash, + 't' => 'cl', + 's' => $c['id'], + ])); $text[] = "\nxray config:
$xr
"; $text[] = "sing-box config:
$si
"; + $text[] = "clash config:
$cl
"; $text[] = "sing-box windows: windows service"; @@ -5812,6 +5822,7 @@ DNS-over-HTTPS with IP: ]; $singtemplate = $c['singtemplate'] ? base64_decode($c['singtemplate']) : 'default(' . ($pac['defaultsingtemplate'] && !empty($pac['singtemplates'][base64_decode($pac['defaultsingtemplate'])]) ? base64_decode($pac['defaultsingtemplate']) : 'origin') . ')'; $v2raytemplate = $c['v2raytemplate'] ? base64_decode($c['v2raytemplate']) : 'default(' . ($pac['defaultv2raytemplate'] && !empty($pac['v2raytemplates'][base64_decode($pac['defaultv2raytemplate'])]) ? base64_decode($pac['defaultv2raytemplate']) : 'origin') . ')'; + $clashtemplate = $c['clashtemplate'] ? base64_decode($c['clashtemplate']) : 'default(' . ($pac['defaultclashtemplate'] && !empty($pac['clashtemplates'][base64_decode($pac['defaultclashtemplate'])]) ? base64_decode($pac['defaultclashtemplate']) : 'origin') . ')'; $data[] = [ [ 'text' => $this->i18n('v2ray') . ": $v2raytemplate", @@ -5821,6 +5832,10 @@ DNS-over-HTTPS with IP: 'text' => $this->i18n('singbox') . ": $singtemplate", 'callback_data' => "/templateUser sing $i", ], + [ + 'text' => $this->i18n('clash') . ": $clashtemplate", + 'callback_data' => "/templateUser clash $i", + ], ]; $data[] = [ [ @@ -5871,7 +5886,17 @@ DNS-over-HTTPS with IP: public function subscription() { - $type = $_GET['t'] == 's' ? 'v2ray' : 'sing'; + switch ($_GET['t']) { + case 's': + $type = 'v2ray'; + break; + case 'si': + $type = 'sing'; + break; + case 'cl': + $type = 'clash'; + break; + } $pac = $this->getPacConf(); $domain = $_GET['cdn'] ?: ($_SERVER['SERVER_NAME'] ?: $this->getDomain($pac['transport'] == 'Websocket')); $xr = $this->getXray(); @@ -5905,6 +5930,11 @@ DNS-over-HTTPS with IP: 't' => 's', 's' => $uid, ])); + $cl = "$scheme://{$domain}/pac/" . base64_encode(serialize([ + 'h' => $hash, + 't' => 'cl', + 's' => $uid, + ])); switch ($_GET['r']) { case 'si': header("Location: sing-box://import-remote-profile/?url=$si"); @@ -5961,6 +5991,14 @@ DNS-over-HTTPS with IP: break; } } + if (!isset($index)) { + foreach ($c['proxies'] as $k => $v) { + if ($v['name'] == $outbound) { + $index = $k; + break; + } + } + } switch ($_GET['t']) { case 's': @@ -6020,27 +6058,103 @@ DNS-over-HTTPS with IP: $c['outbounds'][$index]['tls']['reality']['short_id'] = '~short_id~'; } + $c['route'] = $this->addRuleSet($c['route']); $c['route'] = $this->createRuleSet($c['route'], $uid, $domain); break; + case 'cl': + $c['proxies'][$index]['server'] = '~domain~'; + $c['proxies'][$index]['uuid'] = '~uid~'; + if ($pac['transport'] == 'Websocket') { + unset($c['proxies'][$index]['flow']); + unset($c['proxies'][$index]['reality-opts']); + $c['proxies'][$index]["network"] = "ws"; + $c['proxies'][$index]["ws-opts"]['path'] = '/ws'; + $c['proxies'][$index]["skip-cert-verify"] = false; + $c['proxies'][$index]['servername'] = '~domain~'; + } else { + unset($c['proxies'][$index]["ws-opts"]); + unset($c['proxies'][$index]["skip-cert-verify"]); + $c['proxies'][$index]["network"] = "tcp"; + $c['proxies'][$index]['flow'] = 'xtls-rprx-vision'; + $c['proxies'][$index]['servername'] = '~server_name~'; + $c['proxies'][$index]['reality-opts'] = [ + 'public-key' => '~public_key~', + 'short-id' => '~short_id~', + ]; + } + break; + } + $c = json_decode($this->replaceTags(json_encode($c), [ + '"~pac~"' => json_encode(array_keys(array_filter($pac['includelist'] ?: []))), + '"~block~"' => json_encode(array_keys(array_filter($pac['blocklist'] ?: []))), + '"~warp~"' => json_encode(array_keys(array_filter($pac['warplist'] ?: []))), + '"~process~"' => json_encode(array_keys(array_filter($pac['processlist'] ?: []))), + '"~package~"' => json_encode(array_keys(array_filter($pac['packagelist'] ?: []))), + '~dns~' => "https://$domain/dns-query/$uid", + '~uid~' => $uid, + '~domain~' => $domain, + '~directdomain~' => $pac['domain'], + '~cdndomain~' => $pac['linkdomain'], + '~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0], + '~public_key~' => $pac['xray'], + '~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0], + '~ip~' => $this->ip, + ]), true); + + switch ($_GET['t']) { + case 's': + if (!empty($c['routing']['rules'])) { + foreach ($c['routing']['rules'] as $k => $v) { + if (array_key_exists('domain', $v) && empty($v['domain'])) { + unset($c['routing']['rules'][$k]); + } + } + $c['routing']['rules'] = array_values($c['routing']['rules']); + } + break; + case 'si': + $c['route'] = $this->addRuleSet($c['route']); + $c['route'] = $this->createRuleSet($c['route'], $uid, $domain); + if (!empty($c['route']['rules'])) { + foreach ($c['route']['rules'] as $k => $v) { + if (count($v) < 2) { + unset($c['route']['rules'][$k]); + } + } + $c['route']['rules'] = array_values($c['route']['rules']); + } + break; + case 'cl': + if (!empty($c['rules'])) { + $c['rules'] = $this->clashRules($c['rules']); + } + break; } - $json = $this->replaceTags(json_encode($c), [ - '"~pac~"' => json_encode(array_keys(array_filter($pac['includelist'] ?: []))), - '~dns~' => "https://$domain/dns-query/$uid", - '~uid~' => $uid, - '~domain~' => $domain, - '~directdomain~' => $pac['domain'], - '~cdndomain~' => $pac['linkdomain'], - '~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0], - '~public_key~' => $pac['xray'], - '~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0], - '~ip~' => $this->ip, - ]); - $json = $this->addRuleSet($json); - $json = $this->clearEmptyRules($json); + if ($_GET['t'] == 'cl') { + header('Content-type: text/yaml'); + echo yaml_emit($c); + return; + } header('Content-type: application/json'); - echo $json; + echo json_encode($c); + } + + public function clashRules($rules) + { + foreach ($rules as $v) { + if (isset($v['list'])) { + if (!empty($v['list'])) { + foreach ($v['list'] as $j) { + $tmp[] = "{$v['type']}, $j, {$v['action']}"; + } + } + } else { + $tmp[] = "{$v['type']}, {$v['action']}"; + } + } + return $tmp; } public function replaceTags($subject, $tags) @@ -6048,33 +6162,10 @@ DNS-over-HTTPS with IP: return str_replace(array_keys($tags), array_values($tags), $subject); } - public function clearEmptyRules($json) + public function addRuleSet($route) { - $json = json_decode($json, 1); - if (!empty($json['routing']['rules'])) { - foreach ($json['routing']['rules'] as $k => $v) { - if (array_key_exists('domain', $v) && empty($v['domain'])) { - unset($json['routing']['rules'][$k]); - } - } - $json['routing']['rules'] = array_values($json['routing']['rules']); - } - if (!empty($json['route']['rules'])) { - foreach ($json['route']['rules'] as $k => $v) { - if (count($v) < 2) { - unset($json['route']['rules'][$k]); - } - } - $json['route']['rules'] = array_values($json['route']['rules']); - } - return json_encode($json); - } - - public function addRuleSet($json) - { - $json = json_decode($json, 1); - if (!empty($json['route']['rules'])) { - foreach ($json['route']['rules'] as $k => $v) { + if (!empty($route['rules'])) { + foreach ($route['rules'] as $k => $v) { if (!empty($v['addruleset'])) { $t[$v['outbound']] = $k; } @@ -6084,8 +6175,8 @@ DNS-over-HTTPS with IP: foreach ($p['rulessetlist'] as $k => $v) { if (!empty($v)) { [$type, $time, $url] = explode(':', $k, 3); - if (!empty($json['route']['rules'][$t[$type]])) { - $json['route']['rule_set'][] = [ + if (!empty($route['rules'][$t[$type]])) { + $route['rule_set'][] = [ "tag" => $k, "type" => "remote", "format" => "binary", @@ -6093,16 +6184,16 @@ DNS-over-HTTPS with IP: "download_detour" => "direct", "update_interval" => $time ]; - $json['route']['rules'][$t[$type]]['rule_set'][] = $k; + $route['rules'][$t[$type]]['rule_set'][] = $k; } } } } - foreach ($json['route']['rules'] as $k => $v) { - unset($json['route']['rules'][$k]['addruleset']); + foreach ($route['rules'] as $k => $v) { + unset($route['rules'][$k]['addruleset']); } } - return json_encode($json); + return $route; } public function createRuleSet($route, $uid, $domain) @@ -6114,39 +6205,6 @@ DNS-over-HTTPS with IP: foreach ($route['rules'] as $k => $v) { if (!empty($v['createruleset'])) { foreach ($v['createruleset'] as $r) { - foreach ($r['rules'] as $l => $n) { - switch (true) { - case array_key_exists('domain_suffix', $n): - switch ($n['domain_suffix']) { - case '~pac~': - $t = 'includelist'; - break; - case '~warp~': - $t = 'warplist'; - break; - case '~block~': - $t = 'blocklist'; - break; - } - $r['rules'][$l]['domain_suffix'] = array_keys(array_filter($pac[$t] ?: [])); - if (empty($r['rules'][$l]['domain_suffix'])) { - unset($r['rules'][$l]); - } - break; - case array_key_exists('package_name', $n): - $r['rules'][$l]['package_name'] = array_keys(array_filter($pac['packagelist'] ?: [])); - if (empty($r['rules'][$l]['package_name'])) { - unset($r['rules'][$l]); - } - break; - case array_key_exists('process_name', $n): - $r['rules'][$l]['process_name'] = array_keys(array_filter($pac['processlist'] ?: [])); - if (empty($r['rules'][$l]['process_name'])) { - unset($r['rules'][$l]); - } - break; - } - } if (!empty($_GET['r']) && $r['name'] == $_GET['r']) { header("Content-Disposition: attachment; filename={$r['name']}.srs"); header('Content-Type: application/binary'); diff --git a/app/index.php b/app/index.php index 9a2fd15..7b73dcf 100644 --- a/app/index.php +++ b/app/index.php @@ -37,6 +37,7 @@ if ($hash == substr(md5($c['key']), 0, 8)) { break; case 's': case 'si': + case 'cl': $bot->subscription(); exit; diff --git a/config/clash.json b/config/clash.json new file mode 100644 index 0000000..9425f45 --- /dev/null +++ b/config/clash.json @@ -0,0 +1,119 @@ +{ + "mixed-port": 2080, + "allow-lan": true, + "tcp-concurrent": true, + "enable-process": true, + "find-process-mode": "strict", + "global-client-fingerprint": "chrome", + "mode": "rule", + "log-level": "debug", + "ipv6": false, + "keep-alive-interval": 30, + "unified-delay": false, + "profile": { + "store-selected": true, + "store-fake-ip": true + }, + "sniffer": { + "enable": true, + "sniff": { + "HTTP": { + "ports": [ + 80, + "8080-8880" + ], + "override-destination": true + }, + "TLS": { + "ports": [ + 443, + 8443 + ] + }, + "QUIC": { + "ports": [ + 443, + 8443 + ] + } + } + }, + "tun": { + "enable": true, + "stack": "mixed", + "dns-hijack": [ + "any:53" + ], + "auto-route": true, + "auto-detect-interface": true, + "strict-route": true + }, + "dns": { + "enable": true, + "listen": ":1053", + "prefer-h3": false, + "ipv6": false, + "enhanced-mode": "fake-ip", + "fake-ip-filter": [ + "~domain~", + "+.lan", + "+.local" + ], + "nameserver": [ + "~dns~" + ] + }, + "proxies": [ + { + "name": "~outbound~", + "type": "vless", + "server": "~domain~", + "port": 443, + "uuid": "~uid~", + "network": "tcp", + "flow": "xtls-rprx-vision", + "tls": true, + "reality-opts": { + "public-key": "~public_key~", + "short-id": "~short_id~" + }, + "servername": "~server_name~", + "client-fingerprint": "chrome" + } + ], + "proxy-groups": [ + { + "name": "PROXY", + "type": "select", + "proxies": [ + "~outbound~" + ] + } + ], + "rules": [ + { + "type": "DOMAIN-SUFFIX", + "list": "~block~", + "action": "REJECT" + }, + { + "type": "DOMAIN-SUFFIX", + "list": "~warp~", + "action": "PROXY" + }, + { + "type": "DOMAIN-SUFFIX", + "list": "~pac~", + "action": "PROXY" + }, + { + "type": "PROCESS-NAME", + "list": "~process~", + "action": "REJECT" + }, + { + "type": "MATCH", + "action": "DIRECT" + } + ] +} \ No newline at end of file From 66e204e5ba65667beb12c772fe75eef86d53a08a Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 27 Nov 2024 23:37:39 +0400 Subject: [PATCH 32/58] import url for clash --- app/bot.php | 8 ++++++++ config/clash.json | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 6e9c141..98b9ae6 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5777,6 +5777,8 @@ DNS-over-HTTPS with IP: $text[] = "import://streisand"; $text[] = "import://hiddify"; $text[] = "import://karing"; + $text[] = "import://clash"; + $text[] = "import://clashmeta"; $si = "$scheme://{$domain}/pac/" . base64_encode(serialize([ 'h' => $hash, @@ -5951,6 +5953,12 @@ DNS-over-HTTPS with IP: case 'h': header("Location: hiddify://install-config/?url=$si"); exit; + case 'c': + header("Location: clash://install-config/?url=$cl"); + exit; + case 'cm': + header("Location: clashmeta://install-config/?url=$cl"); + exit; case 'w': $link = htmlspecialchars($si, ENT_XML1, 'UTF-8'); $n = "singbox_$uid.zip"; diff --git a/config/clash.json b/config/clash.json index 9425f45..63cce15 100644 --- a/config/clash.json +++ b/config/clash.json @@ -109,7 +109,12 @@ { "type": "PROCESS-NAME", "list": "~process~", - "action": "REJECT" + "action": "PROXY" + }, + { + "type": "PROCESS-NAME", + "list": "~package~", + "action": "PROXY" }, { "type": "MATCH", From 968d72ce819e94be9cbd21a092d6da9e0a2c2c5a Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 00:12:12 +0400 Subject: [PATCH 33/58] autoscan call fix --- app/bot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 98b9ae6..0e50fc8 100644 --- a/app/bot.php +++ b/app/bot.php @@ -1192,10 +1192,10 @@ class Bot try { $pac = $this->getPacConf(); if (!empty($pac['autoscan'])) { - $r = $this->analysisIp(return: 1); require __DIR__ . '/config.php'; if (!empty($c['admin']) && (empty($this->time3) || ((time() - $this->time3) > $pac['autoscan_timeout']))) { $this->time3 = time(); + $r = $this->analysisIp(return: 1); if (!empty($r)) { foreach ($r as $k => $v) { foreach ($v as $i) { From 28906176f567cdab92b0305c40a8829914a46e26 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 00:21:22 +0400 Subject: [PATCH 34/58] update clash links --- app/bot.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/bot.php b/app/bot.php index 0e50fc8..13bcd5a 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5778,7 +5778,6 @@ DNS-over-HTTPS with IP: $text[] = "import://hiddify"; $text[] = "import://karing"; $text[] = "import://clash"; - $text[] = "import://clashmeta"; $si = "$scheme://{$domain}/pac/" . base64_encode(serialize([ 'h' => $hash, @@ -5954,10 +5953,7 @@ DNS-over-HTTPS with IP: header("Location: hiddify://install-config/?url=$si"); exit; case 'c': - header("Location: clash://install-config/?url=$cl"); - exit; - case 'cm': - header("Location: clashmeta://install-config/?url=$cl"); + header("Location: clash://install-config/?url=$cl&name=$email"); exit; case 'w': $link = htmlspecialchars($si, ENT_XML1, 'UTF-8'); From 7e2d90e7da83256d83a58bb785b58a59b3857e49 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 10:36:10 +0400 Subject: [PATCH 35/58] update prioritet clash rules --- config/clash.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/config/clash.json b/config/clash.json index 63cce15..3180382 100644 --- a/config/clash.json +++ b/config/clash.json @@ -96,16 +96,6 @@ "list": "~block~", "action": "REJECT" }, - { - "type": "DOMAIN-SUFFIX", - "list": "~warp~", - "action": "PROXY" - }, - { - "type": "DOMAIN-SUFFIX", - "list": "~pac~", - "action": "PROXY" - }, { "type": "PROCESS-NAME", "list": "~process~", @@ -116,6 +106,16 @@ "list": "~package~", "action": "PROXY" }, + { + "type": "DOMAIN-SUFFIX", + "list": "~warp~", + "action": "PROXY" + }, + { + "type": "DOMAIN-SUFFIX", + "list": "~pac~", + "action": "PROXY" + }, { "type": "MATCH", "action": "DIRECT" From 62679314759a6ef32ff065e34234b635937737b8 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 12:59:06 +0400 Subject: [PATCH 36/58] fix bug createruleset for singbox --- app/bot.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/bot.php b/app/bot.php index 13bcd5a..cb08371 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6061,9 +6061,6 @@ DNS-over-HTTPS with IP: $c['outbounds'][$index]['tls']['server_name'] = '~server_name~'; $c['outbounds'][$index]['tls']['reality']['short_id'] = '~short_id~'; } - - $c['route'] = $this->addRuleSet($c['route']); - $c['route'] = $this->createRuleSet($c['route'], $uid, $domain); break; case 'cl': $c['proxies'][$index]['server'] = '~domain~'; From 4f4e36e1cbb694c50f9be0df27f4229da524dc84 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 15:17:42 +0400 Subject: [PATCH 37/58] doh ip exclude for analyze ip --- app/bot.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/bot.php b/app/bot.php index cb08371..82258f2 100644 --- a/app/bot.php +++ b/app/bot.php @@ -4395,6 +4395,17 @@ DNS-over-HTTPS with IP: } fclose($r); } + if ($r = fopen('/logs/nginx_doh_access', 'r')) { + while (feof($r) === false) { + $l = fgets($r); + if (preg_match('~(\d+\.\d+\.\d+\.\d+)~', $l, $m)) { + if (!in_array("{$m[1]}/32", $xr)) { + $xr[] = "{$m[1]}/32"; + } + } + } + fclose($r); + } if ($r = fopen('/logs/xray', 'r')) { while (feof($r) === false) { $l = fgets($r); From 19ef5678734df0f625147dc6ac9fb28eb6b131bc Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 19:51:21 +0400 Subject: [PATCH 38/58] fix createruleset --- app/bot.php | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/app/bot.php b/app/bot.php index 82258f2..a0ad6fe 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6208,9 +6208,40 @@ DNS-over-HTTPS with IP: return $route; } + public function cleanEmptyKeys(array $arr) + { + foreach ($arr as $k => $v) { + if (empty($v)) { + unset($arr[$k]); + } elseif (is_array($v)) { + $arr[$k] = $this->cleanEmptyKeys($v); + if (empty($arr[$k])) { + unset($arr[$k]); + } + } + } + return $arr; + } + + public function createSrs(string $name, array $rules) + { + $rules = $this->cleanEmptyKeys($rules); + header("Content-Disposition: attachment; filename=$name.srs"); + header('Content-Type: application/binary'); + $f = "/tmp/$name" . time() . rand(1, 100); + file_put_contents($f, json_encode([ + 'version' => 1, + 'rules' => $rules ?: [], + ])); + exec("sing-box rule-set compile $f"); + echo file_get_contents("$f.srs"); + unlink($f); + unlink("$f.srs"); + exit; + } + public function createRuleSet($route, $uid, $domain) { - $pac = $this->getPacConf(); $scheme = empty($this->nginxGetTypeCert()) ? 'http' : 'https'; $hash = substr(md5($this->key), 0, 8); @@ -6218,18 +6249,7 @@ DNS-over-HTTPS with IP: if (!empty($v['createruleset'])) { foreach ($v['createruleset'] as $r) { if (!empty($_GET['r']) && $r['name'] == $_GET['r']) { - header("Content-Disposition: attachment; filename={$r['name']}.srs"); - header('Content-Type: application/binary'); - $f = "/tmp/{$r['name']}" . time() . rand(1, 100); - file_put_contents($f, json_encode([ - 'version' => 1, - 'rules' => $r['rules'] ?: [], - ])); - exec("sing-box rule-set compile $f"); - echo file_get_contents("$f.srs"); - unlink($f); - unlink("$f.srs"); - exit; + $this->createSrs($r['name'], $r['rules']); } $ruleset[] = [ "tag" => $r['name'], From 8ba7ddedeedf5d5034141248d5136e5d490eee14 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 20:04:53 +0400 Subject: [PATCH 39/58] update version --- version | 3 +++ 1 file changed, 3 insertions(+) diff --git a/version b/version index 6e0819a..f15d4ff 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +28.11.2024 v1.109 +- фикс автоскана +- добавление clash-шаблонов 21.11.2024 v1.108 - xray: addruleset для direct - openconnect:ограничение формата при добавлении подсети From f896b307ea5b110fb844fa0c9dd39855b9ebb3be Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 28 Nov 2024 20:11:05 +0400 Subject: [PATCH 40/58] removed check when adding a subnet to openconnect --- app/bot.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/bot.php b/app/bot.php index a0ad6fe..003d991 100644 --- a/app/bot.php +++ b/app/bot.php @@ -3130,9 +3130,6 @@ DNS-over-HTTPS with IP: public function subnetSave($text, $wgpage, $page, $openconnect) { - if (!preg_match('~^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$~', $text)) { - return $this->send($this->input['chat'], "wrong format: $text", $this->input['message_id']); - } $c = $this->getPacConf(); $subnets = explode(',', $text); if ($subnets) { From 1527b9f8568190daf7ecd6189fdbbe44cfdbcec2 Mon Sep 17 00:00:00 2001 From: mercury Date: Wed, 4 Dec 2024 00:08:32 +0400 Subject: [PATCH 41/58] added rule-set for clash --- app/bot.php | 40 ++++++++++++++++++++++++++++++++++++---- config/clash.json | 2 ++ config/sing.json | 10 +++++----- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/app/bot.php b/app/bot.php index 003d991..03d5d7e 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5811,13 +5811,17 @@ DNS-over-HTTPS with IP: $data[] = [ [ - 'text' => 'xray', + 'text' => $this->i18n('v2ray'), 'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=s&s={$c['id']}"], ], [ - 'text' => 'sing-box', + 'text' => $this->i18n('singbox'), 'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=si&s={$c['id']}"], ], + [ + 'text' => $this->i18n('clash'), + 'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=cl&s={$c['id']}"], + ], ]; $data[] = [ [ @@ -6134,6 +6138,7 @@ DNS-over-HTTPS with IP: } break; case 'cl': + $c = $this->clashRuleSet($c); if (!empty($c['rules'])) { $c['rules'] = $this->clashRules($c['rules']); } @@ -6150,6 +6155,33 @@ DNS-over-HTTPS with IP: echo json_encode($c); } + public function clashRuleSet($c) + { + $p = $this->getPacConf(); + if (!empty($p['rulessetlist']) && $c['add-rule-providers']) { + foreach ($p['rulessetlist'] as $k => $v) { + if (!empty($v)) { + [$type, $time, $url] = explode(':', $k, 3); + if (preg_match('~\.mrs$~', $url)) { + $c['rule-providers'][$type] = [ + 'type' => 'http', + 'url' => $url, + 'interval' => $time, + ]; + array_unshift($c['rules'], [ + 'RULE-SET', $url, strtoupper($type) + ]); + } + } + } + } + unset($c['add-rule-providers']); + if (empty($c['rule-providers'])) { + unset($c['rule-providers']); + } + return $c; + } + public function clashRules($rules) { foreach ($rules as $v) { @@ -6160,7 +6192,7 @@ DNS-over-HTTPS with IP: } } } else { - $tmp[] = "{$v['type']}, {$v['action']}"; + $tmp[] = implode(', ', $v); } } return $tmp; @@ -6184,7 +6216,7 @@ DNS-over-HTTPS with IP: foreach ($p['rulessetlist'] as $k => $v) { if (!empty($v)) { [$type, $time, $url] = explode(':', $k, 3); - if (!empty($route['rules'][$t[$type]])) { + if (preg_match('~\.srs$~', $url) && !empty($route['rules'][$t[$type]])) { $route['rule_set'][] = [ "tag" => $k, "type" => "remote", diff --git a/config/clash.json b/config/clash.json index 3180382..63ea5f0 100644 --- a/config/clash.json +++ b/config/clash.json @@ -90,6 +90,8 @@ ] } ], + "add-rule-providers": true, + "rule-providers": {}, "rules": [ { "type": "DOMAIN-SUFFIX", diff --git a/config/sing.json b/config/sing.json index f4e53fd..ebc80fe 100644 --- a/config/sing.json +++ b/config/sing.json @@ -115,7 +115,7 @@ "createruleset": [ { "name": "pac", - "interval": "15s", + "interval": "30s", "rules": [ { "domain_suffix": "~pac~" @@ -130,7 +130,7 @@ "createruleset": [ { "name": "package", - "interval": "15s", + "interval": "30s", "rules": [ { "package_name": "~package~" @@ -145,7 +145,7 @@ "createruleset": [ { "name": "process", - "interval": "15s", + "interval": "30s", "rules": [ { "process_name": "~process~" @@ -160,7 +160,7 @@ "createruleset": [ { "name": "block", - "interval": "15s", + "interval": "30s", "rules": [ { "domain_suffix": "~block~" @@ -175,7 +175,7 @@ "createruleset": [ { "name": "warp", - "interval": "15s", + "interval": "30s", "rules": [ { "domain_suffix": "~warp~" From f3f9cb5348a5ce4f923823585401242cfe1a2312 Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 6 Dec 2024 22:11:12 +0400 Subject: [PATCH 42/58] fix ruleset for mihomo --- app/bot.php | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/app/bot.php b/app/bot.php index 03d5d7e..9563f47 100644 --- a/app/bot.php +++ b/app/bot.php @@ -2580,9 +2580,9 @@ DNS-over-HTTPS with IP: case 'rulessetlist': $r = $this->send( $this->input['chat'], - "@{$this->input['username']} [direct | block | proxy]:time:URL", + "@{$this->input['username']} outbound[:behavior]:time:URL", $this->input['message_id'], - reply: '[direct | block | proxy]:time:URL', + reply: 'outbound[:behavior]:time:URL', ); break; @@ -6161,16 +6161,27 @@ DNS-over-HTTPS with IP: if (!empty($p['rulessetlist']) && $c['add-rule-providers']) { foreach ($p['rulessetlist'] as $k => $v) { if (!empty($v)) { - [$type, $time, $url] = explode(':', $k, 3); + [$type, $behavior, $time, $url] = explode(':', $k, 4); if (preg_match('~\.mrs$~', $url)) { - $c['rule-providers'][$type] = [ + $c['rule-providers'][$url] = [ 'type' => 'http', 'url' => $url, - 'interval' => $time, + 'interval' => (int) $time, + 'behavior' => $behavior, ]; - array_unshift($c['rules'], [ - 'RULE-SET', $url, strtoupper($type) - ]); + switch ($type) { + case 'reject': + array_unshift($c['rules'], [ + 'RULE-SET', $url, strtoupper($type) + ]); + break; + + default: + array_splice($c['rules'], count($c['rules']) - 1, 0, [[ + 'RULE-SET', $url, strtoupper($type) + ]]); + break; + } } } } From 3627b389b444f1a877698e872e28b8c97d9a4fff Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 6 Dec 2024 22:26:00 +0400 Subject: [PATCH 43/58] mihomo: added yaml support --- app/bot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 9563f47..6baed8e 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6162,7 +6162,7 @@ DNS-over-HTTPS with IP: foreach ($p['rulessetlist'] as $k => $v) { if (!empty($v)) { [$type, $behavior, $time, $url] = explode(':', $k, 4); - if (preg_match('~\.mrs$~', $url)) { + if (preg_match('~\.(?:mrs|yaml|yml)$~', $url)) { $c['rule-providers'][$url] = [ 'type' => 'http', 'url' => $url, From bd5e10fa239fb7972430b2935c023fecf5580fde Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 6 Dec 2024 23:12:22 +0400 Subject: [PATCH 44/58] naming: clash -> mihomo --- app/bot.php | 10 +++++----- app/i18n.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/bot.php b/app/bot.php index 6baed8e..329eeda 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5491,7 +5491,7 @@ DNS-over-HTTPS with IP: 'callback_data' => "/templates sing", ], [ - 'text' => $this->i18n('clash templates'), + 'text' => $this->i18n('mihomo templates'), 'callback_data' => "/templates clash", ], ]; @@ -5785,7 +5785,7 @@ DNS-over-HTTPS with IP: $text[] = "import://streisand"; $text[] = "import://hiddify"; $text[] = "import://karing"; - $text[] = "import://clash"; + $text[] = "import://mihomo"; $si = "$scheme://{$domain}/pac/" . base64_encode(serialize([ 'h' => $hash, @@ -5805,7 +5805,7 @@ DNS-over-HTTPS with IP: $text[] = "\nxray config:
$xr
"; $text[] = "sing-box config:
$si
"; - $text[] = "clash config:
$cl
"; + $text[] = "mihomo config:
$cl
"; $text[] = "sing-box windows: windows service"; @@ -5819,7 +5819,7 @@ DNS-over-HTTPS with IP: 'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=si&s={$c['id']}"], ], [ - 'text' => $this->i18n('clash'), + 'text' => $this->i18n('mihomo'), 'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=cl&s={$c['id']}"], ], ]; @@ -5846,7 +5846,7 @@ DNS-over-HTTPS with IP: 'callback_data' => "/templateUser sing $i", ], [ - 'text' => $this->i18n('clash') . ": $clashtemplate", + 'text' => $this->i18n('mihomo') . ": $clashtemplate", 'callback_data' => "/templateUser clash $i", ], ]; diff --git a/app/i18n.php b/app/i18n.php index facacf6..0464e94 100644 --- a/app/i18n.php +++ b/app/i18n.php @@ -262,8 +262,8 @@ $i = [ 'ru' => 'очистить', ], 'xray' => [ - 'en' => 'Xray', - 'ru' => 'Xray', + 'en' => 'Vless', + 'ru' => 'Vless', ], 'geodb' => [ 'en' => 'GeoIp/GeoSite', From e1c13480d1d32a28fee64d8c942b7485c161f7e9 Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 6 Dec 2024 23:36:43 +0400 Subject: [PATCH 45/58] mihomo: fix empty rules --- app/bot.php | 5 ++++- app/i18n.php | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index 329eeda..d47f7a0 100644 --- a/app/bot.php +++ b/app/bot.php @@ -5328,7 +5328,7 @@ DNS-over-HTTPS with IP: $pac = $this->getPacConf(); $domain = $this->getDomain(); $hash = substr(md5($this->key), 0, 8); - $text[] = "Menu -> " . $this->i18n('xray') . " -> $type templates"; + $text[] = "Menu -> " . $this->i18n('xray') . " -> " . $this->i18n($type) . " templates"; $text[] = <<~outbound~ "~pac~" @@ -6141,6 +6141,9 @@ DNS-over-HTTPS with IP: $c = $this->clashRuleSet($c); if (!empty($c['rules'])) { $c['rules'] = $this->clashRules($c['rules']); + if (count($c['rules']) == 1) { + unset($c['rules']); + } } break; } diff --git a/app/i18n.php b/app/i18n.php index 0464e94..2d2c4b5 100644 --- a/app/i18n.php +++ b/app/i18n.php @@ -265,6 +265,10 @@ $i = [ 'en' => 'Vless', 'ru' => 'Vless', ], + 'clash' => [ + 'en' => 'mihomo', + 'ru' => 'mihomo', + ], 'geodb' => [ 'en' => 'GeoIp/GeoSite', 'ru' => 'GeoIp/GeoSite', From 855f516936236b578025fdcb4fe8ae713660394b Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 6 Dec 2024 23:39:12 +0400 Subject: [PATCH 46/58] update version --- version | 2 ++ 1 file changed, 2 insertions(+) diff --git a/version b/version index f15d4ff..1ec9579 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +06.12.2024 v1.110 +- ruleset для mihomo 28.11.2024 v1.109 - фикс автоскана - добавление clash-шаблонов From 446a5d715039ae9bc3f50153a488c83b83e00bf4 Mon Sep 17 00:00:00 2001 From: mercury Date: Mon, 9 Dec 2024 13:32:25 +0400 Subject: [PATCH 47/58] mihomo: rule-providers add format --- app/bot.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/bot.php b/app/bot.php index d47f7a0..50c4626 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6165,15 +6165,17 @@ DNS-over-HTTPS with IP: foreach ($p['rulessetlist'] as $k => $v) { if (!empty($v)) { [$type, $behavior, $time, $url] = explode(':', $k, 4); - if (preg_match('~\.(?:mrs|yaml|yml)$~', $url)) { + if (preg_match('~\.(mrs|yaml|yml)$~', $url, $m)) { $c['rule-providers'][$url] = [ 'type' => 'http', 'url' => $url, 'interval' => (int) $time, 'behavior' => $behavior, + 'format' => $m[1], ]; switch ($type) { case 'reject': + case 'REJECT': array_unshift($c['rules'], [ 'RULE-SET', $url, strtoupper($type) ]); From 99bce7a9886a658bcc792b8193d01c976749dd51 Mon Sep 17 00:00:00 2001 From: mercury Date: Mon, 9 Dec 2024 14:30:26 +0400 Subject: [PATCH 48/58] update version --- version | 2 ++ 1 file changed, 2 insertions(+) diff --git a/version b/version index 1ec9579..fa64a31 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +09.12.2024 v1.111 +- mihomo: фикс rule-providers format 06.12.2024 v1.110 - ruleset для mihomo 28.11.2024 v1.109 From 18ceb51f4e5dd22c80370866479334e5811a99b2 Mon Sep 17 00:00:00 2001 From: mercury Date: Tue, 10 Dec 2024 16:28:36 +0400 Subject: [PATCH 49/58] mihomo: rules -> rule-providers update core's --- app/bot.php | 58 +++++++++++++++++++++++++++++++++++++-- config/clash.json | 54 ++++++++++++++++++++---------------- docker-compose.yml | 4 +-- dockerfile/php.dockerfile | 23 ++++++++-------- 4 files changed, 100 insertions(+), 39 deletions(-) diff --git a/app/bot.php b/app/bot.php index 50c4626..57637d8 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6138,7 +6138,8 @@ DNS-over-HTTPS with IP: } break; case 'cl': - $c = $this->clashRuleSet($c); + $c = $this->createClashRuleSet($c, $uid, $domain); + $c = $this->addClashRuleSet($c); if (!empty($c['rules'])) { $c['rules'] = $this->clashRules($c['rules']); if (count($c['rules']) == 1) { @@ -6158,7 +6159,60 @@ DNS-over-HTTPS with IP: echo json_encode($c); } - public function clashRuleSet($c) + public function createClashRuleSet($c, $uid, $domain) + { + $scheme = empty($this->nginxGetTypeCert()) ? 'http' : 'https'; + $hash = substr(md5($this->key), 0, 8); + if (!empty($c['rule-providers'])) { + foreach ($c['rule-providers'] as $k => $v) { + if (array_key_exists('list', $v)) { + if (!empty($_GET['r']) && $k == $_GET['r']) { + header("Content-Disposition: attachment; filename=$k.yaml"); + header('Content-Type: text/yaml'); + switch ($v['behavior']) { + case 'domain': + echo yaml_emit(['payload' => array_map(fn($e) => "+.$e", $v['list'])]); + break; + + default: + echo yaml_emit(['payload' => array_map(fn($e) => "PROCESS-NAME,$e", $v['list'])]); + break; + } + exit; + } + $c['rule-providers'][$k] = [ + 'type' => 'http', + 'url' => "$scheme://{$domain}/pac/" . base64_encode(serialize([ + 'h' => $hash, + 't' => 'cl', + 's' => $uid, + 'r' => $k, + ])), + 'interval' => $v['interval'], + 'behavior' => $v['behavior'], + 'format' => 'yaml', + ]; + switch ($v['action']) { + case 'reject': + case 'REJECT': + array_unshift($c['rules'], [ + 'RULE-SET', $k, strtoupper($v['action']) + ]); + break; + + default: + array_splice($c['rules'], count($c['rules']) - 1, 0, [[ + 'RULE-SET', $k, strtoupper($v['action']) + ]]); + break; + } + } + } + } + return $c; + } + + public function addClashRuleSet($c) { $p = $this->getPacConf(); if (!empty($p['rulessetlist']) && $c['add-rule-providers']) { diff --git a/config/clash.json b/config/clash.json index 63ea5f0..08cfd9e 100644 --- a/config/clash.json +++ b/config/clash.json @@ -6,7 +6,7 @@ "find-process-mode": "strict", "global-client-fingerprint": "chrome", "mode": "rule", - "log-level": "debug", + "log-level": "info", "ipv6": false, "keep-alive-interval": 30, "unified-delay": false, @@ -91,33 +91,39 @@ } ], "add-rule-providers": true, - "rule-providers": {}, - "rules": [ - { - "type": "DOMAIN-SUFFIX", + "rule-providers": { + "block": { "list": "~block~", - "action": "REJECT" + "interval": 30, + "action": "REJECT", + "behavior": "domain" }, - { - "type": "PROCESS-NAME", - "list": "~process~", - "action": "PROXY" - }, - { - "type": "PROCESS-NAME", - "list": "~package~", - "action": "PROXY" - }, - { - "type": "DOMAIN-SUFFIX", - "list": "~warp~", - "action": "PROXY" - }, - { - "type": "DOMAIN-SUFFIX", + "pac": { "list": "~pac~", - "action": "PROXY" + "interval": 30, + "action": "PROXY", + "behavior": "domain" }, + "warp": { + "list": "~warp~", + "interval": 30, + "action": "PROXY", + "behavior": "domain" + }, + "package": { + "list": "~package~", + "interval": 30, + "action": "PROXY", + "behavior": "classical" + }, + "process": { + "list": "~process~", + "interval": 30, + "action": "PROXY", + "behavior": "classical" + } + }, + "rules": [ { "type": "MATCH", "action": "DIRECT" diff --git a/docker-compose.yml b/docker-compose.yml index 8b737d2..34d9760 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -96,7 +96,7 @@ services: ipv4_address: 10.10.1.2 logging: *default-logging php: - image: mercurykd/vpnbot-php:1.6 + image: mercurykd/vpnbot-php:1.7 build: dockerfile: dockerfile/php.dockerfile args: @@ -405,7 +405,7 @@ services: ipv4_address: 10.10.0.8 logging: *default-logging xr: - image: mercurykd/vpnbot-xr:1.3 + image: mercurykd/vpnbot-xr:1.4 build: dockerfile: dockerfile/xray.dockerfile args: diff --git a/dockerfile/php.dockerfile b/dockerfile/php.dockerfile index 895c2d1..ef231a4 100644 --- a/dockerfile/php.dockerfile +++ b/dockerfile/php.dockerfile @@ -22,16 +22,17 @@ RUN apk add --no-cache --update php81 \ curl \ git \ py3-qt5 \ - && wget https://github.com/ameshkov/dnslookup/releases/download/v1.9.1/dnslookup-linux-amd64-v1.9.1.tar.gz \ - && tar -xf dnslookup-linux-amd64-v1.9.1.tar.gz \ + && mkdir /root/.ssh \ + && wget https://github.com/ameshkov/dnslookup/releases/download/v1.11.1/dnslookup-linux-amd64-v1.11.1.tar.gz \ + && tar -xf dnslookup-linux-amd64-v1.11.1.tar.gz \ && mv linux-amd64/dnslookup /usr/bin \ - && rm dnslookup-linux-amd64-v1.9.1.tar.gz \ + && rm dnslookup-linux-amd64-v1.11.1.tar.gz \ && rm -rf /linux-amd64 \ - && wget https://github.com/SagerNet/sing-box/releases/download/v1.8.11/sing-box-1.8.11-linux-amd64.tar.gz \ - && tar -xf sing-box-1.8.11-linux-amd64.tar.gz \ - && mv sing-box-1.8.11-linux-amd64/sing-box /usr/bin \ - && rm sing-box-1.8.11-linux-amd64.tar.gz \ - && rm -rf /sing-box-1.8.11-linux-amd64 -RUN apk add openssh \ - && mkdir /root/.ssh - ENV ENV="/root/.ashrc" + && wget https://github.com/SagerNet/sing-box/releases/download/v1.10.3/sing-box-1.10.3-linux-amd64.tar.gz \ + && tar -xf sing-box-1.10.3-linux-amd64.tar.gz \ + && mv sing-box-1.10.3-linux-amd64/sing-box /usr/bin \ + && rm sing-box-1.10.3-linux-amd64.tar.gz \ + && rm -rf /sing-box-1.10.3-linux-amd64 \ + && wget https://github.com/MetaCubeX/mihomo/releases/download/v1.18.10/mihomo-linux-amd64-v1.18.10.gz \ + && gunzip mihomo-linux-amd64-v1.18.10.gz \ + && mv mihomo-linux-amd64-v1.18.10 /usr/bin/mihomo \ No newline at end of file From 3e530000658e996323ea28fe3e8f42013e42cc53 Mon Sep 17 00:00:00 2001 From: mercury Date: Tue, 10 Dec 2024 17:16:05 +0400 Subject: [PATCH 50/58] update version --- version | 3 +++ 1 file changed, 3 insertions(+) diff --git a/version b/version index fa64a31..0baf662 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +10.12.2024 v1.112 +- mihomo: встроенные списки теперь отдаются через rule-providers(т.е подгружаются ядром без обновления конфига) +- обновлены ядра 09.12.2024 v1.111 - mihomo: фикс rule-providers format 06.12.2024 v1.110 From 3349e3b306da3b0e918fdde1bed9baf1037b4993 Mon Sep 17 00:00:00 2001 From: mercury Date: Tue, 10 Dec 2024 22:55:17 +0400 Subject: [PATCH 51/58] mihomo: new rule-set generation scheme --- app/bot.php | 103 ++++++++++++++++++---------------------------- config/clash.json | 73 ++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 94 deletions(-) diff --git a/app/bot.php b/app/bot.php index 57637d8..a336765 100644 --- a/app/bot.php +++ b/app/bot.php @@ -6138,10 +6138,9 @@ DNS-over-HTTPS with IP: } break; case 'cl': - $c = $this->createClashRuleSet($c, $uid, $domain); $c = $this->addClashRuleSet($c); if (!empty($c['rules'])) { - $c['rules'] = $this->clashRules($c['rules']); + $c = $this->clashRules($c, $uid, $domain); if (count($c['rules']) == 1) { unset($c['rules']); } @@ -6159,59 +6158,6 @@ DNS-over-HTTPS with IP: echo json_encode($c); } - public function createClashRuleSet($c, $uid, $domain) - { - $scheme = empty($this->nginxGetTypeCert()) ? 'http' : 'https'; - $hash = substr(md5($this->key), 0, 8); - if (!empty($c['rule-providers'])) { - foreach ($c['rule-providers'] as $k => $v) { - if (array_key_exists('list', $v)) { - if (!empty($_GET['r']) && $k == $_GET['r']) { - header("Content-Disposition: attachment; filename=$k.yaml"); - header('Content-Type: text/yaml'); - switch ($v['behavior']) { - case 'domain': - echo yaml_emit(['payload' => array_map(fn($e) => "+.$e", $v['list'])]); - break; - - default: - echo yaml_emit(['payload' => array_map(fn($e) => "PROCESS-NAME,$e", $v['list'])]); - break; - } - exit; - } - $c['rule-providers'][$k] = [ - 'type' => 'http', - 'url' => "$scheme://{$domain}/pac/" . base64_encode(serialize([ - 'h' => $hash, - 't' => 'cl', - 's' => $uid, - 'r' => $k, - ])), - 'interval' => $v['interval'], - 'behavior' => $v['behavior'], - 'format' => 'yaml', - ]; - switch ($v['action']) { - case 'reject': - case 'REJECT': - array_unshift($c['rules'], [ - 'RULE-SET', $k, strtoupper($v['action']) - ]); - break; - - default: - array_splice($c['rules'], count($c['rules']) - 1, 0, [[ - 'RULE-SET', $k, strtoupper($v['action']) - ]]); - break; - } - } - } - } - return $c; - } - public function addClashRuleSet($c) { $p = $this->getPacConf(); @@ -6252,20 +6198,53 @@ DNS-over-HTTPS with IP: return $c; } - public function clashRules($rules) + public function clashRules($c, $uid, $domain) { - foreach ($rules as $v) { - if (isset($v['list'])) { - if (!empty($v['list'])) { - foreach ($v['list'] as $j) { - $tmp[] = "{$v['type']}, $j, {$v['action']}"; + $scheme = empty($this->nginxGetTypeCert()) ? 'http' : 'https'; + $hash = substr(md5($this->key), 0, 8); + foreach ($c['rules'] as $v) { + if (array_key_exists('list', $v)) { + if ($v['type'] == 'RULE-SET') { + if (!empty($_GET['r']) && $v['name'] == $_GET['r']) { + header("Content-Disposition: attachment; filename={$v['name']}.yaml"); + header('Content-Type: text/yaml'); + switch ($v['behavior']) { + case 'domain': + echo yaml_emit(['payload' => array_map(fn($e) => "+.$e", $v['list'])]); + break; + + default: + echo yaml_emit(['payload' => array_map(fn($e) => "PROCESS-NAME,$e", $v['list'])]); + break; + } + exit; + } + $c['rule-providers'][$v['name']] = [ + 'type' => 'http', + 'url' => "$scheme://{$domain}/pac/" . base64_encode(serialize([ + 'h' => $hash, + 't' => 'cl', + 's' => $uid, + 'r' => $v['name'], + ])), + 'interval' => $v['interval'], + 'behavior' => $v['behavior'], + 'format' => 'yaml', + ]; + $tmp[] = "{$v['type']}, {$v['name']}, {$v['action']}"; + } else { + if (!empty($v['list'])) { + foreach ($v['list'] as $j) { + $tmp[] = "{$v['type']}, $j, {$v['action']}"; + } } } } else { $tmp[] = implode(', ', $v); } } - return $tmp; + $c['rules'] = $tmp; + return $c; } public function replaceTags($subject, $tags) diff --git a/config/clash.json b/config/clash.json index 08cfd9e..84d8b78 100644 --- a/config/clash.json +++ b/config/clash.json @@ -91,39 +91,48 @@ } ], "add-rule-providers": true, - "rule-providers": { - "block": { - "list": "~block~", - "interval": 30, - "action": "REJECT", - "behavior": "domain" - }, - "pac": { - "list": "~pac~", - "interval": 30, - "action": "PROXY", - "behavior": "domain" - }, - "warp": { - "list": "~warp~", - "interval": 30, - "action": "PROXY", - "behavior": "domain" - }, - "package": { - "list": "~package~", - "interval": 30, - "action": "PROXY", - "behavior": "classical" - }, - "process": { - "list": "~process~", - "interval": 30, - "action": "PROXY", - "behavior": "classical" - } - }, + "rule-providers": {}, "rules": [ + { + "type": "RULE-SET", + "list": "~block~", + "action": "REJECT", + "interval": 30, + "behavior": "domain", + "name": "block" + }, + { + "type": "RULE-SET", + "list": "~process~", + "action": "PROXY", + "interval": 30, + "behavior": "domain", + "name": "process" + }, + { + "type": "RULE-SET", + "list": "~package~", + "action": "PROXY", + "interval": 30, + "behavior": "domain", + "name": "package" + }, + { + "type": "RULE-SET", + "list": "~warp~", + "action": "PROXY", + "interval": 30, + "behavior": "domain", + "name": "warp" + }, + { + "type": "RULE-SET", + "list": "~pac~", + "action": "PROXY", + "interval": 30, + "behavior": "domain", + "name": "pac" + }, { "type": "MATCH", "action": "DIRECT" From 270968e4ac38031c97ee6a2bf04c30c1b6f822df Mon Sep 17 00:00:00 2001 From: legiz-ru Date: Wed, 11 Dec 2024 00:32:11 +0300 Subject: [PATCH 52/58] fix behavior clash.json --- config/clash.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/clash.json b/config/clash.json index 84d8b78..8365167 100644 --- a/config/clash.json +++ b/config/clash.json @@ -106,7 +106,7 @@ "list": "~process~", "action": "PROXY", "interval": 30, - "behavior": "domain", + "behavior": "classical", "name": "process" }, { @@ -114,7 +114,7 @@ "list": "~package~", "action": "PROXY", "interval": 30, - "behavior": "domain", + "behavior": "classical", "name": "package" }, { From a1778e6be8d8bdc6add36b85b8db3a995e197494 Mon Sep 17 00:00:00 2001 From: legiz-ru Date: Thu, 12 Dec 2024 13:26:33 +0300 Subject: [PATCH 53/58] Update readme.md --- readme.md | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/readme.md b/readme.md index 8aa9fc7..e5d4a60 100644 --- a/readme.md +++ b/readme.md @@ -1,28 +1,37 @@ telegram bot to manage servers (inside the bot) - + -### XTLS-Reality +### VLESS (Reality OR Websocket) - change secret - qr/config - change fake domain - multiple users -- subscriptions with routing +- subscriptions with routing (xray, sing-box, mihomo) - routing templates per user +- routing via rulesets (sing-box, mihomo) - steal from yourself - +- add domains to warp + +### Main menu VLESS: + + +### User menu VLESS: + ### NaiveProxy - change login - change password - + ### OpenConnect - change secret - change password - change dns - add user - +- add ip subnet +- expose-iroutes (lan between users) + ### Wireguard / Amnezia - create @@ -31,31 +40,38 @@ telegram bot to manage servers (inside the bot) - timer - torrent blocking - qr/config +- AmneziaVPN vpn:// link - statistics - - + + ### Shadowsocks + v2ray - change password - on/off v2ray - qr - short link - + ### AdguardHome - change password - change upstream dns - check dns - +- check safesearch +- add custom clientID for DNSoverTLS (DOT) +- fill allowed clients (WG/AWG + OpenConnect + VLESS) +- custom ID for each user VLESS + ### PAC - the ability to create your own PAC available by url with the ability to substitute the final ip and port - +- Shadowsocks Android PAC +- add [antifilter-community](https://community.antifilter.download/) or [ru-bundle](https://github.com/legiz-ru/sb-rule-sets/blob/main/ru-bundle.lst) domain lists + ### MTProto - change secret - qr/config - + ### Settings - add/change admin @@ -63,10 +79,12 @@ telegram bot to manage servers (inside the bot) - import/export all settings - domain binding - obtain ssl for domain - +- fake html for domain +- ports block + --- -environment: ubuntu 18.04/20.04/22.04, debian 11/12 +environment: ubuntu 22.04/24.04, debian 11/12 ### Install: From 32e49088c2f7fb63b03d22a79166feebe03b007e Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 12 Dec 2024 23:21:17 +0400 Subject: [PATCH 54/58] fix delete upstream --- app/bot.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/bot.php b/app/bot.php index a336765..0166486 100644 --- a/app/bot.php +++ b/app/bot.php @@ -2554,6 +2554,7 @@ DNS-over-HTTPS with IP: $this->stopAd(); $c = yaml_parse_file($this->adguard); unset($c['dns']['upstream_dns'][$k]); + $c['dns']['upstream_dns'] = array_values($c['dns']['upstream_dns']); yaml_emit_file($this->adguard, $c); $this->startAd(); $this->menu('adguard'); From 8c65f8e538332d0c6af3cbaed13e9fe2b9dd4497 Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 13 Dec 2024 01:24:59 +0400 Subject: [PATCH 55/58] update adguardhome version --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 34d9760..4b289d4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -307,7 +307,7 @@ services: ipv4_address: 10.10.0.14 logging: *default-logging ad: - image: mercurykd/vpnbot-ad:1.2 + image: mercurykd/vpnbot-ad:1.3 build: dockerfile: dockerfile/adguard.dockerfile args: From 09a0f778634d17d3413dabd3f8794d5e63005d0c Mon Sep 17 00:00:00 2001 From: mercury Date: Fri, 13 Dec 2024 16:00:03 +0400 Subject: [PATCH 56/58] update version --- version | 3 +++ 1 file changed, 3 insertions(+) diff --git a/version b/version index 0baf662..204b18a 100644 --- a/version +++ b/version @@ -1,3 +1,6 @@ +13.12.2024 v1.113 +- обновлен adguardHome +- фикс краша adg при удалении dns-upstream из бота 10.12.2024 v1.112 - mihomo: встроенные списки теперь отдаются через rule-providers(т.е подгружаются ядром без обновления конфига) - обновлены ядра From b49f088256968796fb30992de900465974b08e5b Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 19 Dec 2024 00:15:41 +0400 Subject: [PATCH 57/58] fix default password for shadowsocks --- config/sslocal.json | 2 +- config/ssserver.json | 2 +- version | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/sslocal.json b/config/sslocal.json index 4c854d4..684d61b 100644 --- a/config/sslocal.json +++ b/config/sslocal.json @@ -3,7 +3,7 @@ "server_port": 8388, "local_address": "0.0.0.0", "local_port": 1080, - "password": "test", + "password": "", "timeout": 120, "method": "chacha20-ietf-poly1305", "no_delay": true, diff --git a/config/ssserver.json b/config/ssserver.json index e25df79..5d35fc8 100644 --- a/config/ssserver.json +++ b/config/ssserver.json @@ -1,7 +1,7 @@ { "server": "0.0.0.0", "server_port": 8388, - "password": "test", + "password": "", "timeout": 120, "method": "chacha20-ietf-poly1305", "no_delay": true, diff --git a/version b/version index 204b18a..3404799 100644 --- a/version +++ b/version @@ -1,3 +1,5 @@ +14.12.2024 v1.114 +- убран дефолтный пароль у shadowsocks 13.12.2024 v1.113 - обновлен adguardHome - фикс краша adg при удалении dns-upstream из бота From 90084c37ff806b056aa284dbdb5a3c9ed0ae3d10 Mon Sep 17 00:00:00 2001 From: mercury Date: Thu, 19 Dec 2024 01:13:31 +0400 Subject: [PATCH 58/58] shadowsocks password generation --- app/bot.php | 16 ++++++++++++++-- app/service.php | 1 + version | 4 +++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/bot.php b/app/bot.php index 0166486..121e9fe 100644 --- a/app/bot.php +++ b/app/bot.php @@ -802,6 +802,14 @@ class Bot ]; } + public function ssPswdCheck() + { + $c = $this->getSSConfig(); + if (empty($c['password']) || ($c['password'] == 'test')) { + $this->sspwdch(password_hash(time(), PASSWORD_DEFAULT), 1); + } + } + public function changeCamouflage() { $r = $this->send( @@ -1024,7 +1032,7 @@ class Bot $this->menu('oc'); } - public function sspwdch($pass) + public function sspwdch($pass, $nomenu = false) { $this->ssh('pkill sslocal', 'proxy'); $this->ssh('pkill ssserver', 'ss'); @@ -1035,7 +1043,11 @@ class Bot file_put_contents('/config/sslocal.json', json_encode($l, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); $this->ssh('ssserver -v -d -c /config.json', 'ss'); $this->ssh('sslocal -v -d -c /config.json', 'proxy'); - $this->menu('ss'); + + $this->sd($c, 1); + if (!empty($nomenu)) { + $this->menu('ss'); + } } public function v2ray() diff --git a/app/service.php b/app/service.php index 63e9cc1..58e00a4 100644 --- a/app/service.php +++ b/app/service.php @@ -13,6 +13,7 @@ if ($c['debug']) { $bot = new Bot($c['key'], $i); $bot->selfUpdate(); +$bot->ssPswdCheck(); $bot->restartTG(); if (!empty($bot->selfupdate)) { $bot->offWarp(); diff --git a/version b/version index 3404799..2bbb289 100644 --- a/version +++ b/version @@ -1,4 +1,6 @@ -14.12.2024 v1.114 +19.12.2024 v1.115 +- генерация устойчивого пароля shadowsocks, если он равен test или пуст +19.12.2024 v1.114 - убран дефолтный пароль у shadowsocks 13.12.2024 v1.113 - обновлен adguardHome