Protecting GWIA SMTP Services
A firewalld + ipsets solution
✅ Project Summary: Protecting GWIA SMTP Services Using firewalld + ipsets
🎯 Objective
Protect GroupWise GWIA SMTP ports (e.g. 192.168.10.249:2525) from unwanted SMTP access by dynamically allowing only:
-
Legitimate mail relay providers (e.g. Dynu Mail Relay)
-
Internal subnets for testing/monitoring
-
Drop all other connections at the firewall level, not at the mail server
This solution requires the external router to preserve the source IP address (via full NAT or DMZ with NAT reflection/hairpin), so that firewall rules can match public sender IPs.
📌 Topology Example
[Dynu SMTP Relay IPs] ──> [Public IP Router (NAT 1:1)] ──> [GWIA Host: 192.168.10.249:2525]
|
+-- Port-forward (WAN 25 → LAN 2525)
📦 Requirements
-
OpenSUSE Leap 15.6 or compatible Linux
-
firewalld(with support for rich rules andipset) -
Scripted dynamic config (
gwiaprotection.sh) -
DNS access to resolve MX records
-
Assumption: router allows original source IP to reach firewall
🧰 Dynamic IP Filtering Strategy
-
Perform DNS MX lookup for your mail domains (e.g.
eacbelcher.net) -
Resolve Dynu’s outbound relays (e.g.
mx1.dynu.com, etc.) -
Resolve A/AAAA records for those MX hosts
-
Add the resulting IPs into an
ipset -
Create rich firewall rules allowing only those IPs on specified ports
🛠️ Installation & Setup
1. 🧪 Ensure firewalld is enabled
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo firewall-cmd --state
2. 📁 Script Location
Place the script here:
/etc/scripts/gwiaprotection.sh
Make executable:
chmod +x /etc/scripts/gwiaprotection.sh
🔐 Sample Invocation
sudo /etc/scripts/gwiaprotection.sh --ip 192.168.10.249 --domain eacbelcher.net --port 2525 --config
Output Example:
[DEBUG] do_config: remove_rules
[DEBUG] do_config: ensure_ipsets
[DEBUG] do_config: populate_ipsets
[DEBUG] do_config: add_rules
[gwiaprotection] Configured 192.168.10.249 for domains: eacbelcher.net on ports: 2525
📄 Rich Firewall Rule Structure
Generated rules (via firewall-cmd) include:
rule priority="-200" family="ipv4" source ipset="gwp_192_168_10_249_v4" destination address="192.168.10.249" port port="2525" protocol="tcp" accept
rule priority="100" family="ipv4" destination address="192.168.10.249" port port="2525" protocol="tcp" drop
rule priority="-200" family="ipv4" source address="192.168.10.0/24" destination address="192.168.10.249" port port="2525" protocol="tcp" accept
✅ Allows:
-
Dynu source IPs (via ipset)
-
Internal subnet
🚫 Denies: -
All others
🔄 Script Workflow (Simplified)
1. Remove existing firewall rules
2. Create or verify ipsets (v4 and v6)
3. Lookup MX records for domain(s)
4. Resolve A/AAAA for each MX
5. Populate ipsets with resolved IPs
6. Add rich rules to allow those IPs on the target port
7. Add fallback drop rule
8. Reload firewalld
🧪 Test & Debug
✅ Check IPSet Contents
sudo ipset list gwp_192_168_10_249_v4
Should list resolved Dynu IPs:
Members:
162.216.242.35
162.216.242.36
...
✅ Show Rich Rules
sudo firewall-cmd --permanent --zone=public --list-rich-rules
✅ Simulate Connection from External IP
From a public host:
telnet mail.ezeasproducts.com.au 25
✅ Monitor in Real Time
sudo tcpdump -i any -nn dst host 192.168.10.249 and dst port 2525
Expected:
-
Allowed IPs: connection established
-
Others: dropped with no response
🔁 To Undo / Reset
sudo /etc/scripts/gwiaprotection.sh --ip 192.168.10.249 --reset
Or manually:
sudo firewall-cmd --permanent --zone=public \
--remove-rich-rule='rule family="ipv4" source ipset="gwp_192_168_10_249_v4" destination address="192.168.10.249" port port="2525" protocol="tcp" accept'
sudo firewall-cmd --permanent --delete-ipset=gw_192_168_10_249_v4
sudo firewall-cmd --reload
📤 Dynu Reference IP Ranges
If you prefer to use static IPs:
162.216.242.0/24
142.202.188.16/29
107.161.27.201
2602:ff23:0:8888::/64
But ideally, resolve from MX records for resilience.
🧾 Summary
| Feature | Value |
|---|---|
| Protection Layer | firewalld + ipsets (L3/L4) |
| Mail Server | GroupWise GWIA |
| Relay Provider | Dynu |
| Allowed IPs Source | Dynamic from MX + A/AAAA resolution |
| Script Location | /etc/scripts/gwiaprotection.sh |
| Config Type | Rich rules + ipsets |
| Router Requirement | Full NAT with original source IP retained |
gwiaprotection.sh
copy this file to server hosting GWIA services.# gwiaprotection.sh
# Lock down a specific GWIA IP:PORT(S) so only MX hosts (plus internal nets/extra IPs) can connect.
# Usage:
# /etc/scripts/gwiaprotection.sh --ip 192.168.10.250 --config
# /etc/scripts/gwiaprotection.sh --ip 192.168.10.250 --status
# /etc/scripts/gwiaprotection.sh --ip 192.168.10.250 --clear
#
# Loads config from /etc/scripts/gwiaprotection.<A.B.C.D>.conf (derived from --ip)
# Config keys:
# GWIA_PORTS="2525 25"
# DOMAINS=("eacbelcher.net")
# INTERNAL_NETS="192.168.10.0/24"
# EXTRA_IPS_V4=""
# EXTRA_IPS_V6=""