Setup NAT on Linux (iptables/nftables/firewalld)

The  Setup

Having this set up where Machine A like to connect to the Internet via Machine B.

+-------------------+          +-----------------+
|                   |          |  Machine B      |
|      Machine A    |          |  (the gateway)  |
|      (the client) |          |                 |
|                   |          |                 |
|              eth0 +----------+  eth1     eth0  |
+-------------------+          +-------------+---+
                                             |
                                             |
                     .-~~~-.                 |
             .- ~ ~-(       )_ _             |
            /                     ~ -.       |
           |        internet           \<----+
            \                         .'
              ~- . _____________ . -~

Iptables

Add the following lines to the iptables

iptables -I FORWARD     -o eth1 -m comment --comment "NAT" -j ACCEPT
iptables -I FORWARD     -i eth1 -m comment --comment "NAT" -j ACCEPT
iptables -I POSTROUTING -o eth0 -m comment --comment "NAT" -j MASQUERADE -t nat

and make sure to enable forwarding on Machine B

sysctl -w net.ipv4.ip_forward=1

Firewalld

If for example the interface eth0 is part of the public zone and eth1 is part of the internal zone, we just need to run

firewalld-cmd --zone=public --add-masquerade 
# To make this setting persistent, repeat the command adding the --permanent option. 

With RHEL/CentOS9 there is a need to add a policy, source[1]

// create new policy
firewall-cmd --permanent --new-policy policy_int_to_ext
firewall-cmd --permanent --policy policy_int_to_ext --add-ingress-zone internal
firewall-cmd --permanent --policy policy_int_to_ext --add-egress-zone external
firewall-cmd --permanent --policy policy_int_to_ext --set-priority 100
firewall-cmd --permanent --policy policy_int_to_ext --set-target ACCEPT

// Enable masquerade on external; 'forward' does not need to be set
firewall-cmd --permanent --zone=external --add-masquerade

// restart firewalld
systemctl restart firewalld.service

The policy looks like this…

# firewall-cmd --info-policy policy_int_to_ext
policy_int_to_ext (active)
priority: 100
target: ACCEPT
ingress-zones: internal
egress-zones: external
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

Resources

  1. https://forums.fedoraforum.org/archive/index.php/t-327324.html

Leave a Reply

Your email address will not be published. Required fields are marked *