Technical Tip: Understanding One-Arm URL Filtering on the FortiGate (AKA offline/parallel Web Filtering)
Description
This article describes the general configuration and function of One-Arm URL Filtering, where the FortiGate is positioned in-parallel to an existing inline router and can use web filtering to reroute and block traffic on behalf of the primary router that is already deployed and handling routing for the network.
Scope
FortiGate, Static URL Filtering.
Solution
As a primer, the following is a high-level overview of how the One-Arm URL Filtering mechanism works on the FortiGate:
- The FortiGate is configured with a series of Simple-type Static URL Filter entries within a special Web Filter profile that are configured with the Block action. Note that this mechanism only supports Simple entries (not Wildcard or Regex) that use the Block action only (Allow, Monitor, and Exempt will be ignored by this mechanism).
- For each entry with a Block action, the FortiGate will resolve the domain contained in the entry against the DNS servers specified under config webfilter ips-urlfilter-dns (up to 5 servers may be specified).
- For each domain that is successfully resolved, the resolved addresses are added to a local cache, and then each address will be injected into the routing table as a Static Route with a configurable Administrative Distance (default: 1) and a Priority of 254. These entries and routes are retained based on the original time-to-live (TTL) of the DNS entry, though it is also possible to override this and set a longer retention period.
- Once these static routes exist, the FortiGate can be configured to redistribute and advertise these routes to another router using a dynamic routing protocol like BGP. These routers will then re-route traffic towards the FortiGate, which can then block it via Web Filtering.
- As a side note, any traffic that matches the destination IP but is intended for a different URL can pass through the FortiGate and be routed back towards the main router. This would result in an asymmetric but otherwise functional flow (Client -> Router -> FortiGate -> Router -> Internet, then Internet -> Router -> Client), though it would require the Primary Router to use a policy-based route (PBR) to ensure that traffic is sent out to the Internet, rather than stuck in a routing loop between it and the FortiGate.
Overall, the primary point of this function is to enable administrators to add FortiGate Web Filtering functionality to existing networks without needing to redesign or replace the current network infrastructure. The following example topology summarizes the above concepts well:

Key Takeaways:
- Once One-Arm URL Filtering is configured, the FortiGate will start to resolve the domains/FQDNs on the block list even if the Web Filter profile is not applied to any Firewall Policies.
- End-client traffic will be routed to the Primary Router in all cases, but from there it is either diverted to the FortiGate (if the destination IP matches a route advertised from FortiGate to the router) or is forwarded through to the Internet like normal.
- Because this mechanism works based on destination IP and routing, it is possible for some end-client traffic to get redirected to the FortiGate if the destination IP is shared for multiple websites (for example, the address belongs to a CDN). It is therefore important that the FortiGate also has routes and Firewall Policies of its own to allow end-client traffic to be forwarded back to the primary router for Internet access if it is not blocked by Web Filtering. The FortiGate also must have functional access to resolve DNS, or this solution will not work.
Configuration Steps:
- In the FortiGate CLI, navigate to config system ips-urlfilter-dns and configure up to five DNS servers that the FortiGate should use to resolve the FQDNs extracted from the Static URL Filter table. Note that for VDOM-enabled FortiGates, this setting is done in the Global VDOM:
config system ips-urlfilter-dns
edit <dns_ip_address_1>
set status [ enable | disable ]
next
edit <dns_ip_address_2...5>
set status [ enable | disable ]
next
end
- Optionally, administrators can modify the DNS refresh interval used to re-query FQDNs as well as the amount of time that the FortiGate will keep the resolved IPs cached for (which together are useful in cases where IP addresses change frequently and DNS TTLs are very short). This setting is also configured in the Global VDOM (if relevant), and the default setting of 0 means that the FortiGate uses the TTL set on the DNS record itself:
config webfilter ips-urlfilter-cache-setting
set dns-retry-interval <0-2147483 seconds, default = 0>
set extended-ttl <0-2147483 seconds, default = 0>
end
- Next, navigate to config webfilter ips-urlfilter-setting to configure the outgoing interface, the next-hop gateway address, and the administrative distance that the FortiGate should use for the static routes generated by One-Arm URL Filter. This setting is configured on a per-VDOM basis, rather than globally.
Note: Set the gateway and device options to the next-hop gateway for the FortiGate (i.e., the Primary Router in the above diagram) and its associated outgoing interface so that the FortiGate uses these routes to send traffic back to the Primary Router. Later on, a route-map can be used to modify this next-hop IP address when advertising the route to the Primary Router.
config webfilter ips-urlfilter-setting
set device <interface>
set distance <1-255, default = 1>
set gateway <next_hop_ip_address>
end
- Finally, create or modify a Web Filter profile and enable Static URL Filtering. Then, in the CLI, navigate to the URL Filter table entry (which is in a separate section from the Web Filter profile itself) and enable one-arm-ips-urlfilter (also done on a per-VDOM basis).
To find the urlfilter table ID associated with the Web Filter profile, run show webfilter profile <wf_profile_name> | grep urlfilter-table.
config webfilter urlfilter
edit <id>
set one-arm-ips-urlfilter [ enable | disable ]
next
end
With the above configuration, any Simple entries with the Block action added to this Static URL Filter table will be resolved via DNS and then injected by the FortiGate as static routes in the routing table. These can be easily viewed via get router info routing-table static:
FortiGate (root) # get router info routing-table static
Routing table for VRF=0
S* 0.0.0.0/0 [1/0] via 172.17.97.3, wan1, [1/0]
S 10.44.0.0/24 [10/0] via 192.168.202.101, ISP_02, [10/0]
[10/0] via 192.168.201.101, ISP_01, [20/0]
S 10.251.0.1/32 [10/0] via testvpn tunnel 10.15.64.101, [1/0]
S 54.151.118.105/32 [1/0] via 172.17.97.3, wan1, [254/0]
S 54.177.212.176/32 [1/0] via 172.17.97.3, wan1, [254/0]
S 104.21.38.177/32 [1/0] via 172.17.97.3, wan1, [254/0]
S 172.67.137.28/32 [1/0] via 172.17.97.3, wan1, [254/0]
From here, configure BGP (or another dynamic routing protocol) to advertise routes from the FortiGate to the Primary Router, then enable static route redistribution to have the FortiGate advertise and withdraw these routes towards the Primary Router.
As noted in Step 3, it is recommended to use route-maps as part of route-redistribution to ensure that a) only the dynamically created static routes are redistributed into the routing protocol (as opposed to static default routes, management networks, etc.), and b) the next-hop address of the redistributed routes is changed to the FortiGate's address. The following is an example prefix-list/route-map/BGP combo to demonstrate the setup:
config router prefix-list
edit "defaultroute"
set comments "prefix representing default route"
config rule
edit 1
set prefix 0.0.0.0 0.0.0.0
unset ge
unset le
next
end
next
end
config router route-map
edit "filterroute"
config rule
edit 1
set action deny
set match-ip-address "defaultroute"
next
edit 2
next
end
next
edit "inject"
config rule
edit 1
set set-community "no-export"
set set-ip-nexthop <fortigate_interface_ip>
next
end
next
end
config router bgp
set as <local_as>
set router-id <fortigate_router_id>
config neighbor
edit <Primary_Router_IP>
set remote-as <remote_as>
set route-map-out "inject"
next
end
config redistribute "static"
set status enable
set route-map "filterroute"
end
end
Related articles:
Technical Tip: Using a static URL filter feature to allow/block web sites
Technical Tip: How to configure FortiGate to perform routing based on specific URLs
