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.

Google Gemini Google Gemini — Google's multimodal AI assistant. Analyzes text, images, code, and files. Available on the web and in apps.
DeepSeek DeepSeek — a powerful open-source AI assistant. Free, fast, available on the web and in apps.
⚠️ Notice! This article is a work in progress. Updates and additions are made as new data becomes available regarding the resilience of new security configurations and hacker activity.
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.

↑ Back to table of contents


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.

↑ Back to table of contents


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.

↑ Back to table of contents


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.

↑ Back to table of contents


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

↑ Back to table of contents

📋 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)

↑ Back to table of contents


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

↑ Back to table of contents


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.

↑ Back to table of contents


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)

↑ Back to table of contents

2.3.2-B КОНФИГУРАЦИЯ 2 Software nftables

nftables version:
1.1.3 (Commodore Bullmoose #4)

nftables ruleset file (13.04.2026):
        

#!/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
  }
}


        
    

↑ Back to table of contents

2.3.2-C CONFIGURATION 2 Software sysctl
sysctl hardening configuration (2026-03-03):
        
	
	
# ============================================
# 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 ==========



↑ Back to table of contents


2.3.2-D CONFIGURATION 2 Software Flatseal overrides
Flatpak application permission overrides (Flatseal):
        
# 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).

↑ Back to table of contents

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 (excerpt):
        
	
# ============================================
# 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"
  }
}

↑ Back to table of contents


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

↑ Back to table of contents


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

↑ Back to table of contents

📋 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.

↑ Back to table of contents


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 filter with 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 (with accept policy), 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.

↑ Back to table of contents


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.

↑ Back to table of contents


2.4.2-C Changes in the nftables config
  • The output chain policy has been changed to drop.
  • Global restrictions and permissions for ports and port ranges have been removed from the output chain.
  • Outbound connections in the output chain 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
        
    
nftables config for configuration 3 (22.06.2026 testing, preliminary version):
        

#!/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.

↑ Back to table of contents


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!
        
    

↑ Back to top


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 output chain — 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 established status 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 <= 150 bytes) are allowed, effectively blocking DNS tunneling, while meta skuid checks completely close off DNS access to ghost system processes (such as nobody or daemon).

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
        
    

↑ Back to top


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.

sysctl hardening configuration (2026-07-04):
        
    
# ============================================
# 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.

        
    

↑ Back to top


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.

More about Quad9:

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.

↑ Back to table of contents


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 disabled
  • AppArmor DISABLE — if only AppArmor is disabled
  • nftables 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()
        
    

↑ Back to table of contents

📋 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 dig to 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 = 2 to 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.conf to 9.9.9.9 with chattr +i protection. 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.

↑ Back to table of contents

📋 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.