Create and Use a firewalld Conntrack Helper
FTP breaks firewalls: it opens a second connection on a random port, and a firewalld conntrack helper teaches the firewall to follow it. You will create a local helper definition, make it available to a service, validate the XML, and apply the change without confusing runtime state with the saved configuration. The example uses the FTP conntrack module on TCP port 2121. Allow about 15 minutes, plus a maintenance window if the service is handling live traffic.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes firewalld 2.1.1, installed here as package version 2.1.1-1. The helper file format comes from that version's firewalld.helper(5) manual page. A helper is a narrowly scoped conntrack definition, not a replacement for opening a firewall port: the service still needs a port or other matching rule that permits the traffic.
1. Check the package and service state
Run these checks as your ordinary user:
$ firewall-cmd --version
FirewallD is running: version: 2.1.1
$ firewall-cmd --state
running
The exact version line can include distribution details. If firewall-cmd --state does not report running, do not continue with commands that require the daemon. Start firewalld through your system's normal service manager, or use the offline configuration tool if you are deliberately preparing an offline image.
Checkpoint
Record the active service name you intend to change. The examples below use ftp-custom as a placeholder; substitute the name of a service file that already exists, or create one through your normal service-management process.
2. Write the helper XML
Custom helper files belong in /etc/firewalld/helpers. Distribution-supplied definitions live in /usr/lib/firewalld/helpers; do not edit those files, because package updates can replace them. The filename, without .xml, becomes the helper name.
This definition associates the kernel's FTP conntrack module with TCP port 2121:
<?xml version="1.0" encoding="utf-8"?>
<helper module="nf_conntrack_ftp">
<short>Custom FTP helper</short>
<description>FTP control traffic on the custom port</description>
<port protocol="tcp" port="2121"/>
</helper>
Create the directory and file with elevated privileges. This command changes persistent firewall configuration, so review the path and contents before running it:
$ sudo install -d -m 0755 /etc/firewalld/helpers
$ sudoedit /etc/firewalld/helpers/ftp-custom.xml
- Keep exactly one helper element in the file. Its
moduleattribute is mandatory and names a netfilter conntrack helper beginning withnf_conntrack_. - Add family="ipv4" only when you mean to restrict it. The optional
familyattribute accepts onlyipv4oripv6; if omitted, the definition applies to both families. - Each port element must be empty and carry both port and protocol. The port can be a number, a range such as
2121-2123, or an empty value when the helper should match the protocol without a port restriction. Accepted protocols aretcp,udp,sctpanddccp. Add anotherportelement for another pair.
3. Validate the file before loading it
First validate XML syntax without touching firewalld:
$ xmllint --noout /etc/firewalld/helpers/ftp-custom.xml
No output and exit status 0 means the XML parser accepted the file. If xmllint is not installed, inspect the file carefully and use firewalld's own configuration check next.
Ask firewalld to check its permanent configuration:
$ sudo firewall-cmd --check-config
success
This checks XML validity and semantics. A failure usually points to an invalid attribute, an unsupported protocol, a missing module name, or a malformed element. Fix the file and run both checks again; do not reload a configuration that has not passed the check.
Checkpoint
The file exists under /etc/firewalld/helpers, xmllint accepts it when available, and firewall-cmd --check-config returns success.
4. Attach the helper to a permanent service
A helper definition is not used merely because its XML file exists. Attach its name to the service that needs it. The operation is permanent and requires elevated privileges:
$ sudo firewall-cmd --permanent --service=ftp-custom --add-helper=ftp-custom
success
$ sudo firewall-cmd --permanent --service=ftp-custom --query-helper=ftp-custom
yes
For a service that does not already exist, stop here and create its service definition first. Do not guess a service name; inspect the saved service definitions instead:
$ firewall-cmd --permanent --get-services
The --permanent change is saved to disk but is not effective in the current runtime configuration. That separation is deliberate: you can validate a saved change before selecting when it becomes active.
5. Apply and verify the change
Reloading makes the current permanent configuration the new runtime configuration. It can discard other runtime-only changes, so check with the firewall owner before doing this on a busy host:
$ sudo firewall-cmd --reload
success
$ firewall-cmd --service=ftp-custom --get-service-helpers
ftp-custom
If the service has a different name, substitute it in both commands. The helper listing confirms firewalld read the service configuration. It does not prove the kernel module is available or that an application is using the expected FTP behaviour: test the actual service from an approved client and review your normal firewall and conntrack monitoring.
When a reload is not appropriate yet, leave the change permanent and schedule the reload. If you need to discard the saved attachment before applying it, remove only that association:
$ sudo firewall-cmd --permanent --service=ftp-custom --remove-helper=ftp-custom
success
$ sudo firewall-cmd --check-config
success
Removing the helper association does not delete /etc/firewalld/helpers/ftp-custom.xml. Delete that file only once you have confirmed that no service or automation refers to it, and keep a copy in case you need to restore it.
Common traps
- A helper is not a port opening. Permit the control port through the relevant zone or service rules as a separate, reviewed change.
- Do not put a custom definition in /usr/lib/firewalld/helpers. Use
/etc/firewalld/helpersfor local configuration. - Do not assume that omitting family means IPv4 only. The documented default is both IPv4 and IPv6.
- Do not use --complete-reload as a routine verification step. The firewall-cmd manual warns that it can terminate active connections by losing state information.
- Do not use --runtime-to-permanent casually. It overwrites the complete permanent configuration with the current runtime configuration, not just this helper change.
Done means
- Helper file placed correctly. The helper XML is under
/etc/firewalld/helpersand names an installed, appropriate conntrack module. - Checks pass. The XML and permanent firewalld configuration checks pass.
- Attached to the right service. The helper is attached to the intended service with
--permanent --add-helper. - Reload state known. A planned reload has made the permanent change runtime, or the reload is intentionally deferred.
- Tested separately. The service port rules and helper behaviour have been tested apart from each other.