mail/rspamd: Mail Protection (#332)

* Init Antispam

* init menu structure

* add the right icon

* add some stuff to the form

* add form elements

* remove postfix from package

* add some values to model

* add rate limit

* add some av stuff

* add surbl

* add options in dkim

* rename package

* models: rename package to Rspamd

* rename

* Makefile: rename to rspamd

* add service stubs

* some fixes

* fix input type of enabled

* add some service files

* move directory; add configd actions

* add av to templates

* add some templates; improve error messages

* add spamtrap

* fix bug

* add surbl

* add graylist; phishing

* add mx_check and ratelimit

* cleaning

* mark as devel

* add pkg description from parent port

* mv security/rspamd mail/rspamd; update Makefile; update Readme.md

* use service name in menu

* reorder categories in makefile

* update makefile: make os-clamav optional

* add clamav plugin missing warning

* add missing field to spamtrap
This commit is contained in:
Fabian Franz, BSc
2017-10-30 20:29:54 +01:00
committed by GitHub
parent 3fba5e1ca1
commit 83dd4a7868
31 changed files with 1441 additions and 1 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ PAGER?= less
all:
@cat ${.CURDIR}/README.md | ${PAGER}
CATEGORIES= devel dns net net-mgmt sysutils security www
CATEGORIES= devel dns net net-mgmt mail security sysutils www
.for CATEGORY in ${CATEGORIES}
_${CATEGORY}!= ls -1d ${CATEGORY}/*
+2
View File
@@ -52,6 +52,8 @@ net-mgmt/snmp -- SNMP Server via bsnmpd
net-mgmt/telegraf -- Agent for collecting metrics and data
net-mgmt/zabbix-agent -- Enterprise-class open source distributed monitoring agent
net-mgmt/zabbix-proxy -- Zabbix-Proxy enables decentralized monitoring
mail/postfix -- SMTP mail relay
mail/rspamd -- Protect your network from spam
sysutils/boot-delay -- Apply a persistent 10 second boot delay
sysutils/monit -- Proactive system monitoring
sysutils/smart -- SMART tools
+8
View File
@@ -0,0 +1,8 @@
PLUGIN_NAME= rspamd
PLUGIN_VERSION= 0.1
PLUGIN_COMMENT= Protect your network from spam
PLUGIN_DEPENDS= rspamd
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
PLUGIN_DEVEL= YES
.include "../../Mk/plugins.mk"
+3
View File
@@ -0,0 +1,3 @@
Rspamd is fast, modular and lightweight spam filter. It is designed to work
with big amount of mail and can be easily extended with own filters written in
lua.
@@ -0,0 +1,62 @@
<?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 rspamd_enabled()
{
$model = new \OPNsense\Rspamd\RSpamd();
if ((string)$model->general->enabled == '1') {
return true;
}
return false;
}
function rspamd_firewall($fw)
{
if (rspamd_enabled()) {
}
}
function rspamd_services()
{
$services = array();
if (rspamd_enabled()) {
$services[] = array(
'description' => gettext('Rapid Spamfilter Daemon'),
'configd' => array(
'restart' => array('rspamd restart'),
'start' => array('rspamd start'),
'stop' => array('rspamd stop'),
),
'name' => 'rspamd',
'pidfile' => '/var/run/rspamd/rspamd.pid'
);
}
return $services;
}
@@ -0,0 +1,139 @@
<?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\Rspamd\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Rspamd\RSpamd;
class ServiceController extends ApiControllerBase
{
/**
* restart rspamd service
* @return array
*/
public function restartAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('rspamd restart');
return array('response' => $response);
} else {
return array('response' => array());
}
}
/**
* retrieve status of rspamd
* @return array
* @throws \Exception
*/
public function statusAction()
{
$backend = new Backend();
$rspamd = new RSpamd();
$response = $backend->configdRun('rspamd status');
if (strpos($response, 'not running') > 0) {
if ((string)$rspamd->general->enabled == 1) {
$status = 'stopped';
} else {
$status = 'disabled';
}
} elseif (strpos($response, 'is running') > 0) {
$status = 'running';
} elseif ((string)$rspamd->general->enabled == 0) {
$status = 'disabled';
} else {
$status = 'unknown';
}
return array('status' => $status);
}
/**
* reconfigure rspamd, generate config and reload
*/
public function reconfigureAction()
{
if ($this->request->isPost()) {
// close session for long running action
$this->sessionClose();
$rspamd = new RSpamd();
$backend = new Backend();
$this->stopAction();
// generate template
$backend->configdRun('template reload OPNsense/Rspamd');
// (re)start daemon
if ((string)$rspamd->general->enabled == '1') {
$this->startAction();
}
return array('status' => 'ok');
} else {
return array('status' => 'failed');
}
}
/**
* stop rspamd service
* @return array
*/
public function stopAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('rspamd stop');
return array('response' => $response);
} else {
return array('response' => array());
}
}
/**
* start rspamd service
* @return array
*/
public function startAction()
{
if ($this->request->isPost()) {
$backend = new Backend();
$response = $backend->configdRun('rspamd start');
return array('response' => $response);
} else {
return array('response' => array());
}
}
}
@@ -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\Rspamd\Api;
use \OPNsense\Base\ApiMutableModelControllerBase;
class SettingsController extends ApiMutableModelControllerBase
{
static protected $internalModelClass = '\OPNsense\Rspamd\RSpamd';
static protected $internalModelName = 'rspamd';
}
@@ -0,0 +1,50 @@
<?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\Rspamd;
use \OPNsense\Core\Backend;
/**
* Class IndexController
* @package OPNsense/Rspamd
*/
class IndexController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
$backend = new Backend();
$this->view->clamav_installed = (trim($backend->configdRun('firmware plugin clamav')) == '1');
$this->view->title = gettext("Rspamd Mail Protection");
$this->view->settings = $this->getForm("settings");
$this->view->pick('OPNsense/Rspamd/index');
}
}
@@ -0,0 +1,342 @@
<form>
<tab id="rspamd-general" description="General Settings">
<subtab id="rspamd-general-settings" description="General rSpamd Settings">
<field>
<id>rspamd.general.enabled</id>
<label>Enable rspamd</label>
<type>checkbox</type>
<help>Enable or disable the rspamd service.</help>
</field>
</subtab>
</tab>
<tab id="rspamd-anti-spam" description="Spam Protection">
<subtab id="rspamd-anti-spam-graylist" description="Graylisting">
<field>
<id>rspamd.graylist.expire</id>
<label>Expiration</label>
<type>text</type>
<help>Time after which the graylist state expires in days.</help>
</field>
<field>
<id>rspamd.graylist.timeout</id>
<label>Timeout</label>
<type>text</type>
</field>
<field>
<id>rspamd.graylist.max_data_len</id>
<label>Maximum Data Length</label>
<type>text</type>
<help>The limit of the length of data to hash.</help>
</field>
<field>
<id>rspamd.graylist.ipv4mask</id>
<label>IPv4 Mask</label>
<type>text</type>
<help>Mask bits are used to limit the network range from which the message may be resent. This is used to avoid a rejection if another server sends the second mail.</help>
</field>
<field>
<id>rspamd.graylist.ipv6mask</id>
<label>IPv6 Mask</label>
<type>text</type>
<help>Mask bits are used to limit the network range from which the message may be resent. This is used to avoid a rejection if another server sends the second mail.</help>
</field>
</subtab>
<subtab id="rspamd-anti-spam-dkim" description="DKIM">
<!-- dkim -->
<field>
<id>rspamd.dkim.cache_size</id>
<label>Cache Size</label>
<type>text</type>
</field>
<field>
<id>rspamd.dkim.cache_expire</id>
<label>Cache Expire</label>
<type>text</type>
</field>
<field>
<id>rspamd.dkim.time_jitter</id>
<label>Time Jitter</label>
<type>text</type>
</field>
<field>
<id>rspamd.dkim.trusted_only</id>
<label>Trusted Only</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.skip_multi</id>
<label>Skip Multi</label>
<type>checkbox</type>
</field>
<!-- dkim signing -->
<field>
<id>rspamd.dkim.allow_envfrom_empty</id>
<label>Allow Environment From Empty</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.allow_hdrfrom_mismatch</id>
<label>Allow Header From Mismatch</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.allow_hdrfrom_multiple</id>
<label>Allow Header From Multiple</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.allow_username_mismatch</id>
<label>Allow Username Mismatch</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.auth_only</id>
<label>Auth Only</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.sign_local</id>
<label>Sign Local</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.try_fallback</id>
<label>Try Fallback</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.dkim.use_domain</id>
<label>Use Domain</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.dkim.use_esld</id>
<label>Use eSLD</label>
<type>checkbox</type>
</field>
</subtab>
<subtab id="rspamd-anti-spam-mx-check" description="MX Check">
<field>
<id>rspamd.mx-check.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.mx_check.expire</id>
<label>Expiration</label>
<type>text</type>
</field>
</subtab>
<subtab id="rspamd-anti-spam-phishing" description="Phishing">
<field>
<id>rspamd.phishing.openphish_enabled</id>
<label>Enable Openphish</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.phishing.openphish_premium_enabled</id>
<label>Enable Openphish Premium</label>
<type>checkbox</type>
</field>
<field>
<id>rspamd.phishing.phishtank_enabled</id>
<label>Enable Phishtank</label>
<type>checkbox</type>
</field>
</subtab>
<subtab id="rspamd-anti-spam-rate-limit" description="Rate Limit">
<field>
<id>rspamd.rate_limit.per_recipient.count</id>
<label>Per Recipient Limit: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_recipient.time</id>
<label>Per Recipient Limit: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_recipient.time_unit</id>
<label>Per Recipient Limit: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip.count</id>
<label>Per IP Limit: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip.time</id>
<label>Per IP Limit: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip.time_unit</id>
<label>Per IP Limit: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip_from.count</id>
<label>Per IP and From Limit: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip_from.time</id>
<label>Per IP and From Limit: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.per_ip_from.time_unit</id>
<label>Per IP and From Limit: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.bounce.count</id>
<label>Bounce Limit: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.bounce.time</id>
<label>Bounce Limit: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.bounce.time_unit</id>
<label>Bounce Limit: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.bounce_ip.count</id>
<label>Bounce Limit per IP: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.bounce_ip.time</id>
<label>Bounce Limit per IP: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.bounce_ip.time_unit</id>
<label>Bounce Limit per IP: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.user.count</id>
<label>User Limit: Mail Count</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.user.time</id>
<label>User Limit: Time</label>
<type>text</type>
</field>
<field>
<id>rspamd.rate_limit.user.time_unit</id>
<label>User Limit: Time Unit</label>
<type>dropdown</type>
</field>
<field>
<id>rspamd.rate_limit.whitelisted_rcpts</id>
<label>Whitelist Recipients</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
</field>
<field>
<id>rspamd.rate_limit.max_rcpt</id>
<label>Maximum Recipients</label>
<type>text</type>
</field>
</subtab>
<subtab id="rspamd-anti-spam-spamtrap" description="Spam Trap">
<field>
<id>rspamd.spamtrap.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
<help>Enable this if you want to enable the spam trap.</help>
</field>
<field>
<id>rspamd.spamtrap.fuzzy_learning</id>
<label>Fuzzy Leraning</label>
<type>checkbox</type>
<help>Enable this if you want to enable fuzzy learning.</help>
</field>
<field>
<id>rspamd.spamtrap.spam_learning</id>
<label>Bayes Leraning</label>
<type>checkbox</type>
<help>Enable this if you want to enable bayes learning.</help>
</field>
<field>
<id>rspamd.spamtrap.spam_recipients</id>
<label>Recipients</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<help>Enter regular expressions in the form trap@example\.com into this field. The value is automatically enclosed in slashes and the case insensitive option is added.</help>
</field>
</subtab>
<subtab id="rspamd-anti-spam-spf" description="Sender Policy Framework (SPF)">
<field>
<id>rspamd.spf.spf_cache_size</id>
<label>Cache Size</label>
<type>text</type>
<help>Enter the size of the SPF cache.</help>
</field>
<field>
<id>rspamd.spf.spf_cache_expire</id>
<label>Cache Expiration</label>
<type>text</type>
<help>Enter how long SPF entries are valid.</help>
</field>
</subtab>
</tab>
<tab id="rspamd-anti-malware" description="Anti Malware">
<subtab id="rspamd-anti-malware-general" description="General Anti Malware Settings">
<field>
<id>rspamd.av.force-reject</id>
<label>Force Reject</label>
<type>checkbox</type>
<help>If set, the mail will be rejected.</help>
</field>
<field>
<id>rspamd.av.attachments-only</id>
<label>Only Scan Attachments</label>
<type>checkbox</type>
<help>If checked, only attached files are scanned and images are omitted.</help>
</field>
<field>
<id>rspamd.av.max-size</id>
<label>Maximum Size</label>
<type>text</type>
<help>If set, a message large than this size will not be scanned.</help>
</field>
<field>
<id>rspamd.av.whitelist</id>
<label>Whitelist</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<help>Mails from IPs entered here will not be scanned.</help>
</field>
</subtab>
<subtab id="rspamd-anti-malware-surbl" description="SURBL">
<field>
<id>rspamd.surbl.whitelist</id>
<label>Whitelist</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
</field>
<field>
<id>rspamd.surbl.exceptions</id>
<label>Exceptions</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
</field>
</subtab>
</tab>
<activetab>rspamd-general-settings</activetab>
</form>
@@ -0,0 +1,9 @@
<acl>
<page-Antispam>
<name>antispam</name>
<patterns>
<pattern>ui/rspamd/*</pattern>
<pattern>api/rspamd/*</pattern>
</patterns>
</page-Antispam>
</acl>
@@ -0,0 +1,5 @@
<menu>
<Services>
<antispam VisibleName="Rspamd" cssClass="fa fa-envelope fa-fw" url="/ui/rspamd/" />
</Services>
</menu>
@@ -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\Rspamd;
use OPNsense\Base\BaseModel;
class RSpamd extends BaseModel
{
}
@@ -0,0 +1,333 @@
<model>
<mount>//OPNsense/Rspamd</mount>
<description>rspamd anti spam filter</description>
<items>
<general>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
</general>
<graylist>
<expire type="IntegerField">
<Required>N</Required>
<MinimumValue>1</MinimumValue>
</expire>
<timeout type="IntegerField">
<Required>N</Required>
<MinimumValue>1</MinimumValue>
</timeout>
<max_data_len type="IntegerField">
<Required>N</Required>
</max_data_len>
<ipv4mask type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>32</MaximumValue>
<ValidationMessage>A valid IPv4 mask must be between 1 and 32 bits.</ValidationMessage>
<default>19</default>
</ipv4mask>
<ipv6mask type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>128</MaximumValue>
<default>64</default>
<ValidationMessage>A valid IPv6 mask must be between 1 and 128 bits. 64 bits are recommended as this is the recommended subnet size in IPv6.</ValidationMessage>
</ipv6mask>
</graylist>
<dkim>
<cache_size type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>A valid cache size must be set.</ValidationMessage>
</cache_size>
<cache_expire type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>A valid cache expiration must be set.</ValidationMessage>
</cache_expire>
<time_jitter type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>A valid time jitter must be set.</ValidationMessage>
</time_jitter>
<trusted_only type="BooleanField">
<default>0</default>
<Required>Y</Required>
</trusted_only>
<skip_multi type="BooleanField">
<default>0</default>
<Required>Y</Required>
</skip_multi>
<!-- dkim signing -->
<allow_envfrom_empty type="BooleanField">
<default>1</default>
<Required>Y</Required>
</allow_envfrom_empty>
<allow_hdrfrom_mismatch type="BooleanField">
<default>0</default>
<Required>Y</Required>
</allow_hdrfrom_mismatch>
<allow_hdrfrom_multiple type="BooleanField">
<default>0</default>
<Required>Y</Required>
</allow_hdrfrom_multiple>
<allow_username_mismatch type="BooleanField">
<default>0</default>
<Required>Y</Required>
</allow_username_mismatch>
<auth_only type="BooleanField">
<default>1</default>
<Required>Y</Required>
</auth_only>
<sign_local type="BooleanField">
<default>1</default>
<Required>Y</Required>
</sign_local>
<try_fallback type="BooleanField">
<default>0</default>
<Required>Y</Required>
</try_fallback>
<use_domain type="OptionField">
<default>header</default>
<Required>Y</Required>
<OptionValues>
<header>Header</header>
<envelope>Envelope</envelope>
</OptionValues>
</use_domain>
<use_esld type="BooleanField">
<default>1</default>
<Required>Y</Required>
</use_esld>
</dkim>
<mx-check>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<expire type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<default>86400</default>
<ValidationMessage>A valid cache expiration must be set.</ValidationMessage>
</expire>
</mx-check>
<phishing>
<openphish_enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</openphish_enabled>
<openphish_premium_enabled>
<default>0</default>
<Required>Y</Required>
</openphish_premium_enabled>
<phishtank_enabled>
<default>0</default>
<Required>Y</Required>
</phishtank_enabled>
</phishing>
<rate_limit>
<per_recipient>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</per_recipient>
<per_ip>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</per_ip>
<per_ip_from>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</per_ip_from>
<bounce>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</bounce>
<bounce_ip>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</bounce_ip>
<user>
<count type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The count value must be a positive number.</ValidationMessage>
</count>
<time type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>The time must be a positive integer.</ValidationMessage>
</time>
<time_unit type="OptionField">
<default>m</default>
<Required>Y</Required>
<OptionValues>
<s>Seconds</s>
<m>Minutes</m>
<h>Hours</h>
</OptionValues>
</time_unit>
</user>
<whitelisted_rcpts type="CSVListField">
<default>postmaster,mailer-daemon</default>
</whitelisted_rcpts>
<max_rcpt type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>Y</Required>
<default>20</default>
</max_rcpt>
</rate_limit>
<spamtrap>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<fuzzy_learning type="BooleanField">
<default>0</default>
<Required>Y</Required>
</fuzzy_learning>
<spam_learning type="BooleanField">
<default>1</default>
<Required>Y</Required>
</spam_learning>
<spam_recipients type="CSVListField">
<Required>N</Required>
</spam_recipients>
</spamtrap>
<spf>
<spf_cache_size type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<default>2</default>
<ValidationMessage>A valid cache size in kilobytes must be set.</ValidationMessage>
</spf_cache_size>
<spf_cache_expire type="IntegerField">
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<ValidationMessage>A valid expiration time must be set.</ValidationMessage>
</spf_cache_expire>
</spf>
<av>
<force-reject type="BooleanField">
<default>1</default>
<Required>Y</Required>
</force-reject>
<attachments-only type="BooleanField">
<default>1</default>
<Required>Y</Required>
</attachments-only>
<max-size type="IntegerField">
<MinimumValue>1</MinimumValue>
<default>20000000</default>
<Required>N</Required>
<ValidationMessage>A valid maximum size in bytes must be set.</ValidationMessage>
</max-size>
<whitelist type="CSVListField">
<Required>N</Required>
</whitelist>
</av>
<surbl>
<whitelist type="CSVListField">
<Required>N</Required>
</whitelist>
<exceptions type="CSVListField">
<Required>N</Required>
</exceptions>
</surbl>
</items>
</model>
@@ -0,0 +1,157 @@
{#
Copyright (C) 2017 Fabian Franz
OPNsense® is Copyright © 2014 2015 by Deciso B.V.
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 = {'frm_rspamd':'/api/rspamd/settings/get'};
// load initial data
mapDataToFormUI(data_get_map).done(function(){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// request service status on load and update status box
ajaxCall(url="/api/rspamd/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['status']);
});
});
// update history on tab state and implement navigation
if(window.location.hash != "") {
$('a[href="' + window.location.hash + '"]').click()
}
$('.nav-tabs a').on('shown.bs.tab', function (e) {
history.pushState(null, null, e.target.hash);
});
// form save event handlers for all defined forms
$('[id*="save_"]').each(function(){
$(this).click(function() {
var frm_id = $(this).closest("form").attr("id");
var frm_title = $(this).closest("form").attr("data-title");
// save data for General TAB
saveFormToEndpoint(url="/api/rspamd/settings/set", formid=frm_id, callback_ok=function(){
// on correct save, perform reconfigure. set progress animation when reloading
$("#"+frm_id+"_progress").addClass("fa fa-spinner fa-pulse");
ajaxCall(url="/api/rspamd/service/reconfigure", sendData={}, callback=function(data,status){
// when done, disable progress animation.
$("#"+frm_id+"_progress").removeClass("fa fa-spinner fa-pulse");
if (status != "success" || data['status'] != 'ok' ) {
// fix error handling
BootstrapDialog.show({
type:BootstrapDialog.TYPE_WARNING,
title: frm_title,
message: JSON.stringify(data),
draggable: true
});
} else {
// request service status after successful save and update status box (wait a few seconds before update)
setTimeout(function(){
ajaxCall(url="/api/rspamd/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['status']);
});
},3000);
}
});
});
});
});
});
</script>
{% if !clamav_installed %}
<div class="alert alert-warning" role="alert" id="missing_clamav" style="min-height:65px;">
<div style="margin-top: 8px;">{{ lang._('No ClamAV plugin found, please install via %sSystem > Firmware > Plugins%s. If the plugin is not installed and enabled, mails cannot be scanned for malware.')|format('<a href="/ui/core/firmware/#plugins">','</a>')}}</div>
</div>
{% endif %}
<ul class="nav nav-tabs" role="tablist" id="maintabs">
{% for tab in settings['tabs']|default([]) %}
{% if tab['subtabs']|default(false) %}
{# Tab with dropdown #}
{# Find active subtab #}
{% set active_subtab="" %}
{% for subtab in tab['subtabs']|default({}) %}
{% if subtab[0]==settings['activetab']|default("") %}
{% set active_subtab=subtab[0] %}
{% endif %}
{% endfor %}
<li role="presentation" class="dropdown {% if settings['activetab']|default("") == active_subtab %}active{% endif %}">
<a data-toggle="dropdown" href="#" class="dropdown-toggle pull-right visible-lg-inline-block visible-md-inline-block visible-xs-inline-block visible-sm-inline-block" role="button" style="border-left: 1px dashed lightgray;">
<b><span class="caret"></span></b>
</a>
<a data-toggle="tab" href="#subtab_{{ tab['subtabs'][0][0] }}" class="visible-lg-inline-block visible-md-inline-block visible-xs-inline-block visible-sm-inline-block" style="border-right:0px;"><b>{{ tab[1] }}</b></a>
<ul class="dropdown-menu" role="menu">
{% for subtab in tab['subtabs']|default({}) %}
<li class="{% if settings['activetab']|default("") == subtab[0] %}active{% endif %}"><a data-toggle="tab" href="#subtab_{{subtab[0]}}"><i class="fa fa-check-square"></i> {{ subtab[1] }}</a></li>
{% endfor %}
</ul>
</li>
{% else %}
{# Standard Tab #}
<li {% if settings['activetab']|default("") == tab[0] %} class="active" {% endif %}>
<a data-toggle="tab" href="#tab_{{ tab[0] }}">
<b>{{ tab[1] }}</b>
</a>
</li>
{% endif %}
{% endfor %}
{# add custom content
<li><a data-toggle="tab" href="#remote_acls"><b>{{ lang._('Remote Access Control Lists') }}</b></a></li>
#}
</ul>
<div class="content-box tab-content">
{% for tab in settings['tabs']|default([]) %}
{% if tab['subtabs']|default(false) %}
{# Tab with dropdown #}
{% for subtab in tab['subtabs']|default({})%}
<div id="subtab_{{subtab[0]}}" class="tab-pane fade{% if settings['activetab']|default("") == subtab[0] %} in active {% endif %}">
{{ partial("layout_partials/base_form",['fields':subtab[2],'id':'frm_'~subtab[0],'data_title':subtab[1],'apply_btn_id':'save_'~subtab[0]]) }}
</div>
{% endfor %}
{% endif %}
{% if tab['subtabs']|default(false)==false %}
<div id="tab_{{tab[0]}}" class="tab-pane fade{% if settings['activetab']|default("") == tab[0] %} in active {% endif %}">
{{ partial("layout_partials/base_form",['fields':tab[2],'id':'frm_'~tab[0],'apply_btn_id':'save_'~tab[0]]) }}
</div>
{% endif %}
{% endfor %}
</div>
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
mkdir -p /var/db/rspamd
mkdir -p /var/log/rspamd
mkdir -p /var/run/rspamd
chown nobody:nobody /var/db/rspamd
chown nobody:nobody /var/log/rspamd
chown nobody:nobody /var/run/rspamd
@@ -0,0 +1,23 @@
[start]
command:/usr/local/opnsense/scripts/rspamd/setup.sh;/usr/local/etc/rc.d/rspamd start
parameters:
type:script
message:starting rspamd
[stop]
command:/usr/local/etc/rc.d/rspamd onestop
parameters:
type:script
message:stopping rspamd
[restart]
command:/usr/local/opnsense/scripts/rspamd/setup.sh;/usr/local/etc/rc.d/rspamd restart
parameters:
type:script
message:restarting rspamd
[status]
command:/usr/local/etc/rc.d/rspamd status;exit 0
parameters:
type:script_output
message:request rspamd status
@@ -0,0 +1,14 @@
rspamd:/etc/rc.conf.d/rspamd
antivirus.wl:/usr/local/etc/rspamd/local.d/antivirus.wl
antivirus.conf:/usr/local/etc/rspamd/local.d/antivirus.conf
dkim_signing.conf:/usr/local/etc/rspamd/local.d/dkim_signing.conf
dkim.conf:/usr/local/etc/rspamd/local.d/dkim.conf
spf.conf:/usr/local/etc/rspamd/local.d/spf.conf
spamtrap.conf:/usr/local/etc/rspamd/local.d/spamtrap.conf
surbl-whitelist.inc.local:/var/db/rspamd/surbl-whitelist.inc.local
2tld.inc.local:/var/db/rspamd/2tld.inc.local
greylist.conf:/usr/local/etc/rspamd/local.d/greylist.conf
phishing.conf:/usr/local/etc/rspamd/local.d/phishing.conf
mx_check.conf:/usr/local/etc/rspamd/local.d/mx_check.conf
ratelimit.conf:/usr/local/etc/rspamd/local.d/ratelimit.conf
spamtrap.map:/usr/local/etc/rspamd/maps.d/spamtrap.map
@@ -0,0 +1,5 @@
{% if helpers.exists('OPNsense.Rspamd.general.enabled') and OPNsense.Rspamd.general.enabled == '1' and helpers.exists('OPNsense.Rspamd.surbl') %}
{% for host in OPNsense.Rspamd.surbl.exceptions.split(',') %}
{{ host }}
{% endfor %}
{% endif %}
@@ -0,0 +1,29 @@
#
# Please don't modify this file as your changes might be overwritten with
# the next update.
#
{% if helpers.exists('OPNsense.Rspamd.general.enabled') and OPNsense.Rspamd.general.enabled == '1' and helpers.exists('OPNsense.Rspamd.av') %}
clamav {
{% if helpers.exists('OPNsense.Rspamd.av.force-reject') and OPNsense.Rspamd.av['force-reject'] == '1' %}
action = "reject";
{% endif %}
{% if helpers.exists('OPNsense.Rspamd.av.attachments-only') and OPNsense.Rspamd.av['attachments-only'] == '1' %}
attachments_only = true;
{% else %}
attachments_only = false;
{% endif %}
{% if helpers.exists('OPNsense.Rspamd.av.max-size') and OPNsense.Rspamd.av.max-size != '' %}
# If `max_size` is set, messages > n bytes in size are not scanned
max_size = {{ OPNsense.Rspamd.av.max-size }};
{% endif %}
symbol = "CLAM_VIRUS";
type = "clamav";
#log_clean = true;
{% if helpers.exists('OPNsense.clamav.general') and OPNsense.clamav.general.enabled == '1' %}
servers = "/var/run/clamav/clamd.sock";
{% endif %}
}
{% endif %}
@@ -0,0 +1,5 @@
{% if helpers.exists('OPNsense.Rspamd.general.enabled') and OPNsense.Rspamd.general.enabled == '1' and helpers.exists('OPNsense.Rspamd.av') %}
{% for host in OPNsense.Rspamd.av.whitelist.split(',') %}
{{ host }}
{% endfor %}
{% endif %}

Some files were not shown because too many files have changed in this diff Show More