Skip to content

Commit 0f707cd

Browse files
committed
feat(BOUN-1003): Adds Crowdsec bouncer to BN
1 parent 6e3edfb commit 0f707cd

File tree

6 files changed

+147
-9
lines changed

6 files changed

+147
-9
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
mode: nftables
2+
3+
update_frequency: 1s
4+
5+
log_mode: stdout
6+
log_level: info
7+
8+
api_url: {API_URL}
9+
api_key: {API_KEY}
10+
11+
supported_decisions_types:
12+
- ban
13+
14+
blacklists_ipv4: crowdsec
15+
blacklists_ipv6: crowdsec6
16+
17+
nftables:
18+
ipv4:
19+
enabled: true
20+
set-only: true
21+
table: filter
22+
23+
ipv6:
24+
enabled: true
25+
set-only: true
26+
table: filter

ic-os/boundary-guestos/rootfs/etc/nftables.conf

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ define ipv6_socks_saddr_ips = {
6464
}
6565

6666
table ip filter {
67-
6867
set connection_limit_200 {
6968
type ipv4_addr
7069
size 256000
@@ -95,9 +94,16 @@ table ip filter {
9594
flags dynamic
9695
}
9796

97+
set crowdsec {
98+
type ipv4_addr
99+
size 262144
100+
flags timeout
101+
}
102+
98103
chain input {
99104
type filter hook input priority filter; policy drop;
100105
iif "lo" accept
106+
ip saddr @crowdsec tcp dport { http, https, $canary_proxy_port } drop
101107
icmp type $icmp_v4_types_accept accept
102108
ct state invalid drop
103109
ct state { established, related } accept
@@ -126,7 +132,6 @@ table ip filter {
126132
}
127133

128134
table ip6 filter {
129-
130135
set connection_limit_200 {
131136
type ipv6_addr
132137
size 256000
@@ -157,9 +162,16 @@ table ip6 filter {
157162
flags dynamic
158163
}
159164

165+
set crowdsec6 {
166+
type ipv6_addr
167+
size 262144
168+
flags timeout
169+
}
170+
160171
chain input {
161172
type filter hook input priority filter; policy drop;
162173
iif "lo" accept
174+
ip6 saddr @crowdsec6 tcp dport { http, https, $canary_proxy_port } drop
163175
icmpv6 type $icmp_v6_in_types_accept accept
164176
ct state invalid drop
165177
ct state { established, related } accept
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[Unit]
2+
Description=Crowdsec nftables bouncer
3+
After=network-online.target
4+
Wants=network-online.target
5+
After=setup-crowdsec.service
6+
BindsTo=setup-crowdsec.service
7+
8+
[Service]
9+
Type=notify
10+
ExecStart=/usr/bin/crowdsec-firewall-bouncer -c /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
11+
ExecStartPre=/usr/bin/crowdsec-firewall-bouncer -c /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml -t
12+
ExecStartPost=/bin/sleep 0.1
13+
Restart=always
14+
RestartSec=10
15+
LimitNOFILE=65536
16+
KillMode=mixed
17+
18+
[Install]
19+
WantedBy=multi-user.target
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[Unit]
2+
Description=Create configuration for Crowdsec
3+
DefaultDependencies=no
4+
After=bootstrap-ic-node.service
5+
Requires=bootstrap-ic-node.service
6+
7+
[Service]
8+
Type=oneshot
9+
RemainAfterExit=true
10+
ExecStart=/opt/ic/bin/setup-crowdsec.sh
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
3+
set -euox pipefail
4+
source '/opt/ic/bin/helpers.shlib'
5+
6+
readonly BN_CONFIG="${BOOT_DIR}/bn_vars.conf"
7+
8+
readonly RUN_DIR='/run/ic-node/etc/crowdsec'
9+
readonly CFG_RO="/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml"
10+
readonly CFG_RW="${RUN_DIR}/crowdsec-firewall-bouncer.yaml"
11+
12+
# Read the config variables. The files must be of the form
13+
# "key=value" for each line with a specific set of keys permissible (see
14+
# code below).
15+
function read_variables() {
16+
if [[ ! -d "${BOOT_DIR}" ]]; then
17+
err "missing node configuration directory: ${BOOT_DIR}"
18+
exit 1
19+
fi
20+
21+
if [ ! -f "${BN_CONFIG}" ]; then
22+
err "missing domain configuration: ${BN_CONFIG}"
23+
exit 1
24+
fi
25+
26+
# Read limited set of keys. Be extra-careful quoting values as it could
27+
# otherwise lead to executing arbitrary shell code!
28+
while IFS="=" read -r key value; do
29+
case "${key}" in
30+
"crowdsec_api_url") API_URL="${value}" ;;
31+
"crowdsec_api_key") API_KEY="${value}" ;;
32+
esac
33+
done <"${BN_CONFIG}"
34+
}
35+
36+
function generate_config() {
37+
mkdir -p "${RUN_DIR}"
38+
cp $CFG_RO $CFG_RW
39+
sed -i "s|{API_URL}|${API_URL}|g" $CFG_RW
40+
sed -i "s|{API_KEY}|${API_KEY}|g" $CFG_RW
41+
mount --bind $CFG_RW $CFG_RO
42+
}
43+
44+
function main() {
45+
read_variables
46+
generate_config
47+
}
48+
49+
main "$@"

ic-os/boundary-guestos/scripts/build-deployment.sh

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ Arguments:
5555
--logging-url specify an endpoint for our logging backend
5656
--logging-user specify a user for our logging backend
5757
--logging-password specify a password for our logging backend
58-
--logging-2xx-sample-rate specify a sampling rate for logging 2XX requests (1 / N)
58+
--crowdsec-api-url speficy a Crowdsec API URL
59+
--crowdsec-api-key speficy a Crowdsec API key
5960
-x, --debug enable verbose console output
6061
'
6162
exit 1
@@ -138,8 +139,11 @@ for argument in "${@}"; do
138139
--logging-password=*)
139140
LOGGING_PASSWORD="${argument#*=}"
140141
;;
141-
--logging-2xx-sample-rate=*)
142-
LOGGING_2XX_SAMPLE_RATE="${argument#*=}"
142+
--crowdsec-api-url=*)
143+
CROWDSEC_API_URL="${argument#*=}"
144+
;;
145+
--crowdsec-api-key=*)
146+
CROWDSEC_API_KEY="${argument#*=}"
143147
;;
144148
*)
145149
echo "Error: Argument \"${argument#}\" is not supported for $0"
@@ -603,13 +607,30 @@ function copy_logging_credentials() {
603607
local NODE_IDX="${NODE["node_idx"]}"
604608
local NODE_PREFIX="${DEPLOYMENT}.${SUBNET_IDX}.${NODE_IDX}"
605609

606-
# Default values
607-
LOGGING_2XX_SAMPLE_RATE=${LOGGING_2XX_SAMPLE_RATE:-1}
608-
609610
echo "logging_url=${LOGGING_URL}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
610611
echo "logging_user=${LOGGING_USER}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
611612
echo "logging_password=${LOGGING_PASSWORD}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
612-
echo "logging_2xx_sample_rate=${LOGGING_2XX_SAMPLE_RATE}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
613+
done
614+
}
615+
616+
function copy_crowdsec_credentials() {
617+
if [[ -z "${CROWDSEC_API_URL:-}" || -z "${CROWDSEC_API_KEY:-}" ]]; then
618+
err "Crowdsec credentials have not been provided, continuing without configuring crowdsec"
619+
return
620+
fi
621+
622+
for n in $NODES; do
623+
declare -n NODE=$n
624+
if [[ "${NODE["type"]}" != "boundary" ]]; then
625+
continue
626+
fi
627+
628+
local SUBNET_IDX="${NODE["subnet_idx"]}"
629+
local NODE_IDX="${NODE["node_idx"]}"
630+
local NODE_PREFIX="${DEPLOYMENT}.${SUBNET_IDX}.${NODE_IDX}"
631+
632+
echo "crowdsec_api_url=${CROWDSEC_API_URL}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
633+
echo "crowdsec_api_key=${CROWDSEC_API_KEY}" >>"${CONFIG_DIR}/${NODE_PREFIX}/bn_vars.conf"
613634
done
614635
}
615636

@@ -668,6 +689,7 @@ function main() {
668689
copy_pre_isolation_canisters
669690
copy_ip_hash_salt
670691
copy_logging_credentials
692+
copy_crowdsec_credentials
671693
build_tarball
672694
build_removable_media
673695
remove_temporary_directories

0 commit comments

Comments
 (0)