Centos – Setting up NAT with firewalld on Centos 7

centosfirewalldnat;routing

I have two servers, which we will call ROUTER and NODE. NODE is on a private network 172.27.1.64/28, with IP address 172.27.1.69. ROUTER is also on that private network, with IP address 172.27.1.71. ROUTER has a public IP address, which we will call 192.168.50.100 for this example. On ROUTER, the private network is accessed via interface eth1 and the public network is accessed via eth0. On NODE, there is only eth0, which is connected to the private network. There is another private subnet which appears in the routing tables below, but shouldn't be relevant (I hope) to this issue.

What I am trying to do is have ROUTER act as, well, a router using NAT. NODE should be able to make connections via ROUTER to the general internet, but no connections should be able to be made in the reverse direction.

There are many guides out there for doing this and I have tried to follow them, but I have not been able to ping or otherwise access hosts by IP address or name from NODE.

Here is what I have in terms of configuration:

The public interface is in the 'public' zone, and the private interface is in the 'internal' zone.

Routing table on NODE:

default via 172.27.1.71 dev eth0 
unreachable 169.254.169.254  scope host 
172.27.1.64/28 dev eth0  proto kernel  scope link  src 172.27.1.69 
172.27.9.192/28 dev eth0  scope link

Routing table on ROUTER:

default via 192.168.50.1 dev eth0 
192.168.50.0/24 dev eth0  proto kernel  scope link  src 192.168.50.100
unreachable 169.254.169.254  scope host 
172.27.1.64/28 dev eth1  proto kernel  scope link  src 172.27.1.71 
172.27.9.192/28 dev eth1  scope link

FirewallD rules on ROUTER:

# firewall-cmd --direct --get-all-rules
ipv4 nat POSTROUTING 0 -o eth0 -j MASQUERADE

I have additionally had these rules on ROUTER, since it would make sense to me to have specific rules to accept packets in each direction, but their presence or absence makes no difference — neither ping nor curl nor ssh work from NODE:

ipv4 filter FORWARD 0 -i eth1 -o eth0 -j ACCEPT
ipv4 filter FORWARD 0 -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

I do have masquerade enabled generally with firewalld:

# firewall-cmd --zone public --query-masquerade
yes

And I have IP forwarded enabled in the kernel:

# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

I try by pinging 8.8.8.8. It works fine from ROUTER, but it does not work from NODE. 100% packet loss. Using curl against google.com's IP address has the same result: works from ROUTER, not from NODE.

Best Answer

Naturally, the problem ended up being somewhere completely different. I needed to disable OpenStack's anti-spoofing on private network interface.

I can verify that all three rules are necessary in the firewall.

Related Topic