One-to-one NAT

Tom Eastep

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover, and with no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.


Table of Contents

One-to-one NAT
ARP cache


This article applies to Shorewall 4.3 and later. If you are running a version of Shorewall earlier than Shorewall 4.3.5 then please see the documentation for that release.

One-to-one NAT


If all you want to do is forward ports to servers behind your firewall, you do NOT want to use one-to-one NAT. Port forwarding can be accomplished with simple entries in the rules file.

One-to-one NAT is a way to make systems behind a firewall and configured with private IP addresses (those reserved for private use in RFC 1918) appear to have public IP addresses. Before you try to use this technique, I strongly recommend that you read the Shorewall Setup Guide.

The following figure represents a one-to-one NAT environment.

One-to-one NAT can be used to make the systems with the 10.1.1.* addresses appear to be on the upper (130.252.100.*) subnet. If we assume that the interface to the upper subnet is eth0, then the following /etc/shorewall/nat file would make the lower left-hand system appear to have IP address and the right-hand one to have IP address It should be stressed that these entries in the /etc/shorewall/nat file do not automatically enable traffic between the external network and the internal host(s) — such traffic is still subject to your policies and rules.


#EXTERNAL       INTERFACE         INTERNAL      ALLINTS            LOCAL  eth0          no                 no  eth0          no                 no

Be sure that the internal system(s) ( and in the above example) is (are) not included in any specification in /etc/shorewall/masq (/etc/shorewall/snat) or /etc/shorewall/proxyarp.


The ALL INTERFACES column is used to specify whether access to the external IP from all firewall interfaces should undergo NAT (Yes or yes) or if only access from the interface in the INTERFACE column should undergo NAT. If you leave this column empty, No is assumed . Specifying Yes in this column will not by itself allow systems on the lower LAN to access each other using their public IP addresses. For example, the lower left-hand system ( cannot connect to and expect to be connected to the lower right-hand system. See FAQ 2a.


Shorewall will automatically add the external address to the specified interface unless you specify ADD_IP_ALIASES=no (or No) in /etc/shorewall/shorewall.conf; If you do not set ADD_IP_ALIASES or if you set it to Yes or yes then you must NOT configure your own alias(es).


The contents of the LOCAL column determine whether packets originating on the firewall itself and destined for the EXTERNAL address are redirected to the internal ADDRESS. If this column contains yes or Yes (and the ALL INTERFACES COLUMN also contains Yes or yes) then such packets are redirected; otherwise, such packets are not redirected. This feature requires that you enabled CONFIG_IP_NF_NAT_LOCAL in your kernel.

Entries in /etc/shorewall/nat only arrange for address translation; they do not allow traffic to pass through the firewall in violation of your policies. In the above example, suppose that you wish to run a web server on (a.k.a. You would need the following entry in /etc/shorewall/rules:

#ACTION     SOURCE     DEST            PROTO       DPORT       SPORT          ORIGDEST
ACCEPT      net        loc:    tcp         80          -    

ARP cache

A word of warning is in order here. ISPs typically configure their routers with a long ARP cache timeout. If you move a system from parallel to your firewall to behind your firewall with one-to-one NAT, it will probably be HOURS before that system can communicate with the Internet.

If you sniff traffic on the firewall's external interface, you can see incoming traffic for the internal system(s) but the traffic is never sent out the internal interface.

You can determine if your ISP's gateway ARP cache is stale using ping and tcpdump. Suppose that we suspect that the gateway router has a stale ARP cache entry for On the firewall, run tcpdump as follows:

tcpdump -nei eth0 icmp

Now from, ping the ISP's gateway (which we will assume is


We can now observe the tcpdump output:

13:35:12.159321 0:4:e2:20:20:33 0:0:77:95:dd:19 ip 98: > icmp: echo request (DF)
13:35:12.207615 0:0:77:95:dd:19 0:c0:a8:50:b2:57 ip 98: > : icmp: echo reply

Notice that the source MAC address in the echo request is different from the destination MAC address in the echo reply!! In this case 0:4:e2:20:20:33 was the MAC of the firewall's eth0 NIC while 0:c0:a8:50:b2:57 was the MAC address of the system on the lower right. In other words, the gateway's ARP cache still associates with the NIC in that system rather than with the firewall's eth0.

If you have this problem, there are a couple of things that you can try:

  1. A reading of TCP/IP Illustrated, Vol 1 by Stevens reveals[1] that a gratuitous ARP packet should cause the ISP's router to refresh their ARP cache (section 4.7). A gratuitous ARP is simply a host requesting the MAC address for its own IP; in addition to ensuring that the IP address isn't a duplicate...

    if the host sending the gratuitous ARP has just changed its hardware address..., this packet causes any other host...that has an entry in its cache for the old hardware address to update its ARP cache entry accordingly.

    Which is, of course, exactly what you want to do when you switch a host from being exposed to the Internet to behind Shorewall using one-to-one NAT (or Proxy ARP for that matter). Happily enough, recent versions of Redhat's iputils package include arping, whose -U flag does just that:

    arping -U -I <net if> <newly proxied IP>
    arping -U -I eth0             # for example

    Stevens goes on to mention that not all systems respond correctly to gratuitous ARPs, but googling for arping -U seems to support the idea that it works most of the time.

    To use arping with one-to-one NAT in the above example, you would have to:

    shorewall clear
    ip addr add dev eth0     # You need to add the addresses only if Shorewall clear
    ip addr add dev eth0     # deletes them
    arping -U -c 10 -I eth0
    arping -U -c 10 -I eth0
    ip addr del dev eth0     # You need to delete the addresses only if you added
    ip addr del dev eth0     # them above
    shorewall start
  2. You can call your ISP and ask them to purge the stale ARP cache entry but many either can't or won't purge individual entries.


There are two distinct versions of arping available:

  1. arping by Thomas Habets (Debian package arping).

  2. arping as part of the iputils package by Alexey Kuznetsov (Debian package iputils-arping).

You want the second one by Alexey Kuznetsov.

[1] Courtesy of Bradey Honsinger


Frequently Used Articles

- FAQs - Manpages - Configuration File Basics - Beginner Documentation - Troubleshooting

Shorewall 4.4/4.5/4.6 Documentation

Shorewall 4.0/4.2 Documentation

Shorewall 5.0/5.1/5.2 HOWTOs and Other Articles

- 6to4 and 6in4 Tunnels - Accounting - Actions - Aliased (virtual) Interfaces (e.g., eth0:0) - Anatomy of Shorewall - Anti-Spoofing Measures - AUDIT Target support - Bandwidth Control - Blacklisting/Whitelisting - Bridge/Firewall - Building Shorewall from GIT - Commands - Compiled Programs - Configuration File Basics - DHCP - DNAT - Docker - Dynamic Zones - ECN Disabling by host or subnet - Events - Extension Scripts - Fallback/Uninstall - FAQs - Features - Fool's Firewall - Forwarding Traffic on the Same Interface - FTP and Shorewall - Helpers/Helper Modules - Installation/Upgrade - IPP2P - IPSEC - Ipsets - IPv6 Support - ISO 3661 Country Codes - Kazaa Filtering - Kernel Configuration - KVM (Kernel-mode Virtual Machine) - Limiting Connection Rates - Linux Containers (LXC) - Linux-vserver - Logging - Macros - MAC Verification - Manpages - Manual Chains - Masquerading - Multiple Internet Connections from a Single Firewall - Multiple Zones Through One Interface - My Shorewall Configuration - Netfilter Overview - Network Mapping - No firewalling of traffic between bridge port - One-to-one NAT - Operating Shorewall - OpenVPN - OpenVZ - Packet Marking - Packet Processing in a Shorewall-based Firewall - 'Ping' Management - Port Forwarding - Port Information - Port Knocking (deprecated) - Port Knocking, Auto Blacklisting and Other Uses of the 'Recent Match' - PPTP - Proxy ARP - QuickStart Guides - Release Model - Requirements - Routing and Shorewall - Routing on One Interface - Samba - Shared Shorewall/Shorewall6 Configuration - Shorewall Events - Shorewall Init - Shorewall Lite - Shorewall on a Laptop - Shorewall Perl - Shorewall Setup Guide - SMB - SNAT - Split DNS the Easy Way - Squid with Shorewall - Starting/stopping the Firewall - Static (one-to-one) NAT - Support - Tips and Hints - Traffic Shaping/QOS - Simple - Traffic Shaping/QOS - Complex - Transparent Proxy - UPnP - Upgrade Issues - Upgrading to Shorewall 4.4 (Upgrading Debian Lenny to Squeeze) - VPN - VPN Passthrough - White List Creation - Xen - Shorewall in a Bridged Xen DomU - Xen - Shorewall in Routed Xen Dom0

Top of Page