├── .buildpath ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.php.core.prefs └── org.eclipse.wst.common.project.facet.core.xml ├── LICENSE ├── Makefile ├── README.md ├── pkg-descr └── src └── opnsense ├── mvc └── app │ ├── controllers │ └── OPNsense │ │ └── Netmaker │ │ ├── Api │ │ ├── ServiceController.php │ │ └── SettingsController.php │ │ ├── ConnectionsController.php │ │ ├── DatabaseController.php │ │ ├── IndexController.php │ │ ├── NetworksController.php │ │ ├── ServersController.php │ │ └── forms │ │ ├── database.xml │ │ ├── dialogNetwork.xml │ │ ├── dialogServer.xml │ │ └── generalSettings.xml │ ├── models │ └── OPNsense │ │ └── Netmaker │ │ ├── ACL │ │ └── ACL.xml │ │ ├── FieldTypes │ │ └── IPAddressBindingField.php │ │ ├── Menu │ │ └── Menu.xml │ │ ├── Netmaker.php │ │ └── Netmaker.xml │ └── views │ └── OPNsense │ └── Netmaker │ ├── database.volt │ ├── index.volt │ ├── networks.volt │ └── servers.volt ├── scripts └── OPNsense │ └── netmaker │ └── test.sh └── service ├── conf └── actions.d │ └── actions_netmaker.conf └── templates └── OPNsense └── Netmaker ├── +TARGETS ├── mosquitto.conf ├── netmaker.yaml └── rc.conf.d /.buildpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.php.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | include_path=0;/os-netmaker 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2023, Kevin Scott Adams 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PLUGIN_NAME= Netmaker 2 | PLUGIN_VERSION= 0.0.1 3 | PLUGIN_COMMENT= Netmaker Networking Platform 4 | PLUGIN_DEPENDS= netmaker 5 | PLUGIN_MAINTAINER= thegrandwazoo@ksatechnologies.com 6 | 7 | .include "../../Mk/plugins.mk" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # os-netmaker 2 | Netmaker plugin for OPNsense 3 | -------------------------------------------------------------------------------- /pkg-descr: -------------------------------------------------------------------------------- 1 | The Netmaker plugin -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/Api/ServiceController.php: -------------------------------------------------------------------------------- 1 | 'Ok'); 51 | } 52 | 53 | public function reconfigureAction() 54 | { 55 | $status = "failed"; 56 | if ($this->request->isPost()) { 57 | $this->sessionClose(); 58 | $mdlNetmaker = new Netmaker; 59 | $runStatus = $this->statusAction(); 60 | 61 | if ($runStatus['status'] == "running" && (string)$mdlNetmaker->general->enabled == 0) { 62 | $this->stopAction(); 63 | } 64 | 65 | $backend = new Backend(); 66 | $bckresult = trim($backend->configdRun('template reload OPNsense/Netmaker')); 67 | if ($bckresult == "OK") { 68 | if ((string)$mdlNetmaker->general->enabled == 1) { 69 | if ($runStatus['status'] == 'running') { 70 | $status = $this->restartAction()['response']; 71 | } else { 72 | $status = $this->startAction()['response']; 73 | } 74 | } else { 75 | $status = "OK"; 76 | } 77 | } else { 78 | $status = "error generating Netmaker template (".$bckresult.")"; 79 | } 80 | } 81 | return array("status" => $status); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/Api/SettingsController.php: -------------------------------------------------------------------------------- 1 | getBase('network', 'networks.network', $uuid); 50 | } 51 | 52 | public function setNetworkAction($uuid) 53 | { 54 | return $this->setBase('network', 'networks.network', $uuid); 55 | } 56 | 57 | public function addNetworkAction() 58 | { 59 | return $this->addBase('network', 'networks.network'); 60 | } 61 | 62 | public function delNetworkAction($uuid) 63 | { 64 | return $this->delBase('networks.network', $uuid); 65 | } 66 | 67 | public function toggleNetworkAction($uuid, $enabled = null) 68 | { 69 | return $this->toggleBase('networks.network', $uuid); 70 | } 71 | 72 | public function searchNetworksAction() 73 | { 74 | $filter_funct = function ($record) { 75 | if ($record->ipv4CIDR == "") { 76 | $record->ipv4CIDR = "None (Default)"; 77 | } 78 | if ($record->ipv6CIDR == "") { 79 | $record->ipv6CIDR = "None (Default)"; 80 | } 81 | return true; 82 | }; 83 | return $this->searchBase('networks.network', array('enabled', 'name', 'description', 'ipv4CIDR', 'ipv6CIDR'), 'name', $filter_funct); 84 | } 85 | 86 | // Server Related API's 87 | public function getServerAction($uuid = null) 88 | { 89 | return $this->getBase('server', 'servers.server', $uuid); 90 | } 91 | 92 | public function setServerAction($uuid) 93 | { 94 | return $this->setBase('server', 'servers.server', $uuid); 95 | } 96 | 97 | public function addServerAction() 98 | { 99 | return $this->addBase('server', 'servers.server'); 100 | } 101 | 102 | public function delServerAction($uuid) 103 | { 104 | return $this->delBase('servers.server', $uuid); 105 | } 106 | 107 | public function toggleServerAction($uuid, $enabled = null) 108 | { 109 | return $this->toggleBase('servers.server', $uuid); 110 | } 111 | 112 | public function searchServersAction() 113 | { 114 | $filter_funct = function ($record) { 115 | if ($record->baseDomain == "") { 116 | $record->baseDomain = "None (Default)"; 117 | } 118 | return true; 119 | }; 120 | return $this->searchBase('servers.server', array('enabled', 'name', 'description', 'baseDomain'), 'name', $filter_funct); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/ConnectionsController.php: -------------------------------------------------------------------------------- 1 | view->pick('OPNsense/Netmaker/connections'); 51 | } 52 | } -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/DatabaseController.php: -------------------------------------------------------------------------------- 1 | view->databaseForm = $this->getForm('database'); 47 | // Set showIntro from General Settings 48 | $mdlNetmaker = new \OPNsense\Netmaker\Netmaker(); 49 | $this->view->showIntro = (string)$mdlNetmaker->general->showIntro; 50 | $this->view->pick('OPNsense/Netmaker/database'); 51 | } 52 | } -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/IndexController.php: -------------------------------------------------------------------------------- 1 | view->formGeneralSettings = $this->getForm("generalSettings"); 51 | $this->view->formDialogNetwork = $this->getForm("dialogNetworks"); 52 | $this->view->formDialogServer = $this->getForm("dialogServers"); 53 | // set additional view parameters 54 | $mdlNetmaker = new \OPNsense\Netmaker\Netmaker(); 55 | $this->view->showIntro = (string)$mdlNetmaker->general->showIntro; 56 | // pick the template to serve 57 | $this->view->pick('OPNsense/Netmaker/index'); 58 | } 59 | } -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/NetworksController.php: -------------------------------------------------------------------------------- 1 | view->formDialogNetwork = $this->getForm('dialogNetwork'); 51 | // Set showIntro from General Settings 52 | $mdlNetmaker = new \OPNsense\Netmaker\Netmaker(); 53 | $this->view->showIntro = (string)$mdlNetmaker->general->showIntro; 54 | // Choose the template 55 | $this->view->pick('OPNsense/Netmaker/networks'); 56 | } 57 | } -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/ServersController.php: -------------------------------------------------------------------------------- 1 | view->formDialogServer = $this->getForm('dialogServer'); 51 | // Set showIntro from General Settings 52 | $mdlNetmaker = new \OPNsense\Netmaker\Netmaker(); 53 | $this->view->showIntro = (string)$mdlNetmaker->general->showIntro; 54 | // Choose the template 55 | $this->view->pick('OPNsense/Netmaker/servers'); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/forms/database.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | netmaker.database.enabled 4 | 5 | checkbox 6 | 7 | 8 | 9 | netmaker.database.name 10 | 11 | text 12 | 13 | 14 | 15 | netmaker.database.description 16 | 17 | text 18 | 19 | 20 | 21 | netmaker.database.dbType 22 | 23 | dropdown 24 | 25 | 26 | 27 | 28 | netmaker.database.bindAddress 29 | 30 | dropdown 31 | 32 | 33 | 34 | 35 | netmaker.database.ipv4DatabaseAddress 36 | 37 | text 38 | 39 | 40 | 41 | 42 | netmaker.database.databasePort 43 | 44 | text 45 | 46 | 47 | true 48 | 49 |
-------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/forms/dialogNetwork.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | network.enabled 4 | 5 | checkbox 6 | Enable this Network 7 | 8 | 9 | network.name 10 | 11 | text 12 | Name of the of the network (Max 12 lowercase and dash characters) 13 | 14 | 15 | network.description 16 | 17 | text 18 | Description of this AoR (Not Parsed) 19 | 20 | 21 | network.ipv4Enabled 22 | 23 | checkbox 24 | Adds private IPv4 to all nodes in a network. 25 | 26 | 27 | network.ipv4CIDR 28 | 29 | text 30 | IPv4 CIDR Value (e.g.: w.x.y.z/s) 31 | 32 | 33 | network.ipv6Enabled 34 | 35 | checkbox 36 | Adds private IPv6 to all nodes in a network. 37 | 38 | 39 | network.ipv6CIDR 40 | 41 | text 42 | Adds private IPv6 to all nodes in a network. 43 | 44 | 45 | network.udpHolePunch 46 | 47 | checkbox 48 | UDP Hole Punching enables the server to perform STUN. This means, when nodes check-in, the server will record return addresses and ports. It will then communicate this information to the other nodes when they check in, allowing them to reach their peers more easily. This setting is usually good to turn on, with some noteable exceptions. This setting can also break peer-to-peer functionality if, for whatever reason, nodes are unable to reach the server. This can enhance connectivity in cases where NAT may block communication. 49 | 50 | 51 | network.defaultAccess 52 | 53 | checkbox 54 | Indicates the default ACL value for a node when it joins in respect to it’s peers (enabled or disabled). 55 | 56 | 57 | network.isPointToSite 58 | 59 | checkbox 60 | Create a network in which all clients have only one, central peer. 61 | 62 | 63 | network.isLocalNetwork 64 | 65 | checkbox 66 | This is almost always best to leave this turned off and is left for very special circumstances. If you are running a data center or a private WAN, you may want to enable this setting. It defines the range that nodes will set for Endpoints. Usually, Endpoints are just the public IP. But in some cases, you don’t want any nodes to be reachable via a public IP, and instead want to use a private range. Use if the server is on the same network (LAN) as you. 67 | 68 |
-------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/forms/dialogServer.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | server.enabled 4 | 5 | checkbox 6 | Enable this server. 7 | 8 | 9 | server.name 10 | 11 | text 12 | Name of the registration 13 | 14 | 15 | server.description 16 | 17 | text 18 | Description of this registration (Not Parsed) 19 | 20 | 21 | server.baseDomain 22 | 23 | text 24 | Domain of this server, e.g. example.com 25 | 26 | 27 | server.apiServerToken 28 | 29 | text 30 | Specifiy a password token used for API calls. 31 | 32 | 33 | server.extApiPort 34 | 35 | text 36 | Specify the port for the API to listen on from the Internet. 37 | 38 | 39 | server.intApiPort 40 | 41 | text 42 | Specify the port for the API to listen on Internally. 43 | 44 | 45 | server.mqHostExt 46 | 47 | dropdown 48 | IPv4 address of the MQ Host, e.g. 0.0.0.0 or 1.2.3.4 49 | 50 | 51 | server.mqPortExt 52 | 53 | text 54 | IPv4 Port of the HQ Host, e.g. 8883 55 | 56 | 57 | server.mqHostInt 58 | 59 | dropdown 60 | IPv4 address of the MQ Host, e.g. 127.0.0.1 or 192.168.100.100 61 | 62 | 63 | server.mqPortInt 64 | 65 | text 66 | IPv4 Port of the HQ Host, e.g. 8883 67 | 68 | 69 | server.mqAdminPwd 70 | 71 | text 72 | Admin Password to the MQ Host 73 | 74 |
-------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/Netmaker/forms/generalSettings.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | netmaker.general.enabled 4 | 5 | checkbox 6 | Enable or disable the Netmaker service. 7 | 8 | 9 | netmaker.general.control 10 | 11 | dropdown 12 | 13 | 14 | 15 | netmaker.general.showIntro 16 | 17 | checkbox 18 | 19 | 20 |
21 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/Netmaker/ACL/ACL.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Services: Netmaker 4 | Allow access to the Netmaker module 5 | 6 | ui/netmaker/* 7 | api/netmaker/* 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/Netmaker/FieldTypes/IPAddressBindingField.php: -------------------------------------------------------------------------------- 1 | object(); 104 | if (!empty($configObj->laggs)) { 105 | foreach ($configObj->laggs->children() as $key => $lagg) { 106 | if (!empty($lagg->members)) { 107 | foreach (explode(',', $lagg->members) as $interface) { 108 | if (!isset($physicalInterfaces[$interface])) { 109 | $physicalInterfaces[$interface] = array(); 110 | } 111 | $physicalInterfaces[$interface][] = (string)$lagg->laggif; 112 | } 113 | } 114 | } 115 | } 116 | return $physicalInterfaces; 117 | } 118 | 119 | /** 120 | * collect parents for vlan interfaces 121 | * @return array named array containing device and vlan interfaces 122 | */ 123 | private function getConfigVLANInterfaces() 124 | { 125 | $physicalInterfaces = array(); 126 | $configObj = Config::getInstance()->object(); 127 | if (!empty($configObj->vlans)) { 128 | foreach ($configObj->vlans->children() as $key => $vlan) { 129 | if (!isset($physicalInterfaces[(string)$vlan->if])) { 130 | $physicalInterfaces[(string)$vlan->if] = array(); 131 | } 132 | $physicalInterfaces[(string)$vlan->if][] = (string)$vlan->vlanif; 133 | } 134 | } 135 | return $physicalInterfaces; 136 | } 137 | 138 | /** 139 | * generate validation data (list of interfaces and well know ports) 140 | */ 141 | protected function actionPostLoadingEvent() 142 | { 143 | if (!isset(self::$internalOptionList[$this->internalCacheKey])) { 144 | self::$internalOptionList[$this->internalCacheKey] = array(); 145 | 146 | $allInterfaces = array(); 147 | $allInterfacesDevices = array(); // mapping device -> interface handle (lan/wan/optX) 148 | $configObj = Config::getInstance()->object(); 149 | // Iterate over all interfaces configuration and collect data 150 | if (isset($configObj->interfaces) && $configObj->interfaces->count() > 0) { 151 | foreach ($configObj->interfaces->children() as $key => $value) { 152 | if (!$this->internalAllowDynamic && !empty($value->internal_dynamic)) { 153 | continue; 154 | } 155 | if (!empty($value->ipaddr) && $value->ipaddr != "dhcp") { 156 | $allInterfaces[(string)$value->ipaddr] = $value; 157 | } else { 158 | $interfaces_details = legacy_interfaces_details(); 159 | $value->ipaddr = (string)$interfaces_details[(string)$value->if]["ipv4"][0]["ipaddr"]; 160 | $allInterfaces[(string)$value->ipaddr] = $value; 161 | } 162 | } 163 | } 164 | 165 | /* 166 | * Iterate through the VIP interfaces 167 | */ 168 | $configObj = Config::getInstance()->object(); 169 | if (isset($configObj->virtualip) && $configObj->virtualip->count() > 0) { 170 | foreach ($configObj->virtualip->children() as $key => $value) { 171 | $allInterfaces[(string)$value->subnet] = $value; 172 | } 173 | } 174 | 175 | if ($this->internalAddParentDevices) { 176 | // collect parents for lagg/vlan interfaces 177 | $physicalInterfaces = $this->getConfigLaggInterfaces(); 178 | $physicalInterfaces = array_merge($physicalInterfaces, $this->getConfigVLANInterfaces()); 179 | 180 | // add unique devices 181 | foreach ($physicalInterfaces as $interface => $devices) { 182 | // construct interface node 183 | $interfaceNode = new \stdClass(); 184 | $interfaceNode->enable = 0; 185 | $interfaceNode->descr = "[{$interface}]"; 186 | $interfaceNode->if = $interface; 187 | foreach ($devices as $device) { 188 | if (!empty($allInterfacesDevices[$device])) { 189 | $configuredInterface = $allInterfaces[$allInterfacesDevices[$device]]; 190 | if (!empty($configuredInterface->enable)) { 191 | // set device enabled if any member is 192 | $interfaceNode->enable = (string)$configuredInterface->enable; 193 | } 194 | } 195 | } 196 | // only add unconfigured devices 197 | if (empty($allInterfacesDevices[$interface])) { 198 | $allInterfaces[$interface] = $interfaceNode; 199 | } 200 | } 201 | } 202 | 203 | // collect this items options 204 | foreach ($allInterfaces as $key => $value) { 205 | // use filters to determine relevance 206 | $isMatched = true; 207 | foreach ($this->internalFilters as $filterKey => $filterData) { 208 | if (isset($value->$filterKey)) { 209 | $fieldData = $value->$filterKey; 210 | } else { 211 | // not found, might be a boolean. 212 | $fieldData = "0"; 213 | } 214 | 215 | if (!preg_match($filterData, $fieldData)) { 216 | $isMatched = false; 217 | } 218 | } 219 | if ($isMatched) { 220 | if (isset($value->mode)) { 221 | self::$internalOptionList[$this->internalCacheKey][$key] = 222 | !empty($value->descr) ? "{$value->subnet} ({$value->descr})" : strtoupper($key); 223 | } else { 224 | self::$internalOptionList[$this->internalCacheKey][$key] = 225 | !empty($value->descr) ? "{$value->ipaddr} ({$value->descr})" : strtoupper($key); 226 | } 227 | } 228 | } 229 | natcasesort(self::$internalOptionList[$this->internalCacheKey]); 230 | } 231 | } 232 | 233 | /** 234 | * set filters to use (in regex) per field, all tags are combined 235 | * and cached for the next object using the same filters 236 | * @param $filters filters to use 237 | */ 238 | public function setFilters($filters) 239 | { 240 | if (is_array($filters)) { 241 | $this->internalFilters = $filters; 242 | $this->internalCacheKey = md5(serialize($this->internalFilters)); 243 | } 244 | } 245 | 246 | /** 247 | * add parent devices to the selection in case the parent has no configuration 248 | * @param $value boolean value 0/1 249 | */ 250 | public function setAddParentDevices($value) 251 | { 252 | if (trim(strtoupper($value)) == "Y") { 253 | $this->internalAddParentDevices = true; 254 | } else { 255 | $this->internalAddParentDevices = false; 256 | } 257 | } 258 | 259 | /** 260 | * select if multiple interfaces may be selected at once 261 | * @param $value boolean value 0/1 262 | */ 263 | public function setMultiple($value) 264 | { 265 | if (trim(strtoupper($value)) == "Y") { 266 | $this->internalMultiSelect = true; 267 | } else { 268 | $this->internalMultiSelect = false; 269 | } 270 | } 271 | 272 | /** 273 | * select if dynamic (hotplug) interfaces maybe selectable 274 | * @param $value boolean value 0/1 275 | */ 276 | public function setAllowDynamic($value) 277 | { 278 | if (trim(strtoupper($value)) == "Y") { 279 | $this->internalAllowDynamic = true; 280 | } else { 281 | $this->internalAllowDynamic = false; 282 | } 283 | } 284 | 285 | /** 286 | * get valid options, descriptions and selected value 287 | * @return array 288 | */ 289 | public function getNodeData() 290 | { 291 | $result = array(); 292 | // Add the 0.0.0.0 (All) network interfaces option. 293 | $result["0.0.0.0"] = array("value" => gettext("0.0.0.0 (All)"), "selected" => 0); 294 | 295 | // explode interfaces 296 | $interfaces = explode(',', $this->internalValue); 297 | foreach (self::$internalOptionList[$this->internalCacheKey] as $optKey => $optValue) { 298 | if (in_array($optKey, $interfaces)) { 299 | $selected = 1; 300 | } else { 301 | $selected = 0; 302 | } 303 | $result[$optKey] = array("value" => $optValue, "selected" => $selected); 304 | } 305 | return $result; 306 | } 307 | 308 | /** 309 | * Validate network options 310 | * @param array $network to validate 311 | * @return bool|Callback 312 | * @throws \OPNsense\Base\ModelException 313 | */ 314 | private function validateNetwork($network) 315 | { 316 | $messages = array(); 317 | if (!Util::isAlias($network) && !Util::isIpAddress($network) && !Util::isSubnet($network)) { 318 | $messages[] = sprintf( 319 | gettext('Entry "%s" is not a valid IP address.'), 320 | $network 321 | ); 322 | } 323 | return $messages; 324 | } 325 | 326 | /** 327 | * retrieve field validators for this field type 328 | * @return array returns validators 329 | */ 330 | public function getValidators() 331 | { 332 | $validators = parent::getValidators(); 333 | if ($this->internalValue != null) { 334 | $validators[] = new CallbackValidator(["callback" => function ($data) { 335 | return $this->validateNetwork($data); 336 | } 337 | ]); 338 | } 339 | return $validators; 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/Netmaker/Menu/Menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/Netmaker/Netmaker.php: -------------------------------------------------------------------------------- 1 | networks->network->Add(); 44 | $uuid = $network->getAttributes()['uuid']; 45 | $network->name = $name; 46 | $network->description = $description; 47 | $network->ipv4cidr = $ipv4cidr; 48 | $network->ipv6cidr = $ipv6cidr; 49 | return $uuid; 50 | } 51 | 52 | /** 53 | * create a new action 54 | * @param string $name 55 | * @param string $description 56 | * @return string 57 | */ 58 | public function newServer($name, $description = "", $basedomain = "None") 59 | { 60 | $server = $this->servers->server->Add(); 61 | $uuid = $server->getAttributes()['uuid']; 62 | $server->name = $name; 63 | $server->description = $description; 64 | $server->basedomain = $basedomain; 65 | return $uuid; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/Netmaker/Netmaker.xml: -------------------------------------------------------------------------------- 1 | 2 | //OPNsense/Netmaker 3 | 0.0.2 4 | 5 | OPNsense Netmaker Server 6 | 7 | 8 | 9 | 10 | 11 | 12 | 0 13 | Y 14 | 15 | 16 | N 17 | now 18 | 19 | Now 20 | Graceful 21 | Convenient 22 | 23 | 24 | 25 | 0 26 | N 27 | 28 | 29 | 0 30 | N 31 | 32 | 33 | 1 34 | N 35 | 36 | 37 | 38 | 39 | 1 40 | Y 41 | 42 | 43 | Y 44 | /^([0-9a-zA-Z_-]){1,255}$/u 45 | Should be an alphanumeric string including _ and - with length between 1 and 255 characters. 46 | 47 | 48 | N 49 | /^.{1,255}$/u 50 | Description is a string between 1 and 255 characters. 51 | 52 | 53 | Y 54 | sqlite 55 | N 56 | 57 | sqlite - SQLite database (Local) 58 | rqlite - Lightweight, distrubuted relational database 59 | postgres - PostgreSQL database 60 | 61 | 62 | 63 | N 64 | 65 | 66 | N 67 | Y 68 | Input a valid IPv4 Network. 69 | 70 | 71 | N 72 | 73 | 74 | 75 | 76 | 77 | 1 78 | Y 79 | 80 | 81 | Y 82 | /^([a-zA-Z-]){1,12}$/u 83 | lower 84 | Should be an lowercase string including - with length between 1 and 12 characters. 85 | 86 | 87 | N 88 | /^.{1,255}$/u 89 | Description is a string between 1 and 255 characters.) 90 | 91 | 92 | N 93 | 94 | 95 | N 96 | Y 97 | Input a valid IPv4 Network. 98 | 99 | 100 | N 101 | 102 | 103 | N 104 | Y 105 | Input a valid IPv6 Network. 106 | 107 | 108 | N 109 | 110 | 111 | N 112 | 113 | 114 | N 115 | 116 | 117 | N 118 | 119 | 120 | 121 | 122 | 123 | 124 | 1 125 | Y 126 | 127 | 128 | Y 129 | /^([0-9a-zA-Z_-]){1,255}$/u 130 | Should be an alphanumeric string including _ and - with length between 1 and 255 characters. 131 | 132 | 133 | N 134 | /^.{1,255}$/u 135 | Description is a string between 1 and 255 characters. 136 | 137 | 138 | N 139 | 140 | 141 | A domain must be set. 142 | DependConstraint 143 | 144 | enabled 145 | 146 | 147 | 148 | 149 | 150 | Y 151 | 152 | 153 | A server Token must be set. 154 | DependConstraint 155 | 156 | enabled 157 | 158 | 159 | 160 | 161 | 162 | N 163 | 164 | 165 | A port must be set. 166 | DependConstraint 167 | 168 | enabled 169 | 170 | 171 | 172 | 443 173 | 174 | 175 | N 176 | 177 | 178 | A port must be set. 179 | DependConstraint 180 | 181 | enabled 182 | 183 | 184 | 185 | 8081 186 | 187 | 188 | Y 189 | 127.0.0.1 190 | /^.{1,255}$/u 191 | Y 192 | 193 | /^((?!dhcp).)*$/ 194 | 195 | Description is a string between 1 and 255 characters.) 196 | 197 | 198 | Y 199 | 8883 200 | /^.{1,255}$/u 201 | Value TCP/UDP port number.) 202 | 203 | 204 | Y 205 | 0.0.0.0 206 | /^.{1,255}$/u 207 | Y 208 | 209 | /^((?!dhcp).)*$/ 210 | 211 | Description is a string between 1 and 255 characters.) 212 | 213 | 214 | Y 215 | 1883 216 | /^.{1,255}$/u 217 | Value TCP/UDP port number.) 218 | 219 | 220 | N 221 | /^.{1,255}$/u 222 | MQTT Password 223 | 224 | 225 | 226 | 227 | 228 | 229 | 1 230 | Y 231 | 232 | 233 | Y 234 | /^([0-9a-zA-Z_-]){1,255}$/u 235 | Should be an alphanumeric string including _ and - with length between 1 and 255 characters. 236 | 237 | 238 | N 239 | /^.{1,255}$/u 240 | Description is a string between 1 and 255 characters.) 241 | 242 | 243 | 244 | 249 | 250 | Endpoint not found 251 | N 252 | Y 253 | 254 | 255 | , 256 | Y 257 | Y 258 | 259 | 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/views/OPNsense/Netmaker/database.volt: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright (c) 2023 KSA Technologies, LLC 3 | # Copyright (c) 2023 kevin.adams@ksatechnologies 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without modification, 7 | # are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 20 | # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | # POSSIBILITY OF SUCH DAMAGE. 26 | #} 27 | 28 | 73 | 74 | 75 | 81 | 82 |
83 | {% if showIntro|default('0')=='1' %} 84 |
85 |
86 |

{{ lang._('Introduction') }}

87 |

{{ lang._('This plugin supports 3 databases:') }}

88 |
    89 |
  • {{ lang._('sqlite - A small, fast, self-contained, and local SQL database engine (default)') }}
  • 90 |
  • {{ lang._('rqlite - A lightweight and easy-to-use distrubuted relational database based on SQLite.') }}
  • 91 |
  • {{ lang._('PostgreSQL - An extended SQL open source object-relational database.') }}
  • 92 |
93 |
94 |
95 | {% endif %} 96 | 97 |
98 | {{ partial("layout_partials/base_form",['fields':databaseForm,'id':'frm_database_settings','label':lang._('Edit Database')])}} 99 |
100 |
101 | 107 |
108 |
109 |
110 |
111 |
112 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/views/OPNsense/Netmaker/index.volt: -------------------------------------------------------------------------------- 1 | {#/ 2 | 3 | Copyright (C) 2018-2019 KSA Technologies, LLC 4 | OPNsense� is Copyright � 2014 � 2015 by Deciso B.V. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED �AS IS� AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 19 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 21 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #} 29 | 30 | 190 | 191 | 217 | 218 |
219 |
220 |
221 |

{{ lang._('Quick Start Guide') }}

222 |

{{ lang._('Welcome to the Netmaker Server plugin! This plugin is designed to offer features and flexibility of an SBC using the Asterisk framework package.')}}

223 |

{{ lang._('Note that you should configure the SBC plugin in the following order:') }}

224 |

{{ lang._('Please be aware that you need to %smanually%s add the required firewall rules for all configured services.') | format('', '') }}

225 |
226 |
227 |
228 |
229 |
230 |

{{ lang._('Settings') }}

231 |

{{ lang._('The netmaker needs to know what protocol (TCP or UDP) and bind address an endpoint will communicate.') }}

232 |
    233 |
  • {{ lang._('%sFQDN or IP:%s The IP address or fully-qualified domain name that should be used when communicating with your server.') | format('', '') }}
  • 234 |
  • {{ lang._('%sPort:%s The TCP or UDP port that should be used. If unset, the same port the client connected to will be used.') | format('', '') }}
  • 235 |
236 |
237 |
238 |
239 |
240 | {{ partial("layout_partials/base_form",['fields':formGeneralSettings,'id':'frm_GeneralSettings'])}} 241 |
242 |
243 | 244 |
245 |
246 |
247 |
248 |
249 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/views/OPNsense/Netmaker/networks.volt: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright (c) 2023 KSA Technologies, LLC 3 | # Copyright (c) 2023 kevin.adams@ksatechnologies 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without modification, 7 | # are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 20 | # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | # POSSIBILITY OF SUCH DAMAGE. 26 | #} 27 | 28 | 313 | 314 | 315 | 321 | 322 |
323 | {% if showIntro|default('0')=='1' %} 324 |
325 |
326 |

{{ lang._('Introduction') }}

327 |

{{ lang._('This plugin supports 3 databases:') }}

328 |
    329 |
  • {{ lang._('sqlite - A small, fast, self-contained, and local SQL database engine (default)') }}
  • 330 |
  • {{ lang._('rqlite - A lightweight and easy-to-use distrubuted relational database based on SQLite.') }}
  • 331 |
  • {{ lang._('PostgreSQL - An extended SQL open source object-relational database.') }}
  • 332 |
333 |
334 |
335 | {% endif %} 336 | 337 | 338 |
339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 360 | 361 | 362 |
{{ lang._('Enabled') }}{{ lang._('Name') }}{{ lang._('Description') }}{{ lang._('IPv4 CIDR') }}{{ lang._('IPv6 CIDR') }}{{ lang._('ID') }}{{ lang._('Commands') }}
357 | 358 | 359 |
363 | 364 |
365 |
366 | 370 | 371 |
372 |
373 |
374 |
375 |
376 | {# Include dialogs #} 377 | {{ partial("layout_partials/base_dialog",['fields':formDialogNetwork,'id':'DialogNetwork','label':lang._('Edit Network')])}} 378 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/views/OPNsense/Netmaker/servers.volt: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright (c) 2023 KSA Technologies, LLC 3 | # Copyright (c) 2023 kevin.adams@ksatechnologies 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without modification, 7 | # are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 20 | # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | # POSSIBILITY OF SUCH DAMAGE. 26 | #} 27 | 28 | 313 | 314 | 315 | 321 | 322 |
323 | {% if showIntro|default('0')=='1' %} 324 |
325 |
326 |

{{ lang._('Introduction') }}

327 |

{{ lang._('This plugin supports 3 databases:') }}

328 |
    329 |
  • {{ lang._('sqlite - A small, fast, self-contained, and local SQL database engine (default)') }}
  • 330 |
  • {{ lang._('rqlite - A lightweight and easy-to-use distrubuted relational database based on SQLite.') }}
  • 331 |
  • {{ lang._('PostgreSQL - An extended SQL open source object-relational database.') }}
  • 332 |
333 |
334 |
335 | {% endif %} 336 | 337 | 338 |
339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 359 | 360 | 361 |
{{ lang._('Enabled') }}{{ lang._('Name') }}{{ lang._('Description') }}{{ lang._('Base Domain') }}{{ lang._('ID') }}{{ lang._('Commands') }}
356 | 357 | 358 |
362 | 363 |
364 |
365 | 369 | 370 |
371 |
372 |
373 |
374 | 375 |
376 | {# Include dialogs #} 377 | {{ partial("layout_partials/base_dialog",['fields':formDialogServer,'id':'DialogServer','label':lang._('Edit Server')])}} 378 | 379 | -------------------------------------------------------------------------------- /src/opnsense/scripts/OPNsense/netmaker/test.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheGrandWazoo/os-netmaker/43859af4d5a7586e0d44c04fce35e3628f4dbac5/src/opnsense/scripts/OPNsense/netmaker/test.sh -------------------------------------------------------------------------------- /src/opnsense/service/conf/actions.d/actions_netmaker.conf: -------------------------------------------------------------------------------- 1 | [stop] 2 | command:/usr/local/etc/rc.d/netmaker stop 3 | parameters: 4 | type:script 5 | message:stop netmaker daemon 6 | 7 | [start] 8 | command:/usr/local/etc/rc.d/netmaker start 9 | parameters: 10 | type:script 11 | message:start netmaker daemon 12 | 13 | [restart] 14 | command:/usr/local/etc/rc.d/netmaker restart 15 | parameters: 16 | type:script 17 | message:restart netmaker daemon 18 | 19 | [status] 20 | command:/usr/local/etc/rc.d/netmaker status; exit 0 21 | parameters: 22 | type:script_output 23 | message:get netmaker status 24 | -------------------------------------------------------------------------------- /src/opnsense/service/templates/OPNsense/Netmaker/+TARGETS: -------------------------------------------------------------------------------- 1 | netmaker.yaml:/usr/local/etc/netmaker/netmaker.yaml 2 | rc.conf.d:/etc/rc.conf.d/netmaker 3 | mosquitto.conf:/usr/local/etc/mosquitto/mosquitto.conf 4 | -------------------------------------------------------------------------------- /src/opnsense/service/templates/OPNsense/Netmaker/mosquitto.conf: -------------------------------------------------------------------------------- 1 | per_listener_settings false 2 | {% if helpers.exists('OPNsense.Netmaker.servers') %} 3 | {% for server in helpers.toList('OPNsense.Netmaker.servers.server') %} 4 | {# # ignore disabled transports #} 5 | {% if server.enabled == '1' %} 6 | listener {{server.mqPortExt}} {{server.mqHostExt}} 7 | allow_anonymous false 8 | 9 | listener {{server.mqPortInt}} {{server.mqHostInt}} 10 | allow_anonymous false 11 | 12 | plugin /usr/local/lib/mosquitto_dynamic_security.so 13 | plugin_opt_config_file /usr/local/etc/mosquitto/data/dynamic-security.json 14 | 15 | {% endif %} 16 | {% endfor %} 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /src/opnsense/service/templates/OPNsense/Netmaker/netmaker.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | {% if helpers.exists('OPNsense.Netmaker.servers') %} 3 | {% for server in helpers.toList('OPNsense.Netmaker.servers.server') %} 4 | {# # ignore disabled transports #} 5 | {% if server.enabled == '1' %} 6 | server: "broker.{{server.baseDomain}}" 7 | apiport: "{{server.intApiPort}}" 8 | apiconn: "api.{{server.baseDomain}}:{{server.extApiPort}}" 9 | masterkey: "{{server.apiServerToken}}" 10 | mqhost: "{{server.mqHostInt}}" 11 | mqport: "{{server.mqPortInt}}" 12 | mqadminpassword: "{{server.mqAdminPwd}}" 13 | {% endif %} 14 | {% endfor %} 15 | {% endif %} 16 | manageiptables: "off" 17 | messagequeuebackend: "off" 18 | -------------------------------------------------------------------------------- /src/opnsense/service/templates/OPNsense/Netmaker/rc.conf.d: -------------------------------------------------------------------------------- 1 | {# Macro import #} 2 | {% if not helpers.empty('OPNsense.Netmaker.general.enabled') %} 3 | netmaker_enable="YES" 4 | mosquitto_enable="YES" 5 | {% else %} 6 | netmaker_enable="NO" 7 | mosquitto_enable="NO" 8 | {% endif %} 9 | --------------------------------------------------------------------------------