calc CIDR for wireguard

This commit is contained in:
mercury
2023-06-04 14:57:41 +04:00
parent 621f4e7541
commit d9f177fdb6
4 changed files with 146 additions and 0 deletions
+62
View File
@@ -135,6 +135,9 @@ class Bot
case preg_match('~^/changeAllowedIps (?P<arg>\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m):
$this->changeAllowedIps(...explode('_', $m['arg']));
break;
case preg_match('~^/calc (?P<arg>\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m):
$this->calc(...explode('_', $m['arg']));
break;
case preg_match('~^/changeIps (?P<arg>\w+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m):
$this->changeIps(...explode('_', $m['arg']));
break;
@@ -1497,9 +1500,68 @@ DNS-over-HTTPS with IP:
$this->subnet($page);
}
public function calc($page)
{
$r = $this->send(
$this->input['chat'],
"@{$this->input['username']} enter like '10.0.0.0/24, -10.0.0.5/32'",
$this->input['message_id'],
reply: 'enter like \'10.0.0.0/24, -10.0.0.5/32\'',
);
$_SESSION['reply'][$r['result']['message_id']] = [
'start_message' => $this->input['message_id'],
'start_callback' => $this->input['callback_id'],
'callback' => 'calcSubnet',
'args' => [$page],
];
}
public function calcSubnet($text)
{
$text = explode(',', $text);
$text = array_map(fn ($e) => trim($e), $text);
if (!empty($text)) {
foreach ($text as $k => $v) {
if (preg_match('~^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}~', $v)) {
$include[] = $v;
}
if (preg_match('~^-(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2})~', $v, $m)) {
$exclude[] = $m[1];
}
}
}
if (!empty($include)) {
foreach ($include as $k => $v) {
$t = explode('/', $v);
$include[$k] = [ip2long($t[0]), ip2long($t[0]) + (1 << (32 - $t[1])) - 1];
}
if (!empty($exclude)) {
foreach ($exclude as $k => $v) {
$t = explode('/', $v);
$exclude[$k] = [ip2long($t[0]), ip2long($t[0]) + (1 << (32 - $t[1])) - 1];
}
}
$c = new Calc();
$r = $c->prepare($include, $exclude ?: []);
if (!empty($r)) {
$t = [];
foreach ($r as $k => $v) {
$t = array_merge($t, $c->toCIDR($v[0], $v[1]));
}
$this->send($this->input['chat'], '<pre>' . implode(', ', $t) . '</pre>');
}
}
}
public function subnet($page = 0, $count = 5)
{
$text = "Menu -> Wireguard -> " . $this->i18n('listSubnet') . "\n";
$data[] = [
[
'text' => $this->i18n('calc'),
'callback_data' => "/calc $page",
],
];
$data[] = [
[
'text' => $this->i18n('add'),
+79
View File
@@ -0,0 +1,79 @@
<?php
class Calc
{
public function merge(array $a, array $b): array
{
if ($b[0] > $a[1] + 1) {
$tmp = [$a, $b];
} elseif ($b[1] <= $a[1]) {
$tmp = [$a];
} else {
$tmp = [[$a[0], $b[1]]];
}
return array_filter($tmp);
}
public function substract(array $a, array $b): array
{
if ($b[0] > $a[1] || $b[1] < $a[0]) {
return [$a];
} elseif ($b[0] <= $a[0] && $b[1] >= $a[1]) {
return [];
} elseif ($b[0] > $a[0] && $b[1] < $a[1]) {
return [[$a[0], $b[0] - 1], [$b[1] + 1, $a[1]]];
} elseif ($b[0] <= $a[0]) {
return [$b[1] + 1, $a[1]];
} else {
return [$a[0], $b[1] - 1];
}
}
public function alignment(array $arr): array
{
usort($arr, fn ($a, $b) => $a[0] <=> $b[0]);
$tmp = [[]];
foreach ($arr as $k => $v) {
$t = array_pop($tmp);
$tmp = array_merge($tmp, $this->merge($t, $v));
}
return $tmp;
}
public function prepare(array $include, array $exclude): array
{
$include = $this->alignment($include);
if (!empty($exclude)) {
$tmp = [];
$exclude = $this->alignment($exclude);
foreach ($exclude as $k => $v) {
foreach ($include as $i => $j) {
$tmp = array_merge($tmp, $this->substract($j, $v));
}
$d = array_filter($tmp);
}
return $tmp;
}
return $include;
}
public function toCIDR(int $a, int $b)
{
$diff = $b - $a + 1;
if ($diff > 1) {
for ($i = 0; $i <= 32; $i++) {
if ($diff / (1 << $i) < 1) {
break;
}
}
$tmp[] = long2ip($a) . "/" . (32 - $i + 1);
$new = $a + (1 << ($i - 1));
if ($new <= $b) {
$tmp = array_merge($tmp, $this->toCIDR($new, $b));
}
} else {
$tmp[] = long2ip($a) . "/32";
}
return $tmp;
}
}
+4
View File
@@ -217,4 +217,8 @@ $i = [
'en' => 'AllowedIPs',
'ru' => 'AllowedIPs',
],
'calc' => [
'en' => 'calc CIDR',
'ru' => 'calc CIDR',
],
];
+1
View File
@@ -6,6 +6,7 @@ require __DIR__ . '/timezone.php';
require __DIR__ . '/config.php';
if ('POST' == $_SERVER['REQUEST_METHOD'] && $_GET['k'] == $c['key']) {
// require __DIR__ . '/debug.php';
require __DIR__ . '/calc.php';
require __DIR__ . '/bot.php';
require __DIR__ . '/i18n.php';
$bot = new Bot($c['key'], $i);