majorwiki/05-troubleshooting/networking/firewalld-mail-ports-reset.md
MajorLinux 26eb13ab2f troubleshooting: document majormail client-connectivity incident (2026-06-05)
- New page: Dovecot IMAP vsz_limit OOM from a bloated/corrupt index.log
  (152M index on an empty folder killed IMAP children with error 83).
- fail2ban IMAP self-ban: add permanent ignoreip-whitelist fix + dynamic-IP caveat.
- firewalld mail ports: add 'submission/587 never added' variant + correct
  Fedora service name; note Ansible now manages the full mail-service set.
- Index + SUMMARY updated with the new page.
2026-06-05 14:04:22 -04:00

4.4 KiB

title domain category tags status created updated
firewalld: Mail Ports Wiped After Reload (IMAP + Webmail Outage) troubleshooting networking
firewalld
mail
imap
fedora
ports
published 2026-04-02 2026-06-05

firewalld: Mail Ports Wiped After Reload (IMAP + Webmail Outage)

If IMAP, SMTP, and webmail all stop working simultaneously on a Fedora/RHEL mail server, firewalld may have reloaded and lost its mail port configuration.

Symptoms

  • openssl s_client -connect mail.example.com:993 returns Connection refused
  • Webmail returns connection refused or times out
  • SSH still works (port 22 is typically in the persisted config)
  • firewall-cmd --list-services --zone=public shows only ssh dhcpv6-client mdns or similar — no mail services
  • Mail was working before a service restart or system event

Why It Happens

firewalld uses two layers of configuration:

  • Runtime — active rules in memory (lost on reload or restart)
  • Permanent — written to /etc/firewalld/zones/public.xml (survives reloads)

If mail ports were added with firewall-cmd --add-service=imaps (without --permanent), they exist only in the runtime config. Any event that triggers a firewall-cmd --reload — including Fail2ban restarting, a system update, or manual reload — wipes the runtime config back to the permanent state, dropping all non-permanent rules.

Diagnosis

# Check what's currently allowed
firewall-cmd --list-services --zone=public

# Check nftables for catch-all reject rules
nft list ruleset | grep -E '(reject|accept|993|143)'

# Test port 993 from an external machine
openssl s_client -connect mail.example.com:993 -brief

If the only services listed are ssh and the port test shows Connection refused, the rules are gone.

Fix

Add all mail services permanently and reload:

firewall-cmd --permanent \
  --add-service=smtp \
  --add-service=smtps \
  --add-service=smtp-submission \
  --add-service=imap \
  --add-service=imaps \
  --add-service=http \
  --add-service=https
firewall-cmd --reload

# Verify
firewall-cmd --list-services --zone=public

Expected output:

dhcpv6-client http https imap imaps mdns smtp smtp-submission smtps ssh

Variant: One port (587) fails while the rest work — service never added

A subtler version of this: IMAP (993) and implicit-TLS submission (465) work fine, but only STARTTLS submission on 587 fails — clients on 587 get "no route to host." This is not a reload wipe; the submission service was simply never added during initial setup (the box's mail ports were opened by hand and one was missed).

# Each mail service, individually — submission will be the odd one out
for s in smtp smtps submission imap imaps; do printf "%-12s " "$s"; firewall-cmd --query-service=$s; done

# Fix (Fedora 44 / firewalld names the 587 service `submission`, NOT `smtp-submission`)
firewall-cmd --permanent --zone=public --add-service=submission
firewall-cmd --reload

On majormail the full mail-service set is now managed declaratively in roles/majormail/tasks/postfix.yml (smtp/smtps/submission/imap/imaps), so a hand-edit can't leave 587 behind again (MajorAnsible commit b75f14a). Seen 2026-06-05.

Key Notes

  • Service name differs by distro/version: the 587 service is submission on current Fedora firewalld; older/other docs may say smtp-submission. Verify with firewall-cmd --get-services | tr ' ' '\n' | grep submission.
  • Always use --permanent when adding services to firewalld on a server. Without it, the rule exists only until the next reload.
  • Fail2ban + firewalld: Fail2ban uses firewalld as its ban backend (firewallcmd-rich-rules). When Fail2ban restarts or crashes, it may trigger a firewall-cmd --reload, resetting any runtime-only rules.
  • Verify after any firewall event: After Fail2ban restarts, system reboots, or firewall-cmd --reload, always confirm mail services are still present with firewall-cmd --list-services --zone=public.
  • Check the permanent config directly: cat /etc/firewalld/zones/public.xml — if mail services aren't in this file, they'll be lost on next reload.