System Hardening Chronicles: In Search of a Configuration Resilient to Targeted Attacks
This article was prepared with the assistance of AI assistants Google Gemini and DeepSeek. They helped structure the material, verify commands, and write sections. The logos are not advertisements, but merely indicate which tools were used in the work.
Last content update: 2026-07-09
📋 TL;DR — Article Summary
- What this article is about: A chronicle of system hardening in response to a targeted attack. Description of the initial configuration, the attack itself, and the enhanced configurations 2 and 3 with detailed settings for nftables, sysctl, AppArmor, OpenSnitch, Flatpak, USBGuard, and Quad9 DNS. Status of configuration testing.
1. Introduction: Analysis of the Initial Configuration and Prerequisites for Hardening
1.1 Context and Assumptions
Adversary Profile:
Presumably, a group with at least 20 years of experience in targeted attacks. This experience has been honed on thousands of real-world targets. Their methods include technological, socio-technical, and psychological vectors.
My Initial Position:
— Since August 2022, working in a security agency (physical security, not cyber).
— Since March 2025, systematically studying cybersecurity.
— Hardware and configurations at the time the attack began (February–March 2011) were not prepared for targeted defense.
— In June 2011, an opportunity existed to receive free configuration and basic training from an acquaintance (a lawyer) — this opportunity was not taken.
Conclusion on the Initial Configuration:
In the initial phase, the system lacked resilience against a targeted attack. I accept full responsibility for this.
1.2 Nature of the Attack (Observed Model)
The attack combines:
- Philosophical-occult rhetoric (active engagement in discussions about intuition, various forms of art, abstract concepts)
- Technological and socio-technical methods (actual OS vulnerabilities, social engineering, psychological pressure)
(For more details, see the article "Analysis of the Detected Targeted Complex Attack".)
This model fully corresponds to the classic scenario of destructive cult operations:
Distracting a person (or group) with metaphysics detached from reality + striking through technical and human vulnerabilities by leveraging superiority in scientific-technical and psychological knowledge.
1.3 Effectiveness of the Scientific Approach as a Countermeasure
The analysis established:
- When fully rejecting adversary-imposed discussions in the field of metaphysics, as well as metaphysical and intuitive thinking models, in favor of scientific-technical analysis (logic, causality, verifiable data) — the intensity of attacking actions increases many times over.
- The increase in pressure from the attacking group is a diagnostic indicator of the correctness of the chosen defense strategy.
Fact:
Attempts at moral and psychological suppression intensify in direct proportion to progress in studying AI, cybersecurity, social engineering, and forensic psychology. The more the victim's smokescreen of metaphysics and abstract concepts dissipates, the more the adversary displays their concern.
1.4 Current Strategy
No emotions. No resentment. No surprise.
The following course has been adopted:
- Systematic study of security, cybersecurity, socio-technical systems, and forensic psychology.
- Documentation of all attacks, vulnerabilities, responses, and configuration changes.
- Continuous system hardening with results recording.
Objective:
Achieve a configuration resilient to targeted attacks, followed by publication of all developed materials under the CC0 license.
1.5 Executive Summary (Technical Report)
| Parameter | Value |
|---|---|
| Initial Security Posture | Low |
| Attack Commencement | February–March 2011 |
| Adversary Experience (Estimate) | ≥ 20 years |
| Countermeasure | Scientific-technical analysis, hardening, documentation |
| Indicator of Effectiveness | Noticeable or even abrupt increase in attacking action intensity |
| Long-term Goal | Publish a resilient configuration under CC0 |
📋 TL;DR — Introduction
- Key points: Adversary has ≥20 years of experience. Initial configuration was not secure. Attack combines metaphysical rhetoric with technical methods. Scientific-technical analysis is an effective countermeasure. Strategy: documentation and hardening.
- Summary: Initial security posture is low. Attack began February–March 2011. Adversary experience ≥20 years. Countermeasure: scientific-technical analysis and hardening. Indicator of effectiveness: increase in attack intensity.
2. Chronicle of Hardening and Attacks
2.1 Description of the Previous System Configuration: CONFIGURATION 1
2.1.1 CONFIGURATION 1 Hardware
Processor and Architecture:
Architecture: x86_64
Model name: AMD Athlon(tm) II X2 220 Processor
RAM (at time of capture):
| Parameter | total | used | free | shared | buff/cache | available |
|---|---|---|---|---|---|---|
| Mem: | 5.8Gi | 2.9Gi | 809Mi | 64Mi | 2.5Gi | 2.9Gi |
| Swap: | 5.6Gi | 256Ki | 5.6Gi | — | — | — |
Motherboard:
SMBIOS 2.6 present.
Manufacturer: BIOSTAR Group
Product Name: N68S3B
Version: (not specified)
Serial Number: None
Type: Motherboard
Network Interface:
00:07.0 Bridge: NVIDIA Corporation MCP61 Ethernet (rev a2)
Subsystem: Biostar Microtech Int'l Corp Device 3407
Interrupt: pin A routed to IRQ 26
Capabilities: Power Management version 2, MSI (enabled)
2.1.2 CONFIGURATION 1 Software
Operating System: Debian 12
Desktop Environment: MATE
Kernel: 6.1.0-34-amd64
Network and System Settings:
- Internet access: ProtonVPN GUI in KillSwitch mode
- Incoming ports in nftables: fully blocked
- Outgoing ports in nftables: partially blocked (only ports required for the system and user applications allowed)
- AppArmor: partially enforced profiles provided by default with the system. Additional profile collections not downloaded, custom profiles not created
- The system was checked for remote access services. All remote access services to the PC (SSH server, remote desktop services, etc.) were either removed, disabled and unconfigured, or not installed.
Configuration 1 finalization date: 2025-08-01
2.2 Attack on Configuration 1
Date of attack: 2026-12-26
Confirmed adversary capabilities (post-factum):
- Reading correspondence with ChatGPT and DeepSeek in authorized browser-based web versions of personal accounts
- Viewing search queries on DuckDuckGo and Google (browser installed system-wide, browser fingerprint was masked)
- Visual monitoring of icons on the MATE desktop environment taskbar
- Viewing folder names in the KeePassXC root and icons of individual password entries (KeePassXC installed system-wide)
- Access to images generated within ChatGPT
- Reading text typed in the Pluma editor
Post-attack action: Old system wiped, clean installation of new configuration performed.
2.3 Hardened Configuration Post-Attack: CONFIGURATION 2
2.3.1 CONFIGURATION 2 Hardware
Same system unit (no changes).
2.3.2 CONFIGURATION 2 Software
2.3.2-A CONFIGURATION 2 Software Main Parameters
Operating System:
Distributor ID: Debian
Description: Debian GNU/Linux 13 (trixie)
Release: 13 (13.4)
Codename: trixie
Kernel:
Linux home 6.12.74+deb13+1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.74-2 (2026-03-08) x86_64 GNU/Linux
Graphics Subsystem:
Environment: GNOME / Wayland
GNOME Shell 48.7
tty (fallback access)
2.3.2-B КОНФИГУРАЦИЯ 2 Software nftables
nftables version:
1.1.3 (Commodore Bullmoose #4)
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
# = Main chain policy =
chain input {
type filter hook input priority 0;
policy drop;
# = Set of general rules =
# 🌀 Allow loopback interface (internal processes)
iif "lo" accept
# == 🔁 Allow established and related connections ==
ct state established,related accept
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
# == 🔒 Limit the rate of NEW connections per source IP (basic anti-DDoS protection) ==
# If you experience issues with slow or failed page loads in your browser,
# try increasing the limit, for example:
# ip saddr 0.0.0.0/0 ct state new limit rate 50/second burst 100 packets accept
ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
ip saddr 0.0.0.0/0 ct state new drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == 🚫 Block SSDP and mDNS (local broadcast protocols) ==
ip daddr 239.255.255.250 udp dport 1900 drop # ❌ SSDP (UPnP/device discovery)
ip daddr 224.0.0.251 udp dport 5353 drop # ❌ mDNS (Bonjour, Avahi)
# == 🛑 Block NetBIOS and LLMNR (internal Windows/systemd protocols) ==
udp dport 137 drop # ❌ NetBIOS Name Service (Windows network names)
udp dport 138 drop # ❌ NetBIOS Datagram Service (LAN browsing)
udp dport 5355 drop # ❌ LLMNR (Link-Local Multicast Name Resolution)
# = Set of rules for blocking IP addresses and ranges =
# == 🧱 Block known botnets and proxies ==
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} log prefix "🔥 BAN: known bots " flags all
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} drop
# == 🚫 Block invalid TCP flags (XMAS, NULL scan, etc.) ==
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop # NULL scan
tcp flags & (fin|psh|urg) == (fin|psh|urg) drop # XMAS scan
tcp flags & (fin|syn) == (fin|syn) drop # SYN-ACK scan
tcp flags & (syn|rst|fin) == (syn|rst|fin) drop # Xmas scan
tcp flags & (syn|fin|rst|psh|ack) == (syn|rst|fin|ack) drop # Xmas scan
# == 🚫 Block fragmented packets — often used to bypass filters ==
ip frag-off & 0x1fff != 0 drop
# == 🔒 Block packets with spoofed IPs (anti-spoofing) ==
ip saddr 127.0.0.0/8 drop # localhost
ip saddr 10.0.0.0/8 drop # private network
ip saddr 172.16.0.0/12 drop # private network
ip saddr 192.168.0.0/16 drop # private network
ip saddr 169.254.0.0/16 drop # APIPA
ip saddr 0.0.0.0/8 drop # invalid address
ip saddr 224.0.0.0/4 drop # multicast
ip saddr 240.0.0.0/5 drop # reserved
}
# = Main chain policy =
chain forward {
type filter hook forward priority 0;
policy accept;
# = Various attack restrictions =
# Only needed in chain forward if you have Docker or Oracle VirtualBox.
# Uncomment if needed.
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
# ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
# ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
# ip saddr 0.0.0.0/0 ct state new drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
# ip protocol icmp icmp type echo-request limit rate 1/second accept
# ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
# ip protocol icmp icmp type echo-request drop
# = Allow necessary TCP/UDP ports and ranges =
# == Allow TCP ports required for applications ==
tcp dport {
53, # DNS — needed for domain name resolution
80, # HTTP — web traffic, downloading updates and resources
443, # HTTPS — secure web traffic, VPN, browser
12043, # Custom 3D application — specific client port
13000-13050 # Custom 3D application — dynamic client port range
} accept
# == Allow UDP ports required for applications ==
udp dport {
53, # DNS — needed for domain name resolution
443, # HTTPS over QUIC/HTTP3, browser protocols
3478, # STUN/TURN — WebRTC and video conferencing
3479-3481 # STUN/TURN — WebRTC and video conferencing
} accept
# = Block potentially dangerous and unnecessary TCP/UDP ports and ranges =
# These restrictions are designed for a DESKTOP / workstation.
# They block remote access, outdated services, proxies, databases, IoT, and ports
# that are frequently used by malware, scanners, and C2 infrastructure.
#
# ⚠ If you are using the system as a SERVER, enable IP forwarding,
# or run services with their own routing
# (Docker NAT/bridge, VirtualBox host-only/bridged, VPN clients),
# be sure to review the list of blocked ports and ranges in the forward chain —
# these services may require additional ports.
# If necessary, adjust or comment out the required ports and ranges.
# == Block various suspicious TCP ports ==
tcp dport {
# === Remote access (high risk) ===
22, # SSH — brute-force target
23, # Telnet — outdated, no encryption
3389, # RDP — Windows remote access
5900, # VNC — remote access, frequent vulnerability
# === FTP / SMB / NetBIOS (dangerous file-sharing services) ===
21, # FTP — insecure protocol
137, # NetBIOS Name Service
138, # NetBIOS Datagram
139, # NetBIOS Session
445, # SMB/CIFS — frequent exploit target
# === Databases (NEVER open to the internet) ===
3306, # MySQL/MariaDB
1433, # MS SQL Server
1434, # MS SQL Browser
# === HTTP-alt/Proxy/Elasticsearch (dangerous, frequently attacked) ===
8080, # HTTP proxy / web interfaces — often open test interfaces
9200, # Elasticsearch API — full remote data access
# === UPnP/IoT (inherently vulnerable by design) ===
1900, # SSDP / UPnP
# === Frequently used by malware (RAT, C2, reverse shells) ===
4444, # Metasploit reverse shell
5555, # Android ADB / IoT botnets
9001, # Tor transport (frequently used by malware)
1234, # Netcat / reverse connections
1337, # Frequent C2 infrastructure port for malware
# === ⚠️ Ports for scanners and potentially vulnerable services ===
1080, # SOCKS proxy — often used by attackers to bypass filters
3128, # Squid HTTP proxy — can be used as a proxy/to bypass blocks
8000, # Alternative HTTP ports, web services — potentially vulnerable
8888, # Alternative web interfaces — test and proxy ports
10000 # Webmin — web admin panel, attack target
} drop
# == Block various suspicious UDP ports ==
udp dport {
161, # SNMP — network monitoring; can be used by attackers
162 # SNMP Trap — similarly, potential vulnerability
} drop
# Attention! When blocking wide port ranges, be careful!
# Do not harm the operation of the system and applications!
# == TCP port ranges not used by workstations during transit routing ==
# Blocked to prevent unwanted traffic forwarding, hidden tunnels,
# NAT bypass, parasitic connections, and potential attacks through the forward path.
tcp dport {
1024-2047, # System and outdated services; almost never needed in forward
2048-4095, # Proprietary and rare daemons; NFS (2049) — check if you use it
4096-8191, # Old VPNs, some games, P2P; rarely needed on a desktop
8192-12287, # Alternative HTTP/proxy, multimedia; test
12288-16383, # Media data/VoIP (TCP fallback); may break calls
16384-24575, # RTP/WebRTC (TCP fallback); block if audio/video not needed
24576-32767, # Dynamic ranges for games/VPN; possible side effects
32768-49151, # Main registered/ephemeral ports; dangerous, can break NAT, Docker, VM
49152-65535 # High ephemeral; actively used by modern applications
} drop
# == 🚫 Block UDP ports — high and dynamic ranges ==
udp dport {
1024-9999, # Low and medium ephemeral ports, rarely used by system services,
# can be used by Trojans, P2P, games, VPNs
10000-32767, # Potentially dangerous ports for outbound connections
# We block them because they are not used by the kernel for ephemeral ports
# P2P clients, games, and malware may be hiding here
32768-60999, # Standard Linux ephemeral ports
# CAUTION! These ports are needed for normal operation:
# - Docker containers (downloading updates)
# - DNS queries (often use high ports)
# - APT and other package managers
# - Normal network operation
61000-65535 # Upper reserved range
# Usually not used by standard applications
# We block to prevent non-standard outbound connections
} drop
# = 🕷️ Suspicious IPs — large ranges frequently used by botnets,
# spam networks, and scanners =
ip saddr {
185.0.0.0/8, # Abused hosting and proxy networks
37.0.0.0/8, # Cheap VPS, scanning sources
88.0.0.0/8, # Frequent brute-force and scanners
77.0.0.0/8, # Mass TOR/proxy nodes
91.0.0.0/8 # Botnets and "gray" hosting
} drop
}
chain output {
# = Main chain policy =
type filter hook output priority 0;
policy accept;
# = Various attack restrictions =
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
ip saddr 0.0.0.0/0 ct state new drop
# = ICMP protocol restrictions =
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == Critically important ICMP for the network ==
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
# == Important ICMPv6 for IPv6 ==
ip6 nexthdr icmpv6 icmpv6 type { 1, 2, 3, 4 } accept
ip6 nexthdr icmpv6 icmpv6 type { 135, 136 } accept # NS/NA
ip6 nexthdr icmpv6 icmpv6 type { 133, 134 } accept # RS/RA
# == Block all other ICMP and ICMPv6 ==
ip protocol icmp drop # all other ICMP drop
ip6 nexthdr icmpv6 drop # all other ICMPv6 drop
# = Block SCTP protocol =
# 99.9% of desktop systems don't use SCTP at all
meta l4proto sctp drop
# = Block DCCP — Datagram Congestion Control Protocol =
# Not used by any mainstream desktop application
meta l4proto dccp drop
# = Allow necessary TCP/UDP ports and ranges =
# == Allow TCP ports and ranges required for applications ==
tcp dport {
53, # DNS client — Required for internet: domain name resolution (UDP/TCP).
80, # HTTP — Traffic to websites without encryption; applications may access APIs/redirects.
443, # HTTPS — Main port for all encrypted web traffic — browser, API, VPN, updates.
3306, # MySQL client — Needed if connecting to MySQL
3478, # STUN/TURN WebRTC — Needed for audio/video/Discord
3000, # Node.js dev servers — Needed during development
3690, # SVN — If working with an old repository
4443, # Alternative HTTPS (some APIs) — Sometimes used by VPN/clients
12043, # Required for custom 3D application
13000-13050 # Required for custom 3D application
} accept
# == Allow UDP ports and ranges required for applications ==
udp dport {
443, # Needed for fast and stable operation of modern websites
# (Google, YouTube, ChatGPT, Cloudflare)
13000-13050 # Required for custom 3D application
} accept
# = Block potentially dangerous and unnecessary TCP/UDP ports and ranges =
# These restrictions are designed for a DESKTOP / workstation.
# ⚠ If you are using the system as a SERVER -
# adjust or comment out the required ports and ranges as needed.
# == Block various suspicious TCP ports ==
tcp dport {
# === Remote access (high risk) ===
22, # SSH — brute-force target
23, # Telnet — outdated, no encryption
3389, # RDP — Windows remote access
5900, # VNC — remote access, frequent vulnerability
# === FTP / SMB / NetBIOS (dangerous file-sharing services) ===
21, # FTP — insecure protocol
137, # NetBIOS Name Service
138, # NetBIOS Datagram
139, # NetBIOS Session
445, # SMB/CIFS — frequent exploit target
# === Databases (NEVER open to the internet) ===
3306, # MySQL/MariaDB
1433, # MS SQL Server
1434, # MS SQL Browser
# === HTTP-alt/Proxy/Elasticsearch (dangerous, frequently attacked) ===
8080, # HTTP proxy / web interfaces — often open test interfaces
9200, # Elasticsearch API — full remote data access
# === UPnP/IoT (inherently vulnerable by design) ===
1900, # SSDP / UPnP
# === Frequently used by malware (RAT, C2, reverse shells) ===
4444, # Metasploit reverse shell
5555, # Android ADB / IoT botnets
9001, # Tor transport (frequently used by malware)
1234, # Netcat / reverse connections
1337, # Frequent C2 infrastructure port for malware
# === ⚠️ Ports for scanners and potentially vulnerable services ===
1080, # SOCKS proxy — often used by attackers to bypass filters
3128, # Squid HTTP proxy — can be used as a proxy/to bypass blocks
8000, # Alternative HTTP ports, web services — potentially vulnerable
8888, # Alternative web interfaces — test and proxy ports
10000 # Webmin — web admin panel, attack target
} drop
# == Block various suspicious UDP ports ==
udp dport {
161, # SNMP — network monitoring; can be used by attackers
162 # SNMP Trap — similarly, potential vulnerability
} drop
# Attention! ⚠️ When blocking wide port ranges, be careful! ⚠️
# Do not harm the operation of the system and applications!
# If you need a specific range, uncomment the line with it.
# If not needed, comment it out.
# == Block "dangerous" and critically unnecessary TCP port ranges for desktops ==
tcp dport {
1-1023, # 🛑 Privileged ports
1024-2047, # r-commands (rlogin, rsh, rexec), old RPC, NFS, outdated daemons
2048-3071, # Rare proprietary protocols and middleware
3072-4999, # Mostly outdated, server and enterprise application ports;
# Almost never needed on regular workstations
5000-5999, # Alternative services, old P2P/administration, rarely needed on desktop
7000-7999, # Alternative services, test ports, often used by Trojans
9000-9999, # Web services, proxies, possible backdoor ports
10000-19998, # Dynamic and high service ports; may be used by applications like Firestorm,
# but not needed by most desktop services
19999-32767 # Old ephemeral port range; actively used by P2P,
# games, some VPNs, but system services rarely touch them
} drop
# == Block "dangerous" and critically unnecessary UDP port ranges for desktops ==
udp dport {
1024-2047, # Old UNIX services, RPC, NFS, r-commands, outdated daemons
# Usually safe to block
2048-4095, # Rarely used standard ports, proprietary services
# Also usually safe to block
# 4096-8191, # VPN, games, P2P, WebRTC, VoIP for some clients
# Can be blocked, but be careful: may affect VPN/applications
8192-12287, # QUIC/HTTP3, proxy, multimedia protocols
# Possible side effects, better to test
12288-16383, # Old RTP/VoIP ranges and media streams
# Can be blocked, but may break video calls
16384-24575, # Main RTP range (audio/video), WebRTC, VoIP
# ❗ Do NOT block if you need video calls/WebRTC/VPN
24576-32767 # Dynamic ports for VPN, P2P, games, streaming data
# ❗ May break VPN and some applications
} drop
# == 🕷️ Block suspicious IPs — large ranges frequently used by botnets,
# spam networks, and scanners ==
ip saddr {
185.0.0.0/8, # Abused hosting and proxy networks
37.0.0.0/8, # Cheap VPS, scanning sources
88.0.0.0/8, # Frequent brute-force and scanners
77.0.0.0/8, # Mass TOR/proxy nodes
91.0.0.0/8 # Botnets and "gray" hosting
} drop
}
}
2.3.2-C CONFIGURATION 2 Software sysctl
# ============================================
# SYSTEM HARDENING CONFIG (Debian 13 / MATE)
# Version: 6.0 (final)
# Date: 2026-03-03 16:31
# ============================================
# Apply: sudo sysctl --system
# ============================================
# ========== CORE NETWORK ==========
net.ipv4.icmp_echo_ignore_all = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.ip_forward = 0
net.ipv4.tcp_rfc1337 = 1
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.default.arp_filter = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 65536 4194304
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv4.tcp_synack_retries = 2
# ========== NETWORK HARDENING ==========
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.*.rp_filter = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# ========== KERNEL HARDENING ==========
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.randomize_va_space = 2
kernel.yama.ptrace_scope = 1
dev.tty.ldisc_autoload = 0
fs.protected_fifos = 2
kernel.sysrq = 0
net.core.bpf_jit_harden = 2
kernel.unprivileged_bpf_disabled = 1
# ========== END OF CONFIG ==========
2.3.2-D CONFIGURATION 2 Software Flatseal overrides
# Retrieved: 22.06.2026
# Command used: for file in ~/.local/share/flatpak/overrides/*; do echo "=== $file ==="; cat "$file"; echo; done
=== /home/user/.local/share/flatpak/overrides/com.viber.Viber ===
[Context]
sockets=!x11
=== /home/user/.local/share/flatpak/overrides/io.gitlab.librewolf-community ===
[Context]
shared=!ipc
sockets=!cups;!pcsc;!fallback-x11
features=per-app-dev-shm
filesystems=/home/user/Videos;/home/user/Pictures;/home/user/Music;/home/user/Downloads;/home/user/Documents;/home/user/Desktop
[Session Bus Policy]
org.a11y.Bus=none
=== /home/user/.local/share/flatpak/overrides/org.geany.Geany ===
[Context]
shared=!ipc;!network
sockets=!fallback-x11;!x11
filesystems=/home/user/Desktop/команды и настройки/Социнженерия/Прочие публикации;!host
=== /home/user/.local/share/flatpak/overrides/org.keepassxc.KeePassXC ===
[Context]
shared=!ipc;!network
sockets=!pcsc;!ssh-auth;!x11
filesystems=/home/user/Desktop/команды и настройки/Коды и пароли;!host
These overrides show the permissions that were modified for applications via Flatseal:
- LibreWolf: IPC, CUPS, PCSC, and X11 access restricted; access allowed to main user folders.
- Geany: IPC and network disabled; X11 blocked (runs via Wayland).
- KeePassXC: IPC, network, PCSC, SSH agent, and X11 disabled.
- Viber: X11 disabled (runs via Wayland).
2.3.2-E CONFIGURATION 2 Software OpenSnitch
OpenSnitch:
GUI version: 1.6.9
protobuf: 4.21.12
grpc: 1.51.1
# ============================================
# OPENSNITCH USER RULES
# Creation date: 2026-04-03 — 2026-04-08
# ============================================
# ========== BROWSERS (allowed) ==========
# LibreWolf
{
"name": "allow-librewolf",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/app/lib/librewolf/librewolf"
}
}
# Firefox ESR
{
"name": "allow-firefox-esr",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/firefox-esr/firefox-esr"
}
}
# ========== APPLICATIONS (allowed) ==========
# Python interpreter (for scripts)
{
"name": "allow-python3.13",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/bin/python3.13"
}
}
# Git (GitHub access)
{
"name": "allow-git-remote-http",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/git-core/git-remote-http"
}
}
# Systemd NTP client (time synchronization)
{
"name": "allow-systemd-timesyncd",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/systemd/systemd-timesyncd"
}
}
# APT (package updates)
{
"name": "allow-apt-http-method",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/apt/methods/http"
}
}
# NetworkManager (main network manager)
{
"name": "allow-networkmanager",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/sbin/NetworkManager"
}
}
# Kernel connection (VPN services)
{
"name": "allow-kernel-connection",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "Kernel connection"
}
}
# Client for updating firmware (fwupdmgr)
{
"name": "allow-fwupdmgr",
"action": "allow",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/bin/fwupdmgr"
}
}
# ========== BLOCKED APPLICATIONS ==========
# Ruby interpreter (suspicious activity)
{
"name": "deny-ruby3.3",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/bin/ruby3.3"
}
}
# DNS utility dig (risk)
{
"name": "deny-dig",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/bin/dig"
}
}
# GNOME Software (not needed)
{
"name": "deny-gnome-software",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/bin/gnome-software"
}
}
# Scanner daemon (not needed)
{
"name": "deny-colord-sane",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/libexec/colord-sane"
}
}
# Printer service (not needed)
{
"name": "deny-gsd-print-notifications",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/libexec/gsd-print-notifications"
}
}
# LibreOffice (internet access denied)
{
"name": "deny-libreoffice-soffice",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/libreoffice/program/soffice.bin"
}
}
# WebKitNetworkProcess (GNOME rendering engine)
{
"name": "deny-webkit-network-process",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/lib/x86_64-linux-gnu/webkitgtk-6.0/WebKitNetworkProcess"
}
}
# Email server (not needed)
{
"name": "deny-exim4",
"action": "deny",
"duration": "always",
"operator": {
"operand": "process.path",
"data": "/usr/sbin/exim4"
}
}
2.3.2-F CONFIGURATION 2 Software Other Programs
AppArmor:
Parser version: 4.1.0
Flatpak:
Version: 1.16.3
Installed Flatpak Applications:
- Flatseal (com.github.tchx84.Flatseal) — 2.4.0
- Viber (com.viber.Viber) — 24.9.0.3 (messenger, installed via Flatpak, system version removed)
- LibreWolf (io.gitlab.librewolf-community) — 149.0-1 (browser, installed via Flatpak, system version removed)
- Geany (org.geany.Geany) — 2.1.0 (code editor, installed via Flatpak, system version removed)
- KeePassXC (org.keepassxc.KeePassXC) — 2.7.12 (password manager, installed via Flatpak, system version removed)
USBGuard:
Version: 1.1.3
Compiled with support for: Linux audit, Libcapng, Seccomp, Systemd, Umockdev
Key changes in Configuration 2 compared to Configuration 1
- Migration from MATE (Xorg) to GNOME (Wayland)
- All critical applications (browser, password manager, code editor, messenger) installed via Flatpak, system versions removed
- Interaction of Flatpak applications with the system restricted using Flatseal (minimum necessary permissions)
- Strict AppArmor profiles configured and set to enforce mode for Nautilus, Pluma, CherryTree, Atril (D-Bus, /proc, /sys, Unix sockets, filesystem, temporary files restricted)
- Incoming ports in nftables: fully blocked
- Outgoing ports in nftables: partially blocked (only necessary ranges allowed)
- OpenSnitch installed on top of nftables; user rules allow outgoing connections only for trusted applications
- Internet access: ProtonVPN GUI in KillSwitch mode
- USBGuard installed and configured to prevent USB device emulation
- Browser fingerprint masking removed (deemed ineffective against this type of attack)
- rkhunter scan performed (however, it is assumed the adversary does not use known rootkits present in anti-rootkit databases)
- Analysis performed using lunis; system changes applied based on recommendations received
Configuration 2 finalization date: 2026-04-07
📋 TL;DR — 2.3.2 Configuration 2 Software
- 2.3.2-A Main parameters: Debian 13 (Trixie), kernel 6.12.74, GNOME 48.7 / Wayland.
- 2.3.2-B nftables: Strict firewall configuration: INPUT and OUTPUT policies set to ACCEPT with limitations, FORWARD — ACCEPT. Blocking botnets, suspicious flags, spoofing. Only necessary ports allowed.
- 2.3.2-C sysctl: Kernel hardening: disabling ICMP Echo, SYN flood protection, source routing prohibition, ptrace restriction (YAMA), IPv6 disabled.
- 2.3.2-D Flatseal overrides: Flatpak application permission restrictions: LibreWolf, Geany, KeePassXC, Viber. Disabling X11, IPC, network, PCSC, SSH agent.
- 2.3.2-E OpenSnitch: User-defined rules for allowing/denying outbound connections for applications (browsers, Python, Git, APT, Ruby, dig, LibreOffice).
- 2.3.2-F Other programs: AppArmor 4.1.0, Flatpak 1.16.3, USBGuard 1.1.3 with audit, seccomp, systemd support.
- 2.3.2-G Key changes: Migration to GNOME/Wayland, application isolation via Flatpak, strict AppArmor profiles, full inbound and partial outbound port blocking, OpenSnitch and USBGuard installation, removal of browser fingerprint masking.
Current status of Configuration 2 (as of 2026-04-10)
— Under testing.
— Preliminary data: not all vulnerabilities have been closed.
— Data requires additional confirmation.
— Configuration 3 will be built based on the attack data gathered against Configuration 2.
- ⚠️ Confirmed (19.06.2026 12:48): — full visibility for the adversary of all activity in the LibreWolf browser installed via Flatpak.
2.4 CONFIGURATION 3
Date of formation: 22.06.2026
2.4.1 CONFIGURATION 2 Hardware
Same system unit (no changes).
2.4.2 CONFIGURATION 3 Software
2.4.2-A Introduction
Repeats configuration 2, except for changes to the nftables output chain and switching to the Quad9 DNS server (9.9.9.9).
Removal of OpenSnitch:
In Configuration 3, it was decided to discontinue the use of OpenSnitch. During testing of Configuration 2, instability was observed in nftables when running simultaneously with OpenSnitch.
Reasons:
- OpenSnitch overwrites nftables rules created by the system configuration upon startup, leading to loss of user-defined settings and security policies.
- OpenSnitch creates its own tables and chains in
inet filterwith the same priority as system rules, which can cause replacement or conflicts. - As a result, strict policies (e.g.,
drop) may be replaced with more permissive OpenSnitch rules (withacceptpolicy), reducing the overall security level of the system.
Solution:
Preference was given to focusing on strengthening nftables configuration, as the primary and native security mechanism of Debian 13.
2.4.2-B Strategic logic of Configuration 3: blocking vectors as a deterrence method
I suspect that configuration 2, like configuration 1, was attacked by firmware malware, some type of designer worm, or malicious software that is created individually and strictly for a specific system (in this case, the author's system).
The goal of configuration 3 is to interrupt the malware's communication with its server by blocking its ability to send data to it. Thanks to the current nftables settings, the system can only send data to servers on the whitelist of trusted servers, thereby blocking data transmission to any other servers outside the trusted list, including the attacker's hacker servers.
It is highly probable that the adversary's malware (presumably firmware malware) uses legitimate, widely used ports (such as 80 and 443) for its traffic, disguising its outbound activity as ordinary legitimate traffic. This makes filtering based solely on port numbers largely ineffective: blocking widely used ports is impossible without disrupting the system's normal operation.
Therefore, a transition to a more stringent and flexible filtering model — based on IP addresses — is required. Under such a model, each trusted IP address, range, or group of ranges is assigned a strictly minimal and sufficient set of allowed outbound ports for its operation. This approach significantly narrows the channels for data exfiltration and blocks most covert outbound connections without compromising the legitimate functioning of the system.
Why this approach:
If the attack is carried out using firmware malware, hunting and analyzing it is pointless. Even if it is detected, suppressed, and its code deanonymized, the attacker will simply create new firmware malware based on different attack principles.
Therefore, the defense strategy is not built on finding a specific attack vector and blocking it, but on creating a protective configuration that blocks as many diverse attack vectors simultaneously as possible. This is the only way to ensure resilience against targeted attacks where the adversary can adapt and change their methods.
The more potential attack vectors are blocked, the fewer remain available to the attacker. Accordingly, their actions become more predictable — they will be forced to use the few vectors that are still available. This provides two important advantages:
- Predictability: We can calculate the list of unblocked vectors that the attacker might use, and this list will become narrower and narrower.
- Reverse engineering accuracy: The narrower the range of possible vectors, the more precise the data for analyzing the attacker's actions, and the easier it becomes to reconstruct their tactics, techniques, and procedures (TTPs).
Thus, the strategy of blocking the maximum number of vectors not only raises the overall level of protection but also turns the system into a kind of "trap" for the attacker, narrowing their maneuverability and simplifying subsequent analysis.
The number of attack vectors available to the adversary is not infinite, and they are depleted, even taking into account the use of an individualized approach to the attack. Each blocked vector is not just a closed door, but a forced change in the adversary's tactics.
At the same time, the fewer attack vectors remain available to the adversary, the higher the cost of the attack and the complexity of writing firmware malware by the attacking side. The adversary is forced to spend more resources, time, and effort on finding new approaches, developing new tools, and testing them to bypass the existing defenses.
As a result, even the adversary's significant technical and resource advantages are reduced to a "Pyrrhic victory" — a victory achieved at such a high cost that it is essentially meaningless. A system that blocks the maximum number of vectors turns into an economically and tactically unfavorable target for attack.
2.4.2-C Changes in the nftables config
- The
outputchain policy has been changed todrop. - Global restrictions and permissions for ports and port ranges have been removed from the
outputchain. - Outbound connections in the
outputchain are now only allowed to trusted IP ranges corresponding to trusted sites. - Each IP range is restricted to only specific ports.
Obtaining IP addresses for the whitelist using dig:
Important warning: when building an IP whitelist, do not use textual domain names. Specify individual IP addresses and CIDR ranges associated with the given domain name. Using domain names instead of numeric IP addresses leads to nftables failures.
To maintain an up-to-date IP whitelist, it is recommended to use the dig utility, which retrieves all A records for a given domain.
Example command:
# Obtain IP addresses for a domain
dig +short wiki.debian.org
Example output:
proxy-ca-01.debian.org.
209.87.16.81
#!/usr/sbin/nft -f
flush ruleset
table inet filter { # Opening the ruleset
# ============================================
# START OF INPUT CHAIN
# ============================================
# = Main chain policy =
chain input {
type filter hook input priority 0;
policy drop;
# = Set of general rules =
# 🌀 Allow loopback interface (internal processes)
iif "lo" accept
# == 🔁 Allow established and related connections ==
ct state established,related accept
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
ip saddr 0.0.0.0/0 ct state new drop
# == 🛡️ Limit pings ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == 🚫 Block SSDP and mDNS (local broadcast protocols) ==
ip daddr 239.255.255.250 udp dport 1900 drop # ❌ SSDP (UPnP/device discovery)
ip daddr 224.0.0.251 udp dport 5353 drop # ❌ mDNS (Bonjour, Avahi)
# == 🛑 Block NetBIOS and LLMNR (internal Windows/systemd protocols) ==
udp dport 137 drop # ❌ NetBIOS Name Service (Windows network names)
udp dport 138 drop # ❌ NetBIOS Datagram Service (LAN recognition)
udp dport 5355 drop # ❌ LLMNR (Link-Local Multicast Name Resolution)
# = Set of rules for blocking IP addresses and ranges =
# == 🧱 Block known botnets and proxies ==
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} log prefix "🔥 BAN: known bots " flags all
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} drop
# == 🚫 Block invalid TCP flags (XMAS, NULL scan, etc.) ==
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop # NULL scan
tcp flags & (fin|psh|urg) == (fin|psh|urg) drop # XMAS scan
tcp flags & (fin|syn) == (fin|syn) drop # SYN-ACK scan
tcp flags & (syn|rst|fin) == (syn|rst|fin) drop # Xmas scan
tcp flags & (syn|fin|rst|psh|ack) == (syn|rst|fin|ack) drop # Xmas scan
# == 🚫 Block fragmented packets — often used to bypass filters ==
ip frag-off & 0x1fff != 0 drop
# == 🔒 Block packets with spoofed IPs ==
ip saddr 127.0.0.0/8 drop # localhost
ip saddr 10.0.0.0/8 drop # private network
ip saddr 172.16.0.0/12 drop # private network
ip saddr 192.168.0.0/16 drop # private network
ip saddr 169.254.0.0/16 drop # APIPA
ip saddr 0.0.0.0/8 drop # invalid address
ip saddr 224.0.0.0/4 drop # multicast
ip saddr 240.0.0.0/5 drop # reserved
}
# ============================================
# END OF INPUT CHAIN
# ============================================
# ============================================
# START OF FORWARD CHAIN
# ============================================
# = Main chain policy =
chain forward {
type filter hook forward priority 0;
policy accept;
# = Various attack restrictions =
# Only needed in the forward chain if you have Docker, Oracle VirtualBox.
# Uncomment if needed.
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
# ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
# ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
# ip saddr 0.0.0.0/0 ct state new drop
# == 🛡️ Limit pings ==
# ip protocol icmp icmp type echo-request limit rate 1/second accept
# ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
# ip protocol icmp icmp type echo-request drop
# = Allow necessary TCP/UDP ports and ranges =
# == Allow TCP ports required for applications ==
tcp dport {
53, # DNS — needed for domain name resolution
80, # HTTP — web traffic, downloading updates and resources
443, # HTTPS — secure web traffic, VPN, browser
873, # Needed for rsync (OpenVAS updates, if rsync goes through Docker)
12043, # Firestorm Viewer — specific client port
13000-13050 # Firestorm Viewer — dynamic client port range
} accept
# Required in the forward chain for proper operation of the OpenVAS web interface
tcp dport 9392 accept
# == Allow UDP ports required for applications ==
udp dport {
53, # DNS — needed for domain name resolution
443, # HTTPS over QUIC/HTTP3, browser protocols
3478, # STUN/TURN — WebRTC and video conferencing
3479-3481 # STUN/TURN — WebRTC and video conferencing
} accept
# = Block potentially dangerous and unnecessary TCP/UDP ports and ranges =
# These restrictions are designed for a DESKTOP / workstation.
# They block remote access, outdated services, proxies, databases, IoT, and ports
# that are frequently used by malware, scanners, and C2 infrastructure.
#
# ⚠ If you are using the system as a SERVER, enable IP forwarding,
# or run services with their own routing
# (Docker NAT/bridge, VirtualBox host-only/bridged, VPN clients),
# be sure to review the list of blocked ports and ranges in the forward chain —
# these services may require additional ports.
# If necessary, adjust or comment out the required ports and ranges.
# == Block various suspicious TCP ports ==
tcp dport {
# === Remote access (high risk) ===
22, # SSH — brute-force target
23, # Telnet — outdated, no encryption
3389, # RDP — Windows remote access
5900, # VNC — remote access, frequent vulnerability
# === FTP / SMB / NetBIOS (dangerous file-sharing services) ===
21, # FTP — insecure protocol
137, # NetBIOS Name Service
138, # NetBIOS Datagram
139, # NetBIOS Session
445, # SMB/CIFS — frequent exploit target
# === Databases (NEVER open to the internet) ===
3306, # MySQL/MariaDB
1433, # MS SQL Server
1434, # MS SQL Browser
# === HTTP-alt/Proxy/Elasticsearch (dangerous, frequently attacked) ===
8080, # HTTP proxy / web interfaces — often open test interfaces
9200, # Elasticsearch API — full remote data access
# === UPnP/IoT (inherently vulnerable by design) ===
1900, # SSDP / UPnP
# === Frequently used by malware (RAT, C2, reverse shells) ===
4444, # Metasploit reverse shell
5555, # Android ADB / IoT botnets
9001, # Tor transport (frequently used by malware)
1234, # Netcat / reverse connections
1337, # Frequent C2 infrastructure port for malware
# === ⚠️ Ports for scanners and potentially vulnerable services ===
1080, # SOCKS proxy — often used by attackers to bypass filters
3128, # Squid HTTP proxy — can be used as a proxy/to bypass blocks
8000, # Alternative HTTP ports, web services — potentially vulnerable
8888, # Alternative web interfaces — test and proxy ports
10000 # Webmin — web admin panel, attack target
} drop
# == Block various suspicious UDP ports ==
udp dport {
161, # SNMP — network monitoring; can be used by attackers
162 # SNMP Trap — similarly, potential vulnerability
} drop
# Attention! When blocking wide port ranges, be careful!
# Do not harm the operation of the system and applications!
# == TCP port ranges not used by workstations during transit routing ==
# Blocked to prevent unwanted traffic forwarding, hidden tunnels,
# NAT bypass, parasitic connections, and potential attacks through the forward path.
tcp dport {
1024-2047, # System and outdated services; almost never needed in forward
2048-4095, # Proprietary and rare daemons; NFS (2049) — check if you use it
4096-8191, # Old VPNs, some games, P2P; rarely needed on a desktop
8192-12287, # Alternative HTTP/proxy, multimedia; test
12288-16383, # Media data/VoIP (TCP fallback); may break calls
16384-24575, # RTP/WebRTC (TCP fallback); block if audio/video not needed
24576-32767 # Dynamic ranges for games/VPN; possible side effects
# 32768-49151, # Main registered/ephemeral ports; dangerous, can break NAT, Docker, VM
# 49152-65535 # High ephemeral; actively used by modern applications
} drop
# == 🚫 Block UDP ports — high and dynamic ranges ==
udp dport {
1024-9999, # Low and medium ephemeral ports, rarely used by system services,
# can be used by Trojans, P2P, games, VPNs
10000-32767, # Potentially dangerous ports for outbound connections
# We block them because they are not used by the kernel for ephemeral ports
# P2P clients, games, and malware may be hiding here
# 32768-60999, # Standard Linux ephemeral ports
# CAUTION! These ports are needed for normal operation:
# - Docker containers (downloading updates)
# - DNS queries (often use high ports)
# - APT and other package managers
# - Normal network operation
61000-65535 # Upper reserved range
# Usually not used by standard applications
# We block to prevent non-standard outbound connections
} drop
# = 🕷️ Suspicious IPs — large ranges frequently used by botnets,
# spam networks, and scanners =
ip saddr {
185.0.0.0/8, # Abused hosting and proxy networks
37.0.0.0/8, # Cheap VPS, scanning sources
88.0.0.0/8, # Frequent brute-force and scanners
77.0.0.0/8, # Mass TOR/proxy nodes
91.0.0.0/8 # Botnets and "gray" hosting
} drop
}
# ============================================
# END OF FORWARD CHAIN
# ============================================
# ============================================
# START OF OUTPUT CHAIN
# ============================================
chain output {
# = Main chain policy =
type filter hook output priority 0;
policy drop;
# = THE VERY FIRST - critically important rules =
ct state established,related accept
oif "lo" accept
# =========================================================================
# 3. DNS SERVICE (Strict binding only to Quad9 at IP 9.9.9.9)
# =========================================================================
# Any other DNS query to the provider or hacker servers will be dropped
ip daddr 9.9.9.9 udp dport 53 ct state new accept
ip daddr 9.9.9.9 tcp dport 53 ct state new accept
# == Critically important ICMP for the network ==
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
# == Important ICMPv6 for IPv6 ==
ip6 nexthdr icmpv6 icmpv6 type { 1, 2, 3, 4 } accept
ip6 nexthdr icmpv6 icmpv6 type { 135, 136 } accept # NS/NA
ip6 nexthdr icmpv6 icmpv6 type { 133, 134 } accept # RS/RA
# =========================================================================
# BLOCKING RARE PROTOCOLS
# =========================================================================
# All rare protocols (SCTP, DCCP, and others) are automatically blocked
# by the policy drop. Explicit rules are not required for them.
# =========================================================================
# === Router web interface ===
ip daddr 192.168.0.1 tcp dport 80 accept
# === Cloudflare (global CDN and DDoS protection network) ===
# Used by ChatGPT, DeepSeek, and many other services for
# faster loading and attack protection. Main pool 104.16.0.0/12.
ip daddr {
104.16.0.0/12, # Main Cloudflare pool (104.16.0.0 – 104.31.255.255)
172.64.0.0/13, # Additional Cloudflare pool
162.158.0.0/15, # European Cloudflare pool
198.41.128.0/17 # American Cloudflare pool
} tcp dport { 80, 443 } ct state new accept
# === Fastly (content delivery network) ===
# Used for loading static content, fonts, and scripts.
ip daddr {
151.101.0.0/16, # Main Fastly pool
199.232.0.0/16 # Additional Fastly pool
} tcp dport { 80, 443 } ct state new accept
# === Amazon CloudFront / AWS (cloud infrastructure) ===
# Widely used for hosting APIs, backends, and CDN.
ip daddr {
13.32.0.0/15, # CloudFront US East
143.204.0.0/16, # CloudFront EU
54.239.128.0/18, # CloudFront Asia Pacific
13.224.0.0/14, # CloudFront Edge (global)
18.160.0.0/13, # CloudFront Edge (additional)
52.84.0.0/15, # CloudFront authentication
3.173.0.0/16, # AWS Edge (general pool)
23.211.0.0/16, # AWS CloudFront (additional)
23.47.0.0/16 # AWS CloudFront (backup)
} tcp dport { 80, 443 } ct state new accept
# === Google Cloud / YouTube (Google infrastructure, ASN 15169) ===
ip daddr {
64.233.160.0/19, # Main Google pool (Search, Accounts)
74.125.0.0/16, # Google service pools, including Gmail and gstatic
142.250.0.0/15, # Largest subnet for YouTube and Gemini API
172.217.0.0/16, # Content delivery servers and googleusercontent
173.194.0.0/16, # Additional routes for Google Drive and authorization
209.85.128.0/17, # Regional Google Cloud/API data centers
216.58.192.0/19, # Old but active Google DNS and frontend pools
35.190.0.0/16, # Google Cloud (general pool)
35.191.0.0/16 # Google Cloud (additional)
} tcp dport { 80, 443 } ct state new accept
# === GitHub (development platform) ===
ip daddr {
140.82.112.0/20, # Main GitHub subnets
192.30.252.0/22, # Additional GitHub pools
185.199.108.0/22 # CDN networks (raw.githubusercontent.com, githubassets.com)
} tcp dport { 80, 443 } ct state new accept
# === Debian Infrastructure (official servers and mirrors) ===
ip daddr {
130.89.148.0/24, # Physical ftp.debian.org servers (Netherlands)
128.31.0.0/16, # Official Debian infrastructure networks (MIT/USA)
149.20.4.0/24, # Technological gateways for mirroring and forums
206.12.19.0/24, # SPI routing backup pools
151.101.0.0/16, # Fastly CDN for deb.debian.org
199.232.0.0/16, # Additional Fastly pool for security
146.75.0.0/17 # Backup Debian package delivery routes
} tcp dport { 80, 443 } ct state new accept
# === openSUSE / Zeek (openSUSE infrastructure) ===
ip daddr {
195.135.220.0/22, # Main openSUSE data center
130.57.0.0/16 # Additional Novell/SUSE server pools
} tcp dport { 80, 443 } ct state new accept
# === LibreWolf (update repository) ===
ip daddr {
179.61.251.0/24, # repo.librewolf.net server (Frantech/BuyVM)
198.251.80.0/20, # BuyVM range in Luxembourg/USA
209.141.32.0/19 # Additional LibreWolf hosting routes
} tcp dport 443 ct state new accept
# === DeepSeek (specific IP addresses and subnets) ===
# Identified based on analysis of your list.
ip daddr {
103.193.104.0/22, # DeepSeek company's own technological routes
154.8.0.0/16, # Asian and global DeepSeek hosting pools
159.69.48.177/32, # Hetzner (Germany) - possible backend
150.171.109.51/32, # Possible backend or partner server
43.109.10.32/27, # Asian pool (range 43.109.10.32 - 43.109.10.63)
38.54.123.48/32, # Cogent Communications (possible route)
95.101.61.198/32, # Small range (Germany, possibly partner)
95.101.61.209/32,
95.101.61.218/32,
111.170.168.113/32, # Chinese provider (regional access)
20.150.95.164/32, # Microsoft Azure (possible backend)
34.107.243.93/32 # Google Cloud (possible backend)
} tcp dport { 80, 443 } ct state new accept
}
# ============================================
# END OF OUTPUT CHAIN
# ============================================
}
The whitelist of addresses allows the following sites to work:
- https://github.com and https://yourusername.github.io
- https://chat.deepseek.com
- https://chatgpt.com/
- https://www.google.com (as well as https://mail.google.com and https://search.google.com)
- https://validator.w3.org/
- https://www.producthunt.com
- https://cache.forums.debian.net
- https://forums.debian.net/
As well as some other useful sites for work.
⚠️ Warning: This configuration 3 config is an individual security measure demonstrating the logic of an experiment in building protection. Refrain from directly copying it. The lists of IP address ranges should be configured individually for your specific system.
When using this defense logic (a strict whitelist of outgoing IP addresses), you must add the IP addresses of your DNS server and your internet service provider to it, and specifically as numeric ranges rather than domain names.
Deep network activity analysis using tcpdump:
If you wish to gain a more comprehensive view of your internet connection activity, perform a traffic capture using tcpdump:
# Start analysis with logging to a file
sudo tcpdump -i enp0s7 -n "((tcp or udp) and (dst port 80 or dst port 443)) and not dst net 192.168.0.0/24" -v > /home/user/ai_traffic_raw.txt
Extracting unique IP addresses:
# Remove duplicates from the file
grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /home/user/ai_traffic_raw.txt | sort -u > /home/user/ai_unique_ips.txt
Submit the resulting list of unique IP addresses to Gemini (or another AI assistant) for analysis and annotation. Based on this analysis, you will obtain the necessary individual IP addresses and CIDR ranges to ensure stable access to your websites.
2.4.2-D Fixing the nftables configuration of Configuration 3
In previous versions of the configuration, errors were made that significantly reduced the effectiveness of the configuration.
The rate-limiting rule that was present in the input and forward chains, as well as in the output chain in earlier versions of the configuration, was placed at the beginning of the chain and contained the accept command, which neutralized a significant portion of the subsequent chain rules:
# == 🔒 Limit new connections per source IP (anti-DDoS) ==
# == 🔒 Limit the rate of NEW connections per source IP (basic anti-DDoS protection) ==
# If you experience issues with slow or failed page loads in your browser,
# try increasing the limit, for example:
# ip saddr 0.0.0.0/0 ct state new limit rate 50/second burst 100 packets accept
ip saddr 0.0.0.0/0 ct state new limit rate 25/second burst 50 packets accept
ip saddr 0.0.0.0/0 ct state new log prefix "🔥 BAN: too many conn " flags all
ip saddr 0.0.0.0/0 ct state new drop
In the current configuration, it has been replaced with:
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 25 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 25/second burst 50 packets log prefix "🔥 BAN: too many conn " flags all drop
for the input and forward chains.
It was also replaced with:
# ATTENTION: There is NO accept keyword here. This rule does NOT allow packets out to the internet.
# The "!" sign means: if the rate exceeds the limit, LOG and DROP the packet.
# If the rate is within limits, the packet silently passes below — to your IP whitelist.
# ATTENTION: meta l4proto { tcp, udp } and th dport cover both TCP and UDP (HTTP/3) with a single shield.
meta l4proto { tcp, udp } th dport { 80, 443 } ct state new limit rate over 20/second burst 40 packets log prefix "🔥 OUT_WEB_LIMIT_BURST: " drop
for the output chain.
Important note: the configuration with erroneous logic was posted on one of the IT forums, where a significant portion of participants, instead of analyzing the logic of the provided configuration and drawing conclusions based on the substance of the configuration's logic, began to engage in personal conflicts with the author, accusing them of paranoia and lies, while failing to notice the errors in the provided configuration. Instead of analyzing the situation impartially and on its merits, a person tends to analyze the situation based on their own emotions (often negative) and prejudices that have nothing to do with objective reality. As a result, the analysis of the situation turns out to be partially or completely erroneous.
Conclusions: in addition to consulting with people, it is essential to verify new configurations multiple times using Gemini, DeepSeek, and other AI tools focused on code work. People have original creative thinking that AI lacks, but at the same time they are subject to negative emotions and prejudices that distract them from an impartial analysis of the situation on its merits, and often completely deprive them of the ability to perform such analysis. AI does not have these negative aspects, which is worth using for additional verification of what has already been submitted for public scrutiny.
Additionally, the list of port permissions and restrictions in the forward chain and the IP whitelist in the output chain have been moved to separate files using the include function. There are no changes in the logic of these restriction lists compared to the previous nftables configuration of Configuration 3.
Fixed nftables configuration of Configuration 3:
#!/usr/sbin/nft -f
# = modification 25 =
# 03.03.2026 19:52 Commented out the outbound UDP port restriction that was interfering with ProtonVPN
# 04.03.2026 19:53 Allowed necessary ports for Docker in the forward chain
# 21.06.2026 08:24 Implemented outbound connection filtering by IP address
flush ruleset
table inet filter { # Opening the ruleset
# ============================================
# START OF INPUT CHAIN
# ============================================
# = Main chain policy =
chain input {
type filter hook input priority 0;
policy drop;
# = Set of general rules =
# 🌀 Allow loopback interface (internal processes)
iif "lo" accept
# == 🔁 Allow established and related connections ==
ct state established,related accept
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 25 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 25/second burst 50 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == 🚫 Block SSDP and mDNS (local broadcast protocols) ==
ip daddr 239.255.255.250 udp dport 1900 drop # ❌ SSDP (UPnP/device discovery)
ip daddr 224.0.0.251 udp dport 5353 drop # ❌ mDNS (Bonjour, Avahi)
# == 🛑 Block NetBIOS and LLMNR (internal Windows/systemd protocols) ==
udp dport 137 drop # ❌ NetBIOS Name Service (Windows network names)
udp dport 138 drop # ❌ NetBIOS Datagram Service (LAN browsing)
udp dport 5355 drop # ❌ LLMNR (Link-Local Multicast Name Resolution)
# = Set of rules for blocking IP addresses and ranges =
# == 🧱 Block known botnets and proxies ==
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} log prefix "🔥 BAN: known bots " flags all
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} drop
# == 🚫 Block invalid TCP flags (XMAS, NULL scan, etc.) ==
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop # NULL scan
tcp flags & (fin|psh|urg) == (fin|psh|urg) drop # XMAS scan
tcp flags & (fin|syn) == (fin|syn) drop # SYN-ACK scan
tcp flags & (syn|rst|fin) == (syn|rst|fin) drop # Xmas scan
tcp flags & (syn|fin|rst|psh|ack) == (syn|rst|fin|ack) drop # Xmas scan
# == 🚫 Block fragmented packets — often used to bypass filters ==
ip frag-off & 0x1fff != 0 drop
# == 🔒 Block packets with spoofed IPs (anti-spoofing) ==
ip saddr 127.0.0.0/8 drop # localhost
ip saddr 10.0.0.0/8 drop # private network
ip saddr 172.16.0.0/12 drop # private network
ip saddr 192.168.0.0/16 drop # private network
ip saddr 169.254.0.0/16 drop # APIPA
ip saddr 0.0.0.0/8 drop # invalid address
ip saddr 224.0.0.0/4 drop # multicast
ip saddr 240.0.0.0/5 drop # reserved
}
# ============================================
# END OF INPUT CHAIN
# ============================================
# ============================================
# START OF FORWARD CHAIN
# ============================================
# = Main chain policy =
chain forward {
type filter hook forward priority 0;
policy accept;
# = Various attack restrictions =
# Only needed in chain forward if you have Docker, Oracle VirtualBox.
# Uncomment if needed.
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 25 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 25/second burst 50 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
# ip protocol icmp icmp type echo-request limit rate 1/second accept
# ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
# ip protocol icmp icmp type echo-request drop
# ⬇️ INSERT: Forward chain port rules
# Blocked and allowed TCP/UDP ports and ranges
include "/etc/nftables.d/forward-tcp-udp.nft"
# ⬆️ END OF INSERT
}
# ============================================
# END OF FORWARD CHAIN
# ============================================
# ============================================
# START OF OUTPUT CHAIN
# ============================================
chain output {
# = Main chain policy =
type filter hook output priority 0;
policy drop;
# = THE VERY FIRST - critically important rules =
ct state established,related accept
oif "lo" accept
# =======================================================================
# 1. GENERAL PROTECTIVE SHIELD (Only rate limiting!)
# =======================================================================
# ATTENTION: There is NO accept keyword here. This rule does NOT allow packets out to the internet.
# The "!" sign means: if the rate exceeds the limit, LOG and DROP the packet.
# If the rate is within limits, the packet silently passes below — to your IP whitelist.
# ATTENTION: meta l4proto { tcp, udp } and th dport cover both TCP and UDP (HTTP/3) with a single shield.
meta l4proto { tcp, udp } th dport { 80, 443 } ct state new limit rate over 20/second burst 40 packets log prefix "🔥 OUT_WEB_LIMIT_BURST: " drop
# =========================================================================
# 3. DNS SERVICE (Strict binding only to Quad9 at IP 9.9.9.9)
# =========================================================================
# Any other DNS query to the provider or hacker servers will be dropped
ip daddr 9.9.9.9 udp dport 53 ct state new accept
ip daddr 9.9.9.9 tcp dport 53 ct state new accept
# == Critically important ICMP for the network ==
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
# == Important ICMPv6 for IPv6 ==
ip6 nexthdr icmpv6 icmpv6 type { 1, 2, 3, 4 } accept
ip6 nexthdr icmpv6 icmpv6 type { 135, 136 } accept # NS/NA
ip6 nexthdr icmpv6 icmpv6 type { 133, 134 } accept # RS/RA
# =========================================================================
# BLOCKING RARE PROTOCOLS
# =========================================================================
# All rare protocols (SCTP, DCCP, and others) are automatically blocked
# by the policy drop. Explicit rules are not required for them.
# =========================================================================
# ⬇️ INSERT: whitelist.nft file contents are inserted here
include "/etc/nftables.d/whitelist.nft"
# ⬆️ END OF INSERT
} # The penultimate brace closes the ruleset of the output chain. Do not remove!
# ============================================
# END OF OUTPUT CHAIN
# ============================================
} # The last brace closes the entire configuration ruleset. Do not remove!
2.4.2-E Enhancing the nftables configuration of Configuration 3
The implementation of the strategy aimed at disrupting communication channels between the presumed hacker infrastructure and the author's system continues.
The objective remains unchanged: in addition to applying other measures that hinder the proper functioning of potential malware — such as kernel parameter tuning via sysctl, system fragmentation using sandboxes (Firejail, Flatpak), and application permission restrictions through AppArmor — it is essential to maximally complicate both the attacker's access to the author's system and the malware's response to the adversary's server.
The communication channel between the attacker's server and the victim's computer represents a critical bottleneck — a "choke point" that, regardless of the sophistication of the hacker infrastructure, cannot be entirely bypassed. For this reason, particular attention must be paid to the analysis and filtering of this network segment.
In order to enhance security and to practically explore the potential of nftables, it was decided to strengthen the nftables configuration of Configuration 3.
For example, many users who have configured security in Windows-based operating systems have noticed that many Windows-oriented firewalls offer outbound traffic filtering by process name.
There is no such logic in nftables, but a somewhat different logic is applied: filtering by UID — username. This is what should be used.
In addition to establishing outbound traffic filtering by IP and fixing the limit on allowed connections per second, made in sections "2.4.2-C Changes in the nftables config" and "2.4.2-D Fixing the nftables configuration of Configuration 3", the following additional security features were added to the configuration and to the whitelist of allowed IPs for the output chain which was extracted from the main config:
- Filtering access to IPs from the whitelist by user UID — even if an IP address is allowed, only specific users (e.g.,
user,_apt,root) are permitted to access it. This prevents malicious processes running under other UIDs from using allowed IP addresses. - Filtering invalid packets in the
outputchain — packets marked as invalid by conntrack are immediately dropped with logging. This prevents suspicious or malformed packets from being sent to the internet. - Stateful Connection Isolation & Hijacking Protection via Socket UID — eliminates the classic firewall "blind spot" where any packets with
establishedstatus are blindly approved. - Mandatory DNS shield with tunneling protection (Strict DNS & Anti-Tunneling) — restricts port 53 (TCP/UDP) exclusively to three servers (Quad9 and the ISP). For UDP, only short queries (
meta length <= 150bytes) are allowed, effectively blocking DNS tunneling, whilemeta skuidchecks completely close off DNS access to ghost system processes (such asnobodyordaemon).
Enhanced nftables configuration of Configuration 3:
#!/usr/sbin/nft -f
# 03.03.2026 19:52 Commented out the outbound UDP port restriction that was interfering with ProtonVPN
# 04.03.2026 19:53 Allowed necessary ports for Docker in the forward chain
# 21.06.2026 08:24 Implemented outbound connection filtering by IP address
# 28.06.2026 21:53 Set a limit on the number of connections per second
# Added filtering of whitelisted IP access by user UID
# Added filtering of invalid packets in the output chain
flush ruleset
table inet filter { # Opening the ruleset
# ============================================
# START OF INPUT CHAIN
# ============================================
# = Main chain policy =
chain input {
type filter hook input priority 0;
policy drop;
# = Set of general rules =
# 🌀 Allow loopback interface (internal processes)
iif "lo" accept
# == 🔁 Allow established and related connections ==
ct state established,related accept
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 100 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 100/second burst 200 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == 🚫 Block SSDP and mDNS (local broadcast protocols) ==
ip daddr 239.255.255.250 udp dport 1900 drop # ❌ SSDP (UPnP/device discovery)
ip daddr 224.0.0.251 udp dport 5353 drop # ❌ mDNS (Bonjour, Avahi)
# == 🛑 Block NetBIOS and LLMNR (internal Windows/systemd protocols) ==
udp dport 137 drop # ❌ NetBIOS Name Service (Windows network names)
udp dport 138 drop # ❌ NetBIOS Datagram Service (LAN browsing)
udp dport 5355 drop # ❌ LLMNR (Link-Local Multicast Name Resolution)
# = Set of rules for blocking IP addresses and ranges =
# == 🧱 Block known botnets and proxies ==
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} log prefix "🔥 BAN: known bots " flags all
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} drop
# == 🚫 Block invalid TCP flags (XMAS, NULL scan, etc.) ==
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop # NULL scan
tcp flags & (fin|psh|urg) == (fin|psh|urg) drop # XMAS scan
tcp flags & (fin|syn) == (fin|syn) drop # SYN-ACK scan
tcp flags & (syn|rst|fin) == (syn|rst|fin) drop # Xmas scan
tcp flags & (syn|fin|rst|psh|ack) == (syn|rst|fin|ack) drop # Xmas scan
# == 🚫 Block fragmented packets — often used to bypass filters ==
ip frag-off & 0x1fff != 0 drop
# == 🔒 Block packets with spoofed IPs (anti-spoofing) ==
ip saddr 127.0.0.0/8 drop # localhost
ip saddr 10.0.0.0/8 drop # private network
ip saddr 172.16.0.0/12 drop # private network
ip saddr 192.168.0.0/16 drop # private network
ip saddr 169.254.0.0/16 drop # APIPA
ip saddr 0.0.0.0/8 drop # invalid address
ip saddr 224.0.0.0/4 drop # multicast
ip saddr 240.0.0.0/5 drop # reserved
}
# ============================================
# END OF INPUT CHAIN
# ============================================
# ============================================
# START OF FORWARD CHAIN
# ============================================
# = Main chain policy =
chain forward {
type filter hook forward priority 0;
policy accept;
# = Various attack restrictions =
# Only needed in chain forward if you have Docker, Oracle VirtualBox.
# Uncomment if needed.
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 100 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 100/second burst 200 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
# ip protocol icmp icmp type echo-request limit rate 1/second accept
# ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
# ip protocol icmp icmp type echo-request drop
# ⬇️ INSERT: Forward chain port rules
# Blocked and allowed TCP/UDP ports and ranges
include "/etc/nftables.d/forward-tcp-udp.nft"
# ⬆️ END OF INSERT
}
# ============================================
# END OF FORWARD CHAIN
# ============================================
# ============================================
# START OF OUTPUT CHAIN
# ============================================
chain output {
# = Main chain policy =
type filter hook output priority 0;
policy drop;
# = THE VERY FIRST - critically important rules =
ct state established,related accept
oif "lo" accept
# Drop any outgoing packets marked as invalid by conntrack
# This ensures immediate destruction of invalid packets
# before the remaining filtering rules are applied.
ct state invalid log prefix "🔥 INVALID_OUT_PACKET: " drop
# =========================================================================
# 🔒 SMART INSPECTION OF ESTABLISHED SESSIONS (Protection against Connection Hijacking)
# =========================================================================
# Allow established sessions ONLY if the packets within them originate from You, Your Browser, APT, or Root.
# System ghosts (nobody, daemon) are completely exiled from here.
ct state established,related meta skuid { user, _flatpak, _apt, root, systemd-timesync } accept
# ⬇️ INSTANT CUTOFF: If an unauthorized system process attempts to hijack your session
ct state established,related log flags skuid prefix "🔥 HIJACK_ATTEMPT_DROP: " drop
# =======================================================================
# 1. GENERAL PROTECTIVE SHIELD (Only rate limiting!)
# =======================================================================
# ATTENTION: There is NO accept keyword here. This rule does NOT allow packets out to the internet.
# The "!" sign means: if the rate exceeds the limit, LOG and DROP the packet.
# If the rate is within limits, the packet silently passes below — to your IP whitelist.
# ATTENTION: meta l4proto { tcp, udp } and th dport cover both TCP and UDP (HTTP/3) with a single shield.
meta l4proto { tcp, udp } th dport { 80, 443 } ct state new limit rate over 100/second burst 200 packets log prefix "🔥 OUT_WEB_LIMIT_BURST: " drop
# =========================================================================
# 2. DNS SERVICE
# Strict binding only to Quad9 at IP 9.9.9.9
# Length control, user filtering, and backup servers
# =========================================================================
# 2.1. For UDP, allow only short requests (<=150 bytes) and strictly from trusted users
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } udp dport 53 meta length <= 150 meta skuid { user, _apt, root } ct state new accept
# 2.2. For TCP, no length limit (for heavy DNSSEC responses), but strictly check the user
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } tcp dport 53 meta skuid { user, _apt, root, systemd-timesync } ct state new accept
# 2.3. All other attempts by any unauthorized services (or long UDP) — log and destroy
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } meta l4proto { tcp, udp } th dport 53 log flags skuid prefix "🔥 OUT_BLOCK_LEAK_DNS: " drop
# == Critically important ICMP for the network ==
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
# == Important ICMPv6 for IPv6 ==
ip6 nexthdr icmpv6 icmpv6 type { 1, 2, 3, 4 } accept
ip6 nexthdr icmpv6 icmpv6 type { 135, 136 } accept # NS/NA
ip6 nexthdr icmpv6 icmpv6 type { 133, 134 } accept # RS/RA
# =========================================================================
# BLOCKING RARE PROTOCOLS
# =========================================================================
# All rare protocols (SCTP, DCCP, and others) are automatically blocked
# by the policy drop. Explicit rules are not required for them.
# =========================================================================
# ⬇️ INSERT: whitelist.nft file contents are inserted here
include "/etc/nftables.d/whitelist.nft"
# ⬆️ END OF INSERT
} # The penultimate brace closes the ruleset of the output chain. Do not remove!
# ============================================
# END OF OUTPUT CHAIN
# ============================================
} # The last brace closes the entire configuration ruleset. Do not remove!
Real-time log monitoring:
To observe nftables rule hits and diagnose blocks in real time, you can use the following command, which displays kernel log messages in real time and filters them by the 🔥 prefix:
# Real-time log monitoring (kernel only, filtered by 🔥)
sudo journalctl -f -k | grep --line-buffered "🔥"
This command is particularly useful for debugging nftables rules — you will see all rule hits with the 🔥 prefix immediately as they occur in the system.
Whitelist of IP addresses for the output chain, with access restricted by port number and user UID:
# /etc/nftables.d/whitelist.nft
# Whitelist of IP addresses for outbound connections
# Also applies filtering by UID
# === Router web interface ===
ip daddr 192.168.0.1 tcp dport 80 meta skuid { user, _flatpak, root } ct state new accept
# =========================================================================
# === Internet service provider ===
# =========================================================================
# Provider's personal account and main website your.provider.net
# Defined using strict CIDR ranges of the autonomous system
# Opened for account top-up even during DNS failures and blocks
ip daddr {
192.0.2.0/24, # Location of the personal account web server
198.51.100.0/24, # Location of the information website
192.0.2.0/19, # Provider's main address pool
198.51.100.0/20 # Subscriber routing pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak, root } ct state new accept
# === Cloudflare (global CDN and DDoS protection network) ===
# Used by ChatGPT, DeepSeek, and many other services for
# faster loading and attack protection. Main pool 104.16.0.0/12.
ip daddr {
104.16.0.0/12, # Main Cloudflare pool (104.16.0.0 – 104.31.255.255)
172.64.0.0/13, # Additional Cloudflare pool
162.158.0.0/15, # European Cloudflare pool
198.41.128.0/17 # American Cloudflare pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Fastly (content delivery network) ===
# Used for loading static content, fonts, and scripts.
ip daddr {
151.101.0.0/16, # Main Fastly pool
199.232.0.0/16 # Additional Fastly pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Amazon CloudFront / AWS (cloud infrastructure) ===
# Widely used for hosting APIs, backends, and CDN.
ip daddr {
13.32.0.0/15, # CloudFront US East
143.204.0.0/16, # CloudFront EU
54.239.128.0/18, # CloudFront Asia Pacific
13.224.0.0/14, # CloudFront Edge (global)
18.160.0.0/13, # CloudFront Edge (additional)
52.84.0.0/15, # CloudFront authentication
3.173.0.0/16, # AWS Edge (general pool)
23.211.0.0/16, # AWS CloudFront (additional)
23.47.0.0/16 # AWS CloudFront (backup)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Amazon Web Services (AWS CloudFront / EC2) ===
ip daddr {
3.0.0.0/8,
54.0.0.0/8,
52.0.0.0/8,
18.66.233.0/24
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Google Cloud / YouTube (Google infrastructure, ASN 15169) ===
ip daddr {
64.233.160.0/19, # Main Google pool (Search, Accounts)
74.125.0.0/16, # Google service pools, including Gmail and gstatic
142.250.0.0/15, # Largest subnet for YouTube and Gemini API
172.217.0.0/16, # Content delivery servers and googleusercontent
173.194.0.0/16, # Additional routes for Google Drive and authorization
209.85.128.0/17, # Regional Google Cloud/API data centers
216.58.192.0/19, # Old but active Google DNS and frontend pools
35.190.0.0/16, # Google Cloud (general pool)
35.191.0.0/16 # Google Cloud (additional)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Google (AS15169) - search, YouTube, Gmail, API ===
ip daddr {
142.250.0.0/15,
172.217.0.0/16,
74.125.0.0/16
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Bing search engine and Microsoft services ===
ip daddr {
150.171.0.0/16, # Main address pool of the Bing search engine
40.126.0.0/18, # Microsoft Live / Office authorization services
20.190.128.0/18, # Azure / Microsoft cloud backends
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === GitHub (development platform) ===
ip daddr {
140.82.112.0/20, # Main GitHub subnets
192.30.252.0/22, # Additional GitHub pools
185.199.108.0/22 # CDN networks (raw.githubusercontent.com, githubassets.com)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Debian Infrastructure (official servers and mirrors) ===
ip daddr {
130.89.148.0/24, # Physical ftp.debian.org servers (Netherlands)
128.31.0.0/16, # Official Debian infrastructure networks (MIT/USA)
149.20.4.0/24, # Technological gateways for mirroring and forums
206.12.19.0/24, # SPI routing backup pools
151.101.0.0/16, # Fastly CDN for deb.debian.org
199.232.0.0/16, # Additional Fastly pool for security
146.75.0.0/17, # Backup Debian package delivery routes
51.83.0.0/16 # Mirror repositories for deb.debian.org updates
} tcp dport { 80, 443 } meta skuid { user, _flatpak, _apt, root } ct state new accept
# === ⏰ Allow system time synchronization (NTP) ===
# This rule is paranoid: UDP port 123 is open EXCLUSIVELY for this process.
# No backdoor running as root or nobody will be able to exploit this loophole.
udp dport 123 meta skuid systemd-timesync ct state new accept
# === Debian Project & Wiki (By domain names in separate lines) ===
ip daddr {
209.87.16.81
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === openSUSE / Zeek (openSUSE infrastructure) ===
ip daddr {
195.135.220.0/22, # Main openSUSE data center
130.57.0.0/16 # Additional Novell/SUSE server pools
} tcp dport { 80, 443 } meta skuid { user, _apt, root } ct state new accept
# === LibreWolf (update repository) ===
ip daddr {
179.61.251.0/24, # repo.librewolf.net server (Frantech/BuyVM)
198.251.80.0/20, # BuyVM range in Luxembourg/USA
209.141.32.0/19 # Additional LibreWolf hosting routes
} tcp dport 443 meta skuid { user, _apt, root } ct state new accept
# === DeepSeek (specific IP addresses and subnets) ===
# Identified based on analysis of your list.
ip daddr {
103.193.104.0/22, # DeepSeek company's own technological routes
154.8.0.0/16, # Asian and global DeepSeek hosting pools
159.69.48.177/32, # Hetzner (Germany) - possible backend
150.171.109.51/32, # Possible backend or partner server
43.109.10.32/27, # Asian pool (range 43.109.10.32 - 43.109.10.63)
38.54.123.48/32, # Cogent Communications (possible route)
95.101.61.198/32, # Small range (Germany, possibly partner)
95.101.61.209/32,
95.101.61.218/32,
111.170.168.113/32, # Chinese provider (regional access)
20.150.95.164/32, # Microsoft Azure (possible backend)
34.107.243.93/32 # Google Cloud (possible backend)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Wikipedia ===
ip daddr {
185.15.59.224
} tcp dport { 443, 80 } meta skuid { user, _flatpak } ct state new accept
# === Facebook / Meta ===
ip daddr 57.144.0.0/14 tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Hetzner Cloud (if you use it) ===
ip daddr 150.171.0.0/16 tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Akamai (extended range 23.32.0.0/11) ===
ip daddr {
23.32.0.0/11,
23.211.0.0/16,
23.64.0.0/16
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Backup DNS Quad9 ===
ip daddr 9.9.9.0/24 udp dport 53 meta skuid { user, _apt, root } accept
# === Backup DNS Quad9 (149.112.0.0/16) ===
ip daddr 149.112.0.0/16 udp dport 53 meta skuid { user, _apt, root } accept
List of TCP and UDP port restrictions and allowances and suspicious IPs restriction for the forward chain
The list of TCP and UDP port restrictions and allowances for the forward chain has not changed, but for the sake of completeness of the nftables configuration picture, I am attaching it to this chapter:
# /etc/nftables.d/forward-tcp-udp.nft
# List of rules for the forward chain TCP UDP
# Status as of 26.06.2026 12:08
# = Allow necessary TCP/UDP ports and ranges =
# == Allow TCP ports required for applications ==
tcp dport {
53, # DNS — needed for domain name resolution
80, # HTTP — web traffic, downloading updates and resources
443, # HTTPS — secure web traffic, VPN, browser
12043, # Custom 3D application — specific client port
13000-13050 # Custom 3D application — dynamic client port range
} accept
# == Allow UDP ports required for applications ==
udp dport {
53, # DNS — needed for domain name resolution
443, # HTTPS over QUIC/HTTP3, browser protocols
3478, # STUN/TURN — WebRTC and video conferencing
3479-3481 # STUN/TURN — WebRTC and video conferencing
} accept
# = Block potentially dangerous and unnecessary TCP/UDP ports and ranges =
# These restrictions are designed for a DESKTOP / workstation.
# They block remote access, outdated services, proxies, databases, IoT, and ports
# that are frequently used by malware, scanners, and C2 infrastructure.
#
# ⚠ If you are using the system as a SERVER, enable IP forwarding,
# or run services with their own routing
# (Docker NAT/bridge, VirtualBox host-only/bridged, VPN clients),
# be sure to review the list of blocked ports and ranges in the forward chain —
# these services may require additional ports.
# If necessary, adjust or comment out the required ports and ranges.
# == Block various suspicious TCP ports ==
tcp dport {
# === Remote access (high risk) ===
22, # SSH — brute-force target
23, # Telnet — outdated, no encryption
3389, # RDP — Windows remote access
5900, # VNC — remote access, frequent vulnerability
# === FTP / SMB / NetBIOS (dangerous file-sharing services) ===
21, # FTP — insecure protocol
137, # NetBIOS Name Service
138, # NetBIOS Datagram
139, # NetBIOS Session
445, # SMB/CIFS — frequent exploit target
# === Databases (NEVER open to the internet) ===
3306, # MySQL/MariaDB
1433, # MS SQL Server
1434, # MS SQL Browser
# === HTTP-alt/Proxy/Elasticsearch (dangerous, frequently attacked) ===
8080, # HTTP proxy / web interfaces — often open test interfaces
9200, # Elasticsearch API — full remote data access
# === UPnP/IoT (inherently vulnerable by design) ===
1900, # SSDP / UPnP
# === Frequently used by malware (RAT, C2, reverse shells) ===
4444, # Metasploit reverse shell
5555, # Android ADB / IoT botnets
9001, # Tor transport (frequently used by malware)
1234, # Netcat / reverse connections
1337, # Frequent C2 infrastructure port for malware
# === ⚠️ Ports for scanners and potentially vulnerable services ===
1080, # SOCKS proxy — often used by attackers to bypass filters
3128, # Squid HTTP proxy — can be used as a proxy/to bypass blocks
8000, # Alternative HTTP ports, web services — potentially vulnerable
8888, # Alternative web interfaces — test and proxy ports
10000 # Webmin — web admin panel, attack target
} drop
# == Block various suspicious UDP ports ==
udp dport {
161, # SNMP — network monitoring; can be used by attackers
162 # SNMP Trap — similarly, potential vulnerability
} drop
# Attention! When blocking wide port ranges, be careful!
# Do not harm the operation of the system and applications!
# == TCP port ranges not used by workstations during transit routing ==
# Blocked to prevent unwanted traffic forwarding, hidden tunnels,
# NAT bypass, parasitic connections, and potential attacks through the forward path.
tcp dport {
1024-2047, # System and outdated services; almost never needed in forward
2048-4095, # Proprietary and rare daemons; NFS (2049) — check if you use it
4096-8191, # Old VPNs, some games, P2P; rarely needed on a desktop
8192-12287, # Alternative HTTP/proxy, multimedia; test
12288-16383, # Media data/VoIP (TCP fallback); may break calls
16384-24575, # RTP/WebRTC (TCP fallback); block if audio/video not needed
24576-32767, # Dynamic ranges for games/VPN; possible side effects
32768-49151, # Main registered/ephemeral ports; dangerous, can break NAT, Docker, VM
49152-65535 # High ephemeral; actively used by modern applications
} drop
# == 🚫 Block UDP ports — high and dynamic ranges ==
udp dport {
1024-9999, # Low and medium ephemeral ports, rarely used by system services,
# can be used by Trojans, P2P, games, VPNs
10000-32767, # Potentially dangerous ports for outbound connections
# We block them because they are not used by the kernel for ephemeral ports
# P2P clients, games, and malware may be hiding here
32768-60999, # Standard Linux ephemeral ports
# CAUTION! These ports are needed for normal operation:
# - Docker containers (downloading updates)
# - DNS queries (often use high ports)
# - APT and other package managers
# - Normal network operation
61000-65535 # Upper reserved range
# Usually not used by standard applications
# We block to prevent non-standard outbound connections
} drop
# = 🕷️ Suspicious IPs — large ranges frequently used by botnets,
# spam networks, and scanners =
ip saddr {
185.0.0.0/8, # Abused hosting and proxy networks
37.0.0.0/8, # Cheap VPS, scanning sources
88.0.0.0/8, # Frequent brute-force and scanners
77.0.0.0/8, # Mass TOR/proxy nodes
91.0.0.0/8 # Botnets and "gray" hosting
} drop
2.3.2-F Enhancing the sysctl configuration of Configuration 3
In Configuration 3, it was decided to apply the kernel.yama.ptrace_scope = 2 parameter. Previously, in Configurations 1 and 2, the kernel.yama.ptrace_scope = 1 parameter was used.
Practical benefits of the kernel.yama.ptrace_scope = 2
Memory isolation and injection blocking (Yama ptrace_scope Hardening) — the kernel.yama.ptrace_scope = 2 system parameter closes the critical Process Injection vector. This completely deprives background malware of the technical capability to use the ptrace system call for covertly injecting spy code or intercepting data within the RAM of a running LibreWolf browser or gaming clients.
# ============================================
# SYSTEM HARDENING CONFIG
# Debian 13 (Trixie) / MATE
# Version: v. 7.0 blackcat568
# Date: 04.03.2026 16:31
# ============================================
# ATTENTION: Apply with: sudo sysctl --system
# After applying, reboot the system to verify stability.
# ============================================
# ========== CORE NETWORK RULES ==========
# 1. Complete ICMP Echo (ping) ignore - INCOMING REQUESTS ONLY
# Effect: The system does not respond to incoming ping requests. Makes your PC "invisible"
# to simple network scanners and automated bots.
# Important: This does NOT block outgoing ping requests from your system.
#
# Side effects:
# - Other hosts on the network will not be able to check your PC's availability via ping.
# - Some VPNs and tunnels may use ICMP for keepalive (rare).
#
# Suitable for:
# ✅ Home/office PC not providing public services — completely safe.
# ❌ Public server — comment this line out. In this case, item 16
# (icmp_ignore_bogus_error_responses) will only filter out erroneous ICMP packets.
#
# Note: Since IPv6 is disabled (item 11), this rule only applies to ICMPv4.
net.ipv4.icmp_echo_ignore_all = 1
# 2. Ignore ICMP broadcast requests
# Effect: Protection against Smurf attacks (traffic amplification via broadcast requests).
# Side effects: None for a typical PC.
net.ipv4.icmp_echo_ignore_broadcasts = 1
# 3. Enable SYN Cookies
# Effect: Protection against SYN flood attacks (DoS). When the SYN queue overflows, it enables cookie mechanism instead of dropping connections.
# Side effects: Slight increase in load during an attack. May affect some high-load servers, but safe for desktops.
net.ipv4.tcp_syncookies = 1
# 4. Disable Source Routing
# Effect: Prevents attackers from specifying packet routes through your system (spoofing protection).
# Side effects: None for regular users.
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 5. Log "martian" packets
# Effect: Logs packets with impossible (obviously forged) source/destination addresses.
# Side effects: May fill logs (journalctl) during network attacks or misconfiguration.
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# 6. Disable ICMP redirects
# Effect: Prevents routing table modification via ICMP packets. Protection against man-in-the-middle attacks.
# Side effects: In complex networks with dynamic routing may require enabling, but safe for stationary PCs.
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# 7. Disable packet forwarding
# Effect: System does not act as a router (does not forward packets between interfaces).
# Side effects: None (default value).
net.ipv4.ip_forward = 0
# 8. Protection against empty TCP window attacks
# Effect: Enables RFC 1337 - protection against attacks using "empty" TCP segments to hold connections.
# Side effects: None.
net.ipv4.tcp_rfc1337 = 1
# 9. ARP request filtering
# Effect: Protects against ARP spoofing by forcing the kernel to filter ARP replies from multiple interfaces.
# Side effects: May cause issues in complex load-balanced networks (requires configuration).
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.default.arp_filter = 1
# 10. TCP window limits
# Effect: Sets minimum, default, and maximum receive/send buffer sizes.
# Side effects: Too low values may reduce download speed, but the specified values are optimal.
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 65536 4194304
# 11. COMPLETE IPv6 DISABLE
# Effect: Disables entire IPv6 stack. Eliminates a whole class of IPv6-related vulnerabilities.
# ⚠️ RED MARK ⚠️
# Side effects: Applications requiring IPv6 stop working (some torrents, Docker containers, some sites via IPv6).
# Note: If using Docker or modern browsers with IPv6 preferences, localhost issues may occur.
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
# 12. Reduce SYN-ACK retry attempts
# Effect: Speeds up closing of "half-open" connections during attacks.
# Side effects: Under poor connectivity, some legitimate connections may terminate faster.
net.ipv4.tcp_synack_retries = 2
# ========== NETWORK HARDENING ==========
# 13. Disable sending ICMP redirects
# Effect: Supplement to item 6 - prevents the system from sending redirects (system is not a router).
# Side effects: None.
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# 14. Reverse Path Filtering
# Effect: Strict protection against IP spoofing. Packet is dropped if it arrives on an interface it shouldn't have.
# ⚠️ RED MARK ⚠️
# Side effects: If you have a complex network with multiple interfaces (e.g., wired + Wi-Fi + VPN), strict mode (1) may disable internet on one of the interfaces.
# Solution: If network issues occur, try value 2 (loose mode).
# If that doesn't help - comment these lines out.
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.*.rp_filter = 1
# 15. Reduce TCP timeouts
# This parameter only works for outgoing (client) connections. For incoming connections (if you were running a server), it's useless.
# Effect: Fast resource release when connections are closed.
# Side effects: In rare cases, may prematurely close "slow" connections.
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
# 16. Ignore bogus ICMP error responses
# Effect: Drops ICMP packets with invalid error codes.
# Side effects: None.
net.ipv4.icmp_ignore_bogus_error_responses = 1
# ========== KERNEL HARDENING ==========
# 17. Restrict access to kernel logs and addresses
# Effect: dmesg_restrict - only root can see kernel message buffer.
# kptr_restrict=2 - kernel pointer addresses are hidden from all, including root.
# Side effects: Makes debugging system issues harder for regular users.
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
# 18. Full Address Space Layout Randomization (ASLR)
# Effect: Maximum protection against memory vulnerability exploitation (buffer overflow).
# Side effects: May cause rare issues with legacy software not compiled with PIC/PIE support.
kernel.randomize_va_space = 2
# 19. Restrict ptrace (YAMA)
# Effect: Prevents processes from tracing (debugging) other processes. Protects browser memory from being read by stealers.
# ⚠️ RED MARK ⚠️
# Side effects: Breaks debuggers (gdb, strace) when attaching to another PID. Does not affect child processes (e.g., terminal debugging still works).
# Note: For regular users - safe and recommended.
kernel.yama.ptrace_scope = 2
# 20. DISABLE USER NAMESPACES
# Effect: Closes the main vector for local privilege escalation. Prevents container isolation for unprivileged users.
# ⚠️⚠️⚠️ RED MARK (HIGH COMPATIBILITY RISK) ⚠️⚠️⚠️
# Side effects:
# - COMPLETELY breaks Flatpak/Snap applications
# - Breaks Docker/Podman for regular users
# - Breaks Chrome/Chromium sandbox (browser may crash or become unstable)
# - Some modern applications may fail to launch
# Test: If browser or app store fails to start after reboot - comment these two lines out (commented by default, uncomment only if necessary).
# kernel.unprivileged_userns_clone = 0
# user.max_user_namespaces = 0
# 21. Disable eBPF for unprivileged users
# Effect: Prevents creation of eBPF programs (frequently used by rootkits and exploits).
# Side effects: Breaks monitoring tools running via eBPF (e.g., bcc-tools) if not run as root.
kernel.unprivileged_bpf_disabled = 1
# 22. DISABLE AUTOMATIC TERMINAL LINE DISCIPLINE LOADING
# Effect: Prevents automatic loading of line disciplines via serial ports (TTY).
# Closes attack vector related to terminal device manipulation.
# Side effects: For typical desktops without specialized hardware — none.
# Does not affect standard terminals, SSH, consoles.
dev.tty.ldisc_autoload = 0
# 23. PROTECTION OF FIFO FILES IN SHARED DIRECTORIES
# Effect: Prevents creation of named pipes (FIFO) in sticky-bit directories (/tmp, /var/tmp).
# Prevents attacks using FIFO for privilege escalation or bypassing restrictions.
# Side effects: Does not affect normal application operation, as they should not create FIFOs
# in public temporary directories. Completely safe for desktops.
fs.protected_fifos = 2
# 24. COMPLETE DISABLE OF SYSREQ (MAGIC KEYS)
# Effect: Disables Alt+SysRq+command combinations, which allow low-level commands
# even when the system freezes (reboot, sync, process termination).
# Prevents accidental or malicious system reset via physical keyboard.
# Side effects: During actual system freeze, you won't be able to use SysRq for safe
# reboot (reboot, sync). For home PCs — not critical, as usually
# the power button or unplugging is used.
kernel.sysrq = 0
# 25. STRENGTHEN BPF JIT COMPILER PROTECTION
# Effect: Enables additional checks and randomization in Berkeley Packet Filter JIT compiler.
# Hardens exploitation of vulnerabilities in eBPF programs that can be used by rootkits.
# Value 2 enables maximum hardening without disabling eBPF.
# Side effects: Slight overhead when compiling BPF programs.
# Does not affect daily system operation. Docker and modern applications
# continue to work normally.
net.core.bpf_jit_harden = 2
# ========== END OF CONFIG ==========
# After applying, check browser and Flatpak application operation.
# For User Namespace issues - see item 20.
2.4.2-G Automating IP range selection for the whitelist via a cron script
This section presents a new nftables configuration that employs two methods for obtaining IP addresses and ranges for the whitelist: using the include function and using a cron script.
Use whichever method is more convenient for the specific websites you visit.
Main nftables configuration for Configuration 3 (dynamic update version):
#!/usr/sbin/nft -f
flush ruleset
table inet filter { # Opening the ruleset
# === # === Adding a container for dynamic IP addresses of websites ===
set whitelist_fqdn {
type ipv4_addr
flags interval
}
# ============================================
# START OF INPUT CHAIN
# ============================================
# = Main chain policy =
chain input {
type filter hook input priority 0;
policy drop;
# = Set of general rules =
# 🌀 Allow loopback interface (internal processes)
iif "lo" accept
# == 🔁 Allow established and related connections ==
ct state established,related accept
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 100 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 100/second burst 200 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
ip protocol icmp icmp type echo-request limit rate 1/second accept
ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
ip protocol icmp icmp type echo-request drop
# == 🚫 Block SSDP and mDNS (local broadcast protocols) ==
ip daddr 239.255.255.250 udp dport 1900 drop # ❌ SSDP (UPnP/device discovery)
ip daddr 224.0.0.251 udp dport 5353 drop # ❌ mDNS (Bonjour, Avahi)
# == 🛑 Block NetBIOS and LLMNR (internal Windows/systemd protocols) ==
udp dport 137 drop # ❌ NetBIOS Name Service (Windows network names)
udp dport 138 drop # ❌ NetBIOS Datagram Service (LAN browsing)
udp dport 5355 drop # ❌ LLMNR (Link-Local Multicast Name Resolution)
# = Set of rules for blocking IP addresses and ranges =
# == 🧱 Block known botnets and proxies ==
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} log prefix "🔥 BAN: known bots " flags all
ip saddr {
45.9.20.0/24,
89.248.160.0/19,
185.220.100.0/22,
198.96.155.0/24,
185.107.56.0/24,
185.129.62.0/23
} drop
# == 🚫 Block invalid TCP flags (XMAS, NULL scan, etc.) ==
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop # NULL scan
tcp flags & (fin|psh|urg) == (fin|psh|urg) drop # XMAS scan
tcp flags & (fin|syn) == (fin|syn) drop # SYN-ACK scan
tcp flags & (syn|rst|fin) == (syn|rst|fin) drop # Xmas scan
tcp flags & (syn|fin|rst|psh|ack) == (syn|rst|fin|ack) drop # Xmas scan
# == 🚫 Block fragmented packets — often used to bypass filters ==
ip frag-off & 0x1fff != 0 drop
# == 🔒 Block packets with spoofed IPs (anti-spoofing) ==
ip saddr 127.0.0.0/8 drop # localhost
ip saddr 10.0.0.0/8 drop # private network
ip saddr 172.16.0.0/12 drop # private network
ip saddr 192.168.0.0/16 drop # private network
ip saddr 169.254.0.0/16 drop # APIPA
ip saddr 0.0.0.0/8 drop # invalid address
ip saddr 224.0.0.0/4 drop # multicast
ip saddr 240.0.0.0/5 drop # reserved
}
# ============================================
# END OF INPUT CHAIN
# ============================================
# ============================================
# START OF FORWARD CHAIN
# ============================================
# = Main chain policy =
chain forward {
type filter hook forward priority 0;
policy accept;
# = Various attack restrictions =
# Only needed in chain forward if you have Docker, Oracle VirtualBox.
# Uncomment if needed.
# == 🔒 Proper protection against aggressive incoming traffic (anti-DDoS) ==
# We do NOT allow traffic, we only instantly destroy what exceeds the limit.
# If the rate exceeds 100 per second, the packet is logged and dropped right here.
# If the rate is within limits, the packet goes further down, where a reliable default DROP awaits it.
ip saddr 0.0.0.0/0 ct state new limit rate over 100/second burst 200 packets log prefix "🔥 BAN: too many conn " flags all drop
# == 🛡️ Rate-limit ICMP echo requests (ping) ==
# ip protocol icmp icmp type echo-request limit rate 1/second accept
# ip protocol icmp icmp type echo-request log prefix "🔥 BAN: ICMP flood " flags all
# ip protocol icmp icmp type echo-request drop
# ⬇️ INSERT: Forward chain port rules
# Blocked and allowed TCP/UDP ports and ranges
include "/etc/nftables.d/forward-tcp-udp.nft"
# ⬆️ END OF INSERT
}
# ============================================
# END OF FORWARD CHAIN
# ============================================
# ============================================
# START OF OUTPUT CHAIN
# ============================================
chain output {
# = Main chain policy =
type filter hook output priority 0;
policy drop;
# = THE VERY FIRST - critically important rules =
ct state established,related accept
oif "lo" accept
# Drop any outgoing packets marked as invalid by conntrack
# This ensures immediate destruction of invalid packets
# before the remaining filtering rules are applied.
ct state invalid log prefix "🔥 INVALID_OUT_PACKET: " drop
# =========================================================================
# 🔒 SMART INSPECTION OF ESTABLISHED SESSIONS (Protection against Connection Hijacking)
# =========================================================================
# Allow established sessions ONLY if the packets within them originate from You, Your Browser, APT, or Root.
# System ghosts (nobody, daemon) are completely exiled from here.
ct state established,related meta skuid { user, _flatpak, _apt, root, systemd-timesync } accept
# ⬇️ INSTANT CUTOFF: If an unauthorized system process attempts to hijack your session
ct state established,related log flags skuid prefix "🔥 HIJACK_ATTEMPT_DROP: " drop
# =======================================================================
# 1. GENERAL PROTECTIVE SHIELD (Only rate limiting!)
# =======================================================================
# ATTENTION: There is NO accept keyword here. This rule does NOT allow packets out to the internet.
# The "!" sign means: if the rate exceeds the limit, LOG and DROP the packet.
# If the rate is within limits, the packet silently passes below — to your IP whitelist.
# ATTENTION: meta l4proto { tcp, udp } and th dport cover both TCP and UDP (HTTP/3) with a single shield.
meta l4proto { tcp, udp } th dport { 80, 443 } ct state new limit rate over 100/second burst 200 packets log prefix "🔥 OUT_WEB_LIMIT_BURST: " drop
# =========================================================================
# 2. DNS SERVICE
# Strict binding only to Quad9 at IP 9.9.9.9
# Length control, user filtering, and backup servers
# =========================================================================
# 2.1. For UDP, allow only short requests (<=150 bytes) and strictly from trusted users
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } udp dport 53 meta length <= 150 meta skuid { user, _apt, root, systemd-timesync } ct state new accept
# 2.2. For TCP, no length limit (for heavy DNSSEC responses), but strictly check the user
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } tcp dport 53 meta skuid { user, _apt, root, systemd-timesync } ct state new accept
# 2.3. All other attempts by any unauthorized services (or long UDP) — log and destroy
ip daddr { 9.9.9.9, 31.43.43.243, 31.43.43.143 } meta l4proto { tcp, udp } th dport 53 log flags skuid prefix "🔥 OUT_BLOCK_LEAK_DNS: " drop
# == Critically important ICMP for the network ==
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
# == Important ICMPv6 for IPv6 ==
ip6 nexthdr icmpv6 icmpv6 type { 1, 2, 3, 4 } accept
ip6 nexthdr icmpv6 icmpv6 type { 135, 136 } accept # NS/NA
ip6 nexthdr icmpv6 icmpv6 type { 133, 134 } accept # RS/RA
# =========================================================================
# BLOCKING RARE PROTOCOLS
# =========================================================================
# All rare protocols (SCTP, DCCP, and others) are automatically blocked
# by the policy drop. Explicit rules are not required for them.
# =========================================================================
# ⬇️ INSERT: Connect to the @whitelist_fqdn list content
ip daddr @whitelist_fqdn tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# ⬆️ END OF INSERT
# ⬇️ INSERT: whitelist.nft file contents are inserted here
include "/etc/nftables.d/whitelist.nft"
# ⬆️ END OF INSERT
} # The penultimate brace closes the ruleset of the output chain. Do not remove!
# ============================================
# END OF OUTPUT CHAIN
# ============================================
} # The last brace closes the entire configuration ruleset. Do not remove!
New whitelist.nft file with fixed IP ranges:
Some domains have been moved to a list for dynamic IP range selection logic via the cron script. Provider IP ranges and the router IP address should be fixed statically in the whitelist.
# /etc/nftables.d/whitelist.nft
# Whitelist of IP addresses for outbound connections
# Also applies filtering by UID
# List (for the provider and utility IPs)
# === Router web interface ===
ip daddr 192.168.0.1 tcp dport 80 meta skuid { user, _flatpak, root } ct state new accept
# =========================================================================
# === Internet service provider ===
# =========================================================================
# Provider's personal account and main website your.provider.net
# Defined using strict CIDR ranges of the autonomous system
# Opened for account top-up even during DNS failures and blocks
ip daddr {
192.0.2.0/24, # Location of the personal account web server
198.51.100.0/24, # Location of the information website
192.0.2.0/19, # Provider's main address pool
198.51.100.0/20 # Subscriber routing pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak, root } ct state new accept
# === Cloudflare (global CDN and DDoS protection network) ===
# Used by ChatGPT, DeepSeek, and many other services for
# faster loading and attack protection. Main pool 104.16.0.0/12.
ip daddr {
104.16.0.0/12, # Main Cloudflare pool (104.16.0.0 – 104.31.255.255)
172.64.0.0/13, # Additional Cloudflare pool
162.158.0.0/15, # European Cloudflare pool
198.41.128.0/17 # American Cloudflare pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Fastly (content delivery network) ===
# Used for loading static content, fonts, and scripts.
ip daddr {
151.101.0.0/16, # Main Fastly pool
199.232.0.0/16 # Additional Fastly pool
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Amazon CloudFront / AWS (cloud infrastructure) ===
# Widely used for hosting APIs, backends, and CDN.
ip daddr {
13.32.0.0/15, # CloudFront US East
143.204.0.0/16, # CloudFront EU
54.239.128.0/18, # CloudFront Asia Pacific
13.224.0.0/14, # CloudFront Edge (global)
18.160.0.0/13, # CloudFront Edge (additional)
52.84.0.0/15, # CloudFront authentication
3.173.0.0/16, # AWS Edge (general pool)
23.211.0.0/16, # AWS CloudFront (additional)
23.47.0.0/16 # AWS CloudFront (backup)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Amazon Web Services (AWS CloudFront / EC2) ===
ip daddr {
3.0.0.0/8,
54.0.0.0/8,
52.0.0.0/8,
18.66.233.0/24
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Google Cloud / YouTube (Google infrastructure, ASN 15169) ===
ip daddr {
64.233.160.0/19, # Main Google pool (Search, Accounts)
74.125.0.0/16, # Google service pools, including Gmail and gstatic
142.250.0.0/15, # Largest subnet for YouTube and Gemini API
172.217.0.0/16, # Content delivery servers and googleusercontent
173.194.0.0/16, # Additional routes for Google Drive and authorization
209.85.128.0/17, # Regional Google Cloud/API data centers
216.58.192.0/19, # Old but active Google DNS and frontend pools
35.190.0.0/16, # Google Cloud (general pool)
35.191.0.0/16 # Google Cloud (additional)
} tcp dport { 80, 443 } meta skuid { user, _flatpak} ct state new accept
# === Google (AS15169) - search, YouTube, Gmail, API ===
ip daddr {
142.250.0.0/15,
172.217.0.0/16,
74.125.0.0/16
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Proton AG (Mail, Drive, VPN) ===
ip daddr {
# Your addresses (mail.proton.me, drive.proton.me)
185.70.42.0/24,
185.70.40.0/24,
185.70.41.0/24,
185.70.43.0/24,
# Main Proton addresses, nearest servers
149.88.110.33, # Via DataCamp
130.195.241.20, # Via M247
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === GitHub (development platform) ===
ip daddr {
140.82.112.0/20, # Main GitHub subnets
192.30.252.0/22, # Additional GitHub pools
185.199.108.0/22 # CDN networks (raw.githubusercontent.com, githubassets.com)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Debian Infrastructure (official servers and mirrors) ===
ip daddr {
130.89.148.0/24, # Physical ftp.debian.org servers (Netherlands)
128.31.0.0/16, # Official Debian infrastructure networks (MIT/USA)
149.20.4.0/24, # Technological gateways for mirroring and forums
206.12.19.0/24, # SPI routing backup pools
151.101.0.0/16, # Fastly CDN for deb.debian.org
199.232.0.0/16, # Additional Fastly pool for security
146.75.0.0/17, # Backup Debian package delivery routes
51.83.0.0/16, # Mirror repositories for deb.debian.org updates
141.76.2.4/32 # Technical University of Dresden
} tcp dport { 80, 443 } meta skuid { user, _flatpak, _apt, root } ct state new accept
# === ⏰ Allow system time synchronization (NTP) ===
# This rule is paranoid: UDP port 123 is open EXCLUSIVELY for this process.
# No backdoor running as root or nobody will be able to exploit this loophole.
udp dport 123 meta skuid systemd-timesync ct state new accept
# === openSUSE / Zeek (openSUSE infrastructure) ===
ip daddr {
195.135.220.0/22, # Main openSUSE data center
130.57.0.0/16 # Additional Novell/SUSE server pools
} tcp dport { 80, 443 } meta skuid { user, _apt, root } ct state new accept
# === LibreWolf (update repository) ===
ip daddr {
179.61.251.0/24, # repo.librewolf.net server (Frantech/BuyVM)
198.251.80.0/20, # BuyVM range in Luxembourg/USA
209.141.32.0/19 # Additional LibreWolf hosting routes
} tcp dport 443 meta skuid { user, _apt, root } ct state new accept
# === DeepSeek (specific IP addresses and subnets) ===
# Identified based on analysis of your list.
ip daddr {
103.193.104.0/22, # DeepSeek company's own technological routes
154.8.0.0/16, # Asian and global DeepSeek hosting pools
159.69.48.177/32, # Hetzner (Germany) - possible backend
150.171.109.51/32, # Possible backend or partner server
43.109.10.32/27, # Asian pool (range 43.109.10.32 - 43.109.10.63)
38.54.123.48/32, # Cogent Communications (possible route)
95.101.61.198/32, # Small range (Germany, possibly partner)
95.101.61.209/32,
95.101.61.218/32,
111.170.168.113/32, # Chinese provider (regional access)
20.150.95.164/32, # Microsoft Azure (possible backend)
34.107.243.93/32 # Google Cloud (possible backend)
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Hetzner Cloud (if you use it) ===
ip daddr {
150.171.0.0/16
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Akamai (extended range 23.32.0.0/11) ===
ip daddr {
23.32.0.0/11,
23.211.0.0/16,
23.64.0.0/16
} tcp dport { 80, 443 } meta skuid { user, _flatpak } ct state new accept
# === Backup DNS Quad9 ===
ip daddr 9.9.9.0/24 udp dport 53 meta skuid { user, _apt, root } accept
# === Backup DNS Quad9 (149.112.0.0/16) ===
ip daddr 149.112.0.0/16 udp dport 53 meta skuid { user, _apt, root } accept
Whitelist of domain names for dynamic updates:
File path: /etc/nftables.d/nftables.domains
# Debian browser services
wiki.debian.org
forums.debian.net
cache.forums.debian.net
# Wikipedia
wikipedia.org
ru.wikipedia.org
en.wikipedia.org
# Social networks, diaries and messengers
facebook.com
t.me
tx.me
telegram.org
api.telegram.org
# Search engines
bing.com
# Media and photo hosting
://imgbb.com
imgbb.com
ibb.co
catbox.moe
Bash script for cron execution:
Script path: /usr/local/bin/update_fqdn.sh
#!/bin/bash
# Path variables
DOMAIN_FILE="/etc/nftables.d/nftables.domains"
SUBNET_FILE=$(mktemp)
# Check if domain file exists
if [ ! -f "$DOMAIN_FILE" ]; then
exit 1
fi
# Hard pause of 15 seconds during system boot
if [ "$1" != "manual" ]; then
sleep 15
fi
# Read domains and query IPs via full path to dig
while read -r domain; do
[[ -z "$domain" || "$domain" =~ ^# ]] && continue
ips=$(/usr/bin/dig +short "$domain" 2>/dev/null | grep -E '^[0-9.]+$')
for ip in $ips; do
if [[ "$domain" =~ "telegram" || "$domain" == "t.me" || "$domain" =~ "facebook" ]]; then
subnet=$(echo "$ip" | cut -d'.' -f1-2)".0.0/16"
else
subnet=$(echo "$ip" | cut -d'.' -f1-3)".0/24"
fi
echo "$subnet" >> "$SUBNET_FILE"
done
done < "$DOMAIN_FILE"
# If subnets found, load them into the firewall via full path to nft
if [ -s "$SUBNET_FILE" ]; then
sort -u "$SUBNET_FILE" -o "$SUBNET_FILE"
/usr/sbin/nft flush set inet filter whitelist_fqdn
while read -r subnet; do
/usr/sbin/nft add element inet filter whitelist_fqdn { "$subnet" }
done < "$SUBNET_FILE"
fi
rm "$SUBNET_FILE"
Cron configuration for automatic updates:
# Enter root's cron:
sudo crontab -e
# Add the following line to the end of the file:
# script for updating the list of allowed IP ranges
# for nftables output chain
# update every 10 minutes.
# on powerful machines you can do it more frequently
*/10 * * * * /usr/local/bin/update_fqdn.sh
Note: The script automatically determines which domains should use /16 (Telegram, Facebook) and which should use /24 (the rest). This allows for optimal balancing between filtering precision and covering all IP addresses of the service.
If you wish to add a new domain that also requires the use of /16 (for example, Google, YouTube, or other large services with a broad pool of IP addresses), you will need to add the corresponding condition to the script. For example:
Abandoning dnsmasq in favor of a cron script:
During the experiment, an attempt was made to configure interactive IP address retrieval via dnsmasq using the nftset mechanism. However, this configuration was not successfully completed: the causes of the errors in the settings remained unresolved. It is assumed that this is due to specific peculiarities in the interaction between dnsmasq and nftables in the Debian 13 (Trixie) environment, or to limitations in the build of the dnsmasq package with nftset support.
Consequently, it was decided to abandon dnsmasq in favor of a simpler, more predictable, and fault-tolerant method — periodically updating the whitelist via a script launched by cron. This approach provides:
- Deterministic behavior — the script runs on a fixed schedule, not at the moment of a DNS query;
- Independence from the DNS resolver state — updates occur separately from the name resolution process;
- Ease of debugging and modification — the script logic is transparent and easily adaptable for new domains;
- Minimal performance impact — updates are performed once every 10 minutes without placing load on the network stack.
This solution is considered more reliable for long-term operation under conditions of a targeted attack, where system stability is of critical importance.
if [[ "$domain" =~ "telegram" || "$domain" == "t.me" || "$domain" =~ "facebook" || "$domain" =~ "google" ]]; then
subnet=$(echo "$ip" | cut -d'.' -f1-2)".0.0/16"
else
subnet=$(echo "$ip" | cut -d'.' -f1-3)".0/24"
fi
This allows you to flexibly customize the script to suit your needs, adding new domains as necessary.
A single website may sometimes require more than one domain name to function correctly. Consult Gemini (Google's AI) about adding additional domain names and whether it is necessary to change the subnet mask for a domain name in the script from 24 to 16 if, after adding one primary domain name with the default /24 mask, the site does not load or loads with errors. Gemini has a good understanding of domain names, as it was trained on a vast amount of internet data, and Google operates one of the largest public DNS services (Google Public DNS).
2.4.2-H Switching to the Quad9 DNS server (9.9.9.9)
The /etc/resolv.conf settings are hardcoded to 9.9.9.9. All contents of the file have been replaced with the line:
nameserver 9.9.9.9
The file is protected from being overwritten by the command:
chattr +i /etc/resolv.conf # locks the file from being changed by the system
Command to allow overwriting the file:
chattr -i /etc/resolv.conf # unlocks the file for changes by the system
Thus, we switch DNS queries to the well-protected and stably operating Quad9 server.
Quad9 (9.9.9.9) is a global, non-correlating DNS service created as a non-profit project (with organizers including the Global Cyber Alliance (GCA), IBM, and the Packet Clearing House foundation).
The main difference between Quad9 and commercial giants like Google (8.8.8.8) and Cloudflare (1.1.1.1) is that its primary goal is not speed of service delivery for data collection, but cybersecurity and strict user privacy.
Here is a detailed comparison of why 9.9.9.9 is much better suited for experiments with Configuration 3 than its competitors:
1. Built-in intelligent shield against malware (Threat Intelligence)
When your computer sends a query through Quad9, the server doesn't just return the website's IP address. It instantly checks the requested domain against constantly updated threat databases (aggregating information from over 30 leading InfoSec companies worldwide, including IBM X-Force, Kaspersky, Proofpoint, and others).
- How this protects against malware: If a hidden Trojan (C2 agent) in your system attempts to send stolen data to its command server at hacker-malware-domain.com, Quad9 will detect that this domain is on the malicious nodes blacklist and block that DNS query (returning an NXDOMAIN error). The malware will be unable to learn its master's IP address and will be "blinded".
- Google (8.8.8.8) and Cloudflare (1.1.1.1) do not have such filtering by default. They will dutifully return the malicious server's IP address because they operate on the principle of neutral transit: "whatever is requested, that is returned."
2. Radical level of privacy (No IP logging)
- Quad9 (9.9.9.9): Is a non-profit organization (registered in Switzerland, which removes it from direct legal pressure from the US). They fundamentally do not log your real IP address. The system does not collect a digital profile of which sites you visited and when. They have nothing to sell to advertisers or hand over to law enforcement, as data is erased directly in the servers' RAM.
- Google (8.8.8.8): Is the world's largest advertising corporation. Queries to 8.8.8.8 are tied to your geolocation and network patterns. Although Google claims to anonymize logs within 24-48 hours, your search habits are still integrated into their global analytical algorithms.
- Cloudflare (1.1.1.1): Is a commercial US-based company. They keep logs for network optimization purposes. Despite regular independent privacy audits, they are subject to US law (including requests via NSLs — National Security Letters from the FBI), which makes them vulnerable to government pressure.
3. Protection against ISP interception (DNS over TLS / HTTPS)
Quad9 perfectly supports modern encrypted DNS traffic protocols. If you configure the system to operate via an encrypted channel to 9.9.9.9, then neither your local ISP nor SORM systems will be able to see which sites you are visiting — for them, it will be an unreadable stream of bytes.
Comparative table of DNS servers
| Criteria | Quad9 (9.9.9.9) | Cloudflare (1.1.1.1) | Google (8.8.8.8) |
|---|---|---|---|
| Jurisdiction | 🇨🇭 Switzerland (Strict laws) | 🇺🇸 USA (Patriot Act) | 🇺🇸 USA (Under intelligence oversight) |
| Organization type | 🏛 Non-profit foundation (NGO) | 🏢 Commercial IT company | 🌐 Advertising IT giant |
| Malware blocking | 🛡 Yes (Automatic on-the-fly) | No (Only in paid tier) | No |
| IP logging | ❌ Completely absent | ⚠️ Partial (For analytics) | ⚠️ Yes (Tied to user profile) |
| Speed (ping) | ⚡ High (Anycast) | 🚀 World's fastest | ⚡ High |
Conclusion for Configuration 3: Using 9.9.9.9 should deprive malware of the ability to use DNS tunneling, prevent the ISP from collecting your browsing history, and exclude commercial corporations from your chain of trust.
2.4.2-I Custom monitoring script for nftables and AppArmor status
During frequent configuration and reloading of nftables and AppArmor, as well as when they need to be disabled for testing, there is a risk of forgetting to re-enable the services or not noticing that they have failed.
To address this issue, a custom monitoring script was created that tracks the status of both services and, in case of failure or disabling, sends system notifications every 5 minutes.
Script features:
- Does not require root privileges — runs as a regular user
- Does not make any changes to the system — monitoring and alerts only
- Runs via GNOME autostart
- Does not require installation of additional icons or services
- Uses native Debian 13 mechanisms (notify-send, systemctl)
- Tested and adapted for Debian 13 GNOME
Notification messages:
nftables DISABLE— if only nftables is disabledAppArmor DISABLE— if only AppArmor is disablednftables and AppArmor DISABLE— if both services are disabled
The script remains silent when both services are running and starts alerting when a failure is detected. The notification is displayed for 4.5 seconds and then disappears automatically.
Installation and startup:
# Create the scripts directory (if it doesn't exist)
mkdir -p ~/userscripts/systemservice
# Save the script to a file
nano ~/userscripts/systemservice/apparmor-nftables-indicator-deb-gnome.py
# Make the script executable
chmod +x ~/userscripts/systemservice/apparmor-nftables-indicator-deb-gnome.py
# Add to GNOME autostart (via ~/.config/autostart/)
# or via GUI: Settings → Applications → Startup Applications
Script code (Python):
#!/usr/bin/env python3
import subprocess
import time
import os
# Status check interval (seconds)
CHECK_INTERVAL = 2
# Repeat notification interval on failure (seconds)
NOTIFY_INTERVAL = 300 # 5 minutes
# Notification display duration (milliseconds)
NOTIFY_TIMEOUT = 4500 # 4.5 seconds
def check_apparmor():
"""Check AppArmor status (without sudo)"""
try:
# Check if the module is loaded
if not os.path.exists('/sys/module/apparmor/parameters/enabled'):
return False
with open('/sys/module/apparmor/parameters/enabled', 'r') as f:
if f.read().strip() != 'Y':
return False
# Check service activity via systemctl
result = subprocess.run(
['systemctl', 'is-active', 'apparmor'],
capture_output=True,
text=True
)
if result.returncode == 0 and result.stdout.strip() == 'active':
return True
# If systemctl fails, try aa-status
if os.path.exists('/usr/sbin/aa-status'):
result = subprocess.run(
['/usr/sbin/aa-status'],
capture_output=True,
text=True
)
if result.returncode == 0 and 'apparmor module is loaded' in result.stdout:
return True
return False
except Exception:
return False
def check_nftables():
"""Check nftables status"""
try:
result = subprocess.run(
['systemctl', 'is-active', 'nftables'],
capture_output=True,
text=True
)
return result.returncode == 0 and result.stdout.strip() == 'active'
except Exception:
return False
def send_notification(message):
"""Send system notification via notify-send"""
try:
subprocess.run(
['notify-send', '-t', str(NOTIFY_TIMEOUT), '⚠️ Security Alert', message],
check=True
)
except Exception as e:
print(f"Failed to send notification: {e}")
def main():
last_notify_time = 0
last_state = (True, True) # (apparmor, nftables)
first_failure_detected = False
print("Monitoring script started. Checking status every 2 seconds...")
while True:
apparmor_ok = check_apparmor()
nftables_ok = check_nftables()
# Determine current state
current_state = (apparmor_ok, nftables_ok)
# If state has changed, reset the last notification timer
if current_state != last_state:
last_state = current_state
last_notify_time = 0
first_failure_detected = False
# Check if there is a failure
if not (apparmor_ok and nftables_ok):
now = time.time()
# Send notification if enough time has passed since the previous one
if now - last_notify_time >= NOTIFY_INTERVAL or not first_failure_detected:
# Format the message
if not apparmor_ok and not nftables_ok:
message = "nftables and AppArmor DISABLE"
elif not nftables_ok:
message = "nftables DISABLE"
else:
message = "AppArmor DISABLE"
send_notification(message)
last_notify_time = now
first_failure_detected = True
# Wait for the next check cycle
time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
main()
📋 TL;DR — 2.4.2 Configuration 3 Software
- 2.4.2-A Introduction: Dropped OpenSnitch due to conflicts with nftables (rule overwriting, priority conflicts, policy replacement). Focus on strengthening nftables as Debian 13's native mechanism.
- 2.4.2-B Strategic logic: Blocking the maximum number of attack vectors as a deterrence method. Shift from port-based filtering to IP-based filtering to counter firmware malware that masks its traffic as legitimate.
- 2.4.2-C Changes in nftables config: OUTPUT policy changed to DROP; IP whitelist added. Warning: do not use domain names in rules. Recommendation to use
digto obtain IP addresses. - 2.4.2-D Configuration fix: Fixed rate-limiting rule error (accept replaced with drop) in input, forward, and output chains. Fixed the config identified on an IT forum.
- 2.4.2-E Configuration hardening: Added UID-based filtering, invalid packet protection, session hijacking protection, and a mandatory DNS shield with tunneling protection.
- 2.4.2-F sysctl hardening: Applied
kernel.yama.ptrace_scope = 2to block Process Injection. Full sysctl configuration v7.0. - 2.4.2-G Automating IP range selection: Added a cron script for dynamic whitelist updates via
dig. Two logics used: static whitelist (include) and dynamic (cron). Abandoned dnsmasq in favor of the cron script. - 2.4.2-H Switching to Quad9 DNS: Hardcoded
/etc/resolv.confto 9.9.9.9 withchattr +iprotection. Detailed comparison of Quad9 with Google and Cloudflare. - 2.4.2-I Custom monitoring script: Python script for monitoring nftables and AppArmor status with GNOME notifications (
notify-send).
2.4.3 Observing the progress of the experiment with configuration 3
Current status of configuration 3 (as of 22.06.2026):
- 🔬 Continues to be tested under hacker attack conditions
- 📊 Preliminary data: awaiting log collection to confirm effectiveness or ineffectiveness.
- 🎯 Verification goal: to confirm or refute that blocking outbound traffic by an IP whitelist disrupts the communication channels of hypothetical malware.
📋 TL;DR — Hardening Chronicle and Attacks
- CONFIGURATION 1 (Debian 12/MATE): Attack confirmed on 2026-12-26 — compromise included reading correspondence, KeePassXC, and image access. System wiped.
- CONFIGURATION 2 (Debian 13/GNOME/Wayland): Hardening implemented: Flatpak isolation, strict nftables, OpenSnitch with rules, AppArmor, USBGuard. Status: under testing; not all vulnerabilities have been closed.
- CONFIGURATION 3 (Debian 13/GNOME/Wayland): Radical outbound control enhancement: OUTPUT policy changed to DROP, only trusted IP addresses allowed (whitelist), DNS forcibly switched to Quad9 (9.9.9.9) with changes locked via chattr. Status: testing, awaiting data on the effectiveness of C2 channel disruption.