security/tor: merge version 0.1 from master

(cherry picked from commit e4be764929)
(cherry picked from commit 1b704043f7)
(cherry picked from commit b74116dba5)
(cherry picked from commit ac4c6102ff)
This commit is contained in:
Fabian Franz 2017-09-17 12:43:34 +02:00 committed by Franco Fichtner
parent 606da11cae
commit b1018848f0
40 changed files with 2368 additions and 0 deletions

View file

@ -57,6 +57,7 @@ security/acme-client -- Let's Encrypt client
security/clamav -- Antivirus engine for detecting malicious threats
security/intrusion-detection-content-pt-open -- IDS PT Research ruleset (only for non-commercial use)
security/tinc -- Tinc VPN
security/tor -- The Onion Router
www/c-icap -- c-icap connects your Proxy with a virus scanner
www/web-proxy-sso -- Add SSO Active Directory to use in Proxy
```

8
security/tor/Makefile Normal file
View file

@ -0,0 +1,8 @@
PLUGIN_NAME= tor
PLUGIN_VERSION= 0.1
PLUGIN_COMMENT= The Onion Router
PLUGIN_DEPENDS= tor
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
PLUGIN_DEVEL= yes
.include "../../Mk/plugins.mk"

View file

@ -0,0 +1,65 @@
<?php
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
function tor_enabled()
{
$model = new \OPNsense\Tor\General();
if ((string)$model->enabled == '1') {
return true;
}
return false;
}
function tor_firewall($fw)
{
if (tor_enabled()) {
}
}
function tor_services()
{
global $config;
$services = array();
if (tor_enabled()) {
$services[] = array(
'description' => gettext('The Onion Router'),
'configd' => array(
'restart' => array('tor restart'),
'start' => array('tor start'),
'stop' => array('tor stop'),
),
'name' => 'tor',
'pidfile' => '/var/run/tor/tor.pid'
);
}
return $services;
}

View file

@ -0,0 +1,169 @@
<?php
/*
* Copyright (C) 2015-2017 Deciso B.V.
* Copyright (C) 2015 Jos Schellevis
* Copyright (C) 2017 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Tor\ACLSocksPolicy;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
class ExitaclController extends ApiMutableModelControllerBase
{
static protected $internalModelName = 'exitpolicy';
static protected $internalModelClass = '\OPNsense\Tor\ACLExitPolicy';
public function searchaclAction()
{
$this->sessionClose();
$mdl = $this->getModel();
$grid = new UIModelGrid($mdl->policy);
return $grid->fetchBindRequest(
$this->request,
array('enabled', 'type', 'network', 'action', 'startport', 'endport')
);
}
public function getaclAction($uuid = null)
{
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('policy.' . $uuid);
if ($node != null) {
// return node
return array('exitpolicy' => $node->getNodes());
}
} else {
$node = $mdl->policy->add();
return array('exitpolicy' => $node->getNodes());
}
return array();
}
public function addaclAction()
{
$result = array('result' => 'failed');
if ($this->request->isPost() && $this->request->hasPost('exitpolicy')) {
$result = array('result' => 'failed', 'validations' => array());
$mdl = $this->getModel();
$node = $mdl->policy->Add();
$node->setNodes($this->request->getPost('exitpolicy'));
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'exitpolicy', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
$mdl->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result['result'] = 'saved';
}
}
return $result;
}
public function delaclAction($uuid)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
if ($mdl->policy->del($uuid)) {
$mdl->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setaclAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost('exitpolicy')) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('policy.' . $uuid);
if ($node != null) {
$result = array('result' => 'failed', 'validations' => array());
$info = $this->request->getPost('exitpolicy');
$node->setNodes($info);
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'exitpolicy', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
unset($result['validations']);
Config::getInstance()->save();
$result = array('result' => 'saved');
}
return $result;
}
}
}
return array('result' => 'failed');
}
public function toggle_handler($uuid, $element)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference($element . '.' . $uuid);
if ($node != null) {
if ($node->enabled->__toString() == '1') {
$result['result'] = 'Disabled';
$node->enabled = '0';
} else {
$result['result'] = 'Enabled';
$node->enabled = '1';
}
$mdl->serializeToConfig();
Config::getInstance()->save();
}
}
}
return $result;
}
public function toggleaclAction($uuid)
{
return $this->toggle_handler($uuid, 'policy');
}
}

View file

@ -0,0 +1,73 @@
<?php
/**
* Copyright (C) 2017 Fabian Franz
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Core\Config;
use \OPNsense\Tor\General;
class GeneralController extends ApiMutableModelControllerBase
{
static protected $internalModelClass = '\OPNsense\Tor\General';
static protected $internalModelName = 'general';
/* override default set action */
public function setAction()
{
$result = array('result'=>'failed');
if ($this->request->isPost()) {
$mdl = new General();
$mdl->setNodes($this->request->getPost('general'));
// perform validation
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
if (!array_key_exists('validations', $result)) {
$result['validations'] = array();
}
$result['validations']['general.'.$msg->getField()] = $msg->getMessage();
}
if ($valMsgs->count() == 0) {
if (empty((string)$mdl->control_port_password) || empty((string)$mdl->control_port_password_hashed)) {
$backend = new Backend();
$keys = json_decode(trim($backend->configdRun('tor genkey')), true);
$mdl->control_port_password_hashed = $keys['hashed_control_password'];
$mdl->control_port_password = $keys['control_password'];
}
$mdl->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'saved';
}
}
return $result;
}
}

View file

@ -0,0 +1,171 @@
<?php
/*
* Copyright (C) 2015-2017 Deciso B.V.
* Copyright (C) 2015 Jos Schellevis
* Copyright (C) 2017 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Tor\HiddenService;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
class HiddenserviceController extends ApiMutableModelControllerBase
{
static protected $internalModelName = 'hiddenservice';
static protected $internalModelClass = '\OPNsense\Tor\HiddenService';
public function searchserviceAction()
{
$this->sessionClose();
$mdl = $this->getModel();
$grid = new UIModelGrid($mdl->service);
return $grid->fetchBindRequest(
$this->request,
array('enabled', 'name')
);
}
public function getserviceAction($uuid = null)
{
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('service.' . $uuid);
if ($node != null) {
// return node
return array('hiddenservice' => $node->getNodes());
}
} else {
$node = $mdl->service->add();
return array('hiddenservice' => $node->getNodes());
}
return array();
}
public function addserviceAction()
{
$result = array('result' => 'failed');
if ($this->request->isPost() && $this->request->hasPost('hiddenservice')) {
$result = array('result' => 'failed', 'validations' => array());
$mdl = $this->getModel();
$node = $mdl->service->Add();
$node->setNodes($this->request->getPost('hiddenservice'));
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'hiddenservice', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result['result'] = 'saved';
}
}
return $result;
}
public function delserviceAction($uuid)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
if ($mdl->service->del($uuid)) {
$mdl->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setserviceAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost('hiddenservice')) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('service.' . $uuid);
if ($node != null) {
$result = array('result' => 'failed', 'validations' => array());
$info = $this->request->getPost('hiddenservice');
$node->setNodes($info);
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'hiddenservice', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
unset($result['validations']);
Config::getInstance()->save();
$result = array('result' => 'saved');
}
return $result;
}
}
}
return array('result' => 'failed');
}
public function toggle_handler($uuid, $element)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference($element . '.' . $uuid);
if ($node != null) {
if ($node->enabled->__toString() == '1') {
$result['result'] = 'Disabled';
$node->enabled = '0';
} else {
$result['result'] = 'Enabled';
$node->enabled = '1';
}
// if item has toggled, serialize to config and save
$mdl->serializeToConfig();
Config::getInstance()->save();
}
}
}
return $result;
}
public function toggleserviceAction($uuid)
{
return $this->toggle_handler($uuid, 'service');
}
}

View file

@ -0,0 +1,170 @@
<?php
/*
* Copyright (C) 2015-2017 Deciso B.V.
* Copyright (C) 2015 Jos Schellevis
* Copyright (C) 2017 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Tor\HiddenServiceACL;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
class HiddenserviceaclController extends ApiMutableModelControllerBase
{
static protected $internalModelName = 'hiddenserviceacl';
static protected $internalModelClass = '\OPNsense\Tor\HiddenServiceACL';
public function searchaclAction()
{
$this->sessionClose();
$mdl = $this->getModel();
$grid = new UIModelGrid($mdl->hiddenserviceacl);
return $grid->fetchBindRequest(
$this->request,
array('enabled', 'hiddenservice', 'port', 'target_host', 'target_port')
);
}
public function getaclAction($uuid = null)
{
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('hiddenserviceacl.' . $uuid);
if ($node != null) {
// return node
return array('hiddenserviceacl' => $node->getNodes());
}
} else {
$node = $mdl->hiddenserviceacl->add();
return array('hiddenserviceacl' => $node->getNodes());
}
return array();
}
public function addaclAction()
{
$result = array('result' => 'failed');
if ($this->request->isPost() && $this->request->hasPost('hiddenserviceacl')) {
$result = array('result' => 'failed', 'validations' => array());
$mdl = $this->getModel();
$node = $mdl->hiddenserviceacl->Add();
$node->setNodes($this->request->getPost('hiddenserviceacl'));
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'hiddenserviceacl', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result['result'] = 'saved';
}
}
return $result;
}
public function delaclAction($uuid)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
if ($mdl->hiddenserviceacl->del($uuid)) {
$mdl->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setaclAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost('hiddenserviceacl')) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('hiddenserviceacl.' . $uuid);
if ($node != null) {
$result = array('result' => 'failed', 'validations' => array());
$info = $this->request->getPost('hiddenserviceacl');
$node->setNodes($info);
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'hiddenserviceacl', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
unset($result['validations']);
Config::getInstance()->save();
$result = array('result' => 'saved');
}
return $result;
}
}
}
return array('result' => 'failed');
}
public function toggle_handler($uuid, $element)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference($element . '.' . $uuid);
if ($node != null) {
if ($node->enabled->__toString() == '1') {
$result['result'] = 'Disabled';
$node->enabled = '0';
} else {
$result['result'] = 'Enabled';
$node->enabled = '1';
}
$mdl->serializeToConfig();
Config::getInstance()->save();
}
}
}
return $result;
}
public function toggleaclAction($uuid)
{
return $this->toggle_handler($uuid, 'hiddenserviceacl');
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
* Copyright (C) 2017 Fabian Franz
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Base\ApiMutableModelControllerBase;
class RelayController extends ApiMutableModelControllerBase
{
static protected $internalModelClass = '\OPNsense\Tor\Relay';
static protected $internalModelName = 'relay';
}

View file

@ -0,0 +1,160 @@
<?php
/**
* Copyright (C) 2015 - 2017 Deciso B.V.
* Copyright (C) 2017 Fabian Franz
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Tor\General;
/**
* Class ServiceController
* @package OPNsense\Tor
*/
class ServiceController extends ApiControllerBase
{
/**
* start tor service
* @return array
*/
public function startAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('tor start');
$backend->configdRun('filter reload');
return array('response' => $response);
} else {
return array('response' => array());
}
}
/**
* stop tor service
* @return array
*/
public function stopAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('tor stop');
return array('response' => $response);
} else {
return array('response' => array());
}
}
/**
* query tor hidden service hostnames
* @return array
*/
public function get_hidden_servicesAction()
{
$backend = new Backend();
$response = json_decode($backend->configdRun('tor gethostnames'));
return array('response' => $response);
}
/**
* restart tor service
* @return array
*/
public function restartAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('tor restart');
$backend->configdRun('filter reload');
return array('response' => $response);
} else {
return array('response' => array());
}
}
/**
* retrieve status of tor
* @return array
* @throws \Exception
*/
public function statusAction()
{
$backend = new Backend();
$general = new General();
$response = $backend->configdRun('tor status');
if (strpos($response, 'not running') > 0) {
if ($general->enabled->__toString() == 1) {
$status = 'stopped';
} else {
$status = 'disabled';
}
} elseif (strpos($response, 'is running') > 0) {
$status = 'running';
} elseif ($general->enabled->__toString() == 0) {
$status = 'disabled';
} else {
$status = 'unknown';
}
return array('status' => $status);
}
/**
* reconfigure tor, generate config and reload
*/
public function reconfigureAction()
{
if ($this->request->isPost()) {
// close session for long running action
$this->sessionClose();
$general = new General();
$backend = new Backend();
$runStatus = $this->statusAction();
// stop tor if it is running or not
$this->stopAction();
// generate template
$backend->configdRun('template reload OPNsense/Tor');
// (re)start daemon
if ($general->enabled->__toString() == 1) {
$this->startAction();
}
return array('status' => 'ok');
} else {
return array('status' => 'failed');
}
}
}

View file

@ -0,0 +1,169 @@
<?php
/*
* Copyright (C) 2015-2017 Deciso B.V.
* Copyright (C) 2015 Jos Schellevis
* Copyright (C) 2017 Fabian Franz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor\Api;
use \OPNsense\Tor\ACLSocksPolicy;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
class SocksaclController extends ApiMutableModelControllerBase
{
static protected $internalModelName = 'policy';
static protected $internalModelClass = '\OPNsense\Tor\ACLSocksPolicy';
public function searchaclAction()
{
$this->sessionClose();
$mdl = $this->getModel();
$grid = new UIModelGrid($mdl->policy);
return $grid->fetchBindRequest(
$this->request,
array('enabled', 'type', 'network', 'action')
);
}
public function getaclAction($uuid = null)
{
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('policy.' . $uuid);
if ($node != null) {
// return node
return array('policy' => $node->getNodes());
}
} else {
$node = $mdl->policy->add();
return array('policy' => $node->getNodes());
}
return array();
}
public function addaclAction()
{
$result = array('result' => 'failed');
if ($this->request->isPost() && $this->request->hasPost('policy')) {
$result = array('result' => 'failed', 'validations' => array());
$mdl = $this->getModel();
$node = $mdl->policy->Add();
$node->setNodes($this->request->getPost('policy'));
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'policy', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
$mdl->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result['result'] = 'saved';
}
}
return $result;
}
public function delaclAction($uuid)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
if ($mdl->policy->del($uuid)) {
$mdl->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setaclAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost('policy')) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference('policy.' . $uuid);
if ($node != null) {
$result = array('result' => 'failed', 'validations' => array());
$info = $this->request->getPost('policy');
$node->setNodes($info);
$valMsgs = $mdl->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, 'policy', $msg->getField());
$result['validations'][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdl->serializeToConfig();
unset($result['validations']);
Config::getInstance()->save();
$result = array('result' => 'saved');
}
return $result;
}
}
}
return array('result' => 'failed');
}
public function toggle_handler($uuid, $element)
{
$result = array('result' => 'failed');
if ($this->request->isPost()) {
$mdl = $this->getModel();
if ($uuid != null) {
$node = $mdl->getNodeByReference($element . '.' . $uuid);
if ($node != null) {
if ($node->enabled->__toString() == '1') {
$result['result'] = 'Disabled';
$node->enabled = '0';
} else {
$result['result'] = 'Enabled';
$node->enabled = '1';
}
$mdl->serializeToConfig();
Config::getInstance()->save();
}
}
}
return $result;
}
public function toggleaclAction($uuid)
{
return $this->toggle_handler($uuid, 'policy');
}
}

View file

@ -0,0 +1,51 @@
<?php
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor;
/**
* Class IndexController
* @package OPNsense/Tor
*/
class IndexController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
$this->view->title = gettext("The Onion Router");
$this->view->general = $this->getForm("general");
$this->view->toracl = $this->getForm("acl_sockspolicy");
$this->view->hidden_service = $this->getForm("hidden_service");
$this->view->hidden_service_acl = $this->getForm("hidden_service_acl");
$this->view->relay = $this->getForm("relay");
$this->view->exitpolicy = $this->getForm("acl_exitpolicy");
$this->view->pick('OPNsense/Tor/general');
}
}

View file

@ -0,0 +1,37 @@
<form>
<field>
<id>exitpolicy.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Enabling this will write the policy to the config file.</help>
</field>
<field>
<id>exitpolicy.type</id>
<label>Protocol</label>
<type>dropdown</type>
</field>
<field>
<id>exitpolicy.network</id>
<label>Network</label>
<type>text</type>
<help>Network on which this ACL is appied.</help>
</field>
<field>
<id>exitpolicy.startport</id>
<label>Start Port</label>
<type>text</type>
<help>Begin of the port range or the port used by this ACL.</help>
</field>
<field>
<id>exitpolicy.endport</id>
<label>End Port</label>
<type>text</type>
<help>Enter an end port if you want to use a port range.</help>
</field>
<field>
<id>exitpolicy.action</id>
<label>Action</label>
<type>dropdown</type>
<help>Reject: Do not allow the connection; Accept: Pass the connection</help>
</field>
</form>

View file

@ -0,0 +1,25 @@
<form>
<field>
<id>policy.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Enabling this will write the policy to the config file.</help>
</field>
<field>
<id>policy.type</id>
<label>Protocol</label>
<type>dropdown</type>
</field>
<field>
<id>policy.network</id>
<label>Network</label>
<type>text</type>
<help>Network on which this ACL is appied.</help>
</field>
<field>
<id>policy.action</id>
<label>Action</label>
<type>dropdown</type>
<help>Reject: Do not allow the connection; Accept: Pass the connection</help>
</field>
</form>

View file

@ -0,0 +1,104 @@
<form>
<field>
<id>general.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>This will activate the onion router.</help>
</field>
<field>
<id>general.socks_listen_ip</id>
<label>Listen Interfaces</label>
<type>select_multiple</type>
<style>dropdownstyle</style>
<help>Add more than localhost IP addresses to listen IPs for SOCKS connections.</help>
</field>
<field>
<id>general.socks_listen_port</id>
<label>SOCKS Port Number</label>
<type>text</type>
<help>Port number on which the SOCKS server should listen. The default is 9050. You should not change this unless you need the port.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.control_port</id>
<label>Control Port</label>
<type>text</type>
<help>Control Port number on which tor should listen. The default is 9051. You should not change this unless you need the port.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.enablelogfile</id>
<label>Create a logfile</label>
<type>checkbox</type>
<help>If you check this, a log file will be written to disk.</help>
</field>
<field>
<id>general.logfilelevel</id>
<label>Logfile level</label>
<type>dropdown</type>
<style>dropdownstyle</style>
<help>This is the detail level of the log. A higher level means more data is logged.</help>
</field>
<field>
<id>general.enablesyslog</id>
<label>Send log messages to syslog</label>
<type>checkbox</type>
<help>Syslog is a service which is made to collect log messages from different software and maybe to a central logging server. Check this box if you have such a setup.</help>
</field>
<field>
<id>general.sysloglevel</id>
<label>Syslog level</label>
<type>dropdown</type>
<style>dropdownstyle</style>
<help>This is the detail level of the log. A higher level means more data is logged.</help>
</field>
<field>
<id>general.fascist_firewall</id>
<label>Fascist Mode</label>
<type>checkbox</type>
<help>This try to circumvent censorship. Please note that the fascist mode does not support "Hidden Services".</help>
</field>
<field>
<id>general.fascist_firewall_ports</id>
<label>Fascist Firewall Ports</label>
<type>select_multiple</type>
<help>Open ports by the fascist firewall.</help>
<allownew>true</allownew>
<style>tokenize</style>
</field>
<field>
<id>general.enable_transparent</id>
<label>Enable Transparent Proxy</label>
<type>checkbox</type>
<help>Enable this, if you want to anonymize traffic originating from a network.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.transparent_port</id>
<label>Transparent Port</label>
<type>text</type>
<help>Port number on which the transparent proxy server should listen. The default is 9040. You should not change this unless you need the port.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.transparent_dns</id>
<label>Transparent DNS Port</label>
<type>text</type>
<help>Port number on which the transparent DNS server should listen. The default is 9053. You should not change this unless you need the port.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.transparent_ip_pool</id>
<label>Transparent IP Pool</label>
<type>text</type>
<help>Enter a network which will be used as an IP Pool to map onion Hosts.</help>
<advanced>true</advanced>
</field>
<field>
<id>general.dns_map_hosts</id>
<label>Map Host To IP Pool</label>
<type>checkbox</type>
<help>Enable this, if you want to map onion services to the IP pool configured above.</help>
<advanced>true</advanced>
</field>
</form>

View file

@ -0,0 +1,14 @@
<form>
<field>
<id>hiddenservice.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Enable this hidden service.</help>
</field>
<field>
<id>hiddenservice.name</id>
<label>Name</label>
<type>text</type>
<help>Enter a directory name for the hidden service. It may consist of lowercase and uppercase characters.</help>
</field>
</form>

View file

@ -0,0 +1,31 @@
<form>
<field>
<id>hiddenserviceacl.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Enable this hidden service.</help>
</field>
<field>
<id>hiddenserviceacl.hiddenservice</id>
<label>Hidden Service</label>
<type>dropdown</type>
</field>
<field>
<id>hiddenserviceacl.port</id>
<label>Port</label>
<type>text</type>
<help>The port number which is exposed in the Tor network.</help>
</field>
<field>
<id>hiddenserviceacl.target_host</id>
<label>Target Host</label>
<type>text</type>
<help>The Target host. Be careful when using localhost as some services may bypass ACLs when connecting from "127.0.0.1" or "::1".</help>
</field>
<field>
<id>hiddenserviceacl.target_port</id>
<label>Target Port</label>
<type>text</type>
<help>Enter the port of your target server.</help>
</field>
</form>

View file

@ -0,0 +1,62 @@
<form>
<field>
<id>relay.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Act as a relay.</help>
</field>
<field>
<id>relay.host</id>
<label>Host</label>
<type>text</type>
<advanced>true</advanced>
</field>
<field>
<id>relay.port</id>
<label>Port</label>
<type>text</type>
</field>
<field>
<id>relay.address</id>
<label>Address</label>
<type>text</type>
<help>The external FQDN of this host.</help>
</field>
<field>
<id>relay.nick</id>
<label>Nickname</label>
<type>text</type>
<help>This may only consist of characters and numbers and is used to identifiy your host.</help>
</field>
<field>
<id>relay.bandwithrate</id>
<label>Bandwith Rate</label>
<type>text</type>
</field>
<field>
<id>relay.bandwithburst</id>
<label>Bandwith Burst</label>
<type>text</type>
</field>
<field>
<id>relay.directory_port</id>
<label>Directory Port</label>
<type>text</type>
</field>
<field>
<id>relay.exitrejectprivateip</id>
<label>Reject Private IPs</label>
<type>checkbox</type>
</field>
<field>
<id>relay.relay</id>
<label>Bridge</label>
<type>checkbox</type>
<help>A bridge is a private relay. It is not visible in the public directory. Check this if you want to become a relay (public).</help>
</field>
<field>
<id>relay.publish</id>
<label>Publish Server Descriptor</label>
<type>checkbox</type>
</field>
</form>

View file

@ -0,0 +1,9 @@
<acl>
<page-tor>
<name>tor</name>
<patterns>
<pattern>ui/tor/*</pattern>
<pattern>api/tor/*</pattern>
</patterns>
</page-tor>
</acl>

View file

@ -0,0 +1,34 @@
<?php
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
class ACLExitPolicy extends BaseModel
{
}

View file

@ -0,0 +1,43 @@
<model>
<mount>//OPNsense/tor/exitpolicy</mount>
<description>ACL for Socks port</description>
<items>
<policy type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<type type="OptionField">
<default>v6</default>
<Required>Y</Required>
<OptionValues>
<v4>IPv4</v4>
<v6>IPv6</v6>
</OptionValues>
</type>
<network type="NetworkField">
<Required>Y</Required>
</network>
<startport type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</startport>
<endport type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</endport>
<action type="OptionField">
<default>accept</default>
<Required>Y</Required>
<OptionValues>
<accept>Accept</accept>
<reject>Reject</reject>
</OptionValues>
</action>
</policy>
</items>
</model>

View file

@ -0,0 +1,34 @@
<?php
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class ACLSocksPolicy extends BaseModel
{
}

View file

@ -0,0 +1,31 @@
<model>
<mount>//OPNsense/tor/aclsockspolicy</mount>
<description>ACL for Socks port</description>
<items>
<policy type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<type type="OptionField">
<default>v6</default>
<Required>Y</Required>
<OptionValues>
<v4>IPv4</v4>
<v6>IPv6</v6>
</OptionValues>
</type>
<network type="NetworkField">
<Required>Y</Required>
</network>
<action type="OptionField">
<default>accept</default>
<Required>Y</Required>
<OptionValues>
<accept>Accept</accept>
<reject>Reject</reject>
</OptionValues>
</action>
</policy>
</items>
</model>

View file

@ -0,0 +1,34 @@
<?php
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class General extends BaseModel
{
}

View file

@ -0,0 +1,103 @@
<model>
<mount>//OPNsense/tor/general</mount>
<description>General Tor configuration</description>
<items>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<socks_listen_ip type="InterfaceField">
<Required>N</Required>
<multiple>Y</multiple>
</socks_listen_ip>
<socks_listen_port type="IntegerField">
<default>9050</default>
<MinimumValue>0</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</socks_listen_port>
<control_port type="IntegerField">
<default>9051</default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</control_port>
<control_port_password type="TextField">
<Required>N</Required>
<mask>/^.+$/</mask>
</control_port_password>
<control_port_password_hashed type="TextField">
<Required>N</Required>
<mask>/^.+$/</mask>
</control_port_password_hashed>
<enablelogfile type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enablelogfile>
<logfilelevel type="OptionField">
<Required>Y</Required>
<multiple>N</multiple>
<default>notifications</default>
<OptionValues>
<err>Errors</err>
<warn>Warnings</warn>
<notice>Notifications</notice>
<info>Informational</info>
<debug>Debugging</debug>
</OptionValues>
</logfilelevel>
<enablesyslog type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enablesyslog>
<sysloglevel type="OptionField">
<Required>Y</Required>
<multiple>N</multiple>
<default>notifications</default>
<OptionValues>
<err>Errors</err>
<warn>Warnings</warn>
<notice>Notifications</notice>
<info>Informational</info>
<debug>Debugging</debug>
</OptionValues>
</sysloglevel>
<fascist_firewall type="BooleanField">
<default>0</default>
<Required>Y</Required>
</fascist_firewall>
<fascist_firewall_ports type="CSVListField">
<default>80,443</default>
<Required>Y</Required>
<mask>/^(\d+,)*\d+$/</mask>
</fascist_firewall_ports>
<enable_transparent type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enable_transparent>
<transparent_port type="IntegerField">
<default>9040</default>
<MinimumValue>0</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</transparent_port>
<transparent_dns type="IntegerField">
<default>9053</default>
<MinimumValue>0</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</transparent_dns>
<transparent_ip_pool type="NetworkField">
<default>172.29.0.0/16</default>
<Required>Y</Required>
</transparent_ip_pool>
<dns_map_hosts type="BooleanField">
<default>0</default>
<Required>Y</Required>
</dns_map_hosts>
</items>
</model>

View file

@ -0,0 +1,34 @@
<?php
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class HiddenService extends BaseModel
{
}

View file

@ -0,0 +1,17 @@
<model>
<mount>//OPNsense/tor/hiddenservice</mount>
<description>Tor hidden service configuration</description>
<items>
<service type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<Required>Y</Required>
<mask>/^[a-z0-9_-]+$/i</mask>
<ValidationMessage>The name should only consist of alphanumeric characters, dashes and underscores.</ValidationMessage>
</name>
</service>
</items>
</model>

View file

@ -0,0 +1,34 @@
<?php
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class HiddenServiceACL extends BaseModel
{
}

View file

@ -0,0 +1,42 @@
<model>
<mount>//OPNsense/tor/hiddenserviceacl</mount>
<description>Tor Hidden Service ACL</description>
<items>
<hiddenserviceacl type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<hiddenservice type="ModelRelationField">
<Model>
<template>
<source>OPNsense.Tor.HiddenService</source>
<items>service</items>
<display>name</display>
</template>
</Model>
<ValidationMessage>A hidden service must be set.</ValidationMessage>
<Multiple>N</Multiple>
<Required>Y</Required>
</hiddenservice>
<port type="IntegerField">
<default>80</default>
<MinimumValue>1</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</port>
<target_host type="NetworkField">
<Required>Y</Required>
<default>127.0.0.1</default>
</target_host>
<target_port type="IntegerField">
<default>80</default>
<MinimumValue>1</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</target_port>
</hiddenserviceacl>
</items>
</model>

View file

@ -0,0 +1,7 @@
<menu>
<Services>
<tor VisibleName="Tor" cssClass="fa fa-bolt fa-fw">
<configuration VisibleName="Configuration" url="/ui/tor/" />
</tor>
</Services>
</menu>

View file

@ -0,0 +1,34 @@
<?php
namespace OPNsense\Tor;
use OPNsense\Base\BaseModel;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class Relay extends BaseModel
{
}

View file

@ -0,0 +1,56 @@
<model>
<mount>//OPNsense/tor/relay</mount>
<description>Tor Relay configuration</description>
<items>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<host type="TextField">
<Required>N</Required>
<mask>/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[a-f0-9:]{2,})$/i</mask>
</host>
<port type="IntegerField">
<default>9001</default>
<MinimumValue>0</MinimumValue>
<Required>Y</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</port>
<directory_port type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>A valid Port number must be specified.</ValidationMessage>
</directory_port>
<address type="TextField">
<Required>N</Required>
<!-- hostname -->
<mask>/^[a-z0-9.-]+$/i</mask>
</address>
<nick type="TextField">
<mask>/^.+$/</mask>
<Required>N</Required>
<!-- by docs -->
<mask>/^[a-zA-Z0-9]+$/</mask>
</nick>
<bandwithrate type="IntegerField">
<Required>N</Required>
</bandwithrate>
<bandwithburst type="IntegerField">
<Required>N</Required>
</bandwithburst>
<relay type="BooleanField">
<default>0</default>
<Required>Y</Required>
</relay>
<exitrejectprivateip type="BooleanField">
<default>1</default>
<Required>Y</Required>
</exitrejectprivateip>
<publish type="BooleanField">
<default>0</default>
<Required>Y</Required>
</publish>
</items>
</model>

View file

@ -0,0 +1,240 @@
{#
Copyright (C) 2017 Fabian Franz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
#}
<script type="text/javascript">
$( document ).ready(function() {
var data_get_map = {
'general': '/api/tor/general/get',
'relay': '/api/tor/relay/get'
};
mapDataToFormUI(data_get_map).done(function(data){
formatTokenizersUI();
$('select.dropdownstyle').selectpicker('refresh');
});
ajaxCall(url="/api/tor/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['result']);
});
// link save button to API set action
[
{'selector': '#generalsaveAct', 'endpoint': '/api/tor/general/set', 'formid': 'general'},
{'selector': '#relaysaveAct', 'endpoint': '/api/tor/relay/set', 'formid': 'relay'}
].forEach(function (cfg) {
$(cfg.selector).click(function(){
saveFormToEndpoint(url=cfg.endpoint, formid=cfg.formid,callback_ok=function(){
$(cfg.selector + " .saveAct_progress").addClass("fa fa-spinner fa-pulse");
ajaxCall(url="/api/tor/service/restart", sendData={}, callback=function(data,status) {
ajaxCall(url="/api/tor/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['result']);
});
$(cfg.selector + " .saveAct_progress").removeClass("fa fa-spinner fa-pulse");
});
});
});
});
$("#grid-hidden").UIBootgrid(
{ 'search':'/api/tor/hiddenservice/searchservice',
'get':'/api/tor/hiddenservice/getservice/',
'set':'/api/tor/hiddenservice/setservice/',
'add':'/api/tor/hiddenservice/addservice/',
'del':'/api/tor/hiddenservice/delservice/',
'toggle':'/api/tor/hiddenservice/toggleservice/',
'options':{selection:false, multiSelect:false}
}
);
$("#grid-hiddenacl").UIBootgrid(
{ 'search':'/api/tor/hiddenserviceacl/searchacl',
'get':'/api/tor/hiddenserviceacl/getacl/',
'set':'/api/tor/hiddenserviceacl/setacl/',
'add':'/api/tor/hiddenserviceacl/addacl/',
'del':'/api/tor/hiddenserviceacl/delacl/',
'toggle':'/api/tor/hiddenserviceacl/toggleacl/',
'options':{selection:false, multiSelect:false}
}
);
$("#grid-toracl").UIBootgrid(
{ 'search':'/api/tor/socksacl/searchacl',
'get':'/api/tor/socksacl/getacl/',
'set':'/api/tor/socksacl/setacl/',
'add':'/api/tor/socksacl/addacl/',
'del':'/api/tor/socksacl/delacl/',
'toggle':'/api/tor/socksacl/toggleacl/',
'options':{selection:false, multiSelect:false}
}
);
$("#grid-exitacl").UIBootgrid(
{ 'search':'/api/tor/exitacl/searchacl',
'get':'/api/tor/exitacl/getacl/',
'set':'/api/tor/exitacl/setacl/',
'add':'/api/tor/exitacl/addacl/',
'del':'/api/tor/exitacl/delacl/',
'toggle':'/api/tor/exitacl/toggleacl/',
'options':{selection:false, multiSelect:false}
}
);
});
</script>
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General') }}</a></li>
<li><a data-toggle="tab" href="#acl">{{ lang._('SOCKS Proxy ACL') }}</a></li>
<li><a data-toggle="tab" href="#hidden">{{ lang._('Hidden Services') }}</a></li>
<li><a data-toggle="tab" href="#hiddenrouting">{{ lang._('Hidden Service Routing') }}</a></li>
<li><a data-toggle="tab" href="#relay">{{ lang._('Relaying') }}</a></li>
<li><a data-toggle="tab" href="#exitnodeacl">{{ lang._('Exit Node ACL') }}</a></li>
</ul>
<div class="tab-content content-box tab-content" style="padding-bottom: 1.5em;">
<div id="general" class="tab-pane fade in active">
{{ partial("layout_partials/base_form",['fields': general,'id':'general'])}}
<div class="col-md-12">
<hr />
<button class="btn btn-primary" id="generalsaveAct" type="button"><b>{{ lang._('Save') }}</b> <i class="saveAct_progress"></i></button>
</div>
</div>
<div id="acl" class="tab-pane fade in">
<table id="grid-toracl" class="table table-responsive" data-editDialog="toracldlg">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="action" data-type="string" data-visible="true">{{ lang._('Action') }}</th>
<th data-column-id="type" data-type="string" data-visible="true">{{ lang._('Protocol') }}</th>
<th data-column-id="network" data-type="string" data-visible="true">{{ lang._('Network') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="3"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<!-- <button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button> -->
</td>
</tr>
</tfoot>
</table>
</div>
<div id="hidden" class="tab-pane fade in">
<table id="grid-hidden" class="table table-responsive" data-editDialog="hiddenservicedlg">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string" data-visible="true">{{ lang._('Name') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="3"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<!-- <button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button> -->
</td>
</tr>
</tfoot>
</table>
</div>
<div id="hiddenrouting" class="tab-pane fade in">
<table id="grid-hiddenacl" class="table table-responsive" data-editDialog="hiddenserviceacl">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="hiddenservice" data-type="string" data-visible="true">{{ lang._('Hidden Service') }}</th>
<th data-column-id="port" data-type="string" data-visible="true">{{ lang._('Port') }}</th>
<th data-column-id="target_host" data-type="string" data-visible="true">{{ lang._('Target Host') }}</th>
<th data-column-id="target_port" data-type="string" data-visible="true">{{ lang._('Target Port') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<!-- <button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button> -->
</td>
</tr>
</tfoot>
</table>
</div>
<div id="relay" class="tab-pane fade in">
{{ partial("layout_partials/base_form",['fields': relay,'id':'relay'])}}
<div class="col-md-12">
<hr />
<button class="btn btn-primary" id="relaysaveAct" type="button"><b>{{ lang._('Save') }}</b> <i class="saveAct_progress"></i></button>
</div>
</div>
<div id="exitnodeacl" class="tab-pane fade in">
<div class="alert alert-danger" role="alert">
{{ lang._('Running an exit node may be lead to legal issues and seized hardware. Be careful with your settings here.') }}
</div>
<table id="grid-exitacl" class="table table-responsive" data-editDialog="torexitacldlg">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="action" data-type="string" data-visible="true">{{ lang._('Action') }}</th>
<th data-column-id="type" data-type="string" data-visible="true">{{ lang._('Protocol') }}</th>
<th data-column-id="network" data-type="string" data-visible="true">{{ lang._('Network') }}</th>
<th data-column-id="startport" data-type="string" data-visible="true">{{ lang._('Start Port') }}</th>
<th data-column-id="endport" data-type="string" data-visible="true">{{ lang._('End Port') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="3"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<!-- <button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button> -->
</td>
</tr>
</tfoot>
</table>
</div>
</div>
{{ partial("layout_partials/base_dialog",['fields': toracl,'id':'toracldlg', 'label':lang._('Edit ACL Entry')]) }}
{{ partial("layout_partials/base_dialog",['fields': hidden_service,'id':'hiddenservicedlg', 'label':lang._('Edit Hidden Service')]) }}
{{ partial("layout_partials/base_dialog",['fields': hidden_service_acl,'id':'hiddenserviceacl', 'label':lang._('Edit Hidden Service Route')]) }}
{{ partial("layout_partials/base_dialog",['fields': exitpolicy,'id':'torexitacldlg', 'label':lang._('Edit Exit Node ACL')]) }}

View file

@ -0,0 +1,35 @@
[start]
command:/usr/local/opnsense/scripts/tor/setup.sh;/usr/local/etc/rc.d/tor start
parameters:
type:script
message:starting tor
[stop]
command:/usr/local/etc/rc.d/tor onestop
parameters:
type:script
message:stopping tor
[restart]
command:/usr/local/opnsense/scripts/tor/setup.sh;/usr/local/etc/rc.d/tor restart
parameters:
type:script
message:restarting tor
[status]
command:/usr/local/etc/rc.d/tor status;exit 0
parameters:
type:script_output
message:request tor status
[genkey]
command:/usr/local/opnsense/service/scripts/tor/gen_key
parameters:
type:script_output
message:generate Tor control key
[gethostnames]
command:/usr/local/opnsense/service/scripts/tor/get_hostnames
parameters:
type:script_output
message:query hostnames of hidden services

View file

@ -0,0 +1,9 @@
#!/bin/sh
PASSWORD=$( /usr/local/bin/openssl rand -base64 32 )
echo "{"
echo -n " \"hashed_control_password\":\""
tor --quiet --hash-password "$PASSWORD" | tr -d '\n' | tr -d '\r'
echo "\","
echo " \"control_password\":\"$PASSWORD\""
echo "}"

View file

@ -0,0 +1,24 @@
#!/usr/local/bin/php
<?php
require_once("config.inc");
require_once('tor_helper.php');
use \OPNsense\Tor\HiddenService;
$hostnames = array();
$services = new HiddenService();
foreach ($services->service->__items as $service) {
$directory_name = ((string)$service->name);
$hostnamefile = TOR_DATA_DIR . '/' . $directory_name . '/hostname';
if (file_exists($hostnamefile)) {
$hostname = @file_get_contents($hostnamefile);
}
if (empty($hostname)) {
$hostname = 'not available';
}
$hostname = trim($hostname);
$hostnames[$directory_name] = $hostname;
}
print json_encode($hostnames);

View file

@ -0,0 +1,7 @@
#!/bin/sh
mkdir -p /var/db/tor
mkdir -p /var/log/tor
mkdir -p /var/run/tor
# required to access the pf device for nat
/usr/sbin/pw groupmod proxy -m _tor

View file

@ -0,0 +1,3 @@
<?php
define('TOR_DATA_DIR', '/var/db/tor');

View file

@ -0,0 +1,2 @@
torrc:/usr/local/etc/tor/torrc
tor:/etc/rc.conf.d/tor

View file

@ -0,0 +1,6 @@
{% if helpers.exists('OPNsense.tor.general.enabled') and OPNsense.tor.general.enabled == '1' %}
tor_enable="YES"
tor_opnsense_bootup_run="/usr/local/opnsense/service/scripts/tor/setup.sh"
{% else %}
tor_enable="NO"
{% endif %}

View file

@ -0,0 +1,182 @@
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
##
## OPNsense autogenerated config file.
## Don't change it because your changes get lost.
##
##
{% if helpers.exists('OPNsense.tor.general.enabled') and OPNsense.tor.general.enabled == '1' %}
SOCKSPort 127.0.0.1:{{ OPNsense.tor.general.socks_listen_port|default('9050') }} # localhost IPv4
SOCKSPort [::1]:{{ OPNsense.tor.general.socks_listen_port|default('9050') }} # localhost IPv6
{% if helpers.exists('OPNsense.tor.general.socks_listen_ip') and OPNsense.tor.general.socks_listen_ip != '' %}
{% for listen_interface in OPNsense.tor.general.socks_listen_ip.split(',') %}
{% if helpers.exists('interfaces.'+listen_interface+'.ipaddr') %}
{% set interface_ip = helpers.getNodeByTag('interfaces.'+listen_interface+'.ipaddr') %}
{% if '.' in interface_ip %}
# {{ listen_interface }}: IPv4
SOCKSPort {{ interface_ip }}:{{ OPNsense.tor.general.socks_listen_port|default('9050') }}
{% endif %}
{% endif %}
{% if helpers.exists('interfaces.'+listen_interface+'.ipaddrv6') %}
{% set interface_ip = helpers.getNodeByTag('interfaces.'+listen_interface+'.ipaddrv6') %}
{% if ':' in interface_ip %}
# {{ listen_interface }}: IPv6
SOCKSPort [{{ interface_ip }}]:{{ OPNsense.tor.general.socks_listen_port|default('9050') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if helpers.exists('OPNsense.tor.aclsockspolicy') %}
{% if helpers.exists('OPNsense.tor.aclsockspolicy.policy') %}
{% for policy in helpers.toList('OPNsense.tor.aclsockspolicy.policy') %}
{% if policy.enabled == '1' %}
SOCKSPolicy {{ policy.action }}{% if policy.type == 'v6' %}6{% endif %} {{ policy.network }}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
SOCKSPolicy reject *
SOCKSPolicy reject6 *
{% if helpers.exists('OPNsense.tor.general.enablelogfile') and OPNsense.tor.general.enablelogfile == '1' %}
Log {{ OPNsense.tor.general.logfilelevel }} file /var/log/tor.log
{% endif %}
{% if helpers.exists('OPNsense.tor.general.enablesyslog') and OPNsense.tor.general.enablesyslog == '1' %}
Log {{ OPNsense.tor.general.sysloglevel }} syslog
{% endif %}
DataDirectory /var/db/tor
{% if helpers.exists('OPNsense.tor.general.control_port') and OPNsense.tor.general.control_port != '' %}
ControlPort {{ OPNsense.tor.general.control_port }}
HashedControlPassword {{ OPNsense.tor.general.control_port_password_hashed }}
{% endif %}
{% if helpers.exists('OPNsense.tor.general.fascist_firewall') and OPNsense.tor.general.fascist_firewall == '1' %}
FascistFirewall 1
{% if helpers.exists('OPNsense.tor.general.fascist_firewall_ports') and OPNsense.tor.general.fascist_firewall_ports != '' %}
FirewallPorts {{ OPNsense.tor.general.fascist_firewall_ports }}
{% endif %}
{% else %}
FascistFirewall 0
{% endif %}
{% if helpers.exists('OPNsense.tor.general.enable_transparent') and OPNsense.tor.general.enable_transparent == '1' %}
TransPort {{ OPNsense.tor.general.transparent_port }}
DNSPort {{ OPNsense.tor.general.transparent_dns }}
VirtualAddrNetwork {{ OPNsense.tor.general.transparent_ip_pool }}
AutomapHostsOnResolve {{ OPNsense.tor.general.dns_map_hosts }}
{% endif %}
{% if helpers.exists('OPNsense.tor.hiddenservice') and helpers.exists('OPNsense.tor.hiddenserviceacl') and helpers.exists('OPNsense.tor.hiddenserviceacl.hiddenserviceacl') %}
############### This section is just for location-hidden services ###
## Once you have configured a hidden service, you can look at the
## contents of the file ".../hidden_service/hostname" for the address
## to tell people.
{% if helpers.exists('OPNsense.tor.hiddenservice.service') %}
{% for service in helpers.toList('OPNsense.tor.hiddenservice.service') %}
HiddenServiceDir /var/db/tor/{{ service.name }}/
{% for acl in helpers.toList('OPNsense.tor.hiddenserviceacl.hiddenserviceacl') %}
{% if helpers.getUUID(acl.hiddenservice).name == service.name %}
HiddenServicePort {{ acl.port}} {{ acl.target_host }}:{{ acl.target_port }}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% endif %}
{% if helpers.exists('OPNsense.tor.relay.enabled') and OPNsense.tor.relay.enabled == '1' %}
ORPort {% if helpers.exists('OPNsense.tor.relay.host') and OPNsense.tor.relay.host != '' %}{{ OPNsense.tor.relay.host }}:{% endif%}{{ OPNsense.tor.relay.port|default('9001') }}
{% if helpers.exists('OPNsense.tor.relay.address') and OPNsense.tor.relay.address != '' %}
Address {{ OPNsense.tor.relay.address }}
{% endif %}
## If you have multiple network interfaces, you can specify one for
## outgoing traffic to use.
## OutboundBindAddressExit will be used for all exit traffic, while
## OutboundBindAddressOR will be used for all other connections.
## If you do not wish to differentiate, use OutboundBindAddress to
## specify the same address for both in a single line.
#OutboundBindAddressExit 10.0.0.4
#OutboundBindAddressOR 10.0.0.5
{% if helpers.exists('OPNsense.tor.relay.nick') and OPNsense.tor.relay.nick != '' %}
Nickname {{ OPNsense.tor.relay.nick }}
{% endif %}
{% if helpers.exists('OPNsense.tor.relay.bandwithrate') and OPNsense.tor.relay.bandwithrate != '' %}
RelayBandwidthRate {{ OPNsense.tor.relay.bandwithrate }} KBytes
{% endif %}
{% if helpers.exists('OPNsense.tor.relay.bandwithburst') and OPNsense.tor.relay.bandwithburst != '' %}
RelayBandwidthBurst {{ OPNsense.tor.relay.bandwithburst }} KBytes
{% endif %}
## Use these to restrict the maximum traffic per day, week, or month.
## Note that this threshold applies separately to sent and received bytes,
## not to their sum: setting "40 GB" may allow up to 80 GB total before
## hibernating.
##
## Set a maximum of 40 gigabytes each way per period.
#AccountingMax 40 GBytes
## Each period starts daily at midnight (AccountingMax is per day)
#AccountingStart day 00:00
## Each period starts on the 3rd of the month at 15:00 (AccountingMax
## is per month)
#AccountingStart month 3 15:00
#ContactInfo 0xFFFFFFFF Random Person <nobody AT example dot com>
{% if helpers.exists('OPNsense.tor.relay.directory_port') and OPNsense.tor.relay.directory_port != '' %}
DirPort {{ OPNsense.tor.relay.directory_port }}
{% endif %}
## Uncomment to return an arbitrary blob of html on your DirPort. Now you
## can explain what Tor is if anybody wonders why your IP address is
## contacting them. See contrib/tor-exit-notice.html in Tor's source
## distribution for a sample.
#DirPortFrontPage /usr/local/etc/tor/tor-exit-notice.html
{% if helpers.exists('OPNsense.tor.relay.exitrejectprivateip') %}
ExitPolicyRejectPrivate {{ OPNsense.tor.relay.exitrejectprivateip }}
{% endif %}
{% if helpers.exists('OPNsense.tor.exitpolicy') %}
{% if helpers.exists('OPNsense.tor.exitpolicy.policy') %}
# exit node policy
{% for policy in helpers.toList('OPNsense.tor.exitpolicy.policy') %}
{% if policy.enabled == '1' %}
ExitPolicy {{ policy.action }}{% if policy.type == 'v6' %}6{% endif
%} {% if policy.network == '' %}*{% if 'v' in policy.type %}{{ policy.type|replace('v','') }}{% endif%}{% else
%}{{ policy.network }}{% endif
%}{% if 'startport' in policy %}:{{ policy.startport
}}{% if 'endport' in policy %}-{{ policy.endport }}{% endif
%}{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
# default: don't pass anything
ExitPolicy reject *:*
ExitPolicy reject6 *:*
BridgeRelay {{ OPNsense.tor.relay.relay|default('1') }}
PublishServerDescriptor {{ OPNsense.tor.relay.publish|default('0') }}
{% endif %}
{% endif %}