diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..8e2db99 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..15f749d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,37 @@ + + + + + + + + Error handlingJava + + + Java + + + Probable bugsJava + + + RESTful Web Service (JAX-RS) + + + Spring + + + Spring BootSpring + + + + + User defined + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b89a405 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..4bf4979 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/protected-resources-list.iml b/.idea/protected-resources-list.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/protected-resources-list.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml new file mode 100644 index 0000000..c76ae96 --- /dev/null +++ b/.idea/sshConfigs.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 0000000..0ccc552 --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 2ba54e9..7e567ab 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,9 @@ ## networks Каталог с файлами сервисов и их подсетей -## utils -Различные скрипты и утилиты - ### Установка ```shell -apk add php php-session jq git +apk add php php-session php-curl jq git cd /opt git clone https://git.kirillius.ru/kirillius/protected-resources-list.git cd /opt/protected-resources-list/ diff --git a/bin/sync-networks b/bin/sync-networks new file mode 100755 index 0000000..16b4f50 --- /dev/null +++ b/bin/sync-networks @@ -0,0 +1,27 @@ +#!/usr/bin/php +getPlugins()["netsync"] ?? null; + if ($instance === null) { + throw new RuntimeException("Plugin is not enabled"); + } + /** + * @var Netsync $instance + */ + + $config = $instance->getRoutingConfig(); + $outfile = $argv[1]; + file_put_contents($outfile, implode("\n", $config)); +} catch (Exception $e) { + echo "\nError:" . $e->getMessage() . "\n"; + exit(1); +} + +exit(0); \ No newline at end of file diff --git a/bin/webui-server b/bin/webui-server index 13d8d14..97ea029 100755 --- a/bin/webui-server +++ b/bin/webui-server @@ -13,4 +13,5 @@ PORT=`jq -r .web.port $CFGFILE` #TODO FIXME !!!! killall php cd $ROOT +php $ROOT/loader.php --init php -S $HOST:$PORT $ROOT/server.php \ No newline at end of file diff --git a/classes/IPluggable.php b/classes/IPluggable.php index 149322f..c8c4349 100644 --- a/classes/IPluggable.php +++ b/classes/IPluggable.php @@ -2,7 +2,7 @@ interface IPluggable { - const PROTECTED_NAMES = ["enable", "disable", "render", "init"]; - - public function init(PluginContext $context); + public function onServerStarted(); + public function onInit(PluginContext $context); + public function onSync(); } \ No newline at end of file diff --git a/classes/Plugin.php b/classes/Plugin.php new file mode 100644 index 0000000..f9e123c --- /dev/null +++ b/classes/Plugin.php @@ -0,0 +1,42 @@ +context = $context; + $this->checkConfig(); + $this->config = $this->context->getConfig()[$context->getName()]; + } + + protected function checkConfig(): void + { + $config = $this->context->getConfig(); + $defaults = $this->context->getMetadata()["config"]; + $name = $this->context->getName(); + + if (!isset($config[$name])) { + $config[$name] = $defaults; + return; + } + + foreach ($defaults as $key => $value) { + if (!isset($config[$name][$key])) { + $config[$name][$key] = $value; + } + } + } +} \ No newline at end of file diff --git a/classes/PluginContext.php b/classes/PluginContext.php index e863662..d8ccfec 100644 --- a/classes/PluginContext.php +++ b/classes/PluginContext.php @@ -5,14 +5,22 @@ class PluginContext private RPC $RPC; private Config $config; private array $metadata; + private string $name; + + public function getName(): string + { + return $this->name; + } /** * @param RPC $RPC * @param Config $config * @param array $metadata + * @param string $name */ - public function __construct(RPC $RPC, Config $config, array $metadata) + public function __construct(RPC $RPC, Config $config, array $metadata, string $name) { + $this->name = $name; $this->RPC = $RPC; $this->config = $config; $this->metadata = $metadata; diff --git a/classes/RPC.php b/classes/RPC.php index 1a0be96..a5f707b 100644 --- a/classes/RPC.php +++ b/classes/RPC.php @@ -14,7 +14,7 @@ class RPC try { $meta = $this->getPluginMetadata($plugin); $inst = $this->loadPlugin($plugin, $meta["class"]); - $inst->init(new PluginContext($this, $this->config, $meta)); + $inst->onInit(new PluginContext($this, $this->config, $meta, $plugin)); } catch (Error $e) { continue; } @@ -117,6 +117,12 @@ class RPC return md5(sha1($what) . md5($what)); } + private function isInternalMethod($name) + { + $cls = new ReflectionClass(IPluggable::class); + return $cls->hasMethod($name); + } + public function __invoke($method, $args) { $parts = explode("::", $method); @@ -126,7 +132,7 @@ class RPC $this->checkAuth(); $plugin = $this->plugins[$parts[0]]; $methodname = $parts[1]; - if (in_array($methodname, IPluggable::PROTECTED_NAMES)) { + if ($this->isInternalMethod($methodname)) { throw new RuntimeException("Unable to invoke internal methods"); } return call_user_func([$plugin, $methodname], $args); diff --git a/loader.php b/loader.php index a943e90..4880f31 100644 --- a/loader.php +++ b/loader.php @@ -3,4 +3,13 @@ require_once __DIR__ . "/common.inc.php"; spl_autoload_register(function ($classname) { require_once __DIR__ . "/classes/" . $classname . ".php"; -}); \ No newline at end of file +}); +if (isset($argv) and in_array("--init", $argv)) { + $rpc = new StaticRPC(); + foreach ($rpc->getPlugins() as $plugin => $instance) { + /** + * @var IPluggable $instance + */ + $instance->onServerStarted(); + } +} \ No newline at end of file diff --git a/networks/habr.json b/networks/habr.json index b63b805..3adf98a 100644 --- a/networks/habr.json +++ b/networks/habr.json @@ -1,7 +1,7 @@ { "description": "habrahabr", "domains": [ -"habr.com" + "habr.com" ], "networks": [ "178.248.237.68/32" diff --git a/plugins/api/API.php b/plugins/api/API.php new file mode 100644 index 0000000..aeaa10a --- /dev/null +++ b/plugins/api/API.php @@ -0,0 +1,20 @@ +config["key"])) { + $this->config["key"] = sha1(rand() . uniqid()); + $this->context->getConfig()->save(); + } + } + + public function getKey(): string + { + return $this->config["key"]; + } + +} \ No newline at end of file diff --git a/plugins/api/metadata.json b/plugins/api/metadata.json new file mode 100644 index 0000000..8e2b88c --- /dev/null +++ b/plugins/api/metadata.json @@ -0,0 +1,5 @@ +{ + "class": "API", + "config": { + } +} \ No newline at end of file diff --git a/plugins/api/plugin.js b/plugins/api/plugin.js new file mode 100644 index 0000000..746ee31 --- /dev/null +++ b/plugins/api/plugin.js @@ -0,0 +1,7 @@ +import {App} from "/assets/App.js"; + +(async function () { + let key = await App.RPC.__invoke("api::getKey"); + + $("body").append("API Key: " + key + "") +})(); \ No newline at end of file diff --git a/plugins/named/BindPlugin.php b/plugins/named/BindPlugin.php new file mode 100644 index 0000000..8f4723b --- /dev/null +++ b/plugins/named/BindPlugin.php @@ -0,0 +1,57 @@ +getConfigs(); + + //add new routes + foreach ($this->context->getConfig()["networks"] as $key) { + + if (isset($networks[$key])) { + foreach ($networks[$key]["domains"] as $domain) { + $selectedDomains[] = $domain; + } + } + } + + $selectedDomains = array_unique($selectedDomains); + + $data = []; + + foreach ($selectedDomains as $domain) { + $data[] = $this->createForwardRecord($domain); + } + + file_put_contents($this->config["file"], implode("\n", $data)); + + + return shell_exec($this->config["restart_cmd"]); + } + + private function createForwardRecord($domain) + { + $fwd = implode(";", $this->config["forwarders"]) . ";"; + return <<restart(); + } + + public function onSync() + { + $this->restart(); + } +} \ No newline at end of file diff --git a/plugins/named/metadata.json b/plugins/named/metadata.json new file mode 100644 index 0000000..ade9a90 --- /dev/null +++ b/plugins/named/metadata.json @@ -0,0 +1,8 @@ +{ + "class": "BindPlugin", + "config": { + "restart_cmd": "/etc/init.d/named restart", + "file": "/var/bind/forward.dns", + "forwarders": ["8.8.8.8", "1.1.1.1"] + } +} \ No newline at end of file diff --git a/plugins/named/plugin.js b/plugins/named/plugin.js new file mode 100644 index 0000000..3768e35 --- /dev/null +++ b/plugins/named/plugin.js @@ -0,0 +1,21 @@ +import {App} from "/assets/App.js"; + +(async function () { + $("#buttons").append(``); + $("#restart-bind").click(function () { + + const self = $(this); + self.prop("disabled", true); + (async function () { + try { + alert(await App.RPC.__invoke("named::restart")); + } finally { + setTimeout(() => { + self.prop("disabled", false); + }, 5000); + } + + })(); + + }); +})(); \ No newline at end of file diff --git a/plugins/netsync/Netsync.php b/plugins/netsync/Netsync.php new file mode 100644 index 0000000..95bfa6d --- /dev/null +++ b/plugins/netsync/Netsync.php @@ -0,0 +1,38 @@ +config["master"]; + $key = $this->config["key"]; + + if (empty($key)) { + throw new RuntimeException("API key is empty"); + } + + $ch = curl_init($host); + + + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ + "jsonrpc" => "2.0", + "id" => "1", + "method" => "getNetworks", + "params" => [] + ])); + + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "X-Auth: " . md5($key), + "Content-type: application/json" + ]); + + $output = curl_exec($ch); + if (curl_error($ch)) { + return curl_error($ch); + } + curl_close($ch); + return $output; + } +} \ No newline at end of file diff --git a/plugins/netsync/metadata.json b/plugins/netsync/metadata.json new file mode 100644 index 0000000..534dff2 --- /dev/null +++ b/plugins/netsync/metadata.json @@ -0,0 +1,7 @@ +{ + "class": "Netsync", + "config": { + "master": "127.0.0.1:8001", + "key": "" + } +} \ No newline at end of file diff --git a/plugins/netsync/plugin.js b/plugins/netsync/plugin.js new file mode 100644 index 0000000..adceea8 --- /dev/null +++ b/plugins/netsync/plugin.js @@ -0,0 +1,21 @@ +import {App} from "/assets/App.js"; + +(async function () { + $("#buttons").append(``); + $("#sync").click(function () { + + const self = $(this); + self.prop("disabled", true); + (async function () { + try { + alert(await App.RPC.__invoke("netsync::sync")); + } finally { + setTimeout(() => { + location.reload(); + }, 5000); + } + + })(); + + }); +})(); \ No newline at end of file diff --git a/plugins/openvpn/Openvpn.php b/plugins/openvpn/Openvpn.php index 8e8b349..a042b47 100755 --- a/plugins/openvpn/Openvpn.php +++ b/plugins/openvpn/Openvpn.php @@ -1,29 +1,15 @@ #!/usr/bin/php context->getConfig()["ovpn"]["restart_cmd"]); + return shell_exec($this->config["restart_cmd"]); } - public function init(PluginContext $context): void - { - $this->context = $context; - $this->checkConfig(); - } - - private function checkConfig(): void - { - $config = $this->context->getConfig(); - if (!isset($config["ovpn"])) { - $config["ovpn"] = $this->context->getMetadata()["config"]; - } - } public function getRoutingConfig(): array { @@ -44,5 +30,15 @@ class Openvpn implements IPluggable return $data; } + + public function onServerStarted() + { + $this->restart(); + } + + public function onSync() + { + $this->restart(); + } } diff --git a/plugins/quagga/QuaggaPlugin.php b/plugins/quagga/QuaggaPlugin.php index f76a613..4b504bb 100644 --- a/plugins/quagga/QuaggaPlugin.php +++ b/plugins/quagga/QuaggaPlugin.php @@ -1,14 +1,14 @@ context->getConfig()["quagga"]["file"]; + $configfile = $this->config["file"]; if (!file_exists($configfile)) { throw new RuntimeException("Quagga config file not found"); @@ -67,23 +67,16 @@ class QuaggaPlugin implements IPluggable file_put_contents($configfile, implode("\n", $lines)); //restart zebra - return shell_exec($this->context->getConfig()["quagga"]["restart_cmd"]); - - + return shell_exec($this->config["restart_cmd"]); } - - public function init(PluginContext $context): void + public function onServerStarted() { - $this->context = $context; - $this->checkConfig(); + $this->restart(); } - private function checkConfig(): void + public function onSync() { - $config = $this->context->getConfig(); - if (!isset($config["quagga"])) { - $config["quagga"] = $this->context->getMetadata()["config"]; - } + $this->restart(); } } \ No newline at end of file diff --git a/plugins/updates/Updates.php b/plugins/updates/Updates.php index 6edc71e..12e54aa 100644 --- a/plugins/updates/Updates.php +++ b/plugins/updates/Updates.php @@ -1,6 +1,6 @@ &1"); } - public function init(PluginContext $context) - { - } } \ No newline at end of file diff --git a/sort.php b/sort.php new file mode 100644 index 0000000..b71950b --- /dev/null +++ b/sort.php @@ -0,0 +1,12 @@ +