If you have followed our journey through the Self-Managed Life series, you have achieved something most modern internet users consider impossible. You have built your own router (Post 3), established a VPN perimeter (Post 5), and deployed a fully functional Mailcow email server (Post 12). You are no longer a tenant in Google’s digital slum; you are the architect of your own castle.

But a castle with the drawbridge permanently down is not a fortress—it is a ruin waiting to happen.

In Post 13, we configured the software side of your email delivery, setting up SMTP relays and DNS records to ensure your emails hit inboxes instead of spam folders. Now, we must turn our attention to the hardware edge. We must configure pfSense to act as the ruthless gatekeeper for your mail server.

This is not simply about “opening ports.” If you blindly open ports 25, 80, and 443 to the entire world without restriction, you are inviting every botnet, script kiddie, and state-sponsored scanner to hammer your server.

In this guide, we will implement a Zero Trust architecture for your mail server. We will not just “allow” traffic; we will curate it. We will use pfSense Aliases to organize our rules, NAT Port Forwarding to precisely direct traffic, and GeoIP Blocking to silence the noise from countries where you have no contacts.

This is the definitive guide to hardening your self-hosted communications infrastructure.

The Philosophy of the “Bouncer”

Understanding the Attack Surface

Before we touch a single setting in the pfSense GUI, we must understand the threat model. A mail server is unique among self-hosted services because it must be publicly accessible to function.

This makes your mail server the most exposed component of your Sovereign Cloud. When you open Port 25 (SMTP) to receiving mail, you are essentially standing on a digital street corner and shouting, “I am here! Talk to me!”

Our goal in pfSense is to ensure that legitimate postmen can deliver mail, but thieves cannot enter the building to steal the furniture. We achieve this through three layers of defense, which we will configure in order:

  1. Aliases: The organizational layer that defines who and what is involved.
  2. NAT (Network Address Translation): The instructional layer that tells the router where to send incoming packets.
  3. Firewall Rules: The permission layer that decides if a packet is allowed to pass at all.

The Foundation – pfSense Aliases

The hallmark of an amateur network administrator is a firewall ruleset littered with raw IP addresses and port numbers. The hallmark of a professional is the use of Aliases.

Aliases allow you to group multiple ports, IPs, or networks into a single, named object. If you ever change your mail server’s internal IP address, you update the Alias once, and every NAT rule and firewall rule automatically updates.

Creating the Ports Alias

Your Mailcow server uses a symphony of ports to communicate. Instead of creating eight separate firewall rules, we will bundle them into a single Alias.

  1. Log in to your pfSense WebGUI.
  2. Navigate to Firewall > Aliases.
  3. Click the Ports tab.
  4. Click Add.

Configuration Values:

Now, add the following ports. It is important to understand why we are adding each one:

PortServiceProtocolWhy We Need It
25SMTPTCPMandatory. This is how other mail servers (Gmail, Yahoo) deliver mail to you.
465SMTPSTCPLegacy/Implicit TLS. Used by some older clients to send mail securely.
587SubmissionTCPModern Standard. Used by your phone/laptop to send mail out via your server.
143IMAPTCPRetrieval. Standard port for fetching emails (STARTTLS).
993IMAPSTCPSecure Retrieval. SSL/TLS encrypted IMAP. The standard for mobile devices.
110POP3TCPLegacy Retrieval. Only needed if you use POP3 (downloads and deletes from server).
995POP3STCPSecure Legacy. SSL/TLS POP3.
80HTTPTCPCertificate Validation. Required for Let’s Encrypt (ACME) to renew SSL certs.
443HTTPSTCPWeb Access. Required for SOGo Webmail, ActiveSync, and Mailcow UI.

Web Access. Required for SOGo Webmail, ActiveSync, and Mailcow UI.

Self-Hoster Tip: If you never use POP3 (and you shouldn’t, IMAP is superior), do not include ports 110 and 995. Minimizing the attack surface is the first rule of security.

  1. Click Save.
pfSense Port Aliases
pfSense Port Aliases

Creating the Host Alias

Next, we define where the mail server lives. In Post 11, you should have assigned your Ubuntu VM a static IP address (e.g., 192.168.1.50). We will reference this now.

  1. Click the IP tab (under Firewall > Aliases).
  2. Click Add.
  3. Name: Mail_Server_IP
  4. Description: Internal IP of Mailcow VM
  5. Type: Host(s)
  6. IP or FQDN: Enter your server’s static LAN IP (e.g., 192.168.1.50).
  7. Click Save and Apply Changes.

You have now created the vocabulary your firewall will use. Instead of saying “Allow TCP traffic on 25 to 192.168.1.50”, you can now say “Allow Mail_Ports to Mail_Server_IP.”

pfSense Host Aliases
pfSense Host Aliases

NAT Port Forwarding – Punching Holes in the Wall

NAT (Network Address Translation) is the process of taking traffic hitting your public WAN IP and rewriting it to go to an internal LAN IP. Without this, your router receives an email packet and drops it, having no idea which device inside your home is the mail server.

The “Fork in the Road”: Public Access vs. VPN Only

At this stage, you must make a critical architectural decision based on FUTO Guide Section 16.

Path A: The “Fortress” Mode (VPN Only)

Path B: The “Public Service” Mode (Standard)

For this guide, we will assume Path B (Standard), as it is what 99% of users require for a functional replacement of Big Tech services.

Creating the NAT Rule

  1. Navigate to Firewall > NAT.
  2. Select the Port Forward tab.
  3. Click Add (Up arrow).

The Rule Configuration:

  1. Click Save and Apply Changes.

You have now created the vocabulary your firewall will use. Instead of saying “Allow TCP traffic on 25 to 192.168.1.50”, you can now say “Allow Mail_Ports to Mail_Server_IP.”

pfSense Firewall Aliases
pfSense Firewall Aliases

NAT Port Forwarding – Punching Holes in the Wall

NAT (Network Address Translation) is the process of taking traffic hitting your public WAN IP and rewriting it to go to an internal LAN IP. Without this, your router receives an email packet and drops it, having no idea which device inside your home is the mail server.

The “Fork in the Road”: Public Access vs. VPN Only

At this stage, you must make a critical architectural decision based on FUTO Guide Section 16.

Path A: The “Fortress” Mode (VPN Only)

Path B: The “Public Service” Mode (Standard)

For this guide, we will assume Path B (Standard), as it is what 99% of users require for a functional replacement of Big Tech services.

Creating the NAT Rule

  1. Navigate to Firewall > NAT.
  2. Select the Port Forward tab.
  3. Click Add (Up arrow).

The Rule Configuration:

  1. Click Save and Apply Changes.
pfSense Port Forwarding
pfSense Port Forwarding

Firewall Rules – The Guards

When you created the NAT rule and selected “Add associated filter rule,” pfSense automatically created a rule on your WAN interface. However, this rule is likely too permissive. We need to audit and refine it.

pfSense Firewall Rules
pfSense Firewall Rules

The Danger of Auto-Generated Rules

Navigate to Firewall > Rules > WAN. You will see a new rule at the bottom allowing traffic to Mail_Server_IP.

The problem? It allows everything in the Mail_Ports alias from anywhere. While Any is necessary for Port 25 (SMTP) because we don’t know where email will come from, it is dangerous for Port 80 (Webmail) and Port 22 (SSH) if you included it.

Splitting the Rules (Advanced Security)

For true “Mastery,” we should split our access logic. We want the world to send us mail (Port 25), but we might only want our country to try and log in (Port 443/993).

Action Plan:

  1. Edit the auto-generated rule.
  2. Change the Destination Port Range from Mail_Ports to just 25 (SMTP).
  3. Save.
  4. Create a second rule for the “User Access” ports (443, 993, 587).
  5. For this second rule, we will apply GeoIP Blocking.

The Shield – Implementing GeoIP Blocking with pfBlockerNG

In Post 6, we installed pfBlockerNG. Now we will weaponize it to protect our mail server.

Most brute-force attacks on mail servers come from a handful of countries. If you live in the United States and have no business associates in Russia, China, or North Korea, there is zero reason for an IP address in those nations to attempt a login on your IMAP port.

pfBlockerNG
pfBlockerNG

Step 1: Configure GeoIP Aliases

  1. Navigate to Firewall > pfBlockerNG > IP > GeoIP.
  2. Ensure you have created an alias for Top Spammers or High Risk countries.
  3. Ensure you have an alias for your Home Country (e.g., North America).

Step 2: Apply to Firewall Rules

We will now modify the firewall rules to be “Allow” lists rather than “Block” lists.

The “User Access” Rule (Ports 443, 993, 587):

  1. Go back to Firewall > Rules > WAN.
  2. Create a new rule ABOVE the default deny rule.
  3. Action: Pass
  4. Source: Single Host or Alias -> pfB_NA_v4 (This is the pfBlocker alias for North America. Adjust for your region).
  5. Destination: Mail_Server_IP
  6. Destination Port: Create a new Alias called Mail_Login_Ports (443, 993, 587) and use it here.
  7. Description: “Allow Mail Login from Home Region Only”.

The “Server Talk” Rule (Port 25): Port 25 is trickier. Legitimate email can come from anywhere. However, 90% of spam comes from botnets in specific regions.

  1. Create a rule allowing Port 25 from Any.
  2. Crucial: Ensure your Block rules from pfBlockerNG (the general bad-guy lists) are processed BEFORE this pass rule.
    • In pfSense, rules are processed top-down. The first match wins.
    • Order should be:
      1. Block Malicious IPs (pfBlockerNG Auto-Rules).
      2. Block GeoIP Spammers (pfBlockerNG Auto-Rules).
      3. Pass Mail_Login_Ports (From Home Region).
      4. Pass Port 25 (From Any).
      5. Deny All.

Troubleshooting & The “Hairpin” Problem

You’ve set it all up. You disconnect your phone from Wi-Fi, and mail syncs perfectly. You walk back inside, connect to Wi-Fi, and suddenly… connection error.

This is the dreaded NAT Reflection (or Hairpin NAT) issue.

The Scenario

Your phone tries to connect to mail.example.com. DNS resolves this to your WAN IP (e.g., 203.0.113.5). Your phone sends a packet to 203.0.113.5. Your pfSense router sees a packet coming from the LAN destined for the WAN IP. Without Reflection, pfSense drops it or gets confused about where to send the reply.

The Fix: Split DNS (The Professional Way)

While we enabled “Pure NAT” earlier as a quick fix, the correct way to solve this in a sovereign cloud is Split DNS.

  1. Navigate to Services > DNS Resolver (Unbound).
  2. Scroll down to Host Overrides.
  3. Click Add.
  4. Host: mail
  5. Domain: yourdomain.com
  6. IP Address: 192.168.1.50 (The LOCAL IP of the server).
  7. Description: Split DNS for Mailcow.

What this does:

Verification – Trust But Verify

Never assume your firewall is working. Test it.

Test 1: The Open Relay Test

Use a tool like MXToolbox to scan your domain.

Test 2: The GeoIP Test

  1. Use a VPN on your phone to tunnel to a blocked country (e.g., Russia or China).
  2. Try to load your Webmail URL (https://mail.yourdomain.com).
  3. Result: It should time out.
  4. Disconnect the VPN.
  5. Result: The login page should load immediately.

The Quiet Confidence of Security

You have now done what few sysadmins take the time to do properly. You haven’t just punched a hole in your firewall; you’ve installed a smart airlock. You’ve segregated traffic, optimized local routing with Split DNS, and erected geofences to keep out the noise.

Your mail server is now ready to face the hostile internet. But a secure server is only useful if it holds valuable data. In Module 3, Post 15, we will tackle the next giant of the Google ecosystem: Google Drive. We will begin building your own resilient, synchronized file cloud.

The next part of this self hosting series covers advanced configuration, hardening techniques, and automation scripts that tie everything together. From DNS tuning to fail2ban integration, the upcoming guide walks through every step with annotated commands and real-world examples from a production self-hosted environment. Every tool, every config file, and every gotcha explained in detail…
COMING SOON

The next part is dropping soon.
Become a member to get early access.

🏠

Next Part of the Self Hosting Series Dropping Soon

Members get early access to every new part of the Self Hosting Series before it goes public — including guides, scripts, and in-depth walkthroughs.

Get Early Access Now
Self Hosting Series
Next Part Dropping Soon
Members get notified and can read the next part before it goes public.
Members Only
Early Access + Full Guides
Get every part of the Self Hosting Series early, complete with scripts and detailed walkthroughs.

Joined by 1,200+ sysadmins, homelabbers, and self-hosting enthusiasts

This post first appeared at - The CyberSec Guru