# Windows DNS Packet Filter A high-performance personal DNS packet filtering application for Windows using WinDivert. Filter DNS requests in real-time based on customizable rules with support for exact matches and wildcard patterns. ## Features - **Real-time DNS Filtering**: Intercepts and filters DNS queries (UDP/TCP port 53) - **Flexible Rule System**: Supports both exact domain matches and wildcard patterns - **JSON Configuration**: Easy-to-edit JSON-based rule configuration - **Live Reload**: Automatically reloads rules when configuration file changes (no restart needed) - **Comprehensive Logging**: Detailed logging of all DNS queries with timestamps and source IPs - **Thread-Safe**: Concurrent access to rules with efficient locking mechanisms - **High Performance**: Optimized for minimal latency impact on DNS queries ## System Requirements - **Operating System**: Windows 7 or later (64-bit) - **Privileges**: Administrator rights (required for WinDivert driver) - **Dependencies**: - WinDivert 2.2 library - Visual C++ Redistributable (2015-2022) ## Project Structure ``` windows-filter/ ├── CMakeLists.txt # Build configuration ├── README.md # This file ├── config/ │ └── rules.json # DNS filtering rules ├── include/ # Header files │ ├── common.h │ ├── dns_parser.h │ ├── rule_engine.h │ ├── logger.h │ ├── config_manager.h │ └── packet_filter.h ├── src/ # Source files │ ├── main.cpp │ ├── dns_parser.cpp │ ├── rule_engine.cpp │ ├── logger.cpp │ ├── config_manager.cpp │ └── packet_filter.cpp └── external/ # Third-party libraries ├── WinDivert/ # WinDivert library └── json/ # nlohmann/json ``` ## Installation ### Step 1: Setup WinDivert Since WinDivert is a Windows-only library, you need to download it on a Windows machine: 1. Download WinDivert 2.2 from: https://github.com/basil00/WinDivert/releases/download/v2.2.2/WinDivert-2.2.2-A.zip 2. Extract the ZIP file 3. Copy the following files to the project: ``` From WinDivert-2.2.2-A/include/: - Copy windivert.h to: external/WinDivert/include/windivert.h From WinDivert-2.2.2-A/x64/: - Copy WinDivert.dll to: external/WinDivert/lib/WinDivert.dll - Copy WinDivert64.sys to: external/WinDivert/lib/WinDivert64.sys - Copy WinDivert.lib to: external/WinDivert/lib/WinDivert.lib ``` ### Step 2: Build the Project #### Using CMake (Recommended) ```bash # Create build directory mkdir build cd build # Configure cmake .. # Build cmake --build . --config Release ``` #### Using Visual Studio ```bash # Generate Visual Studio project files mkdir build cd build cmake .. -G "Visual Studio 17 2022" # Open the generated .sln file in Visual Studio # Build -> Build Solution (or press F7) ``` ### Step 3: Output Files After building, you'll find these files in `build/Release/`: - `dns_filter.exe` - Main application - `WinDivert.dll` - WinDivert library - `WinDivert64.sys` - WinDivert driver - `config/rules.json` - Configuration file ## Usage ### Running the Application **IMPORTANT**: This application requires Administrator privileges. ```bash # Run as Administrator cd build/Release dns_filter.exe ``` To run as Administrator: 1. Right-click on Command Prompt 2. Select "Run as Administrator" 3. Navigate to the application directory 4. Run `dns_filter.exe` ### Command Line Options ```bash # Use default configuration (config/rules.json) dns_filter.exe # Use custom configuration file dns_filter.exe path/to/custom/rules.json ``` ### Stopping the Application Press `Ctrl+C` to gracefully stop the application. Statistics will be displayed upon exit. ## Configuration ### Configuration File Format The configuration file (`config/rules.json`) uses JSON format: ```json { "version": "1.0", "logging": { "enabled": true, "file": "dns_filter.log", "level": "info", "max_size_mb": 100 }, "rules": [ { "domain": "example.com", "action": "block", "comment": "Optional comment" } ] } ``` ### Rule Configuration Each rule has the following fields: - **domain** (required): The domain name to match - **action** (required): Either "block" or "allow" - **comment** (optional): Description of the rule ### Exact Match Rules Block or allow specific domains: ```json { "domain": "malicious-site.com", "action": "block", "comment": "Known malicious domain" } ``` ### Wildcard Rules Use `*` to match multiple domains: ```json { "domain": "*.ads.example.com", "action": "block", "comment": "Block all ad subdomains" } ``` **Wildcard patterns supported:** - `*.example.com` - Matches all subdomains of example.com - `*.ads.*` - Matches domains containing "ads" subdomain - `example.*` - Matches all TLDs for example ### Example Configuration ```json { "version": "1.0", "logging": { "enabled": true, "file": "dns_filter.log", "level": "info", "max_size_mb": 100 }, "rules": [ { "domain": "ads.example.com", "action": "block", "comment": "Block ads" }, { "domain": "*.doubleclick.net", "action": "block", "comment": "Block DoubleClick ads" }, { "domain": "*.facebook.com", "action": "block", "comment": "Block all Facebook domains" }, { "domain": "trusted-site.com", "action": "allow", "comment": "Explicitly allowed" } ] } ``` ### Live Configuration Reload The application automatically detects changes to the configuration file and reloads rules without requiring a restart. Simply edit `config/rules.json` and save it - the changes will take effect within 1-2 seconds. ## Logging ### Log File All DNS queries and filtering actions are logged to `dns_filter.log`. ### Log Format ``` [2026-01-22 15:30:45.123] [INFO] DNS Query: example.com from 192.168.1.100 -> ALLOWED [2026-01-22 15:30:46.234] [WARN] DNS Query: malicious.com from 192.168.1.105 -> BLOCKED ``` ### Log Rotation Logs are automatically rotated when they reach the configured size (default: 100MB). Old logs are renamed to `dns_filter.log.1`. ## Testing ### Basic Functionality Test 1. **Start the filter:** ```bash dns_filter.exe ``` 2. **Test blocking:** - Add a domain to block in `config/rules.json`: ```json {"domain": "test.example.com", "action": "block"} ``` - Open another terminal and run: ```bash nslookup test.example.com ``` - The query should timeout (blocked) 3. **Check logs:** ```bash type dns_filter.log ``` - Look for entries showing the blocked query ### Test Live Reload 1. Start the filter 2. Edit `config/rules.json` to add a new blocked domain 3. Save the file 4. Check the console output - you should see "Configuration reloaded" 5. Test the newly blocked domain with `nslookup` ### Test Wildcard Patterns 1. Add a wildcard rule: ```json {"domain": "*.ads.example.com", "action": "block"} ``` 2. Test various subdomains: ```bash nslookup test.ads.example.com nslookup another.ads.example.com ``` 3. All should be blocked ## How It Works ### Architecture 1. **WinDivert Integration**: Intercepts all DNS traffic (port 53 UDP/TCP) at the network layer 2. **DNS Parser**: Extracts domain names from binary DNS packets 3. **Rule Engine**: Matches domains against configured rules (exact + wildcard) 4. **Packet Decision**: - **ALLOW**: Packet is forwarded to its destination - **BLOCK**: Packet is silently dropped (no response sent) ### Packet Flow ``` Application DNS Query ↓ Windows Network Stack ↓ WinDivert (Intercept) ↓ DNS Packet Filter ↓ Parse DNS Packet → Extract Domain ↓ Check Against Rules ↓ ┌───┴───┐ ALLOW BLOCK ↓ ↓ Forward Drop ``` ### Default Behavior By default, the filter uses a "fail-open" approach: - Unknown domains are **ALLOWED** (safer for general connectivity) - Only explicitly blocked domains are dropped - This prevents breaking internet connectivity if rules are misconfigured ## Performance ### Expected Performance - **Throughput**: 10,000+ DNS queries per second - **Latency**: < 1ms added latency per query - **Memory**: < 50MB under normal load - **CPU**: Minimal impact (< 1% on modern CPUs) ### Optimization Tips 1. Use exact matches when possible (faster than wildcards) 2. Keep rule count reasonable (< 10,000 rules for best performance) 3. Use SSD for log files to reduce I/O bottlenecks ## Troubleshooting ### "Access denied" Error **Problem**: Application fails to start with access denied error. **Solution**: Run the application as Administrator. ### "WinDivert driver not found" Error **Problem**: WinDivert64.sys is missing or inaccessible. **Solution**: - Ensure `WinDivert64.sys` is in the same directory as `dns_filter.exe` - Check that the file is not blocked by antivirus software - Verify Administrator privileges ### No DNS Queries Being Filtered **Problem**: Application runs but no DNS queries are logged. **Solution**: - Check that DNS traffic is actually occurring (try browsing websites) - Verify the filter is running with Administrator privileges - Check firewall settings aren't interfering ### Configuration File Not Loading **Problem**: "Failed to load configuration" error. **Solution**: - Verify `config/rules.json` exists - Check JSON syntax is valid (use a JSON validator) - Ensure file permissions allow reading ### Live Reload Not Working **Problem**: Changes to configuration file don't take effect. **Solution**: - Wait 1-2 seconds after saving (check interval is 1 second) - Check console output for "Configuration reloaded" message - Verify file was actually saved (not just editor buffer) ## Security Considerations ### Administrator Privileges This application **requires** Administrator privileges because: - WinDivert driver needs kernel-level access to intercept packets - Network packet filtering is a privileged operation on Windows ### Firewall and Antivirus Some antivirus software may flag WinDivert as suspicious because it's a packet filtering driver. This is a false positive. WinDivert is legitimate open-source software used for network monitoring and filtering. To resolve: - Add exception for `dns_filter.exe` in antivirus software - Add exception for `WinDivert64.sys` driver ### Privacy All DNS queries are logged locally only. No data is sent to external servers. ## Development ### Building from Source Requirements: - CMake 3.15 or later - C++17 compatible compiler (MSVC 2017+ or MinGW-w64) - WinDivert 2.2 library ### Code Structure - **common.h**: Shared definitions and constants - **dns_parser**: Parse DNS packets (RFC 1035 format) - **rule_engine**: Thread-safe domain matching - **logger**: Thread-safe logging with rotation - **config_manager**: JSON configuration and live reload - **packet_filter**: WinDivert integration and packet processing - **main**: Application entry point and lifecycle management ### Adding New Features The codebase is modular and easy to extend. Common extensions: 1. **Custom DNS responses**: Modify `packet_filter.cpp` to craft DNS responses instead of dropping 2. **Database backend**: Replace `config_manager.cpp` to load rules from SQLite 3. **Web interface**: Add HTTP server for real-time monitoring 4. **Statistics API**: Export metrics for monitoring tools ## License This project uses the following open-source libraries: - WinDivert (LGPL / GPL) - nlohmann/json (MIT License) ## Support For issues, questions, or contributions, please see the project repository. ## Acknowledgments - **WinDivert** by basil00 - Excellent packet filtering library - **nlohmann/json** - Modern JSON library for C++ --- **Note**: This software is provided for legitimate security and filtering purposes. Use responsibly and in compliance with applicable laws and regulations.