Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b49f088256 | |||
| 09a0f77863 | |||
| 8c65f8e538 | |||
| 32e49088c2 | |||
| f666762dfa | |||
| a1778e6be8 | |||
| 4b61e38b6b | |||
| 270968e4ac | |||
| 3349e3b306 | |||
| 3e53000065 | |||
| 18ceb51f4e | |||
| 99bce7a988 | |||
| 446a5d7150 | |||
| 855f516936 | |||
| e1c13480d1 | |||
| bd5e10fa23 | |||
| 3627b389b4 | |||
| f3f9cb5348 | |||
| 1527b9f856 | |||
| f896b307ea | |||
| 8ba7ddedee | |||
| 19ef567873 | |||
| 4f4e36e1cb | |||
| 6267931475 | |||
| 7e2d90e7da | |||
| 28906176f5 | |||
| 968d72ce81 | |||
| 66e204e5ba | |||
| 36e8acd2aa | |||
| cdc20adccd |
+282
-139
@@ -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',
|
||||
@@ -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) {
|
||||
@@ -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');
|
||||
@@ -2580,9 +2581,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;
|
||||
|
||||
@@ -3130,9 +3131,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) {
|
||||
@@ -3828,12 +3826,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 +3878,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 +3898,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'),
|
||||
@@ -4413,6 +4393,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);
|
||||
@@ -5338,10 +5329,14 @@ 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[] = <<<TEXT
|
||||
<code>~outbound~</code>
|
||||
<code>"~pac~"</code>
|
||||
<code>~package~</code>
|
||||
<code>~process~</code>
|
||||
<code>~block~</code>
|
||||
<code>~warp~</code>
|
||||
<code>~dns~</code>
|
||||
<code>~uid~</code>
|
||||
<code>~domain~</code>
|
||||
@@ -5350,10 +5345,6 @@ DNS-over-HTTPS with IP:
|
||||
<code>~short_id~</code>
|
||||
<code>~public_key~</code>
|
||||
<code>~server_name~</code>
|
||||
<code>~app_outbound~</code>
|
||||
<code>~process_outbound~</code>
|
||||
<code>~domains_outbound~</code>
|
||||
<code>~final_outbound~</code>
|
||||
<code>~ip~</code>
|
||||
TEXT;
|
||||
$templates = $pac["{$type}templates"];
|
||||
@@ -5500,6 +5491,10 @@ DNS-over-HTTPS with IP:
|
||||
'text' => $this->i18n('sing-box templates'),
|
||||
'callback_data' => "/templates sing",
|
||||
],
|
||||
[
|
||||
'text' => $this->i18n('mihomo templates'),
|
||||
'callback_data' => "/templates clash",
|
||||
],
|
||||
];
|
||||
$data[] = [
|
||||
[
|
||||
@@ -5589,24 +5584,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[] = [
|
||||
@@ -5795,6 +5786,7 @@ DNS-over-HTTPS with IP:
|
||||
$text[] = "<a href='$scheme://{$domain}/pac?h=$hash&t=s&r=st&s={$c['id']}#{$c['email']}'>import://streisand</a>";
|
||||
$text[] = "<a href='$scheme://{$domain}/pac?h=$hash&t=si&r=h&s={$c['id']}#{$c['email']}'>import://hiddify</a>";
|
||||
$text[] = "<a href='$scheme://{$domain}/pac?h=$hash&t=si&r=k&s={$c['id']}#{$c['email']}'>import://karing</a>";
|
||||
$text[] = "<a href='$scheme://{$domain}/pac?h=$hash&t=si&r=c&s={$c['id']}#{$c['email']}'>import://mihomo</a>";
|
||||
|
||||
$si = "$scheme://{$domain}/pac/" . base64_encode(serialize([
|
||||
'h' => $hash,
|
||||
@@ -5806,21 +5798,31 @@ 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: <pre><code>$xr</code></pre>";
|
||||
$text[] = "sing-box config: <pre><code>$si</code></pre>";
|
||||
$text[] = "mihomo config: <pre><code>$cl</code></pre>";
|
||||
|
||||
$text[] = "sing-box windows: <a href='$scheme://{$domain}/pac?h=$hash&t=si&r=w&s={$c['id']}'>windows service</a>";
|
||||
|
||||
$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('mihomo'),
|
||||
'web_app' => ['url' => "https://{$domain}/pac?h=$hash&t=cl&s={$c['id']}"],
|
||||
],
|
||||
];
|
||||
$data[] = [
|
||||
[
|
||||
@@ -5834,6 +5836,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",
|
||||
@@ -5843,6 +5846,10 @@ DNS-over-HTTPS with IP:
|
||||
'text' => $this->i18n('singbox') . ": $singtemplate",
|
||||
'callback_data' => "/templateUser sing $i",
|
||||
],
|
||||
[
|
||||
'text' => $this->i18n('mihomo') . ": $clashtemplate",
|
||||
'callback_data' => "/templateUser clash $i",
|
||||
],
|
||||
];
|
||||
$data[] = [
|
||||
[
|
||||
@@ -5893,7 +5900,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();
|
||||
@@ -5927,6 +5944,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");
|
||||
@@ -5943,6 +5965,9 @@ DNS-over-HTTPS with IP:
|
||||
case 'h':
|
||||
header("Location: hiddify://install-config/?url=$si");
|
||||
exit;
|
||||
case 'c':
|
||||
header("Location: clash://install-config/?url=$cl&name=$email");
|
||||
exit;
|
||||
case 'w':
|
||||
$link = htmlspecialchars($si, ENT_XML1, 'UTF-8');
|
||||
$n = "singbox_$uid.zip";
|
||||
@@ -5983,6 +6008,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':
|
||||
@@ -6041,32 +6074,178 @@ DNS-over-HTTPS with IP:
|
||||
$c['outbounds'][$index]['tls']['server_name'] = '~server_name~';
|
||||
$c['outbounds'][$index]['tls']['reality']['short_id'] = '~short_id~';
|
||||
}
|
||||
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':
|
||||
$c = $this->addClashRuleSet($c);
|
||||
if (!empty($c['rules'])) {
|
||||
$c = $this->clashRules($c, $uid, $domain);
|
||||
if (count($c['rules']) == 1) {
|
||||
unset($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],
|
||||
'~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);
|
||||
$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 addClashRuleSet($c)
|
||||
{
|
||||
$p = $this->getPacConf();
|
||||
if (!empty($p['rulessetlist']) && $c['add-rule-providers']) {
|
||||
foreach ($p['rulessetlist'] as $k => $v) {
|
||||
if (!empty($v)) {
|
||||
[$type, $behavior, $time, $url] = explode(':', $k, 4);
|
||||
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)
|
||||
]);
|
||||
break;
|
||||
|
||||
default:
|
||||
array_splice($c['rules'], count($c['rules']) - 1, 0, [[
|
||||
'RULE-SET', $url, strtoupper($type)
|
||||
]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($c['add-rule-providers']);
|
||||
if (empty($c['rule-providers'])) {
|
||||
unset($c['rule-providers']);
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
public function clashRules($c, $uid, $domain)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
}
|
||||
$c['rules'] = $tmp;
|
||||
return $c;
|
||||
}
|
||||
|
||||
public function replaceTags($subject, $tags)
|
||||
@@ -6074,33 +6253,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;
|
||||
}
|
||||
@@ -6110,8 +6266,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 (preg_match('~\.srs$~', $url) && !empty($route['rules'][$t[$type]])) {
|
||||
$route['rule_set'][] = [
|
||||
"tag" => $k,
|
||||
"type" => "remote",
|
||||
"format" => "binary",
|
||||
@@ -6119,73 +6275,60 @@ 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 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);
|
||||
|
||||
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');
|
||||
$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'],
|
||||
|
||||
+6
-2
@@ -262,8 +262,12 @@ $i = [
|
||||
'ru' => 'очистить',
|
||||
],
|
||||
'xray' => [
|
||||
'en' => 'Xray',
|
||||
'ru' => 'Xray',
|
||||
'en' => 'Vless',
|
||||
'ru' => 'Vless',
|
||||
],
|
||||
'clash' => [
|
||||
'en' => 'mihomo',
|
||||
'ru' => 'mihomo',
|
||||
],
|
||||
'geodb' => [
|
||||
'en' => 'GeoIp/GeoSite',
|
||||
|
||||
@@ -37,6 +37,7 @@ if ($hash == substr(md5($c['key']), 0, 8)) {
|
||||
break;
|
||||
case 's':
|
||||
case 'si':
|
||||
case 'cl':
|
||||
$bot->subscription();
|
||||
exit;
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"mixed-port": 2080,
|
||||
"allow-lan": true,
|
||||
"tcp-concurrent": true,
|
||||
"enable-process": true,
|
||||
"find-process-mode": "strict",
|
||||
"global-client-fingerprint": "chrome",
|
||||
"mode": "rule",
|
||||
"log-level": "info",
|
||||
"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~"
|
||||
]
|
||||
}
|
||||
],
|
||||
"add-rule-providers": true,
|
||||
"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": "classical",
|
||||
"name": "process"
|
||||
},
|
||||
{
|
||||
"type": "RULE-SET",
|
||||
"list": "~package~",
|
||||
"action": "PROXY",
|
||||
"interval": 30,
|
||||
"behavior": "classical",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
+9
-13
@@ -115,7 +115,7 @@
|
||||
"createruleset": [
|
||||
{
|
||||
"name": "pac",
|
||||
"interval": "15s",
|
||||
"interval": "30s",
|
||||
"rules": [
|
||||
{
|
||||
"domain_suffix": "~pac~"
|
||||
@@ -123,14 +123,14 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"outbound": "~domains_outbound~"
|
||||
"outbound": "~outbound~"
|
||||
},
|
||||
{
|
||||
"addruleset": true,
|
||||
"createruleset": [
|
||||
{
|
||||
"name": "package",
|
||||
"interval": "15s",
|
||||
"interval": "30s",
|
||||
"rules": [
|
||||
{
|
||||
"package_name": "~package~"
|
||||
@@ -138,14 +138,14 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"outbound": "~app_outbound~"
|
||||
"outbound": "~outbound~"
|
||||
},
|
||||
{
|
||||
"addruleset": true,
|
||||
"createruleset": [
|
||||
{
|
||||
"name": "process",
|
||||
"interval": "15s",
|
||||
"interval": "30s",
|
||||
"rules": [
|
||||
{
|
||||
"process_name": "~process~"
|
||||
@@ -153,14 +153,14 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"outbound": "~process_outbound~"
|
||||
"outbound": "~outbound~"
|
||||
},
|
||||
{
|
||||
"addruleset": true,
|
||||
"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~"
|
||||
@@ -184,12 +184,8 @@
|
||||
}
|
||||
],
|
||||
"outbound": "~outbound~"
|
||||
},
|
||||
{
|
||||
"addruleset": true,
|
||||
"outbound": "direct"
|
||||
}
|
||||
],
|
||||
"final": "~final_outbound~"
|
||||
"final": "direct"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"server": "0.0.0.0",
|
||||
"server_port": 8388,
|
||||
"password": "test",
|
||||
"password": "",
|
||||
"timeout": 120,
|
||||
"method": "chacha20-ietf-poly1305",
|
||||
"no_delay": true,
|
||||
|
||||
+3
-3
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
|
||||
+12
-11
@@ -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
|
||||
@@ -1,28 +1,37 @@
|
||||
telegram bot to manage servers (inside the bot)
|
||||
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/d5a81237-5215-41db-87e5-20734120cc9c" width="200">
|
||||
<img src="https://github.com/user-attachments/assets/ec5faa51-987c-461a-a973-d94c7edf7115" width="300">
|
||||
|
||||
### 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
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/39bdf4e0-96a6-4257-b61e-30a14122e236" width="200">
|
||||
- add domains to warp
|
||||
|
||||
### Main menu VLESS:
|
||||
<img src="https://github.com/user-attachments/assets/80d2f671-fade-4819-a96a-efa253741ffd" width="300">
|
||||
|
||||
### User menu VLESS:
|
||||
<img src="https://github.com/user-attachments/assets/5c3c5b5e-1931-4e98-a472-d303bac61a4e" width="300">
|
||||
|
||||
### NaiveProxy
|
||||
- change login
|
||||
- change password
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/2127a4af-0436-452c-bfe2-c750dd5dbc06" width="200">
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/2127a4af-0436-452c-bfe2-c750dd5dbc06" width="300">
|
||||
|
||||
### OpenConnect
|
||||
- change secret
|
||||
- change password
|
||||
- change dns
|
||||
- add user
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/a4ffc04f-965a-439b-862b-210b98e1f87d" width="200">
|
||||
- add ip subnet
|
||||
- expose-iroutes (lan between users)
|
||||
<img src="https://github.com/user-attachments/assets/c3a8a78e-fe99-423c-a626-610b333a2a56" width="300">
|
||||
|
||||
### Wireguard / Amnezia
|
||||
- create
|
||||
@@ -31,31 +40,38 @@ telegram bot to manage servers (inside the bot)
|
||||
- timer
|
||||
- torrent blocking
|
||||
- qr/config
|
||||
- AmneziaVPN vpn:// link
|
||||
- statistics
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/51a79c93-8083-40ba-a14b-a6ef19f00531" width="200">
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/fd6ffd9f-bd75-479c-8dca-ea6c0b938b6c" width="200">
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/51a79c93-8083-40ba-a14b-a6ef19f00531" width="300">
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/fd6ffd9f-bd75-479c-8dca-ea6c0b938b6c" width="300">
|
||||
|
||||
### Shadowsocks + v2ray
|
||||
- change password
|
||||
- on/off v2ray
|
||||
- qr
|
||||
- short link
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/fbe39617-63ae-4536-8ab0-e4269ed8784a" width="200">
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/fbe39617-63ae-4536-8ab0-e4269ed8784a" width="300">
|
||||
|
||||
### AdguardHome
|
||||
- change password
|
||||
- change upstream dns
|
||||
- check dns
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/a7d4ba52-494b-429f-a3e2-08c68c8353c4" width="200">
|
||||
- check safesearch
|
||||
- add custom clientID for DNSoverTLS (DOT)
|
||||
- fill allowed clients (WG/AWG + OpenConnect + VLESS)
|
||||
- custom ID for each user VLESS
|
||||
<img src="https://github.com/user-attachments/assets/1dcdd9f9-f781-4ec2-8e32-01ce6095e0a3" width="300">
|
||||
|
||||
### PAC
|
||||
- the ability to create your own PAC available by url with the ability to substitute the final ip and port
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/5343e009-1b21-450f-918d-b811b98a0549" width="200">
|
||||
- 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
|
||||
<img src="https://github.com/user-attachments/assets/8d039dbb-6478-43a8-811a-4279e766c884" width="300">
|
||||
|
||||
### MTProto
|
||||
- change secret
|
||||
- qr/config
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/411696d8-172a-4dac-b6b7-4a6da3adfab2" width="200">
|
||||
<img src="https://github.com/user-attachments/assets/d37b2e1c-f991-4e1c-8060-1b547eea8fe2" width="300">
|
||||
|
||||
### 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
|
||||
<img src="https://github.com/mercurykd/vpnbot/assets/30900414/431ec09d-9c14-4c74-b8f6-e49c142132e8" width="200">
|
||||
- fake html for domain
|
||||
- ports block
|
||||
<img src="https://github.com/user-attachments/assets/82b78014-eaa2-4b4c-bc90-77f58d03d57c" width="300">
|
||||
|
||||
---
|
||||
environment: ubuntu 18.04/20.04/22.04, debian 11/12
|
||||
environment: ubuntu 22.04/24.04, debian 11/12
|
||||
|
||||
### Install:
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
14.12.2024 v1.114
|
||||
- убран дефолтный пароль у shadowsocks
|
||||
13.12.2024 v1.113
|
||||
- обновлен adguardHome
|
||||
- фикс краша adg при удалении dns-upstream из бота
|
||||
10.12.2024 v1.112
|
||||
- mihomo: встроенные списки теперь отдаются через rule-providers(т.е подгружаются ядром без обновления конфига)
|
||||
- обновлены ядра
|
||||
09.12.2024 v1.111
|
||||
- mihomo: фикс rule-providers format
|
||||
06.12.2024 v1.110
|
||||
- ruleset для mihomo
|
||||
28.11.2024 v1.109
|
||||
- фикс автоскана
|
||||
- добавление clash-шаблонов
|
||||
21.11.2024 v1.108
|
||||
- xray: addruleset для direct
|
||||
- openconnect:ограничение формата при добавлении подсети
|
||||
|
||||
Reference in New Issue
Block a user