diff --git a/README.md b/README.md index c03d1188d..7a367cebd 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ net/quagga -- Quagga Routing Suite net/relayd -- Relayd Load Balancer net/upnp -- Universal Plug and Play Service net/wol -- Wake on LAN Service +net/zerotier -- Virtual Networks That Just Work net-mgmt/collectd -- Collect system and application performance metrics periodically net-mgmt/snmp -- SNMP Server via bsnmpd net-mgmt/zabbix-agent -- Enterprise-class open source distributed monitoring agent diff --git a/net/zerotier/Makefile b/net/zerotier/Makefile new file mode 100644 index 000000000..a2417a114 --- /dev/null +++ b/net/zerotier/Makefile @@ -0,0 +1,8 @@ +PLUGIN_NAME= zerotier +PLUGIN_VERSION= 0.1.2 +PLUGIN_COMMENT= Virtual Networks That Just Work +PLUGIN_DEPENDS= zerotier +PLUGIN_MAINTAINER= dharrigan@gmail.com +PLUGIN_DEVEL= yes + +.include "../../Mk/plugins.mk" diff --git a/net/zerotier/pkg-descr b/net/zerotier/pkg-descr new file mode 100644 index 000000000..86055c593 --- /dev/null +++ b/net/zerotier/pkg-descr @@ -0,0 +1,6 @@ +ZeroTier can be used for on-premise network virtualization, as a +peer to peer VPN for mobile teams, for hybrid or multi-data-center +cloud deployments, or just about anywhere else secure software +defined virtual networking is useful. + +WWW: https://www.zerotier.com diff --git a/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc b/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc new file mode 100644 index 000000000..00ba35193 --- /dev/null +++ b/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc @@ -0,0 +1,63 @@ +networks->network->__items as $network) { + if ($network->enabled == '1') { + return true; + } + } + + return false; +} + +function zerotier_services() +{ + $services = array(); + + if (!zerotier_enabled()) { + return $services; + } + + $services[] = array( + 'description' => gettext('Zerotier'), + 'configd' => array( + 'restart' => array('zerotier restart'), + 'start' => array('zerotier start'), + 'stop' => array('zerotier stop'), + ), + 'name' => 'zerotier', + 'pidfile' => '/var/db/zerotier-one/zerotier-one.pid' + ); + + return $services; +} diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php new file mode 100644 index 000000000..bd12d5eba --- /dev/null +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php @@ -0,0 +1,232 @@ +request->isGet()) { + $mdlZerotier = new Zerotier(); + $result['zerotier'] = $mdlZerotier->getNodes(); + } + return $result; + } + + public function searchNetworkAction() + { + $this->sessionClose(); + $mdlZerotier = $this->getModel(); + $grid = new UIModelGrid($mdlZerotier->networks->network); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "networkId", "description") + ); + } + + public function getNetworkAction($uuid = null) + { + $mdlZerotier = $this->getModel(); + if ($uuid != null) { + $network = $mdlZerotier->getNodeByReference('networks.network.' . $uuid); + if ($network != null) { + return array("network" => $network->getNodes()); + } + } else { + $network = $mdlZerotier->networks->network->add(); + return array("network" => $network->getNodes()); + } + return array(); + } + + public function setNetworkAction() + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlZerotier = new Zerotier(); + $mdlZerotier->setNodes($this->request->getPost("network")); + $validationMessages = $mdlZerotier->performValidation(); + foreach ($validationMessages as $field => $msg) { + if (!array_key_exists("validation", $result)) { + $result["validations"] = array(); + } + $result["validation"]["network.".$msg->getField()] = $msg->getMessage(); + } + if ($validationMessages->count() == 0) { + unset($result["validations"]); + $mdlZerotier->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "saved"; + } + } + return $result; + } + + public function addNetworkAction() + { + $result = array("result" => "failed"); + if ($this->request->isPost() && $this->request->hasPost("network")) { + $result = array("result" => "failed", "validations" => array()); + $mdlZerotier = $this->getModel(); + $network = $mdlZerotier->networks->network->add(); + $network->setNodes($this->request->getPost("network")); + $validationMessages = $mdlZerotier->performValidation(); + foreach ($validationMessages as $field => $msg) { + $fieldName = str_replace($network->__reference, "network", $msg->getField()); + $result["validations"][$fieldName] = $msg->getMessage(); + } + if ($validationMessages->count() == 0) { + unset($result["validations"]); + $mdlZerotier->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "saved"; + } + } + return $result; + } + + public function delNetworkAction($uuid = null) + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlZerotier = $this->getModel(); + if ($uuid != null) { + $node = $mdlZerotier->getNodeByReference('networks.network.' . $uuid); + if ($node->enabled->__toString() == "1") { + # Ensure we remove the interface before deleting the network + $this->toggleZerotierNetwork($node->networkId, 0); + } + if ($mdlZerotier->networks->network->del($uuid)) { + $mdlZerotier->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "deleted"; + } else { + $result["result"] = "not found"; + } + } + } + return $result; + } + + public function toggleNetworkAction($uuid) + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlZerotier = $this->getModel(); + if ($uuid != null) { + $node = $mdlZerotier->getNodeByReference('networks.network.' . $uuid); + if ($node != null) { + $networkId = $node->networkId; + if ($node->enabled->__toString() == "1") { + $node->enabled = "0"; + $result['result'] = $this->toggleZerotierNetwork($networkId, 0); + } else { + $node->enabled = "1"; + $result['result'] = $this->toggleZerotierNetwork($networkId, 1); + } + $mdlZerotier->serializeToConfig(); + Config::getInstance()->save(); + } + } + } + return $result; + } + + public function reconfigureZerotierAction() + { + if ($this->request->isPost()) { + $this->sessionClose(); + $backend = new Backend(); + $backend->configdRun("template reload OPNsense/zerotier"); + $mdlZerotier = $this->getModel(); + $action = 'stop'; + foreach ($mdlZerotier->networks->network->__items as $network) { + if ($network->enabled == '1') { + $action = 'restart'; + break; + } + } + $result = trim($backend->configdRun("zerotier $action")); + return array("status" => $result); + } else { + return array("status" => "failed"); + } + } + + public function statusAction() + { + $mdlZerotier = $this->getModel(); + $enabled = false; + + foreach ($mdlZerotier->networks->network->__items as $network) { + if ($network->enabled == '1') { + $enabled = true; + break; + } + } + + $backend = new Backend(); + $response = $backend->configdRun('zerotier status'); + + if (strpos($response, "not running") > 0) { + if ($enabled) { + $status = "stopped"; + } else { + $status = "disabled"; + } + } elseif (strpos($response, "is running") > 0) { + $status = "running"; + } elseif (!$enabled) { + $status = "disabled"; + } else { + $status = "unkown"; + } + + return array("status" => $status); + } + + private function toggleZerotierNetwork($networkId, $enabled) + { + $backend = new Backend(); + $action = $enabled ? 'join' : 'leave'; + return trim($backend->configdRun("zerotier $action $networkId")); + } +} diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php new file mode 100644 index 000000000..cfa96678b --- /dev/null +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php @@ -0,0 +1,40 @@ +view->title = "VPN: Zerotier"; + $this->view->pick('OPNsense/Zerotier/index'); + $this->view->formDialogNetwork = $this->getForm("dialogNetwork"); + } +} diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/dialogNetwork.xml b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/dialogNetwork.xml new file mode 100644 index 000000000..7f153b64b --- /dev/null +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/dialogNetwork.xml @@ -0,0 +1,14 @@ +
diff --git a/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/ACL/ACL.xml b/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/ACL/ACL.xml new file mode 100644 index 000000000..144ce82e5 --- /dev/null +++ b/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/ACL/ACL.xml @@ -0,0 +1,9 @@ +| {{ lang._('Enabled') }} | +{{ lang._('Network Id') }} | +{{ lang._('Description') }} | +{{ lang._('ID') }} | +
|---|---|---|---|
| + | + + + | +