Technical Tip: FortiNAC client isolation monitoring for captive portal troubleshooting
Description
This article describes a Linux shell script with the purpose to find out which public service belongs to an IP address/FQDN. It uses the FortiGate Internet Service Database to make that lookup.
The script expects an input file that is the result of a TCPDUMP command capturing DNS traffic from a client.
The purpose is to find which services a client tries to access as the FQDN otherwise are obfuscated.
- tcpdump -nnvvi any port 53
- The parsing of an existing PCAP with tcpdump: tcpdump -rnnvv capturefile.pcap.
The article describes FortiNAC-F captive portal troubleshooting, but this may be of use in other environments.
For information about the ISDB, see the Fortinet Documentation Library:
Look up IP address information from the Internet Service Database page.
Scope
FortiGate, FortiNAC, FortiNAC-F.
Solution
The following is the script that can be copied to a script file.
#!/bin/bash
usage=" [-h] [-f filename] [-r FortiGate IP] [-u FortiGate admin user] [-x exclude one IP or subnet] -- This script will read a tcpdump output, extract DNS queries and results from it and query a licensed FortiGate for its ISDB output
where:
-h show this help text
-r FortiGate IP
-x IP to exclude (like the local hosts IP), if a subnet is to be excluded, don't use CIDR notation
-u FortiGate admin user
-f the tcpdump file taken earlier, typically 'tcpdump -nnvvi any port 53'"
CURRENTDATE=$(date +%Y%m%d-%H%M%S)
EXCLUDEIP=0.0.0.0
while getopts ':h:u:f:r:x:' option; do
case "$option" in
h) echo "$usage"
exit
;;
x) EXCLUDEIP=$OPTARG
;;
r) FGTIP=$OPTARG
;;
f) TCPDUMPFILE=$OPTARG
;;
u) FGTUSER=$OPTARG
;;
:) printf "missing argument for -%s\n" "$OPTARG" >&2
echo "$usage" >&2
exit 1
;;
\?) printf "illegal option: -%s\n" "$OPTARG" >&2
echo "$usage" >&2
exit 1
;;
esac
done
echo "Script execution time: $CURRENTDATE"
echo "Using FortiGate at $FGTIP with user $FGTUSER on this file $TCPDUMPFILE, excluding $EXCLUDEIP"
#grep "isolation.isol.edarat.com.domain >" $TCPDUMPFILE | grep ' A \|CNAME' | cut -d ' ' -f 10-80 | sort | uniq > $CURRENTDATE-listdomain.txt
grep "isolation.isol.edarat.com.domain >" $TCPDUMPFILE | grep -v $EXCLUDEIP | grep ' A \|CNAME' | cut -d ' ' -f 10-80 | sort | uniq > $CURRENTDATE-listdomain.txt
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $CURRENTDATE-listdomain.txt | sort | uniq > $CURRENTDATE-listip.txt
IFS=$'\n' # make newlines the only separator
set -f # disable globbing
for i in $(cat < "$CURRENTDATE-listip.txt"); do
echo "checking IP $i"
echo "IP belongs to $(grep $i $CURRENTDATE-listdomain.txt)"
echo "and the set belongs to the following services:"
ssh $FGTUSER@$FGTIP -t "diagnose internet-service match root $i 255.255.255.255"
echo ""
echo ""
done
The script expects several arguments:
- -r: This would hold the FortiGate IP that is to be used for the ISDB lookup.
- -x: This may be used if an IP or subnet is to be excluded from the lookup.
- -u: This needs to be the user that logs in to FortiGate as admin to query the ISDB. Ideally this user uses an SSH key to avoid repeated password queries.
- -f: This option accepts the tcpdump output file.
This is an example of the execution of the script, with the script name being 'ISDB-poll.sh'.
./ISDB-poll.sh -f tcpdump-output.log -r 10.191.21.28 -u FGTadmin -x 10.48.
Script execution time: 20260213-171250
Using FortiGate at 10.191.21.28 with user FGTadmin on this file tcpdump-output.log, excluding 10.48.
checking IP 104.102.18.52
IP belongs to www.msn.com. CNAME www-msn-com-world-atm-default.trafficmanager.net., www-msn-com-world-atm-default.trafficmanager.net. CNAME www.msn.com.edgekey.net., www.msn.com.edgekey.net. CNAME e592.d.akamaiedge.net., e592.d.akamaiedge.net. A 104.102.18.52 (179)
and the set belongs to the following services:
FGT # Internet Service: 7929993(Akamai-CDN), matched entry num: 3, matched num: 3
FGT # checking IP 130.213.27.179
FGT # Internet Service: 327793(Microsoft-Microsoft.Update), matched entry num: 2, matched num: 2
Internet Service: 327786(Microsoft-Azure), matched entry num: 2, matched num: 2
Internet Service: 327681(Microsoft-Web), matched entry num: 4, matched num: 4
Internet Service: 327682(Microsoft-ICMP), matched entry num: 1, matched num: 1
Internet Service: 327683(Microsoft-DNS), matched entry num: 2, matched num: 2
Internet Service: 327684(Microsoft-Outbound_Email), matched entry num: 4, matched num: 4
Internet Service: 327686(Microsoft-SSH), matched entry num: 1, matched num: 1
Internet Service: 327687(Microsoft-FTP), matched entry num: 2, matched num: 2
Internet Service: 327688(Microsoft-NTP), matched entry num: 2, matched num: 2
Internet Service: 327689(Microsoft-Inbound_Email), matched entry num: 4, matched num: 4
Internet Service: 327694(Microsoft-LDAP), matched entry num: 4, matched num: 4
Internet Service: 327695(Microsoft-NetBIOS.Session.Service), matched entry num: 2, matched num: 2
Internet Service: 327696(Microsoft-RTMP), matched entry num: 2, matched num: 2
Internet Service: 327704(Microsoft-NetBIOS.Name.Service), matched entry num: 1, matched num: 1
Internet Service: 327680(Microsoft-Other), matched entry num: 2, matched num: 2
With this output, the client queries can be filtered to certain services, if these need to be allowed by the captive portal host like FortiNAC.