diff --git a/README.md b/README.md index 818d5a8..04566ff 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,18 @@ The service consists of: - **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 ## API Endpoints | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/settings` | Get current DNS settings | -| POST | `/api/settings` | Update 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 | @@ -43,6 +48,8 @@ The service consists of: ### 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 @@ -76,7 +83,7 @@ Edit `config.json` to configure the service: "tls_enabled": true, "tls_cert": "/path/to/certificate.crt", "tls_key": "/path/to/private.key", - "system_initialization": "rc", + "system_initialization": "systemd", "dnsmasq_config": "/etc/dnsmasq.conf" } ``` @@ -89,7 +96,11 @@ Edit `config.json` to configure the service: - `tls_enabled`: Enable/disable HTTPS support - `tls_cert`: Path to SSL certificate file - `tls_key`: Path to SSL private key file -- `system_initialization`: System initialization type +- `system_initialization`: System initialization type for restarting dnsmasq service + - `"systemd"`: Uses `systemctl restart dnsmasq` + - `"rc"` or `"openrc"`: Uses `rc restart dnsmasq` + - `"finit"`: Uses `initctl restart dnsmasq` + - `"init"`: Uses `/etc/init.d/dnsmasq restart` - `dnsmasq_config`: Path to dnsmasq configuration file ## Usage @@ -105,11 +116,13 @@ The service will start HTTP server on the configured address (default: `0.0.0.0: Navigate to `http://localhost:8321` (or your configured address) to access the web interface where you can: -- Configure upstream DNS servers -- Manage local domain mappings +- 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 @@ -122,22 +135,63 @@ curl -X GET http://localhost:8321/api/settings ```bash 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"]}' + -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 dnsmasq +- `resolv` (array of strings): Upstream DNS servers +- `hosts` (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-size` parameter 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.conf` with `nameserver` entries +- 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/hosts` file +- 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"]` + ## Development ### Project Structure ``` dns_service_c/ ├── src/ -│ ├── lib/ # Third-party libraries -│ │ ├── mongoose.c # HTTP server -│ │ ├── cJSON.c # JSON parser +│ ├── 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 +│ ├── 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 @@ -164,10 +218,15 @@ clang-format -i src/*.c src/*.h ## Security Considerations -- The service runs with system privileges to modify DNS configuration +- 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 @@ -176,17 +235,34 @@ clang-format -i src/*.c src/*.h 1. **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 -2. **SSL/TLS certificate errors** +3. **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 + +4. **Failed to restart dnsmasq** + - Ensure the service has appropriate privileges to restart system services + - Verify the `system_initialization` parameter in `config.json` matches your system + - Supported initialization systems: rc, openrc, systemd, finit, init + - Check that dnsmasq service is properly installed and configured on the system + +5. **SSL/TLS certificate errors** - Verify certificate and key file paths in `config.json` - Ensure certificate files have correct permissions - Check certificate validity and format -3. **Port binding errors** +6. **Port binding errors** - Verify ports are not already in use - Check firewall settings - Ensure proper privileges for binding to privileged ports +7. **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 + ### Logging The service uses Mongoose's built-in logging. Set log level in code or use debug build for verbose output. diff --git a/src/set_settings.c b/src/set_settings.c index e2e2549..22c52db 100644 --- a/src/set_settings.c +++ b/src/set_settings.c @@ -1,4 +1,5 @@ #include "settings.h" +#include "restart_dnsmasq.h" void set_settings(struct mg_connection *c, struct mg_http_message *hm) { cJSON *jsonbody = cJSON_Parse(hm->body.buf); @@ -57,6 +58,14 @@ void set_settings(struct mg_connection *c, struct mg_http_message *hm) { return; } + char *error = restart_dnsmasq(); + if (error) { + mg_http_reply(c, 500, HTTP_HEADERS, "{%m:%m}", MG_ESC("error"), + MG_ESC(error)); + free(error); + return; + } + mg_http_reply(c, 200, HTTP_HEADERS, "%s", hm->body.buf); cJSON_Delete(jsonbody); }