Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions crowdsec-firewall-bouncer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# SPDX-License-Identifier: MIT
#
# Copyright (C) 2021-2022 Gerald Kerma <[email protected]>
#

include $(TOPDIR)/rules.mk

PKG_NAME:=crowdsec-firewall-bouncer
PKG_VERSION:=0.0.34
PKG_RELEASE:=1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/crowdsecurity/cs-firewall-bouncer/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=5bd62250f40fc0a05d2431f3ea1cb211d7fc4cc755b53a23585aa2cede8ff985

PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Gerald Kerma <[email protected]>

PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=no-mips16
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_UPSTREAM_VERSION)

CSFB_BUILD_VERSION?=v$(PKG_VERSION)
CSFB_BUILD_GOVERSION:=$(shell go version | cut -d " " -f3 | sed -E 's/[go]+//g')
CSFB_BUILD_TIMESTAMP:=$(shell date +%F"_"%T)
CSFB_BUILD_TAG:=openwrt-$(PKG_VERSION)-$(PKG_RELEASE)
CSFB_VERSION_PKG:=github.com/crowdsecurity/cs-firewall-bouncer/pkg/version

GO_PKG:=github.com/crowdsecurity/cs-firewall-bouncer
GO_PKG_INSTALL_ALL:=1
GO_PKG_LDFLAGS_X:=$(CSFB_VERSION_PKG).Version=$(CSFB_BUILD_VERSION) \
$(CSFB_VERSION_PKG).BuildDate=$(CSFB_BUILD_TIMESTAMP) \
$(CSFB_VERSION_PKG).Tag=$(CSFB_BUILD_TAG) \
$(CSFB_VERSION_PKG).GoVersion=$(CSFB_BUILD_GOVERSION)

include $(INCLUDE_DIR)/package.mk
include ../../lang/golang/golang-package.mk

define Package/crowdsec-firewall-bouncer/Default
SECTION:=net
CATEGORY:=Network
TITLE:=Firewall bouncer for Crowdsec
URL:=https://github.com/crowdsecurity/cs-firewall-bouncer/
endef

define Package/crowdsec-firewall-bouncer
$(call Package/crowdsec-firewall-bouncer/Default)
DEPENDS:=$(GO_ARCH_DEPENDS)
endef

define Package/golang-crowdsec-firewall-bouncer-dev
$(call Package/crowdsec-firewall-bouncer/Default)
$(call GoPackage/GoSubMenu)
TITLE+= (source files)
DEPENDS:=$(GO_ARCH_DEPENDS)
PKGARCH:=all
endef

define Package/crowdsec-firewall-bouncer/Default/description
Crowdsec bouncer written in golang for firewalls.

crowdsec-firewall-bouncer will fetch new and old decisions
from a CrowdSec API to add them in a blocklist used by supported firewalls.

You must install nftables.
endef

define Package/crowdsec-firewall-bouncer/description
$(call Package/crowdsec-firewall-bouncer/Default/description)

This package contains the main program.
endef

define Package/golang-crowdsec-firewall-bouncer-dev/description
$(call Package/crowdsec-firewall-bouncer/Default/description)

This package provides the source files for the program.
endef

define Package/crowdsec-firewall-bouncer/install
$(call GoPackage/Package/Install/Bin,$(1))

$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/crowdsec.config $(1)/etc/config/crowdsec

$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/crowdsec-firewall-bouncer.initd $(1)/etc/init.d/crowdsec-firewall-bouncer
endef

define Package/crowdsec-firewall-bouncer/conffiles
/etc/config/crowdsec
endef

$(eval $(call GoBinPackage,crowdsec-firewall-bouncer))
$(eval $(call BuildPackage,crowdsec-firewall-bouncer))
247 changes: 247 additions & 0 deletions crowdsec-firewall-bouncer/files/crowdsec-firewall-bouncer.initd
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#!/bin/sh /etc/rc.common

USE_PROCD=1

START=99

NAME=crowdsec-firewall-bouncer
PROG=/usr/bin/cs-firewall-bouncer
VARCONFIGDIR=/var/etc/crowdsec/bouncers
VARCONFIG=/var/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml

CONFIGURATION=crowdsec

TABLE="crowdsec"
TABLE6="crowdsec6"

service_triggers() {
procd_add_reload_trigger crowdsec-firewall-bouncer
procd_add_config_trigger "config.change" "crowdsec" /etc/init.d/crowdsec-firewall-bouncer reload
}

init_yaml() {

local section="$1"

local set_only
local hook_priority
local update_frequency
local log_level
local api_url
local api_key
local ipv6
local deny_action
local deny_log
local log_prefix
local log_max_size
local log_max_backups
local log_max_age
local ipv4
local chain_name
local chain6_name
local retry_initial_connect

config_get hook_priority $section priority "4"
config_get update_frequency $section update_frequency '10s'
config_get log_level $section log_level 'info'
config_get api_url $section api_url "http://127.0.0.1:8080"
config_get api_key $section api_key "API_KEY"
config_get_bool ipv6 $section ipv6 '1'
config_get deny_action $section deny_action "drop"
config_get_bool deny_log $section deny_log '0'
config_get log_prefix $section log_prefix "crowdsec: "
config_get log_max_size $section log_max_size '100'
config_get log_max_backups $section log_max_backups '3'
config_get log_max_age $section log_max_age '30'
config_get_bool ipv4 $section ipv4 '1'
config_get chain_name $section chain_name "crowdsec-chain"
config_get chain6_name $section chain6_name "crowdsec6-chain"
config_get_bool retry_initial_connect $section retry_initial_connect '1'

# Create tmp dir & permissions if needed
if [ ! -d "${VARCONFIGDIR}" ]; then
mkdir -m 0755 -p "${VARCONFIGDIR}"
fi;

cat > $VARCONFIG <<-EOM
mode: nftables
pid_dir: /var/run/
update_frequency: $update_frequency
daemonize: true
log_mode: file
log_dir: /var/log/
log_level: $log_level
log_compression: true
log_max_size: $log_max_size
log_max_backups: $log_max_backups
log_max_age: $log_max_age
api_url: $api_url
api_key: $api_key
retry_initial_connect: bool($retry_initial_connect)
insecure_skip_verify: true
disable_ipv6: boolnot($ipv6)
deny_action: $deny_action
deny_log: bool($deny_log)
supported_decisions_type:
- ban
#to change log prefix
deny_log_prefix: "$log_prefix"
#to change the blacklists name
blacklists_ipv4: crowdsec-blacklists
blacklists_ipv6: crowdsec6-blacklists
#type of ipset to use
ipset_type: nethash
#if present, insert rule in those chains
iptables_chains:
- INPUT
# - FORWARD
# - DOCKER-USER
## nftables
nftables:
ipv4:
enabled: bool($ipv4)
set-only: false
table: $TABLE
chain: $chain_name
priority: $hook_priority
ipv6:
enabled: bool($ipv6)
set-only: false
table: $TABLE6
chain: $chain6_name
priority: $hook_priority
nftables_hooks:
- input
- forward
# packet filter
pf:
# an empty string disables the anchor
anchor_name: ""
prometheus:
enabled: false
listen_addr: 127.0.0.1
listen_port: 60601
EOM

sed -i "s/bool(1)/true/g" $VARCONFIG
sed -i "s/bool(0)/false/g" $VARCONFIG
sed -i "s/boolnot(1)/false/g" $VARCONFIG
sed -i "s/boolnot(0)/true/g" $VARCONFIG
sed -i "s,^\(\s*api_url\s*:\s*\).*\$,\1$api_url," $VARCONFIG
sed -i "s,^\(\s*api_key\s*:\s*\).*\$,\1$api_key," $VARCONFIG
}

init_nftables() {

local section="$1"

local hook_priority
local deny_action
local deny_log
local log_prefix
local ipv4
local ipv6
local filter_input
local filter_forward
local chain_name
local chain6_name
local interface
local log_term=""

config_get hook_priority $section priority "4"
config_get deny_action $section deny_action "drop"
config_get_bool deny_log $section deny_log '0'
config_get log_prefix $section log_prefix "crowdsec: "
config_get_bool ipv4 $section ipv4 '1'
config_get_bool ipv6 $section ipv6 '1'
config_get_bool filter_input $section filter_input '1'
config_get_bool filter_forward $section filter_forward '1'
config_get chain_name $section chain_name "crowdsec-chain"
config_get chain6_name $section chain6_name "crowdsec6-chain"
config_get interface $section interface 'eth1'

if [ "$deny_log" -eq "1" ] ; then
local log_term="log prefix \"${log_prefix}\""
fi

local interface="${interface// /, }"

#as of kernel 3.18 we can delete a table without need to flush it
nft delete table ip crowdsec 2>/dev/null
nft delete table ip6 crowdsec6 2>/dev/null

if [ "$ipv4" -eq "1" ] ; then

nft add table ip crowdsec
nft add set ip crowdsec crowdsec-blacklists '{ type ipv4_addr; flags timeout; }'

if [ "$filter_input" -eq "1" ] ; then
nft add chain ip "$TABLE" $chain_name-input "{ type filter hook input priority $hook_priority; policy accept; }"
nft add rule ip "$TABLE" $chain_name-input ct state established,related accept
nft add rule ip "$TABLE" $chain_name-input iifname != { $interface } accept
fi
if [ "$filter_forward" -eq "1" ] ; then
nft add chain ip "$TABLE" $chain_name-forward "{ type filter hook forward priority $hook_priority; policy accept; }"
nft add rule ip "$TABLE" $chain_name-forward ct state established,related accept
nft add rule ip "$TABLE" $chain_name-forward iifname != { $interface } accept
fi
fi

if [ "$ipv6" -eq "1" ] ; then

nft add table ip6 crowdsec6
nft add set ip6 crowdsec6 crowdsec6-blacklists '{ type ipv6_addr; flags timeout; }'

if [ "$filter_input" -eq "1" ] ; then
nft add chain ip6 "$TABLE6" $chain6_name-input "{ type filter hook input priority $hook_priority; policy accept; }"
nft add rule ip6 "$TABLE6" $chain6_name-input ct state established,related accept
nft add rule ip6 "$TABLE6" $chain6_name-input iifname != { $interface } accept
fi
if [ "$filter_forward" -eq "1" ] ; then
nft add chain ip6 "$TABLE6" $chain6_name-forward "{ type filter hook forward priority $hook_priority; policy accept; }"
nft add rule ip6 "$TABLE6" $chain6_name-forward ct state established,related accept
nft add rule ip6 "$TABLE6" $chain6_name-forward iifname != { $interface } accept
fi
fi
}

run_bouncer() {

local section="$1"

local enabled
config_get_bool enabled $section enabled 0

if [ "$enabled" -eq "1" ] ; then

init_yaml "$section"
init_nftables "$section"

procd_open_instance
procd_set_param command "$PROG" -c "$VARCONFIG"
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param nice 10
if [ -x "/sbin/ujail" ]; then
procd_add_jail cs-bouncer log
procd_add_jail_mount $VARCONFIG
procd_add_jail_mount_rw /var/log/
procd_set_param no_new_privs 1
fi
procd_close_instance
fi
}

start_service() {

config_load "${CONFIGURATION}"
config_foreach run_bouncer bouncer
}

service_stopped() {

rm $VARCONFIG

nft delete table ip crowdsec 2>/dev/null
nft delete table ip6 crowdsec6 2>/dev/null
}
Loading