crowdsec-firewall-bouncer: add package

This commit is contained in:
coolsnowwolf 2024-05-08 03:22:38 +08:00
parent 6f445b61c4
commit 46611bf5a4
3 changed files with 350 additions and 0 deletions

View File

@ -0,0 +1,97 @@
# SPDX-License-Identifier: MIT
#
# Copyright (C) 2021-2022 Gerald Kerma <gandalf@gk2.net>
#
include $(TOPDIR)/rules.mk
PKG_NAME:=crowdsec-firewall-bouncer
PKG_VERSION:=0.0.28
PKG_RELEASE:=2
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:=1e0f4d3cd8bc73da21eafc9b965fda0c1c1b0a27a2acc038004602797e4fccf0
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Gerald Kerma <gandalf@gk2.net>
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=no-mips16
PKG_BUILD_DIR:=$(BUILD_DIR)/cs-firewall-bouncer-$(PKG_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))

View File

@ -0,0 +1,238 @@
#!/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 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 input_chain_name
local input6_chain_name
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 input_chain_name $section input_chain_name "input"
config_get input6_chain_name $section input6_chain_name "input"
# 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
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: true
table: $TABLE
chain: $input_chain_name
ipv6:
enabled: bool($ipv6)
set-only: true
table: $TABLE6
chain: $input6_chain_name
# packet filter
pf:
# an empty 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 priority
local deny_action
local deny_log
local log_prefix
local ipv4
local ipv6
local filter_input
local filter_forward
local input_chain_name
local forward_chain_name
local input6_chain_name
local forward6_chain_name
local interface
local log_term=""
config_get 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 input_chain_name $section input_chain_name "input"
config_get forward_chain_name $section forward_chain_name "forward"
config_get input6_chain_name $section input6_chain_name "input"
config_get forward6_chain_name $section forward6_chain_name "forward"
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" $input_chain_name "{ type filter hook input priority $priority; policy accept; }"
nft add rule ip "$TABLE" $input_chain_name iifname { $interface } ct state new ip saddr @crowdsec-blacklists ${log_term} counter $deny_action
fi
if [ "$filter_forward" -eq "1" ] ; then
nft add chain ip "$TABLE" $forward_chain_name "{ type filter hook forward priority $priority; policy accept; }"
nft add rule ip "$TABLE" $forward_chain_name iifname { $interface } ct state new ip saddr @crowdsec-blacklists ${log_term} counter $deny_action
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" $input6_chain_name "{ type filter hook input priority $priority; policy accept; }"
nft add rule ip6 "$TABLE6" $input6_chain_name iifname { $interface } ct state new ip6 saddr @crowdsec6-blacklists ${log_term} counter $deny_action
fi
if [ "$filter_forward" -eq "1" ] ; then
nft add chain ip6 "$TABLE6" $forward6_chain_name "{ type filter hook forward priority $priority; policy accept; }"
nft add rule ip6 "$TABLE6" $forward6_chain_name iifname { $interface } ct state new ip6 saddr @crowdsec6-blacklists ${log_term} counter $deny_action
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
}

View File

@ -0,0 +1,15 @@
config bouncer
option enabled '0'
option ipv4 '1'
option ipv6 '1'
option api_url 'http://localhost:8080/'
option api_key ''
option update_frequency '10s'
option deny_action 'drop'
option deny_log '0'
option log_prefix 'crowdsec: '
option log_level 'info'
option filter_input '1'
option filter_forward '1'
list interface 'eth1'