472 lines
12 KiB
Markdown
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.
|