Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firewall.py complete revamp #2011

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions .gitlab/ci/install.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ upgrade:
extends: .install-stage
image: "core-tests"
script:
- apt update
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb


install-postinstall:
extends: .install-stage
image: "before-install"
script:
- apt update
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
26 changes: 13 additions & 13 deletions conf/fail2ban/jail.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ before = paths-debian.conf
# MISCELLANEOUS OPTIONS
#

# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
#bantime.increment = true

# "bantime.rndtime" is the max number of seconds using for mixing with random time
# "bantime.rndtime" is the max number of seconds using for mixing with random time
# to prevent "clever" botnets calculate exact time IP can be unbanned again:
#bantime.rndtime =
#bantime.rndtime =

# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further)
#bantime.maxtime =
#bantime.maxtime =

# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
# default value of factor is 1 and with default value of formula, the ban time
# default value of factor is 1 and with default value of formula, the ban time
# grows by 1, 2, 4, 8, 16 ...
#bantime.factor = 1

Expand All @@ -69,14 +69,14 @@ before = paths-debian.conf

# "bantime.multipliers" used to calculate next value of ban time instead of formula, corresponding
# previously ban count and given "bantime.factor" (for multipliers default is 1);
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
#bantime.multipliers = 1 2 4 8 16 32 64
# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin,
# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day
#bantime.multipliers = 1 5 30 60 300 720 1440 2880

# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed
# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed
# cross over all jails, if false (default), only current jail of the ban IP will be searched
#bantime.overalljails = false

Expand Down Expand Up @@ -205,8 +205,8 @@ fail2ban_agent = Fail2Ban/%(fail2ban_version)s
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports
banaction = nftables-multiport
banaction_allports = nftables-allports

# The simplest action to take: ban only
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
Expand Down Expand Up @@ -242,11 +242,11 @@ action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# Report block via blocklist.de fail2ban reporting service API
#
#
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
# corresponding jail.d/my-jail.local file).
#
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
Expand Down Expand Up @@ -378,7 +378,7 @@ logpath = /opt/openhab/logs/request.log
port = http,https
logpath = %(nginx_error_log)s

# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module`
# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module`
# and define `limit_req` and `limit_req_zone` as described in nginx documentation
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
# or for example see in 'config/filter.d/nginx-limit-req.conf'
Expand Down Expand Up @@ -839,7 +839,7 @@ backend = %(syslog_backend)s

[xinetd-fail]

banaction = iptables-multiport-log
banaction = nftables-multiport-log
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
maxretry = 2
Expand Down
20 changes: 20 additions & 0 deletions conf/nftables/nftables.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/sbin/nft -f

flush ruleset

table inet filter {
chain input {
type filter hook input priority filter;
}
chain forward {
type filter hook forward priority filter;
}
chain output {
type filter hook output priority filter;
}
}

## Above is the standard nftables.conf
## Below is to include YunoHost configuration

include "/etc/nftables.d/*.conf"
1 change: 1 addition & 0 deletions conf/nftables/nftables.d/fail2ban.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# FIXME:
Salamandar marked this conversation as resolved.
Show resolved Hide resolved
21 changes: 21 additions & 0 deletions conf/nftables/nftables.d/yunohost-firewall.tpl.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/sbin/nft -f

{% set tcp_ports = tcp_ports.strip().split(' ') -%}
{% set udp_ports = udp_ports.strip().split(' ') -%}

table inet filter {
chain input {
ct state related,established counter accept;

{% for port in tcp_ports %}
tcp dport {{port}} counter accept;
{%- endfor %}

{% for port in udp_ports %}
udp dport {{port}} counter accept;
{%- endfor %}

iifname "lo" counter accept;
ip protocol icmp counter accept;
}
}
57 changes: 45 additions & 12 deletions conf/yunohost/firewall.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
uPnP:
enabled: false
TCP: [22, 25, 80, 443, 587, 993, 5222, 5269]
UDP: []
TCP_TO_CLOSE: []
UDP_TO_CLOSE: []
ipv4:
TCP: [22, 25, 53, 80, 443, 587, 993, 5222, 5269]
UDP: [53, 5353]
ipv6:
TCP: [22, 25, 53, 80, 443, 587, 993, 5222, 5269]
UDP: [53, 5353]
router_forwarding_upnp: false

tcp:
22:
open: true
upnp: true
comment: Default SSH port
25:
open: true
upnp: true
comment: SMTP email server (postfix)
80:
open: true
upnp: true
comment: HTTP server (nginx)
443:
open: true
upnp: true
comment: HTTPS server (nginx)
587:
open: true
upnp: true
comment: SMTP MSA email server (postfix)
993:
open: true
upnp: true
comment: IMAP email server (dovecot)

udp:
53:
open: true
upnp: false
comment: DNS server (dnsmasq)
1900:
open: true
upnp: false
comment: UPnP services
5353:
open: true
upnp: false
comment: mDNS (yunomdns)
55354:
open: true
upnp: false
comment: YunoHost UPnP firewall configurator
2 changes: 1 addition & 1 deletion conf/yunohost/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ yunohost-api:
category: admin
yunohost-firewall:
need_lock: true
test_status: iptables -S | grep "^-A INPUT" | grep " --dport" | grep -q ACCEPT
test_status: nft list chain ip filter input | grep "dport" | grep -q "accept"
category: security
yunomdns:
category: mdns
Expand Down
14 changes: 0 additions & 14 deletions conf/yunohost/yunohost-firewall.service

This file was deleted.

4 changes: 4 additions & 0 deletions conf/yunohost/yunohost-nftables-hooks-override.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This override config calls yunohost hooks when nftables is started/reloaded

[Service]
ExecStart=/usr/share/yunohost/yunohost-nftables-hooks
7 changes: 3 additions & 4 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Depends: python3-all (>= 3.11),
, python-is-python3, python3-pydantic, python3-email-validator
, nginx, nginx-extras (>=1.22)
, apt, apt-transport-https, apt-utils, aptitude, dirmngr
, openssh-server, iptables, fail2ban, bind9-dnsutils
, openssh-server, nftables, fail2ban, bind9-dnsutils
, openssl, ca-certificates, netcat-openbsd, iproute2
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
, dnsmasq, resolvconf, libnss-myhostname
Expand All @@ -34,8 +34,7 @@ Recommends: yunohost-admin, yunohost-portal (>= 12.0)
, bash-completion, rsyslog
, unattended-upgrades
, libdbd-ldap-perl, libnet-dns-perl
Conflicts: iptables-persistent
, apache2
Conflicts: apache2
, bind9
, openresolv
, systemd-resolved
Expand All @@ -44,7 +43,7 @@ Conflicts: iptables-persistent
, slapd (>= 2.6)
, dovecot-core (>= 1:2.4)
, fail2ban (>= 1.1)
, iptables (>= 1.8.10)
, nftables (>= 1.1)
Description: manageable and configured self-hosting server
YunoHost aims to make self-hosting accessible to everyone. It configures
an email, Web and IM server alongside a LDAP base. It also provides
Expand Down
17 changes: 5 additions & 12 deletions hooks/conf_regen/01-yunohost
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ do_init_regen() {
# YunoHost services
cp yunohost-api.service /etc/systemd/system/yunohost-api.service
cp yunohost-portal-api.service /etc/systemd/system/yunohost-portal-api.service
cp yunohost-firewall.service /etc/systemd/system/yunohost-firewall.service
cp yunoprompt.service /etc/systemd/system/yunoprompt.service

systemctl daemon-reload
Expand Down Expand Up @@ -278,15 +277,10 @@ ConditionVirtualization=!container
EOF
fi

# Make nftable conflict with yunohost-firewall
mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/
cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF
Salamandar marked this conversation as resolved.
Show resolved Hide resolved
[Unit]
# yunohost-firewall and nftables conflict with each other
Conflicts=yunohost-firewall.service
ConditionFileIsExecutable=!/etc/init.d/yunohost-firewall
ConditionPathExists=!/etc/systemd/system/multi-user.target.wants/yunohost-firewall.service
EOF
cp yunohost-nftables-hooks-override.conf ${pending_dir}/etc/systemd/system/nftables.service.d/yunohost-nftables-hooks.conf
# Delete legacy conflict between yunohost and nftables
touch ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf

# Don't suspend computer on LidSwitch
mkdir -p ${pending_dir}/etc/systemd/logind.conf.d/
Expand All @@ -299,9 +293,10 @@ EOF

cp yunohost-api.service ${pending_dir}/etc/systemd/system/yunohost-api.service
cp yunohost-portal-api.service ${pending_dir}/etc/systemd/system/yunohost-portal-api.service
cp yunohost-firewall.service ${pending_dir}/etc/systemd/system/yunohost-firewall.service
cp yunoprompt.service ${pending_dir}/etc/systemd/system/yunoprompt.service
cp proc-hidepid.service ${pending_dir}/etc/systemd/system/proc-hidepid.service
# Delete legacy yunohost-firewall service
touch ${pending_dir}/etc/systemd/system/yunohost-firewall.service

mkdir -p ${pending_dir}/etc/dpkg/origins/
cp dpkg-origins ${pending_dir}/etc/dpkg/origins/yunohost
Expand Down Expand Up @@ -361,12 +356,10 @@ do_post_regen() {
}
fi

[[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
systemctl daemon-reload
systemctl restart systemd-logind
}
[[ ! "$regen_conf_files" =~ "yunohost-firewall.service" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "yunohost-api.service" ]] || systemctl daemon-reload
[[ ! "$regen_conf_files" =~ "yunohost-portal-api.service" ]] || systemctl daemon-reload

Expand Down
69 changes: 69 additions & 0 deletions hooks/conf_regen/40-nftables
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

set -e

. /usr/share/yunohost/helpers


PY_LIST_PORTS_OF="
import os
import yaml
file = os.environ['FILE']
proto = os.environ['PROTO']
data = yaml.safe_load(open(file, 'r'))
ports = [str(port) for port, info in data[proto].items() if info['open']]
print(' '.join(ports))
"

do_pre_regen() {
pending_dir=$1

firewall_file="/etc/yunohost/firewall.yml"

tcp_ports=$(FILE=$firewall_file PROTO=tcp python3 -c "$PY_LIST_PORTS_OF")
udp_ports=$(FILE=$firewall_file PROTO=udp python3 -c "$PY_LIST_PORTS_OF")
export tcp_ports udp_ports

# # Support different strategy for security configurations
# export compatibility="$(jq -r '.ssh_compatibility' <<< "$YNH_SETTINGS")"
# export port="$(jq -r '.ssh_port' <<< "$YNH_SETTINGS")"
# export password_authentication="$(jq -r '.ssh_password_authentication' <<< "$YNH_SETTINGS" | int_to_bool)"
# export ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2> /dev/null || true)

cd /usr/share/yunohost/conf/nftables
mkdir -p "${pending_dir}/etc/nftables.d"
cp nftables.conf "${pending_dir}/etc/nftables.conf"
ynh_render_template nftables.d/yunohost-firewall.tpl.conf "${pending_dir}/etc/nftables.d/yunohost-firewall.conf"
}

do_post_regen() {
regen_conf_files=$1

if ls -l /etc/nftables.d/*.conf; then
chown root:root /etc/nftables.d/*.conf
chmod 644 /etc/nftables.d/*.conf
fi

[[ -z "$regen_conf_files" ]] \
|| systemctl reload-or-restart nftables
}

do_$1_regen ${@:2}
Loading
Loading