Fortigate as DNS authoritative server with DNS database


Configuration

  • Make sure DNS Database is enabled in Feature Visibility for configuring it in GUI, or config sys settingset gui-dns-database enable

  • A must-to-specify settings: domain name

  • Supported DNS records:

    • A

    • NS

    • CNAME

    • MX

    • AAAA

    • PTR

    • PTR_V6

  • For type secondary, if also set authoritative enable, Fortigate will NOT forward queries for records it does not have, even if the forwarder is also set. E.g. in Windows environment, Fortigate does not support SRV records, so for them to work (Split DNS), we have to set set authoritative disable or Fortigate will drop queries for SRV records.

  • When Fortigate is a Master/Authoritative zone holder, we can specify up to 12 Slave DNS servers to allow zone transfer from this Fortigate. You do so within config sys dns-databaseedit yurisk.com-zoneset allow-transfer "192.168.13.82" "8.8.8.8"

  • Frequent case is when Fortigate is a Slave of Active Directory DNS and the records will not update, even so AD DNS saved the change. Windows DNS sends Notify to the configured Slave servers, but this message tells Fortigate to go and check if there were any changes to the domain. And Fortigate looks first at SOA on the Master and compares with the stored one - if they don’t differ, Fortigate will not pull the changed zone file. You would need to remember to always increase SOA on the Windows AD DNS every time you change the zone file.

Note
Fortigate supports DNS over TLS (DOT) and DNS over HTTPS (DOH) protocols for both - querying external servers as a client, and answering queries as a DNS server. To test/debug those protocols on the client side, use kdig utility, e.g. kdig A +tls google.com @8.8.8.8, kdig can be found on https://www.knot-dns.cz/docs/2.4/html/installation.html. Install on Ubuntu as apt install knot-dnsutils.

Example full config (nse8.com is a Slave, yurisk.com Master):

config system dns-database
    edit "nse8-zone" // name can be anything, up to 35 chars
        set domain "nse8.com" // Domain has to be exact
        set type secondary    // Slave zonefile
        set view shadow    // Answer only to internal clients
        set authoritative disable // disable, see above for why
        set forwarder "192.168.13.82"  // DC as resolver for unknown
domains/records
        set source-ip 0.0.0.0         // Not needed here, but for e.g. VPN
site-to-site may be needed to be set to IP that is inside encryption domain
        set ip-primary 192.168.13.82  // AD DC as master DNS holding nse8.com
    next

    edit "yurisk.com-zone"
        set domain "yurisk.com" //Becomes authoritative by default
        set type primary
        set view shadow
        set ttl 86400           // Default TTL for all records
        set authoritative enable
        unset forwarder
        set source-ip 0.0.0.0
        config dns-entry
            edit 1
                set hostname "bla"
                set ip 192.12.12.12
            next
        end
        set allow-transfer "192.168.13.82" "8.8.8.8"
    next
end

And now, enable DNS service on port2 connected to the LAN:

config system dns-server
    edit "port2"
        set mode recursive      // Default
        set dnsfilter-profile '' // Default
        set doh disable         // Default

Debug and diagnostics

There are quite a few commands available, all gathered under dia test app dnsproxy:

# diagnose test app dnsproxy
worker idx: 0
1. Clear DNS cache
2. Show stats
3. Dump DNS setting
4. Reload FQDN
5. Requery FQDN
6. Dump FQDN
7. Dump DNS cache
8. Dump DNS DB
9. Reload DNS DB
10. Dump secure DNS policy/profile
11. Dump Botnet domain
12. Reload Secure DNS setting
13. Show Hostname cache
14. Clear Hostname cache
15. Show SDNS rating cache
16. Clear SDNS rating cache
17. DNS debug bit mask
18. DNS debug obj mem
99. Restart dnsproxy worker

Below is the output of some of them.

diag test application dnsproxy 8

Before enabling DNS on client-facing interface:

worker idx: 0

After enabling, the cached resolvings:

worker idx: 0
vfid=0 name=nse8-zone domain=nse8.com ttl=86400 authoritative=1 view=shadow
type=secondary serial=1588 refresh=900
forwarder:
192.168.13.82 secure=0
      A: ForestDnsZones.nse8.com-->192.168.13.82(600)
     NS: _msdcs.nse8.com-->win-o4nhhlcjg1c.nse8.com(3600)
      A: WIN10AD.nse8.com-->10.10.17.128(1200)
      A: win2016-gui-dc.nse8.com-->192.168.13.82(3600)
      A: win-o4nhhlcjg1c.nse8.com-->10.10.10.130(3600)
      A: win-o4nhhlcjg1c.nse8.com-->192.168.13.133(3600)
      A: DomainDnsZones.nse8.com-->192.168.13.82(600)
    SOA: nse8.com (primary: win2016-gui-dc.nse8.com, contact:
hostmaster@nse8.com, serial: 1588)(3600)
      A: nse8.com-->192.168.13.82(600)
     NS: nse8.com-->win2016-gui-dc.nse8.com(3600)

diag test application dnsproxy 3

Ongoing DNS connections:

worker idx: 0
VDOM: root, index=0, is primary, vdom dns is enabled, pip-0.0.0.0 dns_log=1
dns64 is disabled
DNS servers:
8.8.8.8:53 vrf=0 tz=0 encrypt=none req=47 to=0 res=47 rt=3 ready=1 timer=0
probe=0 failure=0 last_failed=0
194.90.0.1:53 vrf=0 tz=0 encrypt=none req=57 to=0 res=57 rt=1 ready=1 timer=0
probe=0 failure=0 last_failed=0
96.45.45.45:53 vrf=0 tz=0 encrypt=none req=45 to=2 res=45 rt=5 ready=1 timer=0
probe=0 failure=0 last_failed=0
96.45.46.46:53 vrf=0 tz=0 encrypt=none req=43 to=4 res=43 rt=5 ready=1 timer=0
probe=0 failure=0 last_failed=0
SDNS servers:
208.91.112.220:53 vrf=0 tz=0 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2331 probe=11 failure=0 last_failed=0
65.0.232.185:53 vrf=0 tz=300 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
83.231.212.53:53 vrf=0 tz=60 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
173.243.138.221:53 vrf=0 tz=-480 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
194.69.172.53:53 vrf=0 tz=0 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
208.184.237.71:53 vrf=0 tz=-480 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
154.52.12.53:53 vrf=0 tz=480 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
154.52.24.53:53 vrf=0 tz=600 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
154.52.26.53:53 vrf=0 tz=-300 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
149.5.232.53:53 vrf=0 tz=60 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
140.174.22.53:53 vrf=0 tz=-300 encrypt=none req=0 to=0 res=0 rt=1494 ready=0
timer=2341 probe=11 failure=0 last_failed=0
ALT servers:
Interface selecting method: auto
Specified interface:
FortiGuard interface selecting method: auto
FortiGuard specified interface:

vfid=0, interface=port2, ifindex=4, lb=0, recursive,
DNS_CACHE: hash-size=2048, ttl=1800, min-ttl=60, max-num=5000
DNS FD: udp_s=8 udp_c=18:19 ha_c=23 unix_s=9, unix_nb_s=24, unix_nc_s=10
        v6_udp_s=7, v6_udp_c=21:22, snmp=25, redir=14, v6_redir=15
DNS FD: tcp_s=11, tcp_s6=12, redir=27 v6_redir=28
DNS UNIX FD: dnsproxy_un=29
FGD_DNS_SERVICE_LICENSE:
server=208.91.112.220:53, expiry=0000-00-00, expired=1, type=0
server=65.0.232.185:53, expiry=0000-00-00, expired=1, type=0
server=83.231.212.53:53, expiry=0000-00-00, expired=1, type=0
server=173.243.138.221:53, expiry=0000-00-00, expired=1, type=0
server=194.69.172.53:53, expiry=0000-00-00, expired=1, type=0
server=208.184.237.71:53, expiry=0000-00-00, expired=1, type=0
server=154.52.12.53:53, expiry=0000-00-00, expired=1, type=0
server=154.52.24.53:53, expiry=0000-00-00, expired=1, type=0
server=154.52.26.53:53, expiry=0000-00-00, expired=1, type=0
server=149.5.232.53:53, expiry=0000-00-00, expired=1, type=0
server=140.174.22.53:53, expiry=0000-00-00, expired=1, type=0
FGD_CATEGORY_VERSION:9
SERVER_LDB: gid=0af2, tz=-420, error_allow=0
FGD_REDIR_V4:208.91.112.55 FGD_REDIR_V6:[2620:101:9000:53::55]

diagnose test app dnsproxy 2

See latency to the used DNS servers outside:

worker idx: 0
worker: count=1 idx=0
retry_interval=500 query_timeout=1495
DNS latency info:
vfid=0 server=96.45.45.45 latency=5 updated=3162
vfid=0 server=8.8.8.8 latency=6 updated=2404
vfid=0 server=194.90.0.1 latency=1 updated=4789
vfid=0 server=96.45.46.46 latency=5 updated=7197
SDNS latency info:
vfid=0 server=65.0.232.185 latency=-1 updated=26943
vfid=0 server=208.184.237.71 latency=-1 updated=26938
vfid=0 server=194.69.172.53 latency=-1 updated=26951
vfid=0 server=140.174.22.53 latency=-1 updated=26945
vfid=0 server=149.5.232.53 latency=-1 updated=26951
vfid=0 server=83.231.212.53 latency=-1 updated=26953
vfid=0 server=154.52.12.53 latency=-1 updated=26937
vfid=0 server=154.52.24.53 latency=-1 updated=26927
vfid=0 server=154.52.26.53 latency=-1 updated=26944
vfid=0 server=173.243.138.221 latency=-1 updated=26938
DNS_CACHE: alloc=19, hit=18
RATING_CACHE: alloc=0, hit=0
DNS query: alloc=0
DNS UDP: req=228 res=213 fwd=207 cmp=13 retrans=12 to=40
         cur=6 switched=273106 num_switched=2
         v6_cur=0 v6_switched=0 num_v6_switched=0
DNS FTGD: ftg_fwd=0, ftg_res=0, ftg_retrans=0
DNS TCP: req=0, res=0, fwd=0, retrans=0, to=0

DNS TCP connections:

DNS UNIX streams: cfd=33
FQDN: alloc=6 nl_write_cnt=126 nl_send_cnt=137 nl_cur_cnt=0
Botnet: searched=0 hit=0

diagnose test app dnsproxy 7

Shows resolved FQDN objects:

worker idx: 0
vfid=0, name=gmail.com, ttl=10:0:1787
         172.217.16.197 (ttl=290)
vfid=0, name=login.microsoftonline.com, ttl=186:125:1739
         40.126.32.137 (ttl=186) 40.126.32.132 (ttl=186) 20.190.160.13 (ttl=186)
40.126.32.75 (ttl=186) 20.190.160.15 (ttl=186)
         40.126.32.69 (ttl=186) 20.190.160.23 (ttl=186) 40.126.32.139 (ttl=186)
vfid=0, name=login.microsoft.com, ttl=227:87:1660
         40.126.32.69 (ttl=233) 40.126.32.75 (ttl=233) 20.190.160.23 (ttl=233)
40.126.32.67 (ttl=233) 20.190.160.12 (ttl=233)
         20.190.160.15 (ttl=233) 20.190.160.13 (ttl=233) 40.126.32.137 (ttl=233)
vfid=0, name=login.windows.net, ttl=10:0:1636
         40.126.31.73 (ttl=192) 40.126.31.71 (ttl=192) 20.190.159.68 (ttl=192)
40.126.31.69 (ttl=192) 40.126.31.67 (ttl=192)
         20.190.159.4 (ttl=192) 20.190.159.64 (ttl=192) 20.190.159.2 (ttl=192)
vfid=0, name=skydrive.wns.windows.com, ttl=10:0:1578
         40.113.103.199 (ttl=259)
vfid=0, name=directregistration.fortinet.com, ttl=402:161:1559
         63.137.229.3 (ttl=402)
vfid=0, name=cs.dds.microsoft.com, ttl=286:19:1533
         52.152.90.172 (ttl=286)
vfid=0, name=forticlient.fortinet.net, ttl=10:0:1448
         208.184.237.75 (ttl=0) 173.243.138.98 (ttl=0)
vfid=0, name=ping-edge.smartscreen.microsoft.com, ttl=10:0:1266
         20.86.249.62 (ttl=8)
vfid=0, name=cnn.com, ttl=10:0:1104
         2a04:4e42:600::773 (ttl=131) 2a04:4e42:c00::773 (ttl=131)
2a04:4e42:400::773 (ttl=131) 2a04:4e42:200::773 (ttl=131) 2a04:4e42:800::773
(ttl=131)
         2a04:4e42:e00::773 (ttl=131) 2a04:4e42::773 (ttl=131)
2a04:4e42:a00::773 (ttl=131)
vfid=0, name=cnn.com, ttl=10:0:1104
         151.101.3.5 (ttl=60) 151.101.131.5 (ttl=60) 151.101.67.5 (ttl=60)
151.101.195.5 (ttl=60)
vfid=0, name=google.com, ttl=10:0:1078
         142.250.184.238 (ttl=204)
vfid=0, name=mtalk.google.com, ttl=10:0:1075
         173.194.76.188 (ttl=280)
vfid=0, name=mus.cisco.com, ttl=289:0:1059
         72.163.1.80 (ttl=289)
vfid=0, name=self.events.data.microsoft.com, ttl=10:0:1033
         20.44.10.122 (ttl=6)
vfid=0, name=identity.getvideostream.com, ttl=101:0:1030
         172.67.202.21 (ttl=101) 104.21.76.235 (ttl=101)
vfid=0, name=au.download.windowsupdate.com, ttl=174:0:1030
         93.184.221.240 (ttl=2762)
vfid=0, name=ntp2.fortiguard.com, ttl=41245:40473:1028
         208.91.112.60 (ttl=41743) 208.91.112.62 (ttl=41743)
vfid=0, name=ntp1.fortiguard.com, ttl=41245:40473:1028
         208.91.112.61 (ttl=42508) 208.91.112.63 (ttl=42508)
CACHE num=19

diagnose test app dnsproxy 6

worker idx: 0
vfid=0 name=login.windows.net ver=IPv4 wait_list=0 timer=6 min_refresh=60
min_ttl=1 cache_ttl=0 slot=-1 num=16 wildcard=0
         40.126.31.73 (ttl=192:0:0) 40.126.31.71 (ttl=192:0:0) 20.190.159.68
(ttl=192:0:0) 40.126.31.69 (ttl=192:0:0) 40.126.31.67 (ttl=192:0:0)
         20.190.159.4 (ttl=192:0:0) 20.190.159.64 (ttl=192:0:0) 20.190.159.2
(ttl=192:0:0) 20.190.160.13 (ttl=1:0:0) 20.190.160.21 (ttl=1:0:0) 40.126.32.73
(ttl=1:0:0)
         40.126.32.137 (ttl=1:0:0) 40.126.32.135 (ttl=1:0:0) 40.126.32.132
(ttl=1:0:0) 20.190.160.12 (ttl=1:0:0) 40.126.32.69 (ttl=1:0:0)
vfid=0 name=login.microsoft.com ver=IPv4 wait_list=0 timer=10 min_refresh=60
min_ttl=227 cache_ttl=0 slot=-1 num=8 wildcard=0
         40.126.32.69 (ttl=233:22:22) 40.126.32.75 (ttl=233:22:22) 20.190.160.23
(ttl=233:22:22) 40.126.32.67 (ttl=233:22:22) 20.190.160.12 (ttl=233:22:22)
         20.190.160.15 (ttl=233:22:22) 20.190.160.13 (ttl=233:22:22)
40.126.32.137 (ttl=233:22:22)
vfid=0 name=login.microsoftonline.com ver=IPv4 wait_list=0 timer=48
min_refresh=60 min_ttl=186 cache_ttl=0 slot=-1 num=16 wildcard=0
         20.190.159.70 (ttl=300:113:113) 40.126.31.64 (ttl=300:113:113)
20.190.159.72 (ttl=300:113:113) 20.190.159.1 (ttl=300:113:113) 20.190.159.74
(ttl=300:113:113)
         20.190.159.69 (ttl=300:113:113) 40.126.31.70 (ttl=300:113:113)
40.126.31.72 (ttl=300:113:113) 40.126.32.137 (ttl=186:54:54) 40.126.32.132
(ttl=186:54:54) 20.190.160.13 (ttl=186:54:54)
         40.126.32.75 (ttl=186:54:54) 20.190.160.15 (ttl=186:54:54) 40.126.32.69
(ttl=186:54:54) 20.190.160.23 (ttl=186:54:54) 40.126.32.139 (ttl=186:54:54)
vfid=0 name=gmail.com ver=IPv4 wait_list=0 timer=200 min_refresh=60 min_ttl=290
cache_ttl=0 slot=-1 num=1 wildcard=0
         172.217.16.197 (ttl=290:206:206)
vfid=0 name=*.google.com ver=IPv4 wait_list=0 timer=0 min_refresh=60 min_ttl=280
cache_ttl=0 slot=-1 num=1 wildcard=1
         173.194.76.188 (ttl=280:0:0)
vfid=0 name=*.dropbox.com ver=IPv4 wait_list=0 timer=0 min_refresh=60 min_ttl=0
cache_ttl=0 slot=-1 num=0 wildcard=1

FQDN num=6

diagnose test app dnsproxy 9

No output, just reloads the zone(s), if secondary zone - pulls the zone from the primary.

Windows DNS commands

Some commands to verify/diagnose on Windows Servers.

dnscmd server-name-or-IP /zoneinfo domain-name

Show info on a given (nse8.com) zone hosted on localhost server:

dnscmd localhost  /zoneinfo nse8.com

PS C:\Users\Administrator> dnscmd localhost  /zoneinfo nse8.com

Zone query result:

Zone info:
        ptr                   = 0000021381F37460
        zone name             = nse8.com
        zone type             = 1
        shutdown              = 0
        paused                = 0
        update                = 2
        DS integrated         = 1
        read only zone        = 0
        in DS loading queue   = 0
        currently DS loading  = 0
        data file             = (null)
        using WINS            = 0
        using Nbstat          = 0
        aging                 = 0
          refresh interval    = 168
          no refresh          = 168
          scavenge available  = 0
        Zone Masters    NULL IP Array.
        Zone Secondaries
        Ptr          = 0000021381F371C0
        MaxCount     = 1
        AddrCount    = 1
                Secondary[0] => af=2, salen=16, [sub=0, flag=00000000] p=13568,
addr=192.168.13.237 (1)

        secure secs           = 2
        directory partition   = AD-Domain     flags 00000015
        zone DN               =
DC=nse8.com,cn=MicrosoftDNS,DC=DomainDnsZones,DC=nse8,DC=com
Command completed successfully.
  1. Our Fortigate (192.168.13.237) as a Slave for this (nse8.com) zone is allowed to do a zone transfer from this DNS server.

dnscmd server-name-or-IP /ZoneResetSecondaries domain-name

Reset/delete all allowed secondary servers.

In our case:

dnscmd localhost  /ZoneResetSecondaries nse8.com

dnscmd server-name-or-IP /ZoneResetSecondaries domain-name /SecureList IPsToAllowZoneTransfer

Add IPs allowed to do zone transfer against this WIndows server. In our case, adding 192.168.13.237 and 192.168.13.22 (for example only):

dnscmd localhost  /ZoneResetSecondaries nse8.com /SecureList 192.168.13.237
192.168.13.22

Resources

Follow me on https://www.linkedin.com/in/yurislobodyanyuk/ not to miss what I publish on Linkedin, Github, blog, and more.