FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
syordanov
Staff
Staff
Article Id 359770
Description This article describes how FortiGate performs SNAT when multiple IP pools are configured.
Scope FortiOS 5.x, 6.x, 7.x
Solution

FortiOS allows the configuration of multiple IP pools in a firewall rule. This is useful when two or more interfaces are configured as exit interfaces. By default, FortiOS will not choose the IP pool based on the exit interface. This will only happen when the IP pool has the parameter ' set associated-interface <portx>'.

 

Example:

 

config firewall ippool
       edit "IPpool_1"
           set startip 192.168.0.99
           set endip 192.168.0.99
           set associated-interface "wan1"
       next
          edit "IPpool_2"
          set startip 192.168.0.100
          set endip 192.168.0.100
          set associated-interface "wan2"
       next
end

 

The firewall rule looks like below:

 

config firewall policy
       edit 1
          set name "main_rule"
          set uuid acf88a98-0d3a-51ee-354f-82a9c50a0cf2
          set srcintf "lan"
          set dstintf "wan1" "wan2"
          set action accept
          set srcaddr "all"
          set dstaddr "all"
          set schedule "always"
          set service "ALL"
          set logtraffic all
          set nat enable
          set ippool enable
          set poolname "IPpool_1" "IPpool_2"
      next
end

 

In this case, FortiGate will perform SNAT using IPpool_1 when the exit interface is WAN1. When the exit interface is WAN2, FortiGate will perform SNAT using IPpool_2.

If the configuration parameter 'set associated interface <portx>' is not used, FortiOS will choose the IP pool based on the source IP address. This is purely determined by the source IP and not based on the exit interface.

 

Example configuration :

 

config firewall ippool
     edit "IPpool_1"
        set startip 192.168.0.99
        set endip 192.168.0.99
     next
     edit "IPpool_2"
        set startip 192.168.0.100
        set endip 192.168.0.100
     next
end


config firewall policy
     edit 1
        set name "main_rule"
        set uuid acf88a98-0d3a-51ee-354f-82a9c50a0cf2
        set srcintf "lan"
        set dstintf "wan1" "wan2"
        set action accept
        set srcaddr "all"
        set dstaddr "all"
        set schedule "always"
        set service "ALL"
        set logtraffic all
        set nat enable
        set ippool enable
        set poolname "IPpool_1" "IPpool_2"
     next
end

 

Interface 'wan1' is acting as a primary and 'wan2' is acting as a standby. In this case, FortiGate will use only 'wan1' as an outgoing interface. The network 192.168.1.0/24 is located behind the 'lan' interface.

The mapped IP address is calculated using the following formula:

 

Used_IP_Pool=decimal_value_IP |mod| usable_IP_Pool_addresses:

 

To convert the IP address to decimal, use the following formula:

 

192.168.1.122 = 192*(256)3 + 168*(256)2 + 1*(256) + 122 = 3232235898

192.168.1.119 = 192*(256)3 + 168*(256)2 + 1*(256) + 1119 = 3232235895

 

The range of IP addresses from the first IP pool is 1, and the range of IP addresses from the second IP pool is also 1 .

The IP pool used is calculated using the formula below:

 

Used_IP_Pool=decimal_value_IP |mod| usable_IP_Pool_addresses

 

For the first source IP, the formula looks like the following:

 

Used_IP_Pool=3232235898 |mod| 2 = 0

 

For the second source IP the formula looks like:

 

Used_IP_Pool=3232235895 |mod| 2 = 1

 

|mod| stands for mathematical operation modulus, also known as a mod operation. It calculates the remainder when one number is divided by another.

 

For the examples above result '0' means that FortiOS will choose the first IP pool named IPpool_1, '1' means that FortiOS will choose the second IP pool named  IPpool_2, because the IPpool position in FW starts from 0.  IPpool_1 has position '0' , IPpool_2 has position '1' . Based on the calculations with provided example ( 2 IP pools , every with one usable IP address) , always the result from calculation will be '1' or '0'.

 

Example of 2 sessions from the session list:

 

session info: proto=17 proto_state=01 duration=73 expire=106 timeout=0 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ helper=dns-udp vlan_cos=0/255
state=log may_dirty f00
statistic(bytes/packets/allow_err): org=75/1/1 reply=212/1/1 tuples=2
tx speed(Bps/kbps): 1/0 rx speed(Bps/kbps): 2/0
orgin->sink: org pre->post, reply pre->post dev=31->6/6->31 gwy=192.168.0.1/192.168.1.122
hook=post dir=org act=snat 192.168.1.122:51275->8.8.8.8:53(192.168.0.99:51275)  <- SNAT.
hook=pre dir=reply act=dnat 8.8.8.8:53->192.168.0.99:51275(192.168.1.122:51275)
misc=0 policy_id=1 pol_uuid_idx=695 auth_info=0 chk_client_info=0 vd=0
serial=006df7b8 tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=00000000 ngfwid=n/a
npu_state=0x040108
no_ofld_reason: non-npu-intf

 

 

session info: proto=17 proto_state=01 duration=137 expire=42 timeout=0 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255
state=log may_dirty f00
statistic(bytes/packets/allow_err): org=76/1/1 reply=76/1/1 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=31->6/6->31 gwy=192.168.0.1/192.168.1.119
hook=post dir=org act=snat 192.168.1.119:123->208.91.112.60:123(192.168.0.100:60540)  <- SNAT.
hook=pre dir=reply act=dnat 208.91.112.60:123->192.168.0.100:60540(192.168.1.119:123)
misc=0 policy_id=1 pol_uuid_idx=695 auth_info=0 chk_client_info=0 vd=0
serial=006df759 tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=00000000 ngfwid=n/a
npu_state=0x040108
no_ofld_reason: non-npu-intf