Learn about Centmin Mod LEMP Stack today
Become a Member

CSF Firewall alternative csfa nftables wrapper script demo

Discussion in 'Beta release code' started by eva2000, Sep 6, 2025.

Thread Status:
Not open for further replies.
  1. eva2000

    eva2000 Administrator Staff Member

    58,894
    12,490
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +19,122
    Local Time:
    5:31 PM
    Nginx 1.31.x
    MariaDB 10.x/11.4+/12.3+
    With CSF Firewall shutdown and the open source of CSF v15.00 GPLv3 release, folks are also thinking longer-term for RedHat/AlmaLinux/Rocky Linux 10 (EL10) distributions, which are nftables only.

    Right now, CSF Firewall only works with iptables with RedHat/AlmaLinux/Rocky Linux 8 and 9, and does not fully support nftables in EL10. Updating the CSF Firewall to fully support EL10 and nftables instead of iptables would be a significant task, based on my AI research with Claude Opus 4.1, OpenAI GPT-5, and Gemini 2.5 Pro.

    In the past, I have thought about this, and one option I thought about was using firewalld with nftables for EL10 Linux distros. CSF Firewall, like firewalld, has traditionally been a wrapper to interface with iptables in EL7, EL8, and EL9 Linux distros, or for firewalld in EL10 to interface with nftables. But firewalld can be confusing for noob users to wrap their head around compared to CSF Firewall's csf command line.

    For example with CSF Firewall, to whitelist and allow an IP it's as easy as running c:
    Code (Text):
    csf -a 1.2.3.4

    To block and deny an IP
    Code (Text):
    csf -d 1.2.3.4



    So I could create my own wrapper to nftables called csfa, which maps all the csfa command line arguments directly to nftables. While no feature parity to all that CSF Firewall doesn, this at least makes it easier for Centmin Mod users to do everyday command line tasks with familiar command like as csf.

    Direct nftables commands like nft add rule inet csfa, tell the Linux kernel to apply a firewall rule inside a custom table named csfa in the inet family, which means the rule applies to both IPv4 and IPv6 traffic. This allows us to manage our own dedicated firewall table (csfa) separate from what firewalld has. For firewalld by default uses priority 0 for its chains while csfa wrapper uses priority 10.

    Code (Text):
    nftables (kernel firewall)
    └── Family: inet   (handles both IPv4 + IPv6)
        ├── Table: csfa        (custom, managed by csfa wrapper)
        │    └── Chain: input
        │         ├── rule: ip saddr 1.2.3.4 accept comment "csfa allow 1.2.3.4"
        │         └── rule: ip saddr 5.6.7.8 drop comment "csfa deny 5.6.7.8"
        │
        └── Table: firewalld   (system-managed, owned by firewalld)
             ├── Chain: filter_INPUT
             │    ├── rich-rule: allow source 192.0.2.10
             │    └── rich-rule: drop source 198.51.100.20
             ├── Chain: filter_OUTPUT
             └── Chain: filter_FORWARD
    


    Packets first go through firewalld’s rules (priority 0), then through csfa wrapper rules (priority 10); whichever chain makes the first definitive decision (accept/drop) decides the packet’s fate.
    Code (Text):
    Incoming packet
       │
       ▼
    [inet firewalld] table
     └─ chain filter_INPUT (priority 0)
           ├─ drop source 198.51.100.20   → packet dropped here
           └─ ... (other firewalld rules)
       │
       ▼ (if not yet accepted/dropped)
    [inet csfa] table
     └─ chain input (priority 10)
           ├─ ip saddr 1.2.3.4 accept
           ├─ ip saddr 5.6.7.8 drop
           └─ ...
       │
       ▼
    Default policy (if no rule matched)
    


    For example with csfa wrapper, to whitelist and allow an IP with csfa:
    Code (Text):
    csfa -a 1.2.3.4

    where the equivalent nftables command would be
    Code (Text):
    nft add rule inet csfa input ip saddr 1.2.3.4 accept
    

    and equivalent firewalld command:
    Code (Text):
    # For IPv4
    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="1.2.3.4" accept'
    firewall-cmd --reload
    
    # For IPv6
    firewall-cmd --permanent --add-rich-rule='rule family="ipv6" source address="2001:db8::1" accept'
    firewall-cmd --reload
    

    To block and deny an IP
    Code (Text):
    csfa -d 1.2.3.4

    where equivalent nftables command would be
    Code (Text):
    nft add rule inet csfa input ip saddr 1.2.3.4 drop
    

    and equivalent firewalld command:
    Code (Text):
    # For IPv4
    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="1.2.3.4" drop'
    firewall-cmd --reload
    
    # For IPv6
    firewall-cmd --permanent --add-rich-rule='rule family="ipv6" source address="2001:db8::1" drop'
    firewall-cmd --reload
    


    And examples with comments, to whitelist and allow an IP with csfa:
    Code (Text):
    csfa -a 1.2.3.4 "csfa allow 1.2.3.4"

    where the equivalent nftables command would be
    Code (Text):
    nft add rule inet csfa input ip saddr 1.2.3.4 accept comment "csfa allow 1.2.3.4"
    

    To block and deny an IP
    Code (Text):
    csfa -d 1.2.3.4 "csfa deny 1.2.3.4"

    where the equivalent nftables command would be
    Code (Text):
    nft add rule inet csfa input ip saddr 1.2.3.4 drop comment "csfa deny 1.2.3.4"
    


    I've been automating testing for the csfa nftables wrapper script on AlmaLinux 10 via GitHub workflow actions and below is an example run. Still needs alot of work and testing but there's still a lot of time before AlmaLinux/Rocky Linux 10 (EL10) is production ready given 3rd party YUM repos like EPEL still need to develop packages to support EL10 distros.

    Code (Text):
    csfa -V
    csfa 1.3.0
    

    Code (Text):
    csfa -h
    
    csfa - CSF-like nftables wrapper (v1.3.0)
    
    Usage:
      csfa [-debug] [-method auto|json|text] <command> [args]
    
    Global flags:
      -method auto|json|text   Prefer JSON (with jq) or plain text parsing. Default: auto
      -debug                   Verbose logs
      -V, --version            Show version
    
    Firewall Control (CSF parity):
      -s                       Start firewall
      -f                       Stop/flush firewall (deletes table)
      -sf                      Force restart (bypass systemd)
      -q                       Quick restart (via systemd)
      -e                       Enable firewall (ensure inet table/chains)
      -x                       Disable (flush csfa table)
      -l                       List IPv4/IPv6 rules (csfa table)
      -l6                      List IPv6 rules specifically
      -r                       Restart (flush csfa table)
    
    IP Management:
      -a <IP> [comment]        Allow IP (v4 or v6) with optional comment
      -ar <IP>                 Remove 'allow IP' rule
      -d <IP> [comment]        Deny IP (drop) with optional comment
      -dr <IP>                 Remove 'deny IP' rule
    
    Temporary Rules (Enhanced in v1.3.0):
      -t                       List temporary IP entries with TTL
      -ta <IP> <secs> [-p PORT] [-d DIRECTION] [comment]
                               Temporary allow IP with optional port/direction
      -td <IP> <secs> [-p PORT] [-d DIRECTION] [comment]
                               Temporary deny IP with optional port/direction
      -tr <IP>                 Remove IP from temp lists
      -tra <IP>                Remove IP from temp allow list only
      -trd <IP>                Remove IP from temp deny list only
      -tf                      Flush all temporary IP entries
     
      Port format: 22 or 80,443 or 3000:4000 or 53;udp
      Direction: in (INPUT), out (OUTPUT), inout (both)
    
    Port Management:
      --allow-port <PORT[/proto]>    e.g. 22/tcp, 53/udp, 1000-2000/tcp
      --deny-port  <PORT[/proto]>
      --remove-port <PORT[/proto]> --kind allow|deny
    
    Information & Analysis:
      -p                       View listening ports with processes
      -i <IP>                  Lookup IP geographical information
      -g <pattern>             Grep/search ruleset (by comment)
      --test                   Validate ruleset syntax
    
    Monitoring (New in v1.3.0):
      -w                       Watch mode - real-time firewall monitoring
      --status                 Comprehensive firewall status report
      --check                  Validate configuration and dependencies
      -t [N]                   Trace traffic (first N events or continuous)
      --watch                  Monitor firewall activity (alias for -t)
    
    Configuration:
      --save                   Save full ruleset to /etc/nftables.rules
      --restore                Restore from /etc/nftables.rules
    
    Internal:
      --delete-handle <chain> <handle>    Delete rule by handle
      --delete-handle-list <handles>      Delete multiple handles (chain:handle,...)
      --untrack-temp <IP>                 Remove from temp tracking
    
    CI/Testing:
      --testall                Run a non-destructive functional test suite
    
    Examples:
      csfa -s                          # Start firewall
      csfa -a 192.168.1.100 "Trusted"  # Allow IP with comment
      csfa -td 203.0.113.77 600 -p 22  # Temp deny for 10 min on port 22
      csfa -ta 10.0.0.1 3600 -d out    # Temp allow outbound for 1 hour
      csfa -w                          # Watch mode monitoring
      csfa --status                    # Comprehensive status
      csfa --check                     # Validate configuration
      csfa -l6                         # Show IPv6 rules
      csfa -p                          # Show listening ports
      csfa -method json -l             # Force JSON output
    


    GitHub workflow runs 2 parallel job tests one for csfa wrapper's JSON support and one for it's plain text mode support.

    csfa-nftables-wrapper-github-workflow-demo2-1.png

    2nd csfa workflow run progress

    csfa-nftables-wrapper-github-workflow-demo2-2.png

    2nd csfa workflow run completed in 41 seconds :)

    csfa-nftables-wrapper-github-workflow-demo2-3.png

    inspecting the 2nd csfa workflow run summary and results

    csfa-nftables-wrapper-github-workflow-demo2-4.png

    csfa JSON method support test steps

    csfa-nftables-wrapper-github-workflow-demo2-5.png

    csfa wrapper test nftables service inspection on GitHub workflow's Azure Ubuntu VM instance runner server which is running AlmaLinux 10 docker image with initd enabled

    csfa-nftables-wrapper-github-workflow-demo2-6.png

    csfa wrapper -V and -h flag inspection

    csfa-nftables-wrapper-github-workflow-demo2-7.png

    csfa-nftables-wrapper-github-workflow-demo2-8.png

    csfa-nftables-wrapper-github-workflow-demo2-9.png

    actual csfa wrapper test suite run for various command line parameters which directly interface with nftables

    csfa-nftables-wrapper-github-workflow-demo2-10.png

    csfa-nftables-wrapper-github-workflow-demo2-11.png

    csfa-nftables-wrapper-github-workflow-demo2-12.png

    csfa-nftables-wrapper-github-workflow-demo2-13.png

    csfa-nftables-wrapper-github-workflow-demo2-14.png

    csfa wrapper text method support test suite run

    csfa-nftables-wrapper-github-workflow-demo2-15.png
     
    Last edited: Sep 6, 2025
Thread Status:
Not open for further replies.