Syntactically, the following set of statements is valid (at least as of 8.3):
interface Ethernet0/0
nameif OUTSIDE
ip address 192.0.2.1 255.255.255.0
interface Ethernet0/1
nameif INSIDE
ip address 10.1.1.1 255.255.255.0
object network O_N_EXAMPLE1
host 10.1.1.2
object network O_N_EXAMPLE2
host 10.1.1.3
object service O_S_EXAMPLE1
service tcp destination eq 60001
object service O_S_EXAMPLE2
service tcp destination eq 60002
object-group network OG_N_EXAMPLEHOSTS
network-object object O_N_EXAMPLE1
network-object object O_N_EXAMPLE2
nat (OUTSIDE,INSIDE) source static any any destination static interface OG_N_EXAMPLEHOSTS service O_S_EXAMPLE1 O_S_EXAMPLE2
nat (INSIDE,OUTSIDE) after-auto source dynamic any interface
The second nat
statement is fairly obvious -- it simply translates everything outbound to the WAN IP, in a typical hide-NAT/LAN-to-WAN scenario.
However, the first nat
defines a (probably invalid) rule directing any inbound request for the WAN IP over TCP/60001 to be sent to either of 192.0.2.1:60002 or 192.0.2.2:60002.
The ASA command-line lets you enter it without error.
packet-tracer
doesn't balk at it (at least, assuming an access-group
permits):
packet-tracer input OUTSIDE tcp 192.0.2.100 12345 192.0.2.1 60001
"succeeds", in that it says the final action is to allow, and along the way it untranslates to 10.1.1.2 and identifies the output interface asINSIDE
.packet-tracer input INSIDE tcp 10.1.1.1 60002 192.0.2.1 60002
"succeeds", in that it says the final action is to allow, and along the way it translates to 192.0.2.1, but does not indicate the ouput interface.
What it does not do (and what I think might have been the original intent) is distribute between the two target IPs, nor track which of the two hosts is up and establish a translation to an available node. I don't believe that ASA has any function for that (although I'm happy to be proved wrong!) beyond tracked routes, which are more to do with outbound, LAN-to-multi-WAN traffic.
In practice I expect it accepts the inbound and drops the reply traffic, resulting in a failed TCP handshake.
I note that splitting the nat
statement into two statements results in an ovelap [sic] warning:
# nat (OUTSIDE,INSIDE) source static any any destination static interface O_N_EXAMPLE1 service O_S_EXAMPLE1 O_S_EXAMPLE2
# nat (OUTSIDE,INSIDE) source static any any destination static interface O_N_EXAMPLE2 service O_S_EXAMPLE1 O_S_EXAMPLE2
WARNING: mapped-address 192.0.2.2/60002-0 ovelap with existing static NAT.
So I wonder, how does the ASA interpret that first nat
statement and, in particular, under what circumstances would it actually attempt to translate to 10.1.1.3?
I understand what would happen if the NAT was a destination static
between two object
objects (a simple translation from the first to the second) or even two object-group
objects with the same number of network-object
entries (a one-to-one translation from the nth entry in the first group to the nth entry in the second group), but not in this case, with a one-to-many definition.
Does it just translate between the interface address and the first network-object
, dicarding the second? Or does it work something out with regards to available ephemeral ports (e.g. the first 64K connections go to 192.0.2.1 and the second go to 192.0.2.2)? Does it duplicate the traffic to both? Or something else entirely?