FortiGate as a recursive DNS resolver
FortiOS supports being configured as a recursive DNS resolver. As a resolver, the FortiGate can directly interact with root name servers, Top-Level Domain (TLD) name servers, and finally authoritative name servers to resolve DNS queries. The FortiGate will iterate through these DNS servers to get the final IP address for the FQDN, as opposed to forwarding the request to external resolvers in forwarder mode for example. This can avoid hitting limitations from external resolvers which may limit the number of queries per second. Finally, clients can then use the FortiGate as their DNS server to perform DNS resolution.
To configure the recursive resolver mode in the CLI:
config system dns-server edit <DNS server name> set mode resolver next end
To configure recursive resolver mode in the GUI:
-
Go to Network > DNS Servers.
-
Under DNS Service on Interface, click Create New.
-
Select the Interface to listen to DNS queries.
-
Set the Mode to Resolver.
-
Click OK.
Furthermore, FortiOS also adds support for prioritizing root name servers. By default, a list of 13 public root name servers are known to the FortiGate. These DNS servers can be viewed with diagnose test application dnsproxy 19
.
Prioritized root name servers will be highlighted among the total list of root servers. Prioritized (highlighted) root servers will be queried in round robin fashion. Default (non-highlighted) root servers will only be queried if there are no prioritized root servers.
You may configure root servers from the list of 13 default servers, or you can configure your own custom root name server. Any custom root name servers you configure will be defined with an auto-generated name.
The root name servers can be prioritized and configured with the following:
config system dns set primary <class IP address> set root-servers <DNS root name server IP address> end
At most, two root-servers can be configured.
Example 1
In the following example, we will configure the FortiGate’s WAN interface (port3) in resolver mode and configure 1 DNS entry to return results for override.fortinet.com in the fortinet.com domain.
To configure the FortiGate as DNS resolver in the GUI:
-
Go to Network > DNS Servers.
-
Under DNS Service on Interface, click Create New.
-
For Interface, select WAN (port3).
-
For Mode, select Resolver.
-
Click OK.
-
Under DNS Database, click Create New and configure the following:
Type Primary View Shadow DNS Zone fortinet Domain Name fortinet.com Authoritative Disable -
Under DNS Entries, click Create New and configure the following:
Type Address (A) Hostname override IP Address 10.88.0.30 -
Click OK.
-
-
Click OK.
To configure the FortiGate as DNS resolver in the CLI:
config system dns-server edit "port3" set mode resolver next end config system dns-database edit "fortinet" set domain "fortinet.com" set authoritative disable config dns-entry edit 1 set hostname "override" set ip 10.88.0.30 next end next end
To verify:
-
On the FortiGate, enable dnsproxy debugs:
# diagnose debug application dnsproxy -1 # diagnose debug enable
-
From a client, use dig to issue a lookup for override.fortinet.com.
>dig @10.0.3.254 override.fortinet.com ; <<>> DiG 9.16.23 <<>> @10.0.3.254 override.fortinet.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53910 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;override.fortinet.com. IN A ;; ANSWER SECTION: override.fortinet.com. 86400 IN A 10.88.0.30 ;; Query time: 73 msec ;; SERVER: 10.0.3.254#53(10.0.3.254) ;; WHEN: Tue Jul 23 17:19:47 Pacific Daylight Time 2024 ;; MSG SIZE rcvd: 55
-
From the FortiGate debugs, observe the results are found locally.
FortiGate-VM64-KVM # [worker 0] batch_on_read()-3563 [worker 0] udp_receive_request()-3219: vfid=0, vrf=0, intf=5, len=62, alen=16, 10.0.3.2:51485=>10.0.3.254:53 [worker 0] handle_dns_request()-2497: vfid=0 real_vfid=0 id=0xd296 req_type=3 name=override.fortinet.com qtype=1 [worker 0] dns_nat64_ptr_lookup()-272 [worker 0] dns_nat64_update_request()-305 [worker 0] dns_local_lookup_common()-2578: vfid=0, real_vfid=0, view=2, qname=override.fortinet.com, qtype=1, qclass=1, offset=39, map#=3 max_sz=512 [worker 0] dns_lookup_aa_zone()-627: vfid=0, fqdn=override.fortinet.com [worker 0] dns_local_lookup_common()-2630: found zone=fortinet domain=fortinet.com [worker 0] dnsentry_search()-507: domain=fortinet.com, name=override.fortinet.com, type=1 [worker 0] dnsentry_lookup()-431: domain=fortinet.com, name=override.fortinet.com, type=1 [worker 0] dnsentry_lookup()-441: found entry=override.fortinet.com … [worker 0] dns_send_response()-1626: domain=override.fortinet.com reslen=55
-
From the client, use dig to issue a lookup for www.fortinet.com.
C:\Users\tsmith.FORTIAD>dig @10.0.3.254 www.fortinet.com ; <<>> DiG 9.16.23 <<>> @10.0.3.254 www.fortinet.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24497 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;www.fortinet.com. IN A ;; ANSWER SECTION: www.fortinet.com. 60 IN CNAME fortinet.96983.fortiwebcloud.net. fortinet.96983.fortiwebcloud.net. 60 IN CNAME ipv6.lb-2.us-west-1.aws.waas-online.net. ipv6.lb-2.us-west-1.aws.waas-online.net. 60 IN A 54.177.212.176 ;; Query time: 226 msec ;; SERVER: 10.0.3.254#53(10.0.3.254) ;; WHEN: Tue Jul 23 17:11:04 Pacific Daylight Time 2024 ;; MSG SIZE rcvd: 146
-
From the FortiGate debugs, observe the FortiGate makes the resolver query to each DNS name server directly to resolve the address.
FortiGate-VM64-KVM # [worker 0] dns_query_check_timeout()-623: jiffies=60824828 [worker 0] batch_on_read()-3563 [worker 0] udp_receive_request()-3219: vfid=0, vrf=0, intf=5, len=57, alen=16, 10.0.3.2:52979=>10.0.3.254:53 [worker 0] handle_dns_request()-2497: vfid=0 real_vfid=0 id=0x5fb1 req_type=3 name=www.fortinet.com qtype=1 [worker 0] dns_nat64_ptr_lookup()-272 [worker 0] dns_nat64_update_request()-305 [worker 0] dns_local_lookup_common()-2578: vfid=0, real_vfid=0, view=2, qname=www.fortinet.com, qtype=1, qclass=1, offset=34, map#=3 max_sz=512 [worker 0] dns_lookup_aa_zone()-627: vfid=0, fqdn=www.fortinet.com [worker 0] dns_local_lookup_common()-2630: found zone=fortinet domain=fortinet.com [worker 0] dnsentry_search()-507: domain=fortinet.com, name=www.fortinet.com, type=1 [worker 0] dnsentry_lookup()-431: domain=fortinet.com, name=www.fortinet.com, type=1 [worker 0] dnsentry_lookup()-431: domain=fortinet.com, name=www.fortinet.com, type=5 [worker 0] dns_send_resol_request()-1322: orig id: 0x5fb1 local id: 0x5fb1 domain=www.fortinet.com [worker 0] resolver_check_slist()-392: id=0x5fb1 domain=www.fortinet.com zone=fortinet.com ns=ns3.fortinet.com:208.91.113.63 … [worker 0] dns_send_resol_request()-1322: orig id: 0xa2d9 local id: 0xa2d9 domain=fortinet.96983.fortiwebcloud.net [worker 0] resolver_check_slist()-392: id=0xa2d9 domain=fortinet.96983.fortiwebcloud.net zone=fortiwebcloud.net ns=ns-111.awsdns-13. com:205.251.192.111 … [worker 0] dns_send_resol_request()-1322: orig id: 0x8850 local id: 0x8850 domain=ipv6.lb-2.us-west-1.aws.waas-online.net [worker 0] resolver_check_slist()-392: id=0x8850 domain=ipv6.lb-2.us-west-1.aws.waas-online.net zone=waas-online.net ns=ns-131.awsdn s-16.com:205.251.192.131 … [worker 0] __udp_receive_response()-3419: vd-0: len=210, addr=205.251.192.131:53, rating=0 [worker 0] dns_query_handle_response()-2762: vfid=0 real_vfid=0 vrf=0 id=0x8850 domain=ipv6.lb-2.us-west-1.aws.waas-online.net pktle n=210 … [worker 0] dns_send_response()-1626: domain=www.fortinet.com reslen=146
-
From the FortiGate, change the DNS server setting for WAN (port3) to recursive mode.
-
Restart the dnsproxy:
# diagnose test application dnsproxy 99
-
From the client, use dig to issue a lookup for www.fortinet.com again
-
From the FortiGate debugs, observe the FortiGate now forwards the query to a resolver instead of resolving the query itself.
FortiGate-VM64-KVM # [worker 0] batch_on_read()-3563 [worker 0] udp_receive_request()-3219: vfid=0, vrf=0, intf=5, len=57, alen=16, 10.0.3.2:64510=>10.0.3.254:53 [worker 0] handle_dns_request()-2497: vfid=0 real_vfid=0 id=0x1acc req_type=3 name=www.fortinet.com qtype=1 [worker 0] dns_nat64_ptr_lookup()-272 [worker 0] dns_nat64_update_request()-305 [worker 0] dns_local_lookup_common()-2578: vfid=0, real_vfid=0, view=2, qname=www.fortinet.com, qtype=1, qclass=1, offset=34, map#=3 max_sz=512 [worker 0] dns_lookup_aa_zone()-627: vfid=0, fqdn=www.fortinet.com [worker 0] dns_local_lookup_common()-2630: found zone=fortinet domain=fortinet.com [worker 0] dnsentry_search()-507: domain=fortinet.com, name=www.fortinet.com, type=1 [worker 0] dnsentry_lookup()-431: domain=fortinet.com, name=www.fortinet.com, type=1 [worker 0] dnsentry_lookup()-431: domain=fortinet.com, name=www.fortinet.com, type=5 [worker 0] dns_send_resol_request()-1322: orig id: 0x1acc local id: 0x1acc domain=www.fortinet.com [worker 0] dns_find_best_server()-653: found server: 208.91.112.52 (vfid=0 vrf=0) [worker 0] dns_udp_forward_request()-1064: vdom=root req_type=3 domain=www.fortinet.com oif=0 [worker 0] dns_udp_forward_request()-1185: Send 57B to [208.91.112.52]:53 via fd=18 request:1 [worker 0] batch_on_read()-3563 [worker 0] __udp_receive_response()-3419: vd-0: len=157, addr=208.91.112.52:53, rating=0 [worker 0] dns_query_handle_response()-2762: vfid=0 real_vfid=0 vrf=0 id=0x1acc domain=www.fortinet.com pktlen=157 [worker 0] dns_query_save_response()-2734: domain=www.fortinet.com pktlen=157 … [worker 0] dns_send_response()-1626: domain=www.fortinet.com reslen=157
Example 2
In the following example, the root name servers that should be prioritized will be defined, and the DNS server will be highlighted from the list root name servers.
To define the root name servers:
-
Define the root name servers to prioritize:
config system dns set primary 8.8.8.8 set root-servers "199.7.83.42" "192.33.4.12" end
-
Display the DNS server for the root name servers:
# diagnose test application dnsproxy 19 worker idx: 0 name=. label_count=0 ns_count=13 ns=a.root-servers.net A=198.41.0.4 use=1 ns=b.root-servers.net A=199.9.14.201 use=1 *ns=c.root-servers.net A=192.33.4.12 use=1 ns=d.root-servers.net A=199.7.91.13 use=1 ns=e.root-servers.net A=192.203.230.10 use=1 ns=f.root-servers.net A=192.5.5.241 use=1 ns=g.root-servers.net A=192.112.36.4 use=1 ns=h.root-servers.net A=198.97.190.53 use=1 ns=i.root-servers.net A=192.36.148.17 use=1 ns=j.root-servers.net A=192.58.128.30 use=1 ns=k.root-servers.net A=193.0.14.129 use=1 *ns=l.root-servers.net A=199.7.83.42 use=1 ns=m.root-servers.net A=202.12.27.33 use=1
Example 3
In the following example, the user configures a custom root server which will be added to the root zone cache. The name of the new user-defined root server will be auto-generated.
To configure a specific root name server:
-
Configure the user-defined root name server:
config system dns set primary 8.8.8.8 set root-servers "172.16.200.55" end
-
Display the DNS server for the user-defined root name server:
# diagnose test application dnsproxy 19 worker idx: 0 name=. label_count=0 ns_count=14 ns=a.root-servers.net A=198.41.0.4 use=1 ns=b.root-servers.net A=199.9.14.201 use=1 ns=c.root-servers.net A=192.33.4.12 use=1 ns=d.root-servers.net A=199.7.91.13 use=1 ns=e.root-servers.net A=192.203.230.10 use=1 ns=f.root-servers.net A=192.5.5.241 use=1 ns=g.root-servers.net A=192.112.36.4 use=1 ns=h.root-servers.net A=198.97.190.53 use=1 ns=i.root-servers.net A=192.36.148.17 use=1 ns=j.root-servers.net A=192.58.128.30 use=1 ns=k.root-servers.net A=193.0.14.129 use=1 ns=l.root-servers.net A=199.7.83.42 use=1 ns=m.root-servers.net A=202.12.27.33 use=1 *ns=a.user-root-servers.fgt A=172.16.200.55 use=1