There are already blogs out there on how to use FirewallD as a router. In general, you enable masquerade. However, I could not find any that mentioned how to do it if you have public static IPs.
Prior to using FirewallD, I used iptables for over a decade without an issue. Once FirewallD was setup correctly on a new Internet router on Centos 7, I haven’t had any issues. It has been running rock solid.
There were some lessons I had to learn the hard way due to the lack of documentation both on the blogs on using it as a router and via FirewallD documentation itself.
Presuming you have two zones labeled external and internal, your first step is to enable masquerade for your external zone.
firewall-cmd --zone=external --add-masquerade --permanent
The tricky part was what to do with the internal zone. If you run the same command on it, it will initially appear to run fine. The problem with it is how the IP addresses appear on your servers, which can quickly snowball into a huge problem with security.
The problem that I ran into is that I ran my email server for a week as an open relay and didn’t realize it until my outgoing email was getting rejected due to being blacklisted as a spammer. When I traced the issue, it was because every connection to it appeared to be coming from the internal IP address of my internet router (firewalld), which it trusted. Before you know it, you’re a spam sender for Russian bots.
But, if you don’t enable masquerade on internal, you will be the only one who can’t get to your servers via their public IP addresses. The rest of the world gets routed OK. You get on the Internet OK. You can access your servers via their internal IP OK. But, if you access yourpublicdomain.xyz (pointing to one of your public IPs) from inside your network, your router won’t route you.
It turns out there is a very happy place in the middle using the add-rich-rule option. Let’s say your private subnet that your Internet router is a part if is 10.10.5.0/24, you would simply issue this command:
firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source address=10.10.5.0/24 masquerade'
This enables masquerade for your internal zone ONLY for traffic originating from inside your network. Now you can reach yourpublicdomain.xyz from inside your network without a problem. Meanwhile, if you check your server logs, they are all seeing the correct public IP of outside traffic, and can require SMTP authentication or apply whatever other security protections you have for untrusted sources.
It’s pretty simple. Note that you need to do it on your internal as well as your external even if your destination address is public. So, presuming you were running a web server on public IP 18.104.22.168 that is on your local 10.10.5.51, you would forward ports to it with the following commands:
firewall-cmd --permanent --zone=external --add-rich-rule='rule family=ipv4 destination address=22.214.171.124 forward-port port=80 protocol=tcp to-port=80 to-addr=10.10.5.51' firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 destination address=126.96.36.199 forward-port port=80 protocol=tcp to-port=80 to-addr=10.10.5.51'
You’d repeat that for port 443 to support SSL.
Note that because you are using rich rules, you can easily limit access to internal only for something like SSH via a public IP (and your domain):
firewall-cmd --permanent --zone=external --add-rich-rule='rule family=ipv4 source address=10.10.5.0/24 service name=ssh destination address=188.8.131.52 log prefix="SSH Access" level="notice" accept'