Reviewed-on: #2
DNS Service
A lightweight DNS management service written in C with a web-based interface for configuring DNS settings and managing dnsmasq configuration.
Features
- Web Interface: Modern responsive web UI for DNS configuration
- DNS Settings Management: Configure upstream DNS servers, local domains, and cache settings
- DHCP Configuration: Enable/disable DHCP with range configuration
- File Management: Direct editing of configuration files
- SSL/TLS Support: Optional HTTPS with certificate configuration
- JSON Configuration: Easy-to-manage JSON-based configuration
- Cross-platform: Supports multiple build systems (Make, CMake, Meson)
Architecture
The service consists of:
- HTTP/HTTPS Server: Built on Mongoose web server
- REST API: JSON-based API for configuration management
- Web Interface: Bootstrap-based responsive UI
- Configuration Parser: Custom dnsmasq config parser
- File Operations: Safe file reading/writing utilities
- Settings Management: Direct manipulation of dnsmasq configuration files
- Updates dnsmasq main configuration (
/etc/dnsmasq.conf) - Manages hosts file (
/etc/dnsmasq.conf.d/hosts) - Manages resolv.conf (
/etc/dnsmasq.conf.d/resolv.conf) - Automatically restarts dnsmasq service after configuration changes
- Updates dnsmasq main configuration (
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/settings |
Get current DNS settings |
| POST | /api/settings |
Update DNS settings (cache_size, resolv servers, hosts) and restart dnsmasq |
| GET | /api/settings/file |
Get raw configuration file |
| POST | /api/settings/file |
Update configuration file |
| GET | /# |
Serve web interface |
Requirements
Build Dependencies
- GCC compiler with C23 support
- OpenSSL development libraries
- pthread library
System Dependencies
- dnsmasq (for DNS service functionality)
- SSL certificates (for HTTPS support)
- System initialization service (systemd, openrc, rc, finit, or init)
- Appropriate privileges to restart system services
Installation
Using Make
make
Using CMake
mkdir build && cd build
cmake ..
make
Using Meson
meson setup builddir
meson compile -C builddir
Configuration
Edit config.json to configure the service:
{
"address": "0.0.0.0:8321",
"tls_address": "0.0.0.0:8322",
"web": "./web",
"tls_enabled": true,
"tls_cert": "/path/to/certificate.crt",
"tls_key": "/path/to/private.key",
"system_initialization": "systemd",
"dnsmasq_config": "/etc/dnsmasq.conf"
}
Configuration Parameters
address: HTTP server bind address and porttls_address: HTTPS server bind address and portweb: Path to web interface filestls_enabled: Enable/disable HTTPS supporttls_cert: Path to SSL certificate filetls_key: Path to SSL private key filesystem_initialization: System initialization type for restarting dnsmasq service"systemd": Usessystemctl restart dnsmasq"rc"or"openrc": Usesrc restart dnsmasq"finit": Usesinitctl restart dnsmasq"init": Uses/etc/init.d/dnsmasq restart
dnsmasq_config: Path to dnsmasq configuration file
Usage
Starting the Service
./dns_service
The service will start HTTP server on the configured address (default: 0.0.0.0:8321) and optionally HTTPS server if TLS is enabled.
Web Interface
Navigate to http://localhost:8321 (or your configured address) to access the web interface where you can:
- Configure upstream DNS servers (resolv)
- Manage local domain mappings (hosts)
- Enable/disable DHCP with range settings
- Adjust DNS cache size
- Edit configuration files directly
- Save settings directly to dnsmasq configuration
- Automatic dnsmasq service restart after configuration changes
API Usage
Get Current Settings
curl -X GET http://localhost:8321/api/settings
Update Settings
curl -X POST http://localhost:8321/api/settings \
-H "Content-Type: application/json" \
-d '{
"cache_size": 1000,
"resolv": ["8.8.8.8", "8.8.4.4"],
"hosts": {
"192.168.1.1": "router.local",
"192.168.1.100": ["server1.local", "server1"]
}
}'
The POST /api/settings endpoint accepts the following parameters:
cache_size(integer): DNS cache size for dnsmasqresolv(array of strings): Upstream DNS servershosts(object): Local DNS mappings where keys are IP addresses and values are either single hostnames (string) or arrays of hostnames
Note: After successfully updating the configuration files, the service automatically restarts dnsmasq to apply the changes. The restart method depends on the system_initialization setting in config.json.
Settings Configuration Details
Cache Size (cache_size)
- Configures the DNS cache size in dnsmasq
- Updates the
cache-sizeparameter in/etc/dnsmasq.conf - Accepts integer values (recommended: 150-10000 depending on system resources)
Upstream DNS Servers (resolv)
- Array of DNS server IP addresses to use for upstream resolution
- Creates/updates
/etc/dnsmasq.conf.d/resolv.confwithnameserverentries - Example:
["8.8.8.8", "1.1.1.1", "8.8.4.4"]
Local Hosts (hosts)
- Object mapping IP addresses to hostnames for local DNS resolution
- Creates/updates
/etc/dnsmasq.conf.d/hostsfile - Supports both single hostnames and multiple hostnames per IP
- Format:
- Single hostname:
"192.168.1.1": "router.local" - Multiple hostnames:
"192.168.1.100": ["server1.local", "server1"]
- Single hostname:
Development
Project Structure
dns_service_c/
├── src/
│ ├── lib/ # Third-party libraries
│ │ ├── mongoose.c # HTTP server
│ │ ├── cJSON.c # JSON parser
│ │ └── ...
│ ├── main.c # Application entry point
│ ├── config.c # Configuration management
│ ├── settings.c # DNS settings handlers (GET)
│ ├── set_settings.c # DNS settings handlers (POST)
│ ├── set_dnsmasq_settings_field.c # Update dnsmasq config fields
│ ├── set_hosts.c # Manage hosts file
│ ├── set_resolvs.c # Manage resolv.conf
│ ├── restart_dnsmasq.c # Restart dnsmasq service
│ ├── settings.h # Settings function declarations
│ ├── restart_dnsmasq.h # Restart function declarations
│ └── ...
├── web/ # Web interface files
│ ├── index.html
│ ├── css/
│ └── js/
├── config.json # Service configuration
└── README.md
Building for Development
# With debug symbols
make CFLAGS="-Wall -g -std=gnu2x -DDEBUG"
# Clean build
make clean && make
Code Style
The project uses .clang-format for consistent code formatting:
clang-format -i src/*.c src/*.h
Security Considerations
- The service runs with system privileges to modify DNS configuration files
- HTTPS is strongly recommended for production deployments
- Ensure proper file permissions on certificate files
- The service directly modifies system files (
/etc/dnsmasq.conf,/etc/dnsmasq.conf.d/hosts,/etc/dnsmasq.conf.d/resolv.conf) - Consider firewall rules to restrict access to management interface
- Validate all input data to prevent configuration file corruption
- Backup configuration files before making changes
- Ensure the service has appropriate write permissions to dnsmasq configuration directories
- The service requires privileges to restart the dnsmasq service via system commands
Troubleshooting
Common Issues
-
Permission denied when accessing dnsmasq config
- Ensure the service has read/write permissions to the dnsmasq configuration file
- Run with appropriate privileges or adjust file permissions
- Check permissions for
/etc/dnsmasq.conf.d/directory
-
Failed to write settings
- Verify write permissions to
/etc/dnsmasq.conf,/etc/dnsmasq.conf.d/hosts, and/etc/dnsmasq.conf.d/resolv.conf - Ensure the
/etc/dnsmasq.conf.d/directory exists - Check disk space availability
- Verify write permissions to
-
Failed to restart dnsmasq
- Ensure the service has appropriate privileges to restart system services
- Verify the
system_initializationparameter inconfig.jsonmatches your system - Supported initialization systems: rc, openrc, systemd, finit, init
- Check that dnsmasq service is properly installed and configured on the system
-
SSL/TLS certificate errors
- Verify certificate and key file paths in
config.json - Ensure certificate files have correct permissions
- Check certificate validity and format
- Verify certificate and key file paths in
-
Port binding errors
- Verify ports are not already in use
- Check firewall settings
- Ensure proper privileges for binding to privileged ports
-
Settings not persisting after dnsmasq restart
- Ensure dnsmasq is configured to read from
/etc/dnsmasq.conf.d/directory - Verify the main dnsmasq configuration includes the conf-dir directive
- Check that temporary files are properly cleaned up after configuration updates
- Ensure dnsmasq is configured to read from
Logging
The service uses Mongoose's built-in logging. Set log level in code or use debug build for verbose output.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes following the existing code style
- Test your changes thoroughly
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Third-party Libraries
This project includes the following third-party libraries:
- Mongoose: HTTP/WebSocket server library
- cJSON: JSON parser library
Please refer to their respective licenses for usage terms.
Support
For issues and questions, please check the project's issue tracker or documentation.