Checking firewall status in Linux shows whether incoming traffic is being filtered before it reaches listening services, which matters when validating hardening, troubleshooting an unreachable application, or confirming that a recent rule change took effect.

Linux packet filtering is handled by the kernel netfilter subsystem, but most hosts expose it through one frontend such as ufw, firewalld, direct nftables rules, or older iptables tooling. The clearest status check is to identify which service owns the rules, read that tool's runtime summary, and then compare the firewall view with the ports that are actually listening on the host.

Most status commands are read-only, but they often need sudo privileges to show the live ruleset or packet counters. Minimal containers may have the firewall packages installed without systemd running as PID 1, so systemctl checks fail there even though ufw, firewall-cmd, nft, or iptables can still inspect the backend. If more than one frontend is enabled on the same machine, treat that as a configuration problem until the intended rule owner is clear.

Steps to check firewall status in Linux:

  1. On systemd hosts, list the common firewall units and check which one is currently active.
    $ systemctl list-unit-files --type=service 'ufw*' 'firewalld*' 'nftables*' --no-pager
    UNIT FILE         STATE    PRESET
    firewalld.service enabled  enabled
    nftables.service  disabled enabled
    ufw.service       enabled  enabled
    
    $ systemctl is-active firewalld
    active

    Use the active unit's matching CLI in the next steps. If systemctl reports that the system was not booted with systemd, skip directly to the tool-specific commands instead.

  2. If ufw is the active frontend, print its live summary and default policy.
    $ sudo ufw status verbose
    Status: active
    Logging: on (low)
    Default: deny (incoming), allow (outgoing), deny (routed)
    New profiles: skip
    
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW IN    Anywhere                  
    80/tcp                     ALLOW IN    Anywhere                  
    22/tcp (v6)                ALLOW IN    Anywhere (v6)             
    80/tcp (v6)                ALLOW IN    Anywhere (v6)             

    Status: inactive means ufw is installed but not currently enforcing rules.

  3. If firewalld is the active frontend, confirm that the daemon is running and inspect the active zone.
    $ sudo firewall-cmd --state
    running
    $ sudo firewall-cmd --get-active-zones
    public (default)
    $ sudo firewall-cmd --list-all
    public (default, active)
      target: default
      ingress-priority: 0
      egress-priority: 0
      icmp-block-inversion: no
      interfaces: 
      sources: 
      services: dhcpv6-client ssh
      ports: 
      protocols: 
      forward: yes
      masquerade: no
      forward-ports: 
      source-ports: 
      icmp-blocks: 
      rich rules: 

    The services: and ports: lines show what the active zone is allowing at runtime. Empty interfaces: output is normal in some container-like environments or when the default zone is applied implicitly.

  4. Inspect the kernel ruleset directly with nftables when the host uses nftables natively or when a frontend summary needs backend confirmation.
    $ sudo nft list ruleset | sed -n '1,28p'
    # Warning: table ip filter is managed by iptables-nft, do not touch!
    # Warning: table ip6 filter is managed by iptables-nft, do not touch!
    table ip filter {
    	chain ufw-before-logging-input {
    	}
    
    	chain ufw-before-logging-output {
    	}
    
    	chain ufw-before-logging-forward {
    	}
    
    	chain ufw-before-input {
    		iifname "lo" counter packets 0 bytes 0 accept
    		ct state related,established counter packets 0 bytes 0 accept
    		ct state invalid counter packets 0 bytes 0 jump ufw-logging-deny
    		ct state invalid counter packets 0 bytes 0 drop
    		ip protocol icmp icmp type destination-unreachable counter packets 0 bytes 0 accept
    		ip protocol icmp icmp type time-exceeded counter packets 0 bytes 0 accept
    		ip protocol icmp icmp type parameter-problem counter packets 0 bytes 0 accept
    		ip protocol icmp icmp type echo-request counter packets 0 bytes 0 accept
    		udp sport 67 udp dport 68 counter packets 0 bytes 0 accept
    		counter packets 0 bytes 0 jump ufw-not-local
    		ip daddr 224.0.0.251 udp dport 5353 counter packets 0 bytes 0 accept

    If chain names begin with ufw- or the table name includes firewalld, a higher-level frontend is programming nftables beneath the surface.

  5. Inspect the filter table with iptables when the host still uses legacy iptables tooling or the compatibility layer.
    $ sudo iptables -L -n -v | sed -n '1,20p'
    Chain INPUT (policy DROP 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ufw-before-logging-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-before-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-after-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-after-logging-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-reject-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-track-input  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ufw-before-logging-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-before-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-after-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-after-logging-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-reject-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
        0     0 ufw-track-forward  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

    Start by reading the chain policy and then the explicit ACCEPT, DROP, or REJECT targets. On modern distributions, iptables may still be showing rules from the nftables compatibility layer.

  6. Compare the firewall summary with the ports that are actually listening on the host.
    $ ss -tuln 'sport = :80'
    Netid State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
    tcp   LISTEN 0      1            0.0.0.0:80        0.0.0.0:*          

    A listening socket proves the service is bound locally, but it does not by itself prove that the firewall allows remote access.

  7. Probe the expected listener as a quick sanity check, then repeat from another host when external reachability matters.
    $ nc -vz 127.0.0.1 80
    Connection to 127.0.0.1 80 port [tcp/http] succeeded!

    A loopback test only confirms local reachability. For a decisive inbound check, run the same probe from another host or network namespace that traverses the firewall path.