Suppose we have a network using private IP addresses behind the firewall, and the network contains a server. We need to provide access to this server from the Internet in a such way that connections will be established to the address of the firewall. In this case we need destination address of packets to be rewritten so packets would reach the server on internal network. The simplest rule that translates destination address of incoming packets looks like the one on Figure 7.12, Rule 2.
Basically this rule says "if destination address of the packet matches the external address of the firewall, replace it with the address defined by the object server on dmz". If we had used the "firewall" object as the original destination, instead of the interface, then all external interfaces would be mapped to the DMZ server. Figure 7.26 (A) illustrates this. The red, green, and blue packets come to the firewall from different subnets and all have destination addresses that match address of the corresponding interface. If it were not for our NAT rule, packets like that would have been accepted by the firewall and sent to a process expecting them. However, the NAT rule comes to play and changes destination address of all three packets to 10.3.14.100 (the address of server). Packets with this address do not match any address belonging to the firewall and therefore get sent out of the firewall according to the rules of routing.
A rule that does not specify any service for the translation translates addresses in packets of all protocols. This approach can make some rules impractical because they will translate and bounce any packets that are headed for the firewall, making it impossible to connect to the firewall itself using telnet or any other protocol. This is especially inconvenient since, as we saw earlier, translation happens for packets coming from all directions; this means that you won't be able to connect to the firewall even from inside of your network. To alleviate this problem we just add an appropriate service object to the rule as shown in Figure 7.24:
Rule #0 in Figure 7.24 has limited scope because of the service object "http" in Original Service; it matches and performs address translation only for packets of HTTP protocol, while other packets are processed by TCP/IP stack on the firewall as usual. Very often we only want to translate address for packets coming from particular side of the firewall, typically from the Internet, and do not change other packets. Rule #0 on Figure 7.25 achieves this goal by using firewall's interface object in Original Destination. Only packets with destination address the same as that of interface eth1 of the firewall match this rule and get their address translated. Packets coming from other directions will have different destination address and won't match the rule (see Figure 7.26 (B) ).
Figure 7.26. Translations done to packets going in different directions: (A) when firewall object is used in ODst in the NAT rule and (B) when interface eth1 is used in ODst in the NAT rule
This section demonstrates examples of NAT rules that manipulate the destination address and ports of packets.
In cases where we have no public IP addresses to spare, we can still use NAT to permit access to the server. In this case, we will use address that belongs to the firewall's external interface. Here is a screenshot showing the firewall object, its interfaces, and an address object that belongs to the external interface:
We can either use an interface object or a corresponding address object in the rule. The following two examples of rules are equivalent:
Using an interface object:
Using an address object:
The external interface eth0 of the firewall has just one IP address; therefore, these two variants of the NAT rule are equivalent.
If the firewall has multiple public IP addresses, then you can add them as additional address objects to the external interface object and then use them in the NAT rules. All address objects attached to an interface are equivalent from a NAT rule standpoint.
Both NAT rules demonstrated in this example provide translation for the destination address of the packet so it can reach the server behind the firewall. We still need a policy rule to actually permit this kind of connection. This rule can be added to the global policy as follows:
You always need a combination of the NAT rule and a policy rule to do both address translation and then permit the translated packet.
Here is what Firewall Builder generates for iptables using these NAT and policy rules:
# Rule 0 (NAT) # $IPTABLES -t nat -A PREROUTING -p tcp -m tcp -m multiport -d 192.0.2.1 \ --dports 21,25 -j DNAT --to-destination 172.16.22.100 # Rule 0 (global) # $IPTABLES -A FORWARD -i + -p tcp -m tcp -m multiport -d 172.16.22.100 \ --dports 21,25 -m state --state NEW -j ACCEPT
For PF:
# Rule 0 (NAT) # # rdr on eth0 proto tcp from any to 192.0.2.1 port 21 -> 172.16.22.100 port 21 rdr on eth0 proto tcp from any to 192.0.2.1 port 25 -> 172.16.22.100 port 25 # Rule 0 (global) # # pass in quick inet proto tcp from any to 172.16.22.100 port { 21, 25 }
These are rather standard destination translation rules. Let's see what Firewall Builder generates for the same rules in the GUI when target firewall platform is set to "PIX":
class-map inspection_default match default-inspection-traffic policy-map global_policy class inspection_default inspect ftp inspect esmtp service-policy global_policy global clear config access-list clear config object-group clear config icmp clear config telnet clear config ssh object-group service outside.id13228X30286.srv.tcp.0 tcp port-object eq 21 port-object eq 25 exit ! Rule 0 (global) ! ! access-list outside_acl_in remark 0 (global) access-list outside_acl_in permit tcp any host 172.16.22.100 object-group outside.id13228X30286.srv.tcp.0 access-list inside_acl_in remark 0 (global) access-list inside_acl_in permit tcp any host 172.16.22.100 object-group outside.id13228X30286.srv.tcp.0 access-list dmz50_acl_in remark 0 (global) access-list dmz50_acl_in permit tcp any host 172.16.22.100 object-group outside.id13228X30286.srv.tcp.0 access-group dmz50_acl_in in interface dmz50 access-group inside_acl_in in interface inside access-group outside_acl_in in interface outside ! NAT compiler errors and warnings: ! clear xlate clear config static clear config global clear config nat ! ! Rule 0 (NAT) ! ! access-list id13242X30286.0 permit tcp host 172.16.22.100 eq 21 any static (inside,outside) tcp interface 21 access-list id13242X30286.0 tcp 0 0 access-list id13242X30286.1 permit tcp host 172.16.22.100 eq 25 any static (inside,outside) tcp interface 25 access-list id13242X30286.1 tcp 0 0
PIX configuration is considerably more complex. First, protocol inspectors have been activated to set up protocol support. TCP ports were arranged in an object group that is then used in all rules. Access lists were created and attached to all interfaces with "access-group" commands. Destination address translation in PIX configuration is done using "static" commands, which use small access lists to match packets that should be translated. All of this, however, was generated from exactly the same rules and objects in the GUI. All we did is change the firewall platform in the firewall object dialog and make sure network zones and security levels were configured properly. We did not have to configure two interfaces for each NAT rule for PIX: Firewall Builder automatically determined which interfaces it should use for the "static" command.
Suppose for some reason you do not want to add an address that should be used for NAT to an interface of the firewall. You can use any address object in the "Original Destination" even if this address object is not attached to the interface of the firewall. The problem with this is that the firewall must "own" public address used for NAT in order for it to answer ARP requests for this address from the upstream routers. If the firewall does not "own" the address and does not answer ARP requests, the router will not know where to send packets with this address in destination. To help you solve this problem, Firewall Builder can automatically add a virtual address to the firewall's interface when you use an address in a NAT rule. This is controlled by a checkbox Add virtual addresses for NAT in the "Script" tab of the firewall's platform "advanced" settings dialog. If this checkbox is turned on, and you use an address object that does not belong to any interface of the firewall, the program adds a code fragment to the generated script to create virtual address of the interface of the firewall to make sure NAT rule will work. If this is not the desired behavior, you can turn this automation off by unchecking this option.
If you use this feature, the NAT rules look exactly the same as shown above, except address objects are taken from the Objects/Addresses branch of the tree instead of the interfaces of the firewall. In case of iptables, generated script adds virtual addresses to the firewall with a label that starts with "FWB:" prefix. This helps the script identify and remove addresses it controls when you remove them in Firewall Builder GUI.
In all previous examples, the external interface of the firewall had a static IP address that was used in the destination address translation rules. But what if the address is dynamic and not known at the time when Firewall Builder processes rules? Let's see what happens.
Configuration of objects used in this example:
The only difference is that interface eth0 of the firewall is dynamic and has no IP address. In order to build NAT rules we use this interface in Original Destination (the rule looks exactly the same as rules in the previous examples):
Firewall Builder uses the method specific to the target firewall platform that allows it to use an interface a with dynamic address in policy and NAT rules. For example, the iptables script generated by Firewall Builder runs commands that retrieve the actual address of the interface and assign it to the shell variable. This variable is then used in iptables commands to build policy and NAT rules. OpenBSD PF permits using of interface name in rules, PIX has special syntax for "nat", "static" and "access-list" commands that also permit using interface in place of the address.
Here is generated iptables script:
getaddr() { dev=$1 name=$2 L=`$IP -4 addr show dev $dev | grep inet | grep -v :` test -z "$L" && { eval "$name=''" return } OIFS=$IFS IFS=" /" set $L eval "$name=$2" IFS=$OIFS } getaddr eth0 i_eth0 # Rule 0 (NAT) # test -n "$i_eth0" && $IPTABLES -t nat -A PREROUTING -d $i_eth0 \ -j DNAT --to-destination 172.16.22.100
It defines function getaddr() that retrieves IP address of a given interface and assigns it to a variable, in this example to i_eth0. The script checks if this variable has a non-empty value and uses it in -d clause of iptables command to match destination address of incoming packet. The generated script checks the value of this variable because, if some interface does not have any address at the moment when script is executed, it should not try to run an incorrect iptables command or, worse, install an iptables rule matching "any". Either way, the machine would end up with firewall configuration that would have a meaning different from what was intended.
In PF we can use the (en0) clause to make the firewall match address of an interface without having to retrieve the address manually:
# Rule 0 (NAT) # rdr on en0 proto {tcp udp icmp} from any to (en0) -> 172.16.22.100
The generated PIX configuration uses interface clause to match address of the interface:
! Rule 0 (NAT) ! access-list id29402X30286.0 permit ip host 172.16.22.100 any static (inside,outside) interface access-list id29402X30286.0 tcp 0 0
The rules shown in the examples above translated only the destination address of packets. Sometimes the server uses different ports as well, and the firewall should convert from the standard port numbers to the ones used by the host. For example, the web server might be running on port 8080, but we may want clients to access it using standard port 80. Here is how to do this.
First, we create a TCP service object that defines destination port 8080:
This service object does not have any source port specification. Only the destination port is defined. Now we can use it in the NAT rule as follows:
Firewall Builder generates the following iptables script for this rule:
# Rule 0 (NAT) # $IPTABLES -t nat -A PREROUTING -p tcp -m tcp -d 192.0.2.1 --dport 80 \ -j DNAT --to-destination 172.16.22.100:8080
It uses -j DNAT --to-destination <address>:<port> to translate both destination address and destination port.
Here is how this looks for PF:
# Rule 0 (NAT) # rdr on en0 proto tcp from any to 192.0.2.1 port 80 -> 172.16.22.100 port 8080
PIX rules look like this:
! Rule 0 (NAT) ! ! access-list id37125X30286.0 permit tcp host 172.16.22.100 eq 8080 any static (inside,outside) tcp interface 80 access-list id37125X30286.0 tcp 0 0
Copyright © 2000-2012 NetCitadel, Inc. All rights reserved.
Using free CSS Templates.