windows-filter-windivert/README.md

472 lines
12 KiB
Markdown

# 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.