├── +POST_DEINSTALL.post ├── +POST_INSTALL.post ├── +POST_INSTALL.pre ├── +PRE_DEINSTALL.pre ├── .editorconfig ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── pkg-descr └── src ├── etc ├── cron.d │ └── oscrowdsec.cron ├── crowdsec │ └── acquis.d │ │ └── opnsense.yaml ├── inc │ └── plugins.inc.d │ │ └── crowdsec.inc ├── rc.d │ └── oscrowdsec └── rc.syshook.d │ └── start │ └── 50-crowdsec └── opnsense ├── mvc └── app │ ├── controllers │ └── OPNsense │ │ └── CrowdSec │ │ ├── Api │ │ ├── AlertsController.php │ │ ├── BouncersController.php │ │ ├── CollectionsController.php │ │ ├── DecisionsController.php │ │ ├── GeneralController.php │ │ ├── MachinesController.php │ │ ├── ParsersController.php │ │ ├── PostoverflowsController.php │ │ ├── ScenariosController.php │ │ ├── ServiceController.php │ │ └── VersionController.php │ │ ├── GeneralController.php │ │ ├── OverviewController.php │ │ └── forms │ │ └── general.xml │ ├── models │ └── OPNsense │ │ └── CrowdSec │ │ ├── ACL │ │ └── ACL.xml │ │ ├── General.php │ │ ├── General.xml │ │ └── Menu │ │ └── Menu.xml │ └── views │ └── OPNsense │ └── CrowdSec │ ├── general.volt │ └── overview.volt ├── scripts └── OPNsense │ └── CrowdSec │ ├── debug.sh │ ├── hub-upgrade.sh │ ├── reconfigure.py │ └── reconfigure.sh ├── service ├── conf │ └── actions.d │ │ └── actions_crowdsec.conf └── templates │ └── OPNsense │ └── CrowdSec │ ├── +TARGETS │ ├── crowdsec.rc.conf.d │ ├── crowdsec_firewall.rc.conf.d │ ├── oscrowdsec.rc.conf.d │ └── settings.json └── www └── js └── CrowdSec └── crowdsec.js /+POST_DEINSTALL.post: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Removing the plugin from the web interface will autoremove the dependencies 4 | # too, and here we have to delete the files in rc.conf.d (because they are 5 | # generated from templates when the configuration is saved, and the package 6 | # system did not keep track of them). 7 | 8 | # But.. If the plugin is removed from the command line (which does not happen 9 | # outside of testing conditions), the crowdsec and bouncer services will not be 10 | # removed. However, since we deleted the files that enabled these services, 11 | # they will be disabled at the next reboot. 12 | 13 | rm -f /etc/rc.conf.d/crowdsec \ 14 | /etc/rc.conf.d/crowdsec_firewall \ 15 | /etc/rc.conf.d/oscrowdsec 16 | 17 | 18 | # Remove aliases and with them, the rules. We don't have plugin files 19 | # anymore so we do that on the fly. 20 | 21 | /usr/local/bin/php <<'EOT' 22 | aliases->alias->iterateItems() as $index => $alias) { 35 | if (strval($alias->name) == $name) { 36 | if ($model->aliases->alias->del($index)) { 37 | $model->serializeToConfig(); 38 | Config::getInstance()->save(); 39 | } 40 | } 41 | } 42 | } 43 | 44 | removeAlias('crowdsec_blacklists'); 45 | removeAlias('crowdsec6_blacklists'); 46 | EOT 47 | 48 | 49 | # apply the configuration changes to the packet filter 50 | configctl filter reload 51 | -------------------------------------------------------------------------------- /+POST_INSTALL.post: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | configctl crowdsec reconfigure 4 | -------------------------------------------------------------------------------- /+POST_INSTALL.pre: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # The configuration file used in reconfigure (i.e. settings.json) may eventually 4 | # have credentials, so we need to restrict its permissions. We do so by pre-creating 5 | # the directory, and the template package will use its permissions while creating the file. 6 | # If we do that in setup.sh, the file already exists with bad permissions. 7 | 8 | # shellcheck disable=SC2174 9 | mkdir -p -m 0700 /usr/local/etc/crowdsec/opnsense 10 | -------------------------------------------------------------------------------- /+PRE_DEINSTALL.pre: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # need to temporarily stop the bouncer to remove all the rules 4 | service crowdsec_firewall stop >/dev/null 2>&1 | : 5 | 6 | # the rest of the cleanup is done in the post-deinstall script, otherwise 7 | # the plugin recreates the objects during "filter reload". 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | insert_final_newline = true 8 | 9 | [*.{js,py,php,inc,volt}] 10 | indent_size = 4 11 | trim_trailing_whitespace = true 12 | 13 | [*.xml] 14 | indent_size = 2 15 | trim_trailing_whitespace = false 16 | 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | work/ 2 | node_modules 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2021 Crowdsec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PLUGIN_NAME= crowdsec 2 | PLUGIN_VERSION= 1.0 3 | PLUGIN_DEPENDS= crowdsec 4 | PLUGIN_COMMENT= Lightweight and collaborative security engine 5 | PLUGIN_MAINTAINER= marco@crowdsec.net 6 | PLUGIN_WWW= https://crowdsec.net/ 7 | 8 | .include "../../Mk/plugins.mk" 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Beware 3 | ------ 4 | 5 | * The code in this repository has been merged in [https://github.com/opnsense/plugins](https://github.com/opnsense/plugins) 6 | and new releases are done through the OPNsense channels. 7 | 8 | * The documentation is available at [docs.crowdsec.net](https://docs.crowdsec.net/docs/next/getting_started/install_crowdsec_opnsense). 9 | 10 | * Don't expect many features on the web interface, but feel free to give us a sense 11 | of your priorities. The command line should work the same as under Linux. 12 | 13 | * The exact same application under Linux and FreeBSD can have logs in 14 | different location and format. This means that supporting OPNsense plugins 15 | may require modifying the existing parsers or writing new ones. We did that 16 | for SSH and the web interface, let us know what else you want us to protect 17 | on your firewall. 18 | 19 | * For the changelog, see [pkg-descr](pkg-descr) 20 | 21 | -------------------------------------------------------------------------------- /pkg-descr: -------------------------------------------------------------------------------- 1 | Crowdsec is an open-source, lightweight software, detecting peers with 2 | aggressive behaviors to prevent them from accessing your systems. Its user 3 | friendly design and assistance offers a low technical barrier of entry and 4 | nevertheless a high security gain. 5 | 6 | WWW: https://crowdsec.net/ 7 | 8 | Plugin Changelog 9 | ================ 10 | 11 | 1.0 12 | 13 | * first non-devel release 14 | * changed service restart to reload on hub update; fixed "service oscrowdsec status" 15 | 16 | 0.2 17 | 18 | * first published release 19 | * added options `lapi_enabled`, `crowdsec_firewall_verbose` 20 | * removed options `crowdsec_flags`, `crowdsec_firewall_flags` 21 | * changed default for `agent_enabled`, `firewall_bouncer_enabled` to 1 22 | 23 | 0.1 24 | 25 | * fixed packet tags with ipv6 26 | * custom `crowdsec_flags`, `crosdsec_firewall_flags` 27 | 28 | 0.0.9 29 | 30 | * fixed the javascript, 0.0.8 had a syntax error 31 | * new option: rules_tag 32 | * new option: lapi_manual_configuration 33 | * ipv4/ipv6 validation with regexp 34 | 35 | 0.0.8 36 | 37 | * crowdsec update 1.3.2 38 | * configurable `rules_log` and LAPI address/port 39 | 40 | 0.0.7 41 | 42 | * automated removal of Alias objects when the plugin is uninstalled 43 | 44 | 0.0.6 45 | 46 | * crowdsec update 1.3.1.r1 47 | * bouncer update to 0.0.23.r1 48 | * automated creation of Alias and Rule objects 49 | 50 | 0.0.5 51 | 52 | * fixed an issue that prevented the bouncer from banning IPs on opnsense 53 | * fixed support for notification plugins 54 | -------------------------------------------------------------------------------- /src/etc/cron.d/oscrowdsec.cron: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT THIS FILE -- OPNsense auto-generated file 2 | # 3 | # User-defined crontab files can be loaded via /etc/cron.d 4 | # or /usr/local/etc/cron.d and follow the same format as 5 | # /etc/crontab, see the crontab(5) manual page. 6 | SHELL=/bin/sh 7 | PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin 8 | #minute hour mday month wday who command 9 | 0 1,13 * * * root /usr/local/opnsense/scripts/OPNsense/CrowdSec/hub-upgrade.sh 10 | -------------------------------------------------------------------------------- /src/etc/crowdsec/acquis.d/opnsense.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Before 22.1, OPNsense used circular logs under /var/log/*.log that 3 | # can still be around. They are old, in binary format and are not needed by crowdsec. 4 | # 5 | # For this reason we don't scan /var/log/*.log, but some plugins can write 6 | # their (plaintext) logs in that location, in such case add their pathnames too. 7 | # 8 | 9 | filenames: 10 | # ssh 11 | - /var/log/audit/*.log 12 | # web admin 13 | - /var/log/lighttpd/*.log 14 | labels: 15 | type: syslog 16 | -------------------------------------------------------------------------------- /src/etc/inc/plugins.inc.d/crowdsec.inc: -------------------------------------------------------------------------------- 1 | 5 | 6 | use OPNsense\Core\Config; 7 | use OPNsense\Firewall\Alias; 8 | use OPNsense\Firewall\Plugin; 9 | 10 | function add_alias_if_not_exist($name, $description, $proto) 11 | { 12 | $model = new Alias(); 13 | 14 | if ($model->getByName($name) != null) { 15 | return; 16 | } 17 | 18 | $new_alias = $model->aliases->alias->Add(); 19 | $new_alias->name = $name; 20 | $new_alias->description = $description; 21 | $new_alias->proto = $proto; 22 | $new_alias->type = 'external'; 23 | $model->serializeToConfig(); 24 | Config::getInstance()->save(); 25 | } 26 | 27 | function crowdsec_firewall(Plugin $fw) 28 | { 29 | global $config; 30 | 31 | $general = $config['OPNsense']['crowdsec']['general']; 32 | 33 | $bouncer_enabled = isset($general['firewall_bouncer_enabled']) && $general['firewall_bouncer_enabled']; 34 | 35 | if (!$bouncer_enabled) { 36 | return; 37 | } 38 | 39 | $rules_log_enabled = isset($general['rules_log']) && $general['rules_log']; 40 | 41 | $rules_tag = ""; 42 | if (isset($general['rules_tag'])) { 43 | $rules_tag = $general['rules_tag']; 44 | } 45 | 46 | add_alias_if_not_exist('crowdsec_blacklists', 'CrowdSec (IPv4)', 'IPv4'); 47 | 48 | // https://github.com/opnsense/core/blob/master/src/opnsense/mvc/app/library/OPNsense/Firewall/FilterRule.php 49 | 50 | $fw->registerFilterRule( 51 | 1, /* priority */ 52 | array( 53 | 'ipprotocol' => 'inet', 54 | 'descr' => 'CrowdSec (IPv4)', 55 | 'from' => '$crowdsec_blacklists', # $ to reference an alias 56 | 'type' => 'block', 57 | 'log' => $rules_log_enabled, 58 | 'tag' => $rules_tag, 59 | 'label' => 'blocked by crowdsec', 60 | 'quick' => true 61 | ), 62 | null 63 | ); 64 | 65 | add_alias_if_not_exist('crowdsec6_blacklists', 'CrowdSec (IPv6)', 'IPv6'); 66 | 67 | $fw->registerFilterRule( 68 | 1, /* priority */ 69 | array( 70 | 'ipprotocol' => 'inet6', 71 | 'descr' => 'CrowdSec (IPv6)', 72 | 'from' => '$crowdsec6_blacklists', # $ to reference an alias 73 | 'type' => 'block', 74 | 'log' => $rules_log_enabled, 75 | 'tag' => $rules_tag, 76 | 'label' => 'blocked by crowdsec', 77 | 'quick' => true 78 | ), 79 | null 80 | ); 81 | } 82 | 83 | function crowdsec_services() 84 | { 85 | $services[] = array( 86 | 'description' => 'CrowdSec', 87 | 'configd' => array( 88 | 'restart' => array('crowdsec restart'), 89 | 'start' => array('crowdsec start'), 90 | 'stop' => array('crowdsec stop'), 91 | ), 92 | 'name' => 'crowdsec' 93 | ); 94 | 95 | return $services; 96 | } 97 | -------------------------------------------------------------------------------- /src/etc/rc.d/oscrowdsec: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # $FreeBSD$ 4 | # 5 | 6 | # PROVIDE: oscrowdsec 7 | # REQUIRE: NETWORKING syslogd 8 | # BEFORE: DAEMON 9 | # KEYWORD: shutdown 10 | 11 | # shellcheck disable=SC1091 12 | . /etc/rc.subr 13 | 14 | name="oscrowdsec" 15 | rcvar="oscrowdsec_enable" 16 | 17 | load_rc_config $name 18 | 19 | : "${oscrowdsec_enable="NO"}" 20 | 21 | 22 | oscrowdsec_start () { 23 | # 24 | # Start, or stop the services according to the plugin's configuration. 25 | # When starting -> error if the services are already running 26 | # When stopping -> no error 27 | # 28 | 29 | if service crowdsec enabled; then 30 | service crowdsec start 31 | else 32 | service crowdsec stop || : 33 | fi 34 | 35 | if service crowdsec_firewall enabled; then 36 | service crowdsec_firewall start 37 | else 38 | service crowdsec_firewall stop || : 39 | fi 40 | } 41 | 42 | oscrowdsec_stop () { 43 | # Always stop the services, enabled or not, running or not. No errors. 44 | 45 | service crowdsec stop || : 46 | service crowdsec_firewall stop || : 47 | } 48 | 49 | oscrowdsec_restart () { 50 | oscrowdsec_stop || : 51 | oscrowdsec_start 52 | } 53 | 54 | oscrowdsec_status () { 55 | # return error if at least one program is not running 56 | service crowdsec status 57 | ret=$? 58 | 59 | if ! service crowdsec_firewall status; then 60 | ret=1 61 | fi 62 | return $ret 63 | } 64 | 65 | oscrowdsec_reload () { 66 | if service crowdsec enabled; then 67 | if service crowdsec status >/dev/null 2>&1; then 68 | service crowdsec reload 69 | else 70 | service crowdsec restart 71 | fi 72 | fi 73 | 74 | if service crowdsec_firewall enabled; then 75 | # the bouncer does not support reload 76 | service crowdsec_firewall restart 77 | fi 78 | } 79 | 80 | case $1 in 81 | start) 82 | oscrowdsec_start 83 | exit $? 84 | ;; 85 | stop) 86 | oscrowdsec_stop 87 | exit $? 88 | ;; 89 | restart) 90 | oscrowdsec_restart 91 | exit $? 92 | ;; 93 | status) 94 | oscrowdsec_status 95 | exit $? 96 | ;; 97 | reload) 98 | oscrowdsec_reload 99 | exit $? 100 | ;; 101 | esac 102 | -------------------------------------------------------------------------------- /src/etc/rc.syshook.d/start/50-crowdsec: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # https://docs.opnsense.org/development/backend/autorun.html 4 | 5 | /usr/local/opnsense/scripts/OPNsense/CrowdSec/hub-upgrade.sh 6 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/AlertsController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class AlertsController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of alerts 19 | * @return array of alerts 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec alerts-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list alerts"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/BouncersController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class BouncersController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of bouncers 19 | * @return array of bouncers 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec bouncers-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list bouncers"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/CollectionsController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class CollectionsController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of collections 19 | * @return array of collections 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec collections-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list collections"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/DecisionsController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class DecisionsController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of decisions 19 | * @return array of decisions 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec decisions-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list decisions"); 32 | } 33 | 34 | public function deleteAction($decision_id) 35 | { 36 | if ($this->request->isDelete()) { 37 | $backend = new Backend(); 38 | $bckresult = $backend->configdRun("crowdsec decisions-delete ${decision_id}"); 39 | if ($bckresult !== null) { 40 | // why does the action return \n\n for empty output? 41 | if (trim($bckresult) === '') { 42 | return array("message" => "OK"); 43 | } 44 | // TODO handle error 45 | return array("message" => $bckresult); 46 | } 47 | return array("message" => "OK"); 48 | } else { 49 | $this->response->setStatusCode(405, "Method Not Allowed"); 50 | $this->response->setHeader("Allow", "DELETE"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/GeneralController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiMutableModelControllerBase; 9 | 10 | /** 11 | * @package OPNsense\CrowdSec 12 | */ 13 | class GeneralController extends ApiMutableModelControllerBase 14 | { 15 | protected static $internalModelName = 'general'; 16 | protected static $internalModelClass = '\OPNsense\CrowdSec\General'; 17 | } 18 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/MachinesController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class MachinesController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of registered machines 19 | * @return array of machines 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec machines-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list machines"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/ParsersController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class ParsersController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of registered parsers 19 | * @return array of parsers 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec parsers-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list parsers"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/PostoverflowsController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class PostoverflowsController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of registered postoverflows 19 | * @return array of postoverflows 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec postoverflows-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list postoverflows"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/ScenariosController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class ScenariosController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve list of registered scenarios 19 | * @return array of scenarios 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | $bckresult = json_decode(trim($backend->configdRun("crowdsec scenarios-list")), true); 27 | if ($bckresult !== null) { 28 | // only return valid json type responses 29 | return $bckresult; 30 | } 31 | return array("message" => "unable to list scenarios"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/ServiceController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\Core\Backend; 10 | 11 | /** 12 | * Class ServiceController 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class ServiceController extends ApiControllerBase 16 | { 17 | /** 18 | * reconfigure CrowdSec 19 | */ 20 | public function reloadAction() 21 | { 22 | $status = "failed"; 23 | if ($this->request->isPost()) { 24 | $backend = new Backend(); 25 | $bckresult = trim($backend->configdRun('template reload OPNsense/CrowdSec')); 26 | if ($bckresult == "OK") { 27 | $bckresult = trim($backend->configdRun('crowdsec reconfigure')); 28 | if ($bckresult == "OK") { 29 | $status = "ok"; 30 | } 31 | } 32 | } 33 | return array("status" => $status); 34 | } 35 | 36 | /** 37 | * retrieve status of crowdsec 38 | * @return array 39 | * @throws \Exception 40 | */ 41 | public function statusAction() 42 | { 43 | $backend = new Backend(); 44 | $response = $backend->configdRun("crowdsec crowdsec-status"); 45 | 46 | $status = "unknown"; 47 | if (strpos($response, "not running") > 0) { 48 | $status = "stopped"; 49 | } elseif (strpos($response, "is running") > 0) { 50 | $status = "running"; 51 | } 52 | 53 | $response = $backend->configdRun("crowdsec crowdsec-firewall-status"); 54 | 55 | $firewall_status = "unknown"; 56 | if (strpos($response, "not running") > 0) { 57 | $firewall_status = "stopped"; 58 | } elseif (strpos($response, "is running") > 0) { 59 | $firewall_status = "running"; 60 | } 61 | 62 | return array( 63 | "crowdsec-status" => $status, 64 | "crowdsec-firewall-status" => $firewall_status, 65 | ); 66 | } 67 | 68 | /** 69 | * return debug information 70 | * @return array 71 | */ 72 | public function debugAction() 73 | { 74 | $backend = new Backend(); 75 | $response = $backend->configdRun("crowdsec debug"); 76 | return array("message" => $response); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/Api/VersionController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec\Api; 7 | 8 | use OPNsense\Base\ApiControllerBase; 9 | use OPNsense\CrowdSec\CrowdSec; 10 | use OPNsense\Core\Backend; 11 | 12 | /** 13 | * @package OPNsense\CrowdSec 14 | */ 15 | class VersionController extends ApiControllerBase 16 | { 17 | /** 18 | * retrieve version description 19 | * @return version description 20 | * @throws \OPNsense\Base\ModelException 21 | * @throws \ReflectionException 22 | */ 23 | public function getAction() 24 | { 25 | $backend = new Backend(); 26 | return $backend->configdRun("crowdsec version"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/GeneralController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec; 7 | 8 | /** 9 | * Class GeneralController 10 | * @package OPNsense\CrowdSec 11 | */ 12 | class GeneralController extends \OPNsense\Base\IndexController 13 | { 14 | public function indexAction() 15 | { 16 | $this->view->pick('OPNsense/CrowdSec/general'); 17 | $this->view->generalForm = $this->getForm("general"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/OverviewController.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | namespace OPNsense\CrowdSec; 7 | 8 | /** 9 | * Class OverviewController 10 | * @package OPNsense\CrowdSec 11 | */ 12 | class OverviewController extends \OPNsense\Base\IndexController 13 | { 14 | public function indexAction() 15 | { 16 | $this->view->pick('OPNsense/CrowdSec/overview'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/controllers/OPNsense/CrowdSec/forms/general.xml: -------------------------------------------------------------------------------- 1 |
96 | -------------------------------------------------------------------------------- /src/opnsense/mvc/app/models/OPNsense/CrowdSec/ACL/ACL.xml: -------------------------------------------------------------------------------- 1 |This plugin installs a CrowdSec agent/LAPI 55 | node, and a Firewall Bouncer.
56 | 57 |Out of the box, by enabling them in the "Settings" tab, they can protect the OPNsense server 58 | by receiving thousands of IP addresses of active attackers, which are immediately banned at the 59 | firewall level. In addition, the logs of the ssh service and OPNsense administration interface are 60 | analyzed for possible brute-force attacks; any such scenario triggers a ban and is reported to the 61 | CrowdSec Central API 62 | (meaning timestamp, scenario, attacking IP).
63 | 64 |Other attack behaviors can be recognized on the OPNsense server and its plugins, or 65 | any other agent 66 | connected to the same LAPI node. Other types of remediation are possible (ex. captcha test for scraping attempts).
67 | 68 | We recommend you to register to the Console. This helps you manage your instances, 69 | and us to have better overall metrics. 70 | 71 |Please refer to the tutorials to explore 72 | the possibilities.
73 | 74 |For the latest plugin documentation, including how to use it with an external LAPI, see Install 76 | CrowdSec (OPNsense)
77 | 78 |A few remarks:
79 | 80 |sysrc
or /etc/rc.conf
94 | like you would on vanilla freebsd, the plugin takes care of that.
95 | 122 | On the Settings tab, you can expose CrowdSec to the LAN for other servers by changing `LAPI listen address`. 123 | Otherwise, leave the defualt value. 124 |
125 | 126 |127 | Select the first three checkboxes: IDS, LAPI and IPS. Click Apply. If you need to restart, you can do so 128 | from the System > Diagnostics > Services page. 129 |
130 | 131 |134 | A quick way to test that everything is working correctly is to 135 | execute the following command. 136 |
137 | 138 |139 | Your ssh session should freeze and you should be kicked out from 140 | the firewall. You will not be able to connect to it (from the same 141 | IP address) for two minutes. 142 |
143 | 144 |145 | It might be a good idea to have a secondary IP from which you can 146 | connect, should anything go wrong. 147 |
148 | 149 |[root@OPNsense ~]# cscli decisions add -t ban -d 2m -i
150 |
151 | 152 | This is a more secure way to test than attempting to brute-force 153 | yourself: the default ban period is 4 hours, and Crowdsec reads the 154 | logs from the beginning, so it could ban you even if you failed ssh 155 | login 10 times in 30 seconds two hours before installing it. 156 |
157 | 158 |Name | 58 |IP Address | 59 |Last Update | 60 |Validated? | 61 |Version | 62 |
---|---|---|---|---|
Name | 78 |IP Address | 79 |Valid | 80 |Last API Pull | 81 |Type | 82 |Version | 83 |
---|---|---|---|---|---|
Name | 99 |Status | 100 |Version | 101 |Local Path | 102 |
---|---|---|---|
Name | 118 |Status | 119 |Version | 120 |Path | 121 |Description | 122 |
---|---|---|---|---|
Name | 138 |Status | 139 |Version | 140 |Local Path | 141 |Description | 142 |
---|---|---|---|---|
Name | 158 |Status | 159 |Version | 160 |Local Path | 161 |Description | 162 |
---|---|---|---|---|
ID | 178 |Value | 179 |Reason | 180 |Country | 181 |AS | 182 |Decisions | 183 |Created At | 184 |
---|---|---|---|---|---|---|
cscli decisions list -a
in a shell.
198 | 202 | | ID | 203 |Source | 204 |Scope:Value | 205 |Reason | 206 |Action | 207 |Country | 208 |AS | 209 |Events | 210 |Expiration | 211 |Alert ID | 212 |
---|---|---|---|---|---|---|---|---|---|---|
225 |226 |