Configuring NAT in FortiOS
This article is a continuation of the introduction to Network Address Translation. Please see this link for the previous post.
FortiOS handles NAT in a way that traditionally different from other next generation firewall (NGFW) providers. In most cases, NGFWs maintain a separate NAT table and a separate access policy rule base. See the following example from the firewall vendor Checkpoint:


FortiOS default configuration is to combine both the NAT functions into the same rule as the access policies.

Due to this method, there is confusion when migrating to FortiOS from a different NGFW platform. To better understand the nuances associated with the default FortiOS method of applying NAT, I will illustrate some common use cases and configurations.
Source NAT (Overload)
FortiOS can translate the source IP address of a packet to either its outgoing interface IP address assigned to the firewall or to a dynamic IP pool object. Below is an example of an IPv4 Policy where the NAT policy dictates that the source IP address of matching traffic should be translated to the “Outgoing Interface Address” of the FortiGate.

config firewall policy
edit 1
set name "default outbound"
set srcintf "port2"
set dstintf "port1"
set srcaddr "n-internal"
set dstaddr "all"
set action accept
set schedule "always"
set service "ALL"
set fsso disable
set nat enable
next
end
However, if the FortiOS administrator wishes to use a different IP address than that which is assigned to the FortiGate outgoing interface, an IP Pool object can be leveraged to specify the IP address to use.

config firewall ippool
edit "ippool_external_50.50.1.100"
set startip 50.50.1.100
set endip 50.50.1.100
next
end
Please note: The “ARP Reply” setting will force the FortiGate to answer ARP requests for this IP address on any interface. Please make sure this is intended when assigning the IP address to the FortiGate.
After the creation of the IP Pool object, it can be referenced in the NAT section of the access rule.

config firewall policy
edit 1
set name "default outbound"
set srcintf "port2"
set dstintf "port1"
set srcaddr "n-internal"
set dstaddr "all"
set action accept
set schedule "always"
set service "ALL"
set ippool enable
set poolname "ippool_external_50.50.1.100"
set fsso disable
set nat enable
next
end
Source NAT (One-to-one)
In the case where you want to map multiple hosts to their own respective corresponding public IP Addresses, IP pools can be leveraged. As part of the IP Pool definition, there is an option to specify “one-to-one”.

config firewall ippool
edit "ippool_r-external_50.50.1.101-102"
set type one-to-one
set startip 50.50.1.101
set endip 50.50.1.102
next
end
It is important to note to create an address object that corresponds to the exact number of IP addresses defined in the IP Pool. This will allow for this function to operate in a predictable manner.

config firewall address
edit "r-internal"
set type iprange
set start-ip 10.4.93.20
set end-ip 10.4.93.21
next
end
Once this parameter has been configured, a corresponding IPv4 Access rule referencing this object can be created.

config firewall policy
edit 1
set name "default outbound"
set srcintf "port2"
set dstintf "port1"
set srcaddr "n-internal"
set dstaddr "all"
set action accept
set schedule "always"
set service "ALL"
set ippool enable
set poolname "ippool_r-external_50.50.1.101-102"
set fsso disable
set nat enable
next
end
Also, the FortiGate assigns the lowest source IP in the address object to the lowest IP address of the IP Pool and increments up from there. To illustrate this point, see the following example:
IP Pool Range: 50.50.1.101,50.50.1.102
Internal Hosts: 10.4.93.20, 10.4.93.21
IP address Mapping
Internal IP | IP Pool |
10.4.93.20 | 50.50.1.101 |
10.4.93.21 | 50.50.1.102 |

Destination NAT/Virtual IP (One-to-One)
FortiOS can translate the destination IP address of incoming packets to expose services and applications for hosts that are behind it. The most common method to accomplish this is via the Virtual IP method mapping an external IP address to an internal host behind the FortiGate.
As an example, suppose a webserver at IP address 10.9.43.20 is behind the FortiGate. To reach the webserver from the Internet, the FortiGate is configured with a Virtual IP to allow traffic sent to the IP address 50.50.1.103 to the internal webserver. The configuration to allow this would be as follows:

config firewall vip
edit "dnat_external_webserver"
set extip 50.50.1.103
set extintf "any"
set mappedip "10.4.93.20"
next
end
Once the Virtual IP has been configured, it is activated by using it within a firewall policy:

config firewall policy
edit 2
set name "Inbound WebServer Access"
set srcintf "port1"
set dstintf "port2"
set srcaddr "all"
set dstaddr "dnat_external_webserver"
set action accept
set schedule "always"
set service "HTTP" "HTTPS"
set fsso disable
next
end
By using the Virtual IP object within the firewall automatically activates the destination IP address translation. It is not required to enable “NAT” under the “Firewall / Network Options” section in most cases as that option is used to perform NAT on the source address. The common exception where you may want to enable “NAT” is when the host you are translating the IP address to does not have the FortiGate configured as its default gateway.
Destination NAT/Virtual IP (Port Forwarding)
FortiOS can examine the destination port of an incoming packet and based on that, perform a translation to a specific internal host behind the FortiGate. This is extremely useful from when there is a limited number of public facing IP addresses available to use but you want to expose multiple applications and services for different internal hosts.
As an example, suppose there are two internal webservers behind a FortiGate and the FortiGate only has one public address to use to expose their services. The FortiGate can be configured to allow port 50443 traffic to be redirected to 10.4.93.20 on port 443. Concurrently, it can allow port 51443 traffic to be redirected to 10.4.93.21 on port 443. A table of this example is as follows:
External IP | External Port | Internal IP | Internal Port |
50.50.1.104 | 50443 | 10.4.93.20 | 443 |
50.50.1.104 | 51443 | 10.4.93.20 | 443 |
The equivalent of this configuration in FortiOS is shown as follows:

config firewall vip
edit "dnat_webserver1"
set extip 50.50.1.104
set extintf "any"
set portforward enable
set mappedip "10.4.93.20"
set extport 50443
set mappedport 443
next
end
The configuration above creates a Virtual IP port forwarding object that takes traffic destined to 50.50.1.104 on port 50443 and translates it to the internal web server at 10.4.993.20. As 50443 is not typically a well-known server port for web servers, the FortiGate translates the port to 443 so that the web server listening on that port can receive the traffic destined to it on the port that the application binds to.

config firewall vip
edit "dnat_webserver2"
set extip 50.50.1.104
set extintf "any"
set portforward enable
set mappedip "10.4.93.21"
set extport 51443
set mappedport 443
next
end
Similar to the explanation above, the configuration above creates a Virtual IP port forwarding object that takes traffic destined to 50.50.1.104 on port 51443 and translates it to 10.4.93.21 on port 443.
Once the corresponding Virtual IP objects have been created, they can be added to a firewall rule as shown below:

config firewall policy
edit 3
set name "Inbound Web Port Forwarding"
set srcintf "port1"
set dstintf "port2"
set srcaddr "all"
set dstaddr "dnat_webserver1" "dnat_webserver2"
set action accept
set schedule "always"
set service "HTTPS"
set fsso disable
next
end
Please note that in the definition of the firewall rule, it is only required to specify the “service” to match the translated port. This is why only “HTTPS” (TCP/443) is being referenced in the firewall object.
This topic is core to the foundation of the FortiGate deployment as many networks still require NAT today. Hopefully this serves as a good primer for those who may have come from a different NGFW and need clarification on how to use NAT in FortiOS. Please let me know your thoughts in the comments below.
A really good explanation about Fortigate NAT, I appreciate your effort and time to make this post. It helped me a lot implementing this topic in real network, coming from a person who is implementing fortinet as its very first time.