Disclaimer: I do not work for Cisco or Checkpoint. This page is not supported, endorsed or approved by Checkpoint, Cisco, Nortel, Nokia, nor my employer.
"Outgoing" in this doc, and in Cisco doc means "from a more secure network to a less secure network."
For a packet to move through the PIX from the more secure network to the less secure network it has to pass the following hurdles:
Apply Inbound ACL's on the more secure interface
NAT of outgoing traffic part one (before any VPN decision is made)
apply "alias" statementsapply "static" statements
Decide if traffic is a part of a VPN
(Do source and destination match an ACL specified in a crypto map?)
YES
NO Apply NAT 0 statements associated with an ACL
Continue to NAT/GLOBAL evaluation Ecapsulate traffic in encrypted packet with source and destination addresses of VPN gateways
Evaluate NAT and GLOBAL statements(Note that VPN traffic does go through this step, but only AFTER encapsulation, so at this point, the source and destination are already set to those of the gateways)
Match source address to most specific NAT statement
Rewrite source address to the global matching the selected NAT statement
Perform routing descision to determine which interface the packet will exit on
Apply any outbound ACLS to traffic leaving less secure interface
To take these in order:
NAT of a packet is processed after any inbound ACL's are processed. Inbound ACL's must match the IP source and destination in the packet when it arrives on the interface.
For example, if you have a host in your network of 10.0.0.1 which will be initiating traffic to an external server of 1.2.3.4, and that's the packet that arrives on the PIX's inside interface, the access list must specify
access-list acl_in permit <something> host 10.0.0.1 host 1.2.3.4
After ACL's, NAT is processed, before VPN's or routing are considered. The very first next thing that the PIX does is to after allowing the packet into the PIX is to rewrite the headers in accordance with your alias and static setup.
Let's first examine NAT of packets which originate from your network (from a higher security-level interface) and are going to be sent out of your network (out on a lower security-level interface). We're going to call this an "outgoing packet."
This NAT is governed by four statements:
The "alias" statement rewrites the the destination address of the packet
The "nat" and "global" statements determine how the source address (and port) of the packet will be rewritten. In theory, the "nat" statements determine whether or a not a packet's source address will be rewritten, and the "global" statement determines what it will be rewritten to. The "nat" and "gobal" statements usually apply to outgoing packets, but in later versions of the PIX OS, "nat" can be used for inbound NAT as well. The application of "nat" to inbound packets is an ugly kludge.Avoid it by using "alias" if at all possible.
The "static" statement (like alias) is intended to determine how the desination address of a packet will be rewritten. In theory, it's point is to decide if the desination of incoming traffic will be translated to some normaly private addresses. However, "static" statements will perform rewrites on outgoing packets that match them. The application of "static" to outbound packets is an ugly kludge, but due to the order of processing, may be required for VPN packets prior to encapsulation.
alias
The "alias" statement, when used to rewrite the destination address of an outgoing packet, is dead simple. (It can do other stuff, but it's rarely used in that way.) The basic form is:
alias (interface_the packet_arrives-on) original_destination address_to_rewrite_it_to netmask_for_both
for example
alias (inside) 10.0.0.1 1.2.3.4 255.255.255.255
rewrites packets received on the "inside" interface destined for 10.0.0.1 to have a new destination of 1.2.3.4
This
alias (inside) 10.0.0.0 1.2.3.0 255.255.255.0
does a one-for for rewrite from 10.0.0.0/24 to 1.2.3.0/24. i.e. 10.0.0.1 will get rewritten to 1.2.3.1, 10.0.0.2 will get rewritten to 1.2.3.2 and so on.
Yes, in theory, you could do:
alias (inside) 10.0.0.1 1.2.3.4 255.255.255.255
alias (dmz) 10.0.0.1 2.3.4.5 255.255.255.255Though I've never had a reason to do it, so can't swear there's not some hidden gotcha.
This:
alias (outside) <anything>
looks like it would work straightforwardly to perform incoming NAT. HAH! Not anywhere near that easy. It doesn't work, because that's not how you're supposed to do incoming NAT.
static
The "static" statement determines if and how how the desination address of a matching packet will be rewritten, and allows it from a lower security inteface to a higher security network if required. It has the following syntax.
static (interface_the packet_will_go_out_on, interface_the packet_will_arrive-on) original_destination address_to_rewrite_it_to netmask netmask_for_both
for example
static (outside,dmz) 1.2.3.0 1.2.3.0 netmask 255.255.255.0
forces packets received on the "outside" interface destined for 1.2.3.0 to be allowed to the higher security "dmz" network (assuming the ACL's have allowed it) without altering the destination address
In normal use, interface_the packet_will_go_out_on will be the more secure interface, and interface_the packet_will_arrive-on will be the less secure interface. If you're using static as a kludge to force some sort of NAT'ing prior to VPN processing that isn't necessarily so. You might do this:
static (inside,outside) 1.2.3.4 10.11.12.13 netmask 255.255.255.255
to forcibly rewrite 1.2.3.4 to 10.11.12.13 prior to encapsulation.
The mechanics of VPN setup are out of scope for this little reminder document. Just bear in mind that this is the VPN encapsulaton step. The packet along with the headers -- including source and destination IP's -- is encrypted and stuffed into a new packet where the source and destination IP's are those of the peer gateways.
aliases work before VPN encapsulation
statics work before VPN encapsulation
nat associated with an ACL works before VPN encapsulation
nat 0 works after VPN encapsulation
nat n works after VPN encapsulation
globals work with nat n after VPN encapsulation
Note that VPN traffic does go through this step, but only AFTER encapsulation, so at this point, the source and destination are already set to those of the gateways
The "nat" and "global" statements with two interfacesThe "nat (foo) n x.x.x.x y.y.y.y" statement defines which addresses coming in on the "foo" interface (network x.x.x.x mask y.y.y.y) will be NAT'd to an address in the "global n" statement.
The "global n" statement defines the nonsecure address(es) behind which the local network in the "nat (foo) n x.x.x.x y.y.y.y" will hide.
The "nat" and "global" statements need to be considered together, because they're not quite as distinct as you'd think, and they have odd interactions.
The simplest case is to say "don't NAT the source address at all with only inside and outside interfaces involved"
One might think this is possible by putting in no global or nat statements at all. One would be wrong. The PIX loves NAT. The PIX always wants to NAT. It assumes you want to NAT, too. If you put in no global or nat statements at all, it still assumes you want to NAT, and just haven't told it any specifics, so it gets confused. It issues the miserable, unhelpful "no translation group found" message when it sees the packet, and drops it on the floor. You must set up NAT, at least enough to tell it NOT to NAT.
The correct way is with a "nat 0" statement. This:
<no global statement>
nat (inside) 0 0.0.0.0 0.0.0.0 0 0makes it not rewrite the source address on any headers at all. This:
<random global statement>
nat (inside) 0 0.0.0.0 0.0.0.0 0 0theoretically shouldn't either (after all the "zero" should mean "associate me with no global at all, just use the real addresses). But if you really, truly aren't using NAT at all, I'd get rid of the global.
A global statement with no NAT statements, like this:
global (outside) 1 1.2.3.4
<no nat statements>is an error. It's syntactically valid -- the PIX will acccept it -- but it won't work to do anything. It certainly won't just turn off NAT -- everything will error with "no translation found" because the PIX will be confused.
In the statement:
nat (inside) 0 0.0.0.0 0.0.0.0 0 0
the "0.0.0.0 0.0.0.0" is obviously a network and mask, and yes, one could say
<no global statement>
nat (inside) 0 1.0.0.0 255.0.0.0 0 0if one wanted to leave 1.x.x.x un-NAT'ed and drop everything else coming from the inside interface on the floor with the miserable, unhelpful "no translation group found" message. Or, one could say:
<no global statement>
nat (inside) 0 1.0.0.0 255.0.0.0 0 0
nat (inside) 0 2.0.0.0 255.0.0.0 0 0if one wanted to leave both 1.x.x.x and 2.x.x.x un-NAT'ed and drop everything else coming from the inside interface on the floor with the miserable, unhelpful "no translation group found" message.
The next simplest case is to NAT everything behind a single address with only inside and outside interfaces involved.
This
global (outside) 1 1.2.3.4
nat (inside) 1 0.0.0.0 0.0.0.0 0 0NAT's everything to 1.2.3.4 via PAT. Note that here we use "nat 1" vs. "nat 0". While "nat 0" has the special meaning of "don't rewrite the source address" the "1" in "nat 1" is an arbitrary nat group identifier. It serves to associate the nat statement to the global statement (to assocuiate the command telling it what addresses to NAT with the comand telling the PIX what addresses to nat them to). This
global (outside) 2 1.2.3.4
nat (inside) 2 0.0.0.0 0.0.0.0 0 0is functionally identical. This
global (outside) 1 1.2.3.4
nat (inside) 2 0.0.0.0 0.0.0.0 0 0is an error. It's syntactically valid, but the PIX will drop all of the outgoing traffic it receives on the floor.
It's also fairly simple to "hide NAT everything except foo with only inside and outside interfaces involved""
This:
global (outside) 1 1.2.3.4
nat (inside) 1 4.0.0.0 255.255.255.0 0 0
nat (inside) 0 10.0.0.0 255.255.255.0 0 0NAT's 4.x.x.x addresses coming from the inside interface going to the outside to 1.2.3.4.
10.0.0.0/24 coming from the inside interface won't be NAT'ed at all
Traffic other than 4.0.0.0/24 or 10.0.0.0/24 will error with "no translation found"Nor, really, is it any problem to "NAT foo to X, NAT bar to Y"
This:
global (outside) 1 1.2.3.4
global (outside) 2 2.3.4.5
nat (inside) 1 4.0.0.0 255.255.255.0 0 0
nat (inside) 2 10.0.0.0 255.255.255.0 0 0NAT's 4.x.x.x addresses coming from the inside interface going to the outside to 1.2.3.4.
10.0.0.0/24 coming from the inside interface get NAT'ed to 2.3.4.5
Traffic other than 4.0.0.0/24 or 10.0.0.0/24 will error with "no translation found"
I want to use my PIX's own address for my Hide NAT address
You do, huh? I hate doing that. Consider if being unable to tell if the traffic is from the PIX itself, or something behind it may not cause you headaches down the line. Especially, are teghre other firewalls down the line somewhere where you'll be annoyed that you can't split up what you allow from the PIX vs. what you allow for its clients. But it's easy enough to do. Just use the word "interface" instead of an IP address:
global (outside) 1 interface
nat (inside) 1 0.0.0.0 0.0.0.0 0 0will Hide NAT everything behind the PIX's own address.
But one hide NAT address isn't enough
Really? You do know that with PAT that one address will get over 64,000 connections, right? But if you really need more, it's easy enough. The "global" statement allows you to define a pool. In fact, you can define it in two different ways. Suppose you have this:
global (outside) 1 1.1.1.1
nat (inside) 1 0.0.0.0 0.0.0.0 0 0i.e. you hide NAT everything behind 1.1.1.1. You decide you need three addresses, not one for a "hide NAT pool" That's easy:
global (outside) 1 1.1.1.1-1.1.1.3
nat (inside) 1 0.0.0.0 0.0.0.0 0 0expands it to use a pool between 1.1.1.1 and 1.1.1.3
Or, if you prefer using subnets, and decide to devote 1.1.1.0/29 to a pool you can specify it like so:
global (outside) 1 1.1.1.0 netmask 255.255.255.248
nat (inside) 1 0.0.0.0 0.0.0.0 0 0I need to NAT servers X and Y to specific addresses
Well, not quite so easy, but still doable. You need one global for each NAT address, and some corresponding "nat" statements. Suppose you have hosts as follows:
10.0.0.1 mailserver1
10.0.0.2 mailserver2
10.1.1.1 appserverYou want to NAT both mailservers to one address, the appserver to another, and everything else to some third address. You can do it like this:
global (outside) 1 1.1.1.1
nat (inside) 1 10.0.0.1 255.255.255.255
nat (inside) 1 10.0.0.2 255.255.255.255
: NAT's the mailservers to 1.1.1.1global (outside) 2 1.1.1.2
nat (inside) 2 10.1.1.1 255.255.255.255
: NAT's the appserver to 1.1.1.2global (outside) 3 1.1.1.3
nat (inside) 3 0.0.0.0 0.0.0.0
: NAT's everything else to 1.1.1.3
The "nat" and "global" statements with more than two interfaces
Now. if you have only inside and outside interfaces involved, you're lucky. Your NAT can be starightforwardly configured according to the above rules. More than two gets uglier.
Let's presume we have three interfaces: "inside", "outside" and "dmz" -- we're just using "dmz" as an arbitrary name here.
The simplest case, again, is to say "don't NAT the source addresses at all"
Easy enough with a couple of "nat 0" statements, like:
<no global statement>
nat (inside) 0 0.0.0.0 0.0.0.0 0 0
nat (dmz) 0 0.0.0.0 0.0.0.0 0 0Do not depend on this:
<no global statement>
nat (inside) 0 0.0.0.0 0.0.0.0 0 0working to turn off NAT on both "inside" and "dmz". It may, in fact work, but that's because of some ugliness in how the PIX handles these "nat" statements. We'll talk about that more below, but by the descriptions in he command reference, it should not work.
And, as you would expect, the next simplest case is to NAT everything behind a single address.
This
global (outside) 1 1.2.3.4
nat (inside) 1 0.0.0.0 0.0.0.0 0 0
nat (dmz) 1 0.0.0.0 0.0.0.0 0 0NAT's everything to 1.2.3.4 via PAT, just as you'd expect it to.
Additional addresses and hiding behind the interface
These effect only the global statement, so they work exactly the way that they do when you have only two interfaces.
NAT servers X and Y to specific addresses
This also works pretty much the same as it does for two-interface PIX's, just specify the correct interfaces on the "nat" statements.
I want to NAT traffic going out the outside (or some other) interface to one address, and not NAT traffic going to the DMZ (or any other interface).
You're still fine. This follws the same setup as NAT servers X and Y to specific addresses. Just make sure that the DMZ (or other interfaces) has a NAT 0
I want to NAT traffic going out the dmz interface to one address, and traffic going to the outside interface to a different one.
Oh, boy. If your goal is to have one NAT address on the outside interface, and a different one on a DMZ interface, it's going to be painful. While it looks logical, this:
global (outside) 1 1.2.3.4
global (dmz) 1 4.5.6.7
nat (inside) 1 0.0.0.0 0.0.0.0 0 0will simply cause errors ("%PIX-3-305006: portmap translation creation failed for tcp src inside:<address>/<port> dst dmz:<address>/<port>) for any traffic going to the dmz interface. Yes, it ought to work. It doesn't. So, we deal with it. Here's the not-quite documented principle we can deduce from it:
Using the same nat ID number on multiple global statements is an error, and won't work.
The next logical-looking config that doesn't work is this:
global (outside) 1 1.2.3.4
global (dmz) 2 4.5.6.7
nat (inside) 1 0.0.0.0 0.0.0.0 0 0
nat (inside) 2 5.0.0.0 255.0.0.0 0 0will NAT any 5.x.x.x address to 4.5.6.7 regardless of whether the traffic is going to the outside or the DMZ. Here are the not-quite documented principles we can deduce from it:
If traffic coming in from a given interface can match mutiple "nat" statements, it will match the most specific.
Traffic that matches a given "nat" statement will be rewritten to use the address in the matching global statement regardless of whether it's going to be routed out that interface or not. This is in accordance with the order of operations that dictates NAT is performed before routing is considered at all.
Thus, this:
global (outside) 1 1.2.3.4
global (dmz) 2 4.5.6.7
nat (inside) 1 5.0.0.0 255.0.0.0 0 0
nat (inside) 2 6.0.0.0 255.0.0.0 0 0will NAT any 5.x.x.x address to 1.2.3.4 and any 6.x.x.x to 4.5.6.7 regardless of whether the traffic is going to the outside or the DMZ, further confirming that principle.
This:
global (outside) 1 1.2.3.4
global (dmz) 2 4.5.6.7
nat (inside) 1 0.0.0.0 0.0.0.0 0 0
nat (inside) 2 0.0.0.0 0.0.0.0 0 0will ignore the first nat statement, and NAT any address to 4.5.6.7, from which we can deduce the following not-quite documented principle:
If traffic matches more than one "nat" statement with equal specificity, it will be considered to match the last one encountered. This is because NAT processing goes through the entire list looking for the best match -- it does not use the logic of "first hit and out."
No one on our team has figured out a good way to make it work.
We've got an ugly, ugly kludge. It only works for limited set of addresses (i.e. not 0.0.0.0/0 but the range(s) can be very broad). I'm not 100% sure why it even works at all. We first set up two globals and two nat's, like this:
global (outside) 1 1.2.3.4
global (dmz) 2 4.5.6.7
nat (inside) 1 0.0.0.0 0.0.0.0 0 0
nat (inside) 2 10.0.0.0 255.255.255.0 0 0
OK, we know what this will do. It will NAT a 10.0.0.0/24 address to 4.5.6.7 regardless of what interface it goes out. It will NAT any other address to 1.2.3.4
Now for the kludge. We drag in the "static" statement, which in theory has to do only with incoming traffic, and shouldn't effect outgoing traffic at all.
static (inside,dmz) 4.5.6.8 10.0.0.0 netmask 255.255.255.0 0 0
In theory this means "If traffic with a source address of 10.0.0/24 shows up on the dmz interface bound for 4.5.6.8 on the inside go ahead and create a 'translation' for it even though this traffic is moving from a lower to higher security interface. " This should have absolutely nothing to do with traffic originating on the inside bound for the DMZ. Note that 4.5.6.8 isn't even the address that's being used for the global.
In practice, though, this somehow works to NAT 10.0.0.0/24 to 4.5.6.7 on the DMZ and 1.2.3.4 on the outside.
There's not even a hint in the Cisco doc that this should change anything, but here's what I think is happening:
- The packet comes in and passes the ACL
- The PIX looks to see if the source's address+interface or the destination's address+interface matches either side of a static statement
- If it does, NAT is entirely processed by the "static" code according to one algorithm which understands how to apply the address found in the "global" in one way
- If it doesn't, it's processed by the "global" code according to a different algorithm which understands how to apply the address found in the "global" in a different way
At this point, you've set the source and destination addresses of your packet. Unless you're using a VPN, move on to "Outbound ACL's."
Routing, at least, is perfectly normal and starightforward, so long as you bear in mind that it's done AFTER a;l NAT'ing.
NAT of a packet is processed before the outbound ACL's are processed. Outbound ACL's must match the IP source and destination in the packet after it is rewriten by NAT.