Implement modular nftables architecture and Gitea SSH firewall management

- Restructure security playbook with modular nftables loader
- Base rules loaded first, service rules second, drop rule last
- Add Gitea self-contained firewall management (port 2222)
- Add fail2ban protection for Gitea SSH brute force attacks
- Update documentation with new firewall architecture
- Create comprehensive Gitea deployment and testing guide

This enables self-contained service roles to manage their own firewall
rules without modifying the central security playbook. Each service
deploys rules to /etc/nftables.d/ which are loaded before the final
drop rule, maintaining the defense-in-depth security model.
This commit is contained in:
2025-12-16 21:45:22 +01:00
parent 9b12225ec8
commit 2fe194ba82
12 changed files with 933 additions and 43 deletions

View File

@@ -123,23 +123,37 @@
name: nftables
state: present
- name: Create nftables configuration
- name: Create nftables rules directory
file:
path: /etc/nftables.d
state: directory
mode: '0755'
- name: Create base nftables configuration
copy:
content: |
#!/usr/sbin/nft -f
# Main firewall table
# Flush existing rules for clean slate
flush ruleset
# Main firewall table - Rick-Infra Security
# Architecture: Base rules -> Service rules -> Drop rule
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# ======================================
# Base Infrastructure Rules
# ======================================
# Allow loopback interface
iif "lo" accept
# Allow established and related connections
ct state established,related accept
# Allow SSH (port 22)
# Allow SSH (port 22) - Infrastructure access
tcp dport 22 ct state new accept
# Allow HTTP and HTTPS for Caddy reverse proxy
@@ -148,9 +162,6 @@
# Allow ping with rate limiting
icmp type echo-request limit rate 1/second accept
icmpv6 type echo-request limit rate 1/second accept
# Log and drop everything else
counter drop
}
chain forward {
@@ -165,9 +176,43 @@
mode: '0755'
backup: yes
register: nft_config_changed
- name: Create nftables drop rule (loaded last)
copy:
content: |
# Final drop rule - Rick-Infra Security
# This file is loaded LAST to drop all unmatched traffic
# Service-specific rules in /etc/nftables.d/ are loaded before this
add rule inet filter input counter drop comment "Drop all other traffic"
dest: /etc/nftables.d/99-drop.nft
mode: '0644'
backup: yes
register: nft_drop_changed
- name: Create nftables loader script
copy:
content: |
#!/usr/sbin/nft -f
# Rick-Infra nftables loader
# Loads rules in correct order: base -> services -> drop
# Load base infrastructure rules
include "/etc/nftables.conf"
# Load service-specific rules (00-98 range)
include "/etc/nftables.d/[0-8]*.nft"
# Load final drop rule (99-drop.nft)
include "/etc/nftables.d/99-drop.nft"
dest: /etc/nftables-load.conf
mode: '0755'
backup: yes
register: nft_loader_changed
- name: Test nftables configuration syntax
command: nft -c -f /etc/nftables.conf
command: nft -c -f /etc/nftables-load.conf
changed_when: false
failed_when: false
register: nft_test
@@ -177,18 +222,31 @@
msg: "nftables configuration test failed: {{ nft_test.stderr }}"
when: nft_test.rc != 0
- name: Update nftables systemd service to use loader
lineinfile:
path: /usr/lib/systemd/system/nftables.service
regexp: '^ExecStart='
line: 'ExecStart=/usr/sbin/nft -f /etc/nftables-load.conf'
backup: yes
register: nft_service_changed
- name: Reload systemd daemon if service changed
systemd:
daemon_reload: yes
when: nft_service_changed.changed
- name: Flush existing nftables rules before applying new configuration
command: nft flush ruleset
failed_when: false
changed_when: false
when: nft_config_changed.changed
when: nft_config_changed.changed or nft_drop_changed.changed or nft_loader_changed.changed
- name: Enable and start nftables service
systemd:
name: nftables
enabled: yes
state: restarted
when: nft_config_changed.changed
when: nft_config_changed.changed or nft_drop_changed.changed or nft_loader_changed.changed or nft_service_changed.changed
- name: Wait for nftables to be active
pause: