Advanced Policy Firewall (APF)

· Published · 24 min read

Linux administrator validating an APF ruleset while preserving an administrative access path and blocking untrusted traffic

Advanced Policy Firewall, usually called APF, is an iptables and netfilter firewall manager for internet-facing Linux servers. It turns a long ruleset into one annotated configuration, a trust system, and a practical command-line workflow. The useful part is not how quickly it can start. It is whether an operator can change policy without losing access or allowing traffic that was never intended.

APF is actively maintained. Version 2.0.2 was current when this guide was reviewed. The workflow below uses its current command interface, configuration, IPv6 behavior, container support, trust sources, validation, and recovery controls.

What APF does

APF builds Linux packet-filter rules from a central file, normally /etc/apf/conf.apf. Its policy has three broad layers:

  • Static policy: ports, protocols, interfaces, and host allow or deny rules.
  • Stateful policy: connection tracking that recognizes established and related traffic.
  • Sanity policy: checks for malformed packets, forged source ranges, fragments, and suspicious connection patterns.

Current APF releases add dual-stack IPv6 filtering, temporary trust entries with expiry, ipset block lists, GeoIP country rules, structured audit events, connection limits, SYN-flood controls, systemd integration, and a compatibility mode for container-managed rules. APF can use either the traditional iptables backend or iptables running on the nftables backend.

That last sentence is easy to misread. APF supporting iptables-nft does not mean it becomes a native nftables policy manager. It still manages policy through the iptables interface.

Choose one firewall owner

Do not layer APF casually on top of firewalld, a hand-maintained nftables ruleset, or another firewall package. Several tools writing the same packet path create an order-of-evaluation problem, not defense in depth. A restart by either tool can remove, duplicate, or bypass rules owned by the other.

ChooseIt is a good fit whenMain caution
APFYou operate an existing APF estate or want its host trust, reactive blocking, remote lists, and per-address policy modelIt owns iptables policy and must be tested with distro and container networking
firewalldYou want distro-integrated zones, runtime and permanent policy, and common NetworkManager integrationDirect rules can behave differently with its nftables backend
Native nftablesYou need a custom ruleset and your team can own its syntax, testing, persistence, and automationYou also own every operating guardrail that a higher-level manager would provide

Pick the manager that matches the server fleet and support model. If you are replacing an existing manager, document that migration as a separate change. Our Linux Server Support service can help review the host, access path, and rollback plan before a firewall change.

Prepare without locking yourself out

A firewall change on a remote server is also an access-control change. Before installing APF, arrange an out-of-band console or hypervisor console that does not depend on the interface being filtered. Keep the current administrative session open and plan to test with a second session.

Build an inventory from the server rather than assuming SSH is on port 22 or that the public interface is named eth0:

ip -brief address
ip route
ss -lntup
systemctl is-active firewalld
systemctl is-active nftables
iptables --version
iptables-save
ip6tables-save

Record every required inbound service, its address family, interface, source restriction, and owning application. Include monitoring, backup, DNS, VPN, control-panel, cluster, and application health traffic. Then map outbound dependencies such as DNS resolution, package repositories, time synchronization, APIs, databases, webhooks, and mail relays.

Save the current IPv4 and IPv6 rules in your approved change record. Confirm how the server will restore them. An APF rollback that merely flushes rules may recover access, but it does not reconstruct another manager's earlier policy.

Install a reviewed release

Use the official R-fx Networks repository and review the release before executing its installer. At the time of this review, the project identified v2.0.2 as the latest release. If the Releases page shows a newer version, review its changelog and substitute the approved tag.

git clone https://github.com/rfxn/advanced-policy-firewall.git
cd advanced-policy-firewall
git tag --sort=-v:refname | head
git checkout --detach v2.0.2
git status --short
less README.md
less CHANGELOG
sudo bash install.sh

The default installation path is /etc/apf, and the command is installed as /usr/local/sbin/apf. The installer also provides a systemd unit on modern systems. Do not enable persistent boot loading merely because installation completed. Configure and test the policy first.

Configure the policy you actually need

Open /etc/apf/conf.apf and read the comments above each setting. New installations start with DEVEL_MODE="1". In development mode, APF schedules an automatic flush every five minutes to reduce the chance of a permanent lockout. This is a safety net, not a replacement for console access and a tested rollback.

Review these settings first:

SettingDecisionCommon mistake
IFACE_UNTRUSTEDThe internet-facing interface or interfaces APF should filterCopying an old interface name after a network or distro migration
IFACE_TRUSTEDInterfaces that are intentionally exemptTrusting a broad interface when only a narrow source rule was required
IG_TCP_CPORTSRequired inbound TCP destination portsLeaving only the default port 22 when administration uses another port
IG_UDP_CPORTSRequired inbound UDP destination portsForgetting DNS, VPN, application, or monitoring traffic
USE_IPV6Whether APF must build the IPv6 policy tooProtecting IPv4 while leaving an active IPv6 path unreviewed
EGFWhether outbound filtering is enabledEnabling it before mapping DNS, updates, APIs, mail, and other dependencies
DOCKER_COMPATHow APF preserves container-runtime rules during a reloadAssuming auto-detection replaces a real container connectivity test
DEVEL_MODEAutomatic test-mode flush until validation is completeDisabling it before a second access session and application checks pass

IPv6 should be an explicit decision. If the host has routable IPv6, either build and test an IPv6 policy or disable IPv6 through an approved host and network design. Silently ignoring it leaves a second packet path outside the expected rule set. Keep essential ICMPv6 behavior intact because IPv6 neighbor discovery and path operation depend on it.

Validate in development mode

Validate the configuration before loading it, then keep the console and current administrative session available:

sudo apf config validate
sudo apf -o
sudo apf -s
sudo apf status
sudo systemctl status apf --no-pager
sudo iptables -S
sudo ip6tables -S

From a second session, repeat the real administration path. Test each exposed application from an appropriate external source, not only from localhost. Confirm monitoring and backups still connect. For a stateful firewall, also test a new connection after the rules are loaded; an already established session can hide a missing allow rule.

If the policy fails, use the out-of-band console to inspect the APF log and rules. apf -f stops APF and flushes its firewall policy, so use it only as part of the prepared recovery procedure. Do not fire that command through a failing remote session and hope the connection survives.

Only after the second login, application tests, IPv4 and IPv6 checks, logging, and rollback test pass should you set DEVEL_MODE="0", restart APF, and verify persistence through the supported systemd unit. Do not combine systemd, a SysV script, and rc.local startup methods.

Use the APF command line

APF 2.0.x supports both the familiar single-letter commands and structured subcommands. Commands such as apf -r, apf -a, and apf -d remain current. Run them with root privileges. Use sudo apf ... when /usr/local/sbin is already in the root command path, or use the complete installed path sudo /usr/local/sbin/apf ....

HOST can be an IPv4 address, IPv6 address, CIDR network, fully qualified domain name, or supported country code. CMT is an optional quoted comment. Use documentation ranges such as 198.51.100.0/24 and 203.0.113.0/24 only in examples. Replace them with an address you verified and own before making a real rule.

CommandWhat it doesExampleResult and safety check
apf -s
apf --start
Loads the complete configured firewall policy.sudo apf -sUse it for the first development-mode load. Keep console recovery and the existing SSH session open, then test a new SSH session and every required service.
apf -r
apf --restart
Flushes and reloads all APF firewall rules.sudo apf --validate
sudo apf -r
Validate first. A wrong interface, port, or source rule can end remote access during reload. Verify with apf --info, a second login, and external service tests.
apf -f
apf --stop
apf --flush
Stops APF and flushes all firewall rules.sudo apf -fThis removes firewall protection. Use it only from the prepared recovery console or an approved rollback procedure, then restore the intended policy.
apf --info
apf status
Shows an APF status summary, rule counts, trust counts, enabled filtering, subsystems, and recent logging.sudo apf --infoUse this after start or restart. It is a summary, so still test the real allowed and denied network paths.
apf -t
apf --status
apf status log
Pages through the full APF status log at /var/log/apf_log.sudo apf -tUse it to investigate loading and runtime events. Press q to leave the pager.
apf --rules
apf status rules
Writes active rules to standard output in iptables -S form.sudo apf --rulesUse it for review or controlled filtering. It reports loaded rules, not whether the application behind an allowed port is healthy.
apf -l
apf --list
Opens the complete firewall rules in an editor for browsing.sudo apf -lThis is not the allow-list command. Use apf --la to display allow entries and apf --ld for deny entries.
apf -o
apf --dump-config
apf config dump
Outputs all effective APF configuration variables.sudo apf -oSave it with a change record or support case after reviewing whether the output contains internal operational details.
apf --validate
apf --check
apf config validate
Checks the configuration without starting or restarting the firewall.sudo apf config validateRun this after every configuration edit. Success proves the file parsed, not that the policy permits the correct production traffic.
apf -a HOST [CMT]
apf --allow HOST [CMT]
Adds a persistent allow entry and loads it immediately. No restart is required.sudo apf -a 198.51.100.25 "office VPN example"A bare address broadly trusts that host. Confirm the entry with apf --lookup and apf -g. Use advanced syntax when only one service should be allowed.
apf -d HOST [CMT]
apf --deny HOST [CMT]
Adds a persistent deny entry and loads it immediately. No restart is required.sudo apf -d 203.0.113.50 "confirmed abusive host example"Verify the source address and current sessions first. Confirm the stored and loaded rule with apf --lookup and apf -g.
apf -u HOST
apf --remove HOST
apf --unban HOST
Removes a matching host or country code from all local and global trust files, including allow, deny, and temporary entries.sudo apf -u 203.0.113.50This is broader than only undoing -d. Check where the host exists before removal, then confirm apf --lookup returns not found.
apf --la
apf --list-allow
Displays allow trust entries without comments and blank lines.sudo apf --laUse it before and after -a or -u. Also search global and loaded rules when investigating effective policy.
apf --ld
apf --list-deny
Displays deny trust entries without comments and blank lines.sudo apf --ldUse it before and after -d or -u. A host can also be affected by global, country, ipset, or reactive rules.
apf --lookup HOST
apf trust lookup HOST
Checks whether the exact host exists in an allow, deny, global, country, or temporary trust file.sudo apf --lookup 203.0.113.50Exit status is 0 when found and 1 when not found. It searches trust files, not every generated firewall rule.
apf -g PATTERN
apf --search PATTERN
Searches IPv4 and IPv6 rules, ipsets, and trust files for an address, port, chain, or other pattern.sudo apf -g 203.0.113.50
sudo apf -g :443
Use this when --lookup is too narrow. Read the matched chain and action instead of treating any match as a block.
apf -e
apf --refresh
apf trust refresh
Refreshes trust chains and re-resolves FQDN entries.sudo apf -eUse it after a dynamic DNS change. It is not a complete policy restart and does not refresh classic DLIST_* feeds.
apf -ta HOST TTL [CMT]
apf trust temp add
Adds a temporary allow entry with an expiry such as 5m, 1h, or 7d.sudo apf -ta 198.51.100.25 1h "approved maintenance example"Confirm the expiry with apf --temp-list. Temporary access still needs an owner, purpose, and approval.
apf -td HOST TTL [CMT]
apf trust temp deny
Adds a temporary deny entry with automatic expiry.sudo apf -td 203.0.113.50 30m "incident containment example"Confirm the correct source, expiry, evidence, and permanent follow-up before relying on a temporary block.
apf --temp-list
apf trust temp list
Lists temporary allow and deny entries with their remaining time.sudo apf --temp-listUse it during maintenance and incident handoff so temporary access or blocking is not forgotten.
apf --temp-flush
apf trust temp flush
Removes every temporary trust entry.sudo apf --temp-list
sudo apf --temp-flush
Review the list first. This removes temporary allows and temporary denies together, which can restore abusive traffic or remove emergency access.
apf -v
apf --version
Prints the installed APF version.sudo apf -vRecord it before comparing behavior with documentation or opening a support issue.
apf -h
apf --help
man apf
Shows command help and the installed manual.man apfThe installed manual is the complete reference for the exact release on that server.

Use narrow rules when broad host trust is unnecessary

A bare apf -a 198.51.100.25 trusts that address broadly. If the requirement is only SSH from an administration VPN, specify the protocol, direction, destination port, and source:

sudo apf -a "tcp:in:d=22:s=198.51.100.25" "SSH from office VPN example"
sudo apf --lookup 198.51.100.25
sudo apf -g 198.51.100.25

# IPv6 in advanced syntax uses brackets around the address.
sudo apf -a "tcp:in:d=22:s=[2001:db8::25]" "IPv6 SSH source example"

For a targeted deny example, the following blocks traffic from one source to destination port 3306. Because the protocol is omitted, APF creates both TCP and UDP rules:

sudo apf -d "d=3306:s=203.0.113.50" "database probing example"
sudo apf -g 203.0.113.50
sudo apf -u "d=3306:s=203.0.113.50"
sudo apf --lookup 203.0.113.50

Use your real service port and verified source. A firewall allow rule does not authenticate a person, and a deny rule does not repair the vulnerable service that attracted the traffic.

Feature command groups

Current commandClassic equivalentPurpose and exampleImportant caution
apf config validateapf --validateValidate conf.apf without loading rules: sudo apf config validate.Run it before apf -s or apf -r, then perform network tests because syntax validation cannot prove policy intent.
apf config dumpapf -oPrint effective configuration for review or support: sudo apf config dump.Review the output before sharing it outside the operating team.
apf cc info CNapf --cc CNShow detail for a country or continent code. Use apf cc info without a code for the overview.Country is not identity. Geolocation changes and can block legitimate VPN, mobile, or cloud traffic.
apf cc lookup 203.0.113.50apf --cc 203.0.113.50Looks up the APF GeoIP country result for an IP or CIDR.The documentation address is only an example. Do not treat one lookup as permanent evidence of a user's location.
apf cc updateapf --cc-updateRefreshes GeoIP data and its ipsets: sudo apf cc update.Review source health and resulting counts before enforcing a large country-policy change.
apf ct statusapf --ct-statusShows connection-tracking limit configuration and last-scan information.Confirm port, state, thresholds, exemptions, and escalation settings before enabling blocking.
apf ct scanapf --ct-scanRuns the connection-limit scan and can block offenders.This can change live policy. Review the status and exemptions first and monitor false positives.
apf ipset statusNo direct classic status flagLists APF ipset names: sudo apf ipset status.Also inspect list age, entry count, source, and the loaded firewall rule that references each set.
apf ipset updateapf --ipset-updateHot-reloads configured ipset block lists without restarting the complete firewall.A bad remote feed can affect many addresses quickly. Monitor download errors and unexpected count changes.
apf gre statusapf --gre-statusShows APF-managed GRE tunnel status.Verify routes and both tunnel endpoints, not only the reported interface state.
apf gre up
apf gre down
apf --gre-up
apf --gre-down
Brings configured GRE tunnels up or down.Changing a tunnel can remove the administration or application route. Use console recovery and a tested path.
apf --csf-helpSame commandShows mappings for operators moving from ConfigServer Security and Firewall commands.Use it as a translation aid, then verify APF behavior. Similar command names do not make the two policy models identical.

Example: change configuration and reload safely

# Keep the current SSH session and out-of-band console available.
sudo apf -v
sudo apf config validate
sudo apf -r
sudo apf --info
sudo apf --rules

# From a second external session, test SSH and each required service.
# Then confirm the status log and the systemd unit.
sudo apf -t
sudo systemctl status apf --no-pager

Do not use apf -r as the first test of an unreviewed configuration. Do not use apf -f as routine troubleshooting. Validate first, reload from a recoverable session, verify the rules, and prove the network path with a new connection.

The command names and dispatch behavior above were checked directly against the upstream APF executable command dispatcher and the APF README usage reference. On an installed server, apf -v and man apf remain the final checks for that exact release.

Manage trust with narrow rules

APF stores local allow and deny entries in allow_hosts.rules and deny_hosts.rules. The command interface reduces manual editing errors:

sudo apf trust add 198.51.100.25 "administration VPN example"
sudo apf trust deny 203.0.113.50 "confirmed abusive host example"
sudo apf trust lookup 198.51.100.25
sudo apf trust remove 203.0.113.50

The addresses above are documentation examples. Replace them with verified sources from your own policy. Avoid permanently trusting a whole office, hosting-provider, or consumer ISP range when the real requirement is one VPN address and one administration port.

Version 2.0.2 also supports temporary trust entries with time to live:

sudo apf trust temp add 198.51.100.25 1h "approved maintenance example"
sudo apf trust list --temp

Temporary access is useful for maintenance, but expiry is not authorization. Record who approved it, why it exists, which service it reaches, and what evidence confirms that it expired.

Follow a changing address with dynamic DNS

This is one of APF's most practical features. The trust files accept fully qualified domain names as well as IPv4 addresses, IPv6 addresses, and CIDR blocks. APF resolves a hostname before loading its trust rule. When the DNS answer changes, APF can resolve it again without requiring an administrator to edit the firewall by hand.

The current conf.apf defaults are designed for this workflow:

SET_REFRESH="10"
SET_REFRESH_MD5="0"
FQDN_TIMEOUT="10"

SET_REFRESH="10" means APF refreshes the trust system every 10 minutes. The refresh flushes and reloads the TALLOW, TDENY, TGALLOW, and TGDENY chains, downloads enabled global trust files, and re-resolves hostnames in the rules. Set it to 0 only when automatic trust refresh is intentionally disabled.

Keep SET_REFRESH_MD5="0" when a trust entry uses dynamic DNS. With the MD5 optimization enabled, APF can skip a refresh when the trust file itself has not changed. A dynamic hostname can point to a new address while the text in allow_hosts.rules remains exactly the same.

For example, a home administrator with a changing public address can publish that address through a dynamic DNS provider such as Duck DNS, then add the hostname to APF:

getent ahosts your-subdomain.duckdns.org
sudo apf trust add your-subdomain.duckdns.org "home administrator dynamic DNS"
sudo apf -e
sudo apf trust lookup your-subdomain.duckdns.org
sudo apf -g your-subdomain.duckdns.org

Replace your-subdomain with the hostname you control. apf -e performs an immediate trust refresh and DNS re-resolution; the automatic cycle handles later changes. If USE_IPV6="1", APF can resolve and load both A and AAAA answers, so verify both address families.

A hostname allow rule is still a trust rule, not user authentication. APF evaluates local and global allow chains before deny chains, remote block lists, and normal port filtering. Anyone who gains control of the dynamic DNS account or its update token can point that trusted name at another address. Protect the dynamic DNS credentials, monitor unexpected changes, keep console recovery available, and use a VPN or stable bastion when a broad host-trust rule is more access than the server should grant.

Do not store a Duck DNS update token in conf.apf or a trust file. The dynamic DNS updater owns that secret. APF needs only the published hostname.

Use remote lists and global trust deliberately

APF has three related automation models. They refresh on different schedules, so it is worth knowing which one you have enabled.

MechanismPurposeRefresh behavior
Classic DLIST_* importsProject Honey Pot, Spamhaus DROP, DShield, reserved networks, and the ECN compatibility listDownloaded and loaded on a full APF start or restart
Global trust with USE_RGTYour centrally maintained glob_allow.rules and glob_deny.rulesDownloaded and reloaded by the trust refresh cycle, which defaults to 10 minutes
ipset.rulesLarge local or remote IP and CIDR sets with efficient matchingThe installed cron runs hourly; each list and IPSET_REFRESH control whether an update is due

Classic remote-list imports

The DLIST_* switches in conf.apf control the remote-list system. Each enabled feed has a companion URL. APF validates downloaded entries and retains a backup so a failed download does not silently replace the last usable file.

  • DLIST_SPAMHAUS loads the Spamhaus DROP advisory list. It is a list of high-risk netblocks, not a general list of every IP associated with unwanted mail.
  • DLIST_DSHIELD imports DShield's current top suspicious hosts.
  • DLIST_PHP imports the Project Honey Pot harvester and spammer list supplied through R-fx Networks.
  • DLIST_RESERVED updates the reserved or unassigned network file. It matters when BLK_RESNET="1", and the default configuration enables both.
  • DLIST_ECNSHAME is not a deny feed. When SYSCTL_ECN="1", it identifies destinations that need ECN disabled for compatibility.

Do not change a vendor URL merely to point at a convenient mirror. The feed format is part of the integration. Test the source, certificate validation, parser result, entry count, and rollback before enabling a new or replacement URL.

Global allow and deny files

Global trust is valuable when several servers must share one reviewed source of truth. Publish the files from an HTTPS location you control, set GA_URL and GD_URL, and enable USE_RGT="1". APF downloads the files into glob_allow.rules and glob_deny.rules, then loads them into the TGALLOW and TGDENY chains.

USE_RGT="1"
GA_URL="https://security.example.net/apf/glob_allow.rules"
GD_URL="https://security.example.net/apf/glob_deny.rules"
SET_REFRESH="10"

The example host is a placeholder. A production feed needs restricted publishing access, change review, TLS validation, monitoring, and a recovery copy. Global allow deserves the strictest control because APF checks TGALLOW before local and global deny chains and before remote block lists. One mistaken line can allow an address that a later control was expected to block.

Global rule file format

The official glob_allow.rules template and glob_deny.rules template use the same line-oriented syntax. Their effect is different: a rule downloaded into TGALLOW grants the matching traffic, while a rule downloaded into TGDENY blocks it.

A bare IPv4 address, IPv4 CIDR, or IPv6 address applies to the host or network generally:

# one IPv4 address
198.51.100.25

# one IPv4 network
198.51.100.0/24

# one IPv6 address
2001:db8::25

In glob_allow.rules, a bare entry is broad trust. Use it only when that source should bypass later deny, block-list, and normal port-filter checks. In glob_deny.rules, a bare entry is a broad block. When the requirement concerns one service or direction, use the advanced format instead:

proto:flow:[s/d]=port:[s/d]=ip(/mask)

The fields describe protocol, packet direction, source or destination port, and source or destination address. For example, a centrally managed allow file can grant one administration source access only to inbound TCP port 22:

# CHG-142: administration VPN, review 2026-09-01
tcp:in:d=22:s=198.51.100.25

A global deny file can block inbound access to a database port from one network without denying every other conversation with that network:

# Block inbound database probes from this reviewed network
tcp:in:d=3306:s=203.0.113.0/24

Plain IPv6 addresses work as bare entries. In advanced syntax, wrap the IPv6 address or prefix in brackets so its colons are not confused with the rule-field separators:

tcp:in:d=443:s=[2001:db8:1200::/48]

Keep one rule per line. Use comments to record ownership, reason, approval, and review or expiry date. Publish plain text, and replace the remote file atomically so a refresh never downloads a partially written policy. Review both files together because an allow match is evaluated before a deny match.

After enabling global trust, validate and refresh it without waiting for the next interval:

sudo apf config validate
sudo apf -e
sudo apf status
sudo apf -g 198.51.100.25

Use a known documentation or test address only in a non-production feed. In production, search for an exact approved address and an exact denied address, then test the real traffic path from both sources.

Large lists with ipset

The newer ipset.rules subsystem is a better model for large feeds because one iptables rule can reference a kernel hash set instead of adding one firewall rule per address. The installed APF cron calls apf --ipset-update hourly. The default IPSET_REFRESH="21600" makes a list with no per-list interval eligible every six hours, while the hourly cron sets the minimum effective check interval.

You can request an immediate hot reload without restarting the complete firewall:

sudo apf --ipset-update
sudo apf ipset status
sudo apf status

Automatic refresh is powerful because it removes repetitive manual work. It also turns DNS and remote feeds into live firewall dependencies. Monitor download failures, resolution failures, unexpected entry-count changes, and the age of the last successful refresh.

Treat automated blocking as a control

Reactive Address Blocking, remote lists, GeoIP policy, connection limits, and SYN rate controls can reduce noise and contain obvious abuse. They can also block valid traffic when thresholds or data sources do not match the application.

  • Start in an observable mode and measure what would be blocked.
  • Keep administrative and health-check sources narrowly exempted where justified.
  • Set an owner and expiry for temporary blocks.
  • Monitor the structured audit log at /var/log/apf/audit.log and the main APF status log.
  • Test failover addresses, proxies, NAT gateways, mobile users, and IPv6 separately.

Country filtering is not an identity control. IP geolocation can be stale or ambiguous, and legitimate users may arrive through VPNs, mobile networks, or global services. Use country rules only when the business requirement and false-positive response are clear.

Containers need a separate test plan

Docker, Podman, Kubernetes components, and network plugins may create their own iptables chains, forwarding policy, NAT rules, and address sets. APF's current DOCKER_COMPAT="auto" mode attempts to preserve external chains and container networking during an APF flush. It also disables APF fast-load snapshots when compatibility mode is active.

That feature improves coexistence, but it cannot prove every CNI, proxy, published port, overlay, or service route remains correct. Stage the change on a representative node. Test host ingress, published container ports, service-to-service traffic, outbound NAT, DNS, health probes, and workload restart behavior. For platform-wide firewall and deployment work, see our DevOps Services.

Upgrade an existing APF installation safely

A server still using APF 1.7.5 should be treated as a migration, not a routine package refresh. The modern installer backs up the existing APF directory, and the included importconf utility can carry recognized values into the new configuration while leaving new variables at current defaults. That is helpful, but it does not make the old policy correct.

  1. Export the active IPv4 and IPv6 rules and copy the complete old APF directory.
  2. Inventory interfaces, listeners, source restrictions, outbound dependencies, containers, and startup methods again.
  3. Read every release note between the installed and target versions.
  4. Import the old configuration into a fresh current template.
  5. Diff the result and review each carried value, especially modules, ports, interfaces, IPv6, sysctl, remote lists, and hooks.
  6. Test in development mode with console recovery and two administration sessions.
  7. Remove the old startup method after the systemd path is verified.

Start from the configuration template shipped with the target release. Imported values still need individual review because a prior file may omit current safety, IPv6, container, audit, GeoIP, or connection-control settings.

Troubleshooting

SymptomLikely areaUseful evidence
A new SSH session failsWrong port, interface, source rule, address family, or another firewall managerss -lntup, route, APF config, active rules, console test
Rules disappear after five minutesDEVEL_MODE is still enabledAPF config, cron entry, status and audit logs
Rules disappear after rebootStartup unit is disabled, failing, or competing with another loadersystemctl status apf, boot journal, enabled units
IPv4 works but IPv6 failsUSE_IPV6, IPv6 port policy, route, or ICMPv6 behaviorIPv6 address and route, ip6tables -S, external IPv6 test
Containers lose networkCompatibility detection, forwarding, NAT, CNI, or restart orderRuntime chains before and after APF start, workload and service tests
Application can receive but not call dependenciesOutbound filtering is incompleteDestination, protocol, DNS, route, APF egress rules, application logs
Expected host is blockedTrust order, remote list, GeoIP, RAB, or temporary rule expiryapf trust lookup, apf -g, audit log, source address
Dynamic DNS points to a new address but access failsThe updater, DNS answer, SET_REFRESH, MD5 optimization, or address familygetent ahosts, apf -e, APF status and audit logs
Global trust file is staleUSE_RGT, URL, TLS, DNS, file format, or refresh failureConfigured URL, downloaded file, refresh log, expected entry search
Remote block list is stale after apf -eClassic DLIST_* feeds need a full start or restart; they are not trust chainsAPF restart log, downloaded list timestamp, active chain and entry count

Operating checklist

  • One named firewall manager owns the host policy.
  • The current rules, APF configuration, and recovery path are backed up.
  • The untrusted interface and every listening service were discovered from evidence.
  • IPv4 and IPv6 were both reviewed.
  • Development mode remained enabled through a second-session test.
  • Container and application traffic was tested from outside the host.
  • Dynamic DNS names resolve to the intended IPv4 and IPv6 addresses, and automatic trust refresh is monitored.
  • Global trust and remote-list publishers are controlled, reviewed, and recoverable.
  • Automated lists and blocking thresholds have owners, logs, and false-positive procedures.
  • Persistence was tested through one supported startup method.
  • The change record includes rollback, validation, and the next review date.

APF is useful when its policy model matches the way a team operates Linux servers. It is not useful merely because it can generate many rules. A good deployment has one owner, narrow intent, visible evidence, a recovery console, and a test that proves both allowed and denied traffic behave as designed.

Official sources

Related technical notes

Mail queue investigation separating deferred traffic, SMTP responses, route health, and safe diagnostic evidenceLinux, MTA & Security · Jul 20, 2026 · 3 min read

Postfix Queue Backlog: A Safe Diagnostic Runbook

Diagnose a Postfix backlog from queue age, destination groups, SMTP responses, host health, DNS, and route evidence before changing retries or concurrency.

Technical review

Need this checked against your own sending system?

Share the domain, headers, bounces, provider warning, logs, or infrastructure symptom and NitWings will identify the practical next step.

Schedule a Technical Review
Advertisement