{"id":15148327,"url":"https://github.com/coopsdev/forti-hole","last_synced_at":"2025-07-11T20:38:57.642Z","repository":{"id":255074524,"uuid":"848465025","full_name":"coopsdev/forti-hole","owner":"coopsdev","description":"Pi-hole inspired DNS blacklisting tool, integrates with FortiGate external connector threat feeds via the api","archived":false,"fork":false,"pushed_at":"2024-09-12T23:25:26.000Z","size":131,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-21T05:03:08.984Z","etag":null,"topics":["blocklists","cybersecurity","dns","dns-blocklists","dns-filtering","fortigate","fortigate-firewall","network-security","pi-hole"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coopsdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-27T20:07:50.000Z","updated_at":"2024-09-12T23:25:28.000Z","dependencies_parsed_at":"2024-09-11T23:04:54.497Z","dependency_job_id":"c891a9e7-c9c5-4023-a022-36538bf7e798","html_url":"https://github.com/coopsdev/forti-hole","commit_stats":null,"previous_names":["coopsdev/forti-hole"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/coopsdev/forti-hole","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopsdev%2Fforti-hole","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopsdev%2Fforti-hole/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopsdev%2Fforti-hole/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopsdev%2Fforti-hole/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coopsdev","download_url":"https://codeload.github.com/coopsdev/forti-hole/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopsdev%2Fforti-hole/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261338998,"owners_count":23143900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blocklists","cybersecurity","dns","dns-blocklists","dns-filtering","fortigate","fortigate-firewall","network-security","pi-hole"],"created_at":"2024-09-26T13:02:54.307Z","updated_at":"2025-06-22T18:09:19.855Z","avatar_url":"https://github.com/coopsdev.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# forti-hole\n\n## Update 9/12/24\n### An inherent limitation in use\n* This solution works brilliantly for DNS filters when applied on a policy basis.\n* The problem: when your needs grow to desire DNS Service on Interface (ie an internal dns server with recursive resolution and caching), you quickly learn that DNS service on interface is an 'in-policy' route which bypasses firewall policy level filtering all interface devices.\n  * Additionally: if you apply a DNS filter to your interface DNS server, because its operating at the application layer (7), it causes all kinds of ssl warnings that make browsing impossible. The policy level filters evidently apply the filters on layer 2 the network layer which evades this detection.\n* You may see where this is going... you can't run a dns service on interface (layer 7) AND have policy level DNS filtering (layer 2) at the same time.\n\n### This is still a solid DNS solution, if you don't have an interface DNS server running natively on the fortigate.\n* As you can guess, pi-hole is once again the solution.\n* This is a solid DNS filter but its limited in scope and you end up needing an external DNS server to truly deliver a secure DNS environment.\n* I will leave this up and likely continue to maintain and evolve it to help *anyone who doesn't need to host a DNS server or pay for UTP* to get great DNS filtering served as Threat Feeds via API.\n\n## Build and Installation Instructions\n\n### 👯 Step 1: Clone the Repository\n\nFirst, clone the **forti-hole** repository:\n\n```bash\ngit clone https://github.com/coopsdev/forti-hole.git\ncd forti-hole\n```\n\n### 🛠 Step 2: Build the Program\n\nRun the `build.sh` script to compile the program and create the `config.yaml` file.\n\n```bash\n./bin/build.sh\n```\n\nThis script will check if `config.yaml` exists and create it from `config.example.yaml` if necessary.\n\n### 👷 Step 3: Configure `config.yaml`\n\nBefore running the program, make sure you properly configure the `config.yaml` file located in the build directory. Adjust the relevant settings to match your environment (e.g., API keys, IP addresses, and certificate paths).\n\n### 🚀 Step 4: Run the Program\n\nOnce `config.yaml` is properly configured, you can run the program:\n\n```bash\n./bin/run.sh\n```\n\nThis script will build the program if necessary and execute it using the configurations in `config.yaml`.\n\n### 🔃 Step 5: Install as a Systemd Service (Linux Only)\n\nTo install **forti-hole** as a systemd service on Linux with a default 5am everyday run-timer, use the `install.sh` script:\n\n```bash\n./bin/install.sh\n```\n\nThis script will install the program as a service, allowing it to run automatically on boot and at 5am (easily customizable) everyday.\n\n### 🪬 Step 6: Update the Program\n\nTo update the repository, remove the build directory, and rebuild the program, run the `update.sh` script:\n\n```bash\n./bin/update.sh\n```\n\nThis script pulls the latest changes from the repository, removes the existing build directory, and triggers a fresh build.\n\n## Overview\n\n**forti-hole** is a cutting-edge DNS Threat Feed management tool, engineered for FortiGate users who need to manage DNS blocklists at an unprecedented scale. Inspired by Pi-hole, forti-hole is designed to tackle the challenges of handling massive domain lists, overcoming issues like buffer overflow and network traffic interruptions that plague FortiGate’s non-API managed threat feeds.\n\n**forti-hole** delivers a tested payload of 16+ files, encompassing over 2 million unique DNS entries, without causing any network interruption or delay to users. It directly addresses the challenges associated with managing 'pull' update method threat feeds on FortiGate, where a simultaneous refresh can overwhelm the buffers in an alarmingly short timespan, forcing a manual reset of the FortiGate and impacting all network users.\n\nThe default configuration includes a blocklist 'recipe' with these domains, organized into a 2-level security system, and scores up to 94+% on the [d3ward ad-block test](https://d3ward.github.io/toolz/adblock).\n\nWhile forti-hole isn't a Pi-hole replacement, it excels in simplicity and scale. If you need YAML-configured control and the capability to efficiently manage vast DNS blocklists on your FortiGate, **forti-hole** is your solution.\n\n## Key Features\n\n- **Efficient DNS Blocklist Management**: Manage blocklists containing over 2 million unique DNS entries across multiple files without causing network interruptions.\n- **YAML Configuration**: Simplified management through a YAML config file, allowing for easy customization and deployment.\n- **Automated Security Level Assignment**: Future releases will automate DNS filter assignments to reduce manual management.\n- **[forti-api](https://github.com/coopsdev/forti-api) Integration**: Provides deep control over your FortiGate setup via a type-safe, nlohmann-based syntax.\n- **Buffer Overflow Protection**: Prevents buffer overflow issues caused by dynamic feed updates in FortiGate, specifically addressing issues with the 'pull' update method that can force a manual reset.\n- **Future forti2ban Integration**: Planned integration with [forti2ban](https://github.com/coopsdev/forti2ban) for synchronized category management.\n\n## Why forti-hole?\n\nFortiGate devices often struggle with large DNS blocklists due to memory limitations and lack of overflow protections. **forti-hole** manages threat feeds via the API, preventing the buffer overflow issues that can occur when refreshing massive domain lists through the 'pull' update method. This tool is for network security professionals who need a reliable way to manage DNS blocklists on FortiGate devices without risking network downtime.\n\nWith upcoming features like automatic security level management and forti2ban integration, **forti-hole** is set to become an indispensable tool for anyone serious about network security on FortiGate.\n\n## Default 'Advanced' Settings - Results from [d3ward.github.io/toolz/adblock](https://d3ward.github.io/toolz/adblock)\n\n![Ad-block Test Results](https://cooperhlarson.com/media/Screenshot%202024-08-31%20at%205.07.39%C3%A2%C2%AFPM.png)\n\n## Contributing\n\nContributions are welcome! As **forti-hole** transitions from Python to a more robust C++ implementation, there are many opportunities to get involved. **Owning a FortiGate firewall is required** for testing, as I cannot provide access to my personal FortiGate 60F. The project is licensed under the MIT License, so your contributions will benefit the broader community.\n\n## Status\n\n**forti-hole** is in active production. Many features may be broken as the project undergoes a significant refactor from its original Python version. However, the core functionality is rapidly improving, with a major release planned for September 10, 2024, including a multi-platform precompiled executable with configuration and `.env` files.\n\nStay tuned for updates and help make **forti-hole** the go-to tool for managing DNS blocklists on FortiGate!\n\n# Sample forti-hole output\n\n```markdown\nStarting blocklist scraping process...\n\nProcessing config file...\n\nScraping blocklists...\n\nFetching URL: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.plus.txt\nFetching URL: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/tif.txt\nFetching URL: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/ultimate.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/ads-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/tracking-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/malware-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/phishing-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/ransomware-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/scam-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/abuse-ags.txt\nFetching URL: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/fraud-ags.txt\nFetching URL: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts/default.txt\n\nParsing response data...\n\nParsing response data: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.plus.txt\nParsing response data: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/tif.txt\nParsing response data: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/ultimate.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/ads-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/tracking-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/malware-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/phishing-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/ransomware-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/scam-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/abuse-ags.txt\nParsing response data: https://raw.githubusercontent.com/blocklistproject/Lists/master/adguard/fraud-ags.txt\nParsing response data: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts/default.txt\n\nBlocklist processing successfully completed...\n\nConsolidating data...\nGathering threat feed information...\nCreating threat feed containers...\nUpdating firewall policies...\nConstructing files and pushing threat feeds...\n\nSecurity Level 0: { Files: 14, LPF: 128423 }\n\nBuilt file: forti-hole_security_level-0_part-1 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-1\n\nBuilt file: forti-hole_security_level-0_part-2 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-2\n\nBuilt file: forti-hole_security_level-0_part-3 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-3\n\nBuilt file: forti-hole_security_level-0_part-4 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-4\n\nBuilt file: forti-hole_security_level-0_part-5 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-5\n\nBuilt file: forti-hole_security_level-0_part-6 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-6\n\nBuilt file: forti-hole_security_level-0_part-7 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-7\n\nBuilt file: forti-hole_security_level-0_part-8 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-8\n\nBuilt file: forti-hole_security_level-0_part-9 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-9\n\nBuilt file: forti-hole_security_level-0_part-10 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-10\n\nBuilt file: forti-hole_security_level-0_part-11 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-11\n\nBuilt file: forti-hole_security_level-0_part-12 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-12\n\nBuilt file: forti-hole_security_level-0_part-13 with 128424 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-13\n\nBuilt file: forti-hole_security_level-0_part-14 with 128423 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-0_part-14\nSecurity Level 1: { Files: 2, LPF: 100084 }\n\nBuilt file: forti-hole_security_level-1_part-1 with 100085 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-1_part-1\n\nBuilt file: forti-hole_security_level-1_part-2 with 100084 lines.\nSuccessfully uploaded to FortiGate: forti-hole_security_level-1_part-2\n\nforti-hole finished successfully in 33s\n```\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoopsdev%2Fforti-hole","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoopsdev%2Fforti-hole","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoopsdev%2Fforti-hole/lists"}