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.
Benoit_Rech_FTNT
Purpose
The purpose of this article is to expose a solution to use Policy Based Routing (PbR) on traffic managed by the web-proxy of the FortiGate.

When you enable explicit proxy of the FortiGate, the concerned traffic is "proxied" on the FortiGate. That is to say that the FortiGate works as a termination for the ingress traffic, and a source for the egress traffic.
From an IP point of view, the source IP address of the egress traffic is no more the host generating the request, but the IP address of the interface selected through the routing lookup. Moreover, the ingress interface is no more a physical interface, but the a virtual interface called "web-proxy".

As a consequence, it is not possible to apply policy based routing (PbR), because it is not possible to select the "web-proxy" interface.

A solution is to create a separate VDOM, containing the explicit proxy. This VDOM will handle the HTTP traffic, and route this traffic to the "root" VDOM.


Scope
This article is related to the explicit proxy running in the FortiGate.
Diagram
kb_explicit_pbr.png

Expectations, Requirements
Expectations :

- user group 2 HTTP traffic should use Fortigate explicit proxy. For this traffic, explicit proxy should use port2 to reach internet.
- user group 2 non-HTTP traffic goes directly to internet using port1
- user group 1 all traffic go through default route on port1


It is supposed that you have already setup a dual-wan configuration, with port1 as primary interface, and port2 as a "secondary" interface, that will be used to handle the HTTP traffic from the web-proxy.

The routing table should looks like:
FG300A-6 (root) # get router info routing all
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
       O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2
       i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
       * - candidate default
S*      0.0.0.0/0 [10/0] via 172.31.19.254, port1, [5/0]
                  [10/0] via 172.31.227.254, port2, [10/0]
C       10.10.0.0/30 is directly connected, INTERVDOM1
C       10.10.0.2/32 is directly connected, INTERVDOM1
C       10.10.10.0/24 is directly connected, port4
C       10.120.0.0/22 is directly connected, VLAN120
C       172.31.16.0/22 is directly connected, port1
C       172.31.224.0/22 is directly connected, port2

Configuration
Find there after the configuration steps to add an EXPLICIT proxy VDOM, and allow traffic going from this VDOM to port2.

1/ enable multi-vdom mode, and create the "EXPLICIT" VDOM. Move the VLAN121 interface to the EXPLICIT vdom.
config system global set vdom-admin enable

You need to login again at this step.

create vdom
edit EXPLICIT
end
config global config system interface edit "VLAN121" set vdom "EXPLICIT" end

2/ Create intervdom link (network in /30) and default route from "EXPLICIT" vdom to "root" vdom
config global
config system vdom-link
edit "INTERVDOM"
end
config system interface
edit "INTERVDOM0"
set vdom "EXPLICIT"
set ip 10.10.0.1 255.255.255.252
end
config system interface
edit "INTERVDOM1"
set ip 10.10.0.2 255.255.255.252
end
end
config vdom
edit EXPLICIT config router static edit 0 set device "INTERVDOM0" set gateway 10.10.0.2 end

Intermediate Verification
config vdom
edit EXPLICIT

FG300A-6 (EXPLICIT) # get router info routing all
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2,
ia - IS-IS inter area * - candidate default
S* 0.0.0.0/0 [10/0] via 10.10.0.2, INTERVDOM0
C 10.10.0.0/30 is directly connected, INTERVDOM0
C 10.10.0.1/32 is directly connected, INTERVDOM0

C 10.121.0.0/22 is directly connected, VLAN121

3/ Enable the explicit proxy on the VLAN121 interface, and enable explicit proxy in VDOM "EXPLICIT"
config global
config system interface
edit "VLAN121"
set explicit-web-proxy enable
end
config vdom
edit EXPLICIT
config web-proxy explicit
set status enable
end

4/ Create a firewall object that is associate to the user group2. This user should use the explicit proxy, and their traffic should go through port2.
config vdom
edit EXPLICIT
config firewall address
edit "USER_GROUP2"
set associated-interface "VLAN121"
set subnet 10.121.0.0 255.255.252.0
end

5/ Create a firewall policy to allow DNS requests, ICMP_ANY
config vdom
edit EXPLICIT
config firewall policy
edit 0
set srcintf "VLAN121"
set dstintf "INTERVDOM0"
set srcaddr "USER_GROUP2"
set dstaddr "all"
set action accept
set schedule "always"
set service "DNS" "ICMP_ANY"
set nat enable
end

6/ Create a firewall policy for the HTTP traffic, which is proxied. You can add log, UTM on the policy, if needed
config vdom
edit EXPLICIT
config firewall policy
edit 0
set srcintf "web-proxy"
set dstintf "INTERVDOM0"
set srcaddr "all"
set dstaddr "all"
set action accept
set schedule "always"
set service "webproxy"
end

At this step, we are done with the EXPLICIT vdom, we now need to add some policies on the root VDOM to allow ICMP, DNS, and HTTP traffic, as well as the PbR.

7/ Create firewall object representing the EXPLICIT VDOM address (NAT or proxy). Even it is not possible to enable NAT on the firewall associated policy, remember that the explicit proxy will use the IP address associated to the route lookup, so in our case 10.10.0.1/32 (the same address as if traffic was NATed)
config vdom
edit root
FG300A-6 (global) # 0: config firewall address
edit "EXPLICIT_VDOM"
set associated-interface "INTERVDOM1"
set subnet 10.10.0.1 255.255.255.255
end

8/ create firewall policy for DNS and ICMP traffic through port1 (the default route).
config firewall policy
edit 0
set srcintf "INTERVDOM1"
set dstintf "port1"
set srcaddr "EXPLICIT_VDOM"
set dstaddr "all"
set action accept
set schedule "always"
set service "DNS" "ICMP_ANY"
set nat enable
end

Intermediate Verification:
At this step you can check that DNS lookup and ping works correctly. All the traffic should go through port1.

on a host from "user group1", make a ping with no DNS request

ping 8.8.8.8

config vdom
edit root
diag sniffer packet any 'icmp' 4 0 a
2012-10-03 12:52:54.731248 VLAN121 in 10.121.2.12 -> 8.8.8.8: icmp: echo request
2012-10-03 12:52:54.731248 INTERVDOM1 in 10.10.0.1 -> 8.8.8.8: icmp: echo request
2012-10-03 12:52:54.731284 port1 out 172.31.16.144 -> 8.8.8.8: icmp: echo request
2012-10-03 12:52:54.764134 port1 in 8.8.8.8 -> 172.31.16.144: icmp: echo reply
2012-10-03 12:52:54.764134 INTERVDOM0 in 8.8.8.8 -> 10.10.0.1: icmp: echo reply
2012-10-03 12:52:54.764158 VLAN121 out 8.8.8.8 -> 10.121.2.12: icmp: echo reply
2012-10-03 12:52:54.764161 port6 out 8.8.8.8 -> 10.121.2.12: icmp: echo reply

On the same hosts, perform a ping with a DNS resolution.
ping www.google.com
config vdom
edit root
diag sniffer packet any 'icmp' 4 0 a
2012-10-03 12:53:45.451261 VLAN121 in 10.121.2.12 -> 74.125.132.106: icmp: echo request
2012-10-03 12:53:45.451261 INTERVDOM1 in 10.10.0.1 -> 74.125.132.106: icmp: echo request
2012-10-03 12:53:45.451361 port1 out 172.31.16.144 -> 74.125.132.106: icmp: echo request
2012-10-03 12:53:45.483006 port1 in 74.125.132.106 -> 172.31.16.144: icmp: echo reply
2012-10-03 12:53:45.483006 INTERVDOM0 in 74.125.132.106 -> 10.10.0.1: icmp: echo reply
2012-10-03 12:53:45.483070 VLAN121 out 74.125.132.106 -> 10.121.2.12: icmp: echo reply
2012-10-03 12:53:45.483075 port6 out 74.125.132.106 -> 10.121.2.12: icmp: echo reply

But HTTP traffic should be blocked (no firewall policy matching in root VDOM)


9/ Create a firewall policy in the root VDOM for traffic going from INTERVDOM link to port2
config vdom
edit root
edit 0
set srcintf "INTERVDOM1"
set dstintf "port2"
set srcaddr "EXPLICIT_VDOM"
set dstaddr "all"
set action accept
set schedule "always"
set service "HTTP"
set nat enable
end

10/ Create the policy route in VDOM root, to catch HTTP traffic and redirect it to port2 instead of port1

config vdom
edit root
config router policy
edit 0
set input-device "INTERVDOM1"
set src 10.10.0.1 255.255.255.255
set protocol 6
set start-port 80
set end-port 80
set gateway 172.31.227.254
set output-device "port2"
end



Verification
As the explicit proxy of the FortiGate listen on port 8080, you need to capture the debug on port 8080 (ingress traffic), and port 80 (egress traffic). Check that the traffic is going through port2, and not port1.

config vdom
edit root
diag sniffer packet any 'port 8080 or port 80' 4 0 a
2012-10-03 13:01:11.324335 VLAN121 in 10.121.2.12.49245 -> 10.121.0.144.8080: psh 1496000172 ack 1219578005
2012-10-03 13:01:11.324389 VLAN121 out 10.121.0.144.8080 -> 10.121.2.12.49245: ack 1496000931
2012-10-03 13:01:11.324396 port6 out 10.121.0.144.8080 -> 10.121.2.12.49245: ack 1496000931
2012-10-03 13:01:11.324568 INTERVDOM1 in 10.10.0.1.1081 -> 74.125.132.94.80: psh 4213665554 ack 324854760
2012-10-03 13:01:11.324595 port2 out 172.31.224.144.63681 -> 74.125.132.94.80: psh 4213665554 ack 324854760
2012-10-03 13:01:11.400337 port2 in 74.125.132.94.80 -> 172.31.224.144.63681: 324854760 ack 4213666287
2012-10-03 13:01:11.400337 INTERVDOM0 in 74.125.132.94.80 -> 10.10.0.1.1081: 324854760 ack 4213666287
2012-10-03 13:01:11.400400 INTERVDOM1 in 10.10.0.1.1081 -> 74.125.132.94.80: ack 324856178
2012-10-03 13:01:11.400411 port2 out 172.31.224.144.63681 -> 74.125.132.94.80: ack 324856178
2012-10-03 13:01:11.400549 VLAN121 out 10.121.0.144.8080 -> 10.121.2.12.49245: psh 1219578005 ack 1496000931
2012-10-03 13:01:11.400558 port6 out 10.121.0.144.8080 -> 10.121.2.12.49245: psh 1219578005 ack 1496000931


Troubleshooting
To troubleshoot this issue you can use the well-known commands:
  • diag sniffer packet
  • diag debug flow

diag sniffer packet should be used on 'any' interface, with the appropriate filter. You need to select ingress port (in general 8080), as well as egress port (in general 80). If you have the IP address of the destination, you should also include this address to limit the amount of logs displayed. The "diag sniffer packet" should be run on the "root" vdom.

diag debug flow should be used to ensure that the traffic is accepted in VDOM explicit, and is directed to the inter-vdom link. Then, the "diag debug flow" should show that the traffic is accepted on the "root" vdom, and is going through the port2.

in this example, a host from "user group 2" browses http://www.fortinet.com

config vdom
edit EXPLICIT
diag debug flow show console enable
diag debug flow filter addr 66.171.121.34
diag debug flow trace start 100
diag debug enable
FG300A-6 (EXPLICIT) # id=36871 trace_id=1 msg="vd-EXPLICIT received a packet(proto=6, 10.10.0.1:1093->66.171.121.34:80) from local."
id=36871 trace_id=1 msg="allocate a new session-00000ad1"
id=36871 trace_id=2 msg="vd-root received a packet(proto=6, 10.10.0.1:1093->66.171.121.34:80) from INTERVDOM1."
id=36871 trace_id=2 msg="allocate a new session-00000ad2"
id=36871 trace_id=2 msg="Match policy routing: to 172.31.227.254 via ifindex-3"
id=36871 trace_id=2 msg="find a route: gw-172.31.227.254 via port2"
id=36871 trace_id=2 msg="find SNAT: IP-172.31.224.144, port-63677"
id=36871 trace_id=2 msg="Allowed by Policy-2: SNAT"
id=36871 trace_id=2 msg="SNAT 10.10.0.1->172.31.224.144:63677"
id=36871 trace_id=3 msg="vd-root received a packet(proto=6, 66.171.121.34:80->172.31.224.144:63677) from port2."
id=36871 trace_id=3 msg="Find an existing session, id-00000ad2, reply direction"
id=36871 trace_id=3 msg="DNAT 172.31.224.144:63677->10.10.0.1:1093"
id=36871 trace_id=3 msg="find a route: gw-10.10.0.1 via INTERVDOM1"
id=36871 trace_id=4 msg="vd-EXPLICIT received a packet(proto=6, 66.171.121.34:80->10.10.0.1:1093) from INTERVDOM0."
id=36871 trace_id=4 msg="Find an existing session, id-00000ad1, reply direction"
id=36871 trace_id=5 msg="vd-EXPLICIT received a packet(proto=6, 10.10.0.1:1093->66.171.121.34:80) from local."
id=36871 trace_id=5 msg="Find an existing session, id-00000ad1, original direction"
id=36871 trace_id=6 msg="vd-root received a packet(proto=6, 10.10.0.1:1093->66.171.121.34:80) from INTERVDOM1."
id=36871 trace_id=6 msg="Find an existing session, id-00000ad2, original direction"
id=36871 trace_id=6 msg="enter fast path"
id=36871 trace_id=6 msg="SNAT 10.10.0.1->172.31.224.144:63677"

Internal Notes


Contributors