Automating FortiGate quarantined IP's to Threat Lists

Automating FortiGate quarantined IP's to Threat Lists

I would consider that if our Firewall rules in place are open enough yet still solid, analyzing traffic and therefore taking the right decision at the appropriate time, offenders should be tagged as they are.

Well, you've got all it takes to make a nice loop. The loop is the following, your FortiGate is configured to trigger, silently or directly, on any offending connection. Your IPS security profiles and/or Application Control security profiles shall be set to put offenders in so called quarantine.

Here is an example of such an IPS profile:

That IPS Filter will quarantine any potential "intruder" triggering IPS filters that matches the HTTP and/or HTTPS filter set. So to sum up, anyone sending your backend web servers any virtually shielded vulnerabilities (as an example) would end up being quarantined for 30 minutes.

Well that's good, that's already very good. Although, why not gather the offenders information and stock pile that? Why not making your own threat list with such offenders information's? FortiGate food served to FortiGate..

Well, you don't need much, python, a FortiOS REST API user sitting on your FortiGate and off you go.

Once the REST API user is in place, as shown here with read only permissions, you're free to interact with your FortiGate unit or even narrow this down to the Virtual Domain layer. For me here the latter, my WAN L2 virtual domain.

Now basically all you'd need is the following python script, preferably running from a FortiGate reachable internal web server, in order to gather and collect your offenders info's and re-serve that same content on your web server.

# anything starting with ***** shall be edited

from datetime import datetime
import requests
import json
import os
import time
import warnings

warnings.filterwarnings('ignore', message='Unverified HTTPS request')

now =
timestr = time.strftime("%d%m%Y%H%M%S")

params = (
    ('vdom', '***** vDOM-NAME *****'),
    ('access_token', '***** T000000k33333333nnnnnnnnnnnnnn *****'),

filename = str("/TF/QUARIPS/quarantined.txt")
f = open(filename, 'w+')

response = requests.get('https://***** yourfortigate *****/api/v2/monitor/user/banned', params=params, verify=False)
data = response.json()

print"--===[ ------------------------------------------------------ ]===--"
print"--===[ Quarantined pull           : start                       ]===--"
print"--===[ Quarantined pull time      :", now, " ]===--"

for ip in data["results"]:
    print ip["ip_address"]
    f.write(ip["ip_address"] + '\n')

# Write output to file above

# sorting unique IP's toward precedent ips.txt contents in new file [ips.done]
os.system("/usr/bin/sort /TF/QUARIPS/quarantined.txt /TF/QUARIPS/ips.txt | uniq > /TF/QUARIPS/ips.done")
# making sure no local IPs are part of our threat feeds, could be messy =)
os.system("/usr/bin/sed -i '/10\.168\./d;/10\.192\./d' /TF/QUARIPS/ips.done")
# removing temporary files
os.system("/usr/bin/rm -f /TF/QUARIPS/quaran*")
# deleting previous version of [ips.txt]
os.system("/usr/bin/rm -f /TF/QUARIPS/ips.txt")
# copying ips.done to ips.txt
os.system("/bin/cp /TF/QUARIPS/ips.done /TF/QUARIPS/ips.txt")
# copying ips.txt to WWW root
os.system("/bin/cp -rf /TF/QUARIPS/ips.txt /www/html/ips.txt")
# backing up ips.done for further references if needed
os.system("/usr/bin/mv /TF/QUARIPS/ips.done /TF/QUARIPS/backups/ips.done_" + str(timestr))
# deleting backups older then 60 minutes
os.system("/usr/bin/find /TF/QUARIPS/backups -mmin +60 -delete")

print"--===[ Quarantined pull           : success                     ]===--"
print"--===[ Quarantined pull           : END                         ]===--"
print"--===[ ------------------------------------------------------ ]===--"

This script will gather the newly quarantined IPs, keep the old ones, make sure none of your local LAN IPs are part of the package (cautious SysOps shall test things out), backup the previous database and keep that backup file for 60 min. To trigger this script, I'm simply using a crontab job and run it every 15 minutes from an internal web server. Here is my crontab entry:

*/15 * * * * /usr/bin/python /TF/QUARIPS/ >> /var/log/cronlogs/quarapi.log 2>&1

If anyone who's having better python skills then myself would help, I'd be happy to replace the os.system(" calls with pure python =) (my email is below!!!)

Our next step is to gather the ips.txt file as a Threat Feed update on our FortiGate (obviously, you need a working web server for that):

And you're now free to setup deny rules on anything matching the Threat Feeds contents you've gathered, mangled and re-feed to your FortiGate:

This will now loop, any new offenders will be added to your threat list. Triggering once, not twice.


Show Comments