Skip to content

silasmontgomery/ddns-server-for-virtualmin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DDNS Server for Virtualmin

A secure PHP-based Dynamic DNS server that interfaces with Virtualmin web panels through session-based authentication. This server provides encrypted credential storage, comprehensive logging, and both web and CLI interfaces for DNS record management.

Features

  • Encrypted Security: AES-256-CBC encryption with PBKDF2 key derivation for credential storage
  • Session Authentication: Cookie-based Virtualmin login via /session_login.cgi
  • Comprehensive Logging: Daily log files with automatic rotation and cleanup
  • Multiple Interfaces: Web API, CLI, and direct PHP class integration
  • HTTPS Enforcement: Required HTTPS for all non-localhost connections
  • DNS Validation: Built-in DNS record verification using gethostbyname() and dig
  • Record Management: Only modify existing records

Architecture

The system has evolved into a complete DNS management solution with these components:

Core Files

  • ddns.php - Main API logic with encryption, logging, and DNS operations
  • setup.php - Web-based setup interface with encrypted credential storage
  • cli.php - Command-line interface for automated updates
  • public_html/index.php - Web endpoint that routes to main DDNS logic

Support Classes

  • virtualmin.php - Virtualmin session management and DNS record operations
  • encrypt.php - AES-256-CBC encryption class for secure credential storage
  • log.php - Daily logging system with automatic cleanup
  • .config - Five-line encrypted configuration (credentials, endpoint, log retention, nameserver)

Prerequisites

  • PHP 7.4+ with OpenSSL and cURL extensions
  • Web Server (Apache/Nginx) with HTTPS support
  • Virtualmin Panel with /session_login.cgi and /save_record.cgi endpoints
  • File Permissions: Write access for .config, .webminsesh, and logs/ directory
  • Virtualmin Web Panel User credentials

Installation

  1. Clone or download this repository to your web server
  2. Set proper permissions for PHP to create configuration and session files
  3. Configure web server to serve the public_html directory as document root
  4. Ensure HTTPS is available (required for all non-localhost connections)

Setup

Initial Configuration

  1. Navigate to the setup page: https://ddns.yourdomain.com/setup.php
  2. Fill in the required fields:
    • Username: Virtualmin master administrator username
    • Password: Virtualmin master administrator password
    • Virtualmin URL: Full URL to your Virtualmin panel (e.g., https://server.example.com:10000)
    • Log Age: Number of days to retain log files (default: 7)
    • Nameserver: Optional DNS server for record verification
  3. Click "Setup" to encrypt credentials and generate API key
  4. Save the generated API key - required for all DDNS requests

Configuration File

The setup creates a .config file with encrypted data:

<encrypted_username_base64>
<encrypted_password_base64>
https://server.example.com:10000
7
8.8.8.8

Usage

Web API Requests

Send HTTP GET requests to your DDNS endpoint with these parameters:

https://yourdomain.com/?api_key=YOUR_API_KEY&domain_id=DOMAIN_ID&type=RECORD_TYPE&name=RECORD_NAME&value=RECORD_VALUE

Required Parameters:

  • api_key - The API key generated during setup (also serves as decryption key)
  • domain_id - Virtualmin's internal domain identifier (not the domain name)
  • type - DNS record type (A, AAAA, CNAME, MX, etc.)
  • name - Full record name including domain (e.g., "test.example.com")
  • value - Record value (IP address, target, etc.)

Example:

curl "https://ddns.example.com/?api_key=abc123def456789&domain_id=123456789&type=A&name=home.example.com&value=192.168.1.100"

Command Line Interface

Use cli.php for automated updates or scripts:

php cli.php <domain_id> <type> <name> <value> <username> <password> [endpoint] [nameserver]

Example:

php cli.php 123456789 A home.example.com 192.168.1.100 admin secret123 https://server.example.com:10000 8.8.8.8

Direct PHP Integration

For integration in PHP applications, use the Virtualmin class:

<?php
require_once 'virtualmin.php';

// Initialize with Virtualmin endpoint and credentials
$virtualmin = new Virtualmin(
    'https://your-virtualmin-server:10000',
    'admin_username', 
    'admin_password'
);

// Modify an existing DNS record  
$result = $virtualmin->updateRecord(1234567890, 'test.example.com', 'A', '192.168.1.200');

// Check results
if ($result['status_code'] == 200) {
   echo "Result: " . $result['response']  . "\n";
} else {
   echo "Result: " . $result['response']  . "\n";
   echo "Error: " . $result['error'] . "\n";
   echo "Status Code: " . $result['status_code'] . "\n";
}
?>

Encryption Usage

For secure credential storage:

<?php
require_once 'encrypt.php';

$encryption = new Encryption();
$api_key = bin2hex(random_bytes(16));

// Encrypt credentials
$encrypted_username = $encryption->encrypt('admin', $api_key);
$encrypted_password = $encryption->encrypt('password123', $api_key);

// Decrypt when needed
$username = $encryption->decrypt($encrypted_username, $api_key);
$password = $encryption->decrypt($encrypted_password, $api_key);
?>

Logging & Monitoring

Daily Log Files

  • Location: logs/YYYY-MM-DD.log
  • Content: Client IP, timestamp, request URI, operations, and errors
  • Rotation: Automatic cleanup based on logage setting
  • CLI Logging: Command-line operations logged with 'CLI' identifier

Log Management

$logger = new DDNSLog($client_ip, $log_retention_days);
$logger->write("DNS update successful for test.example.com");

Security Model

  • AES-256-CBC Encryption: Credentials encrypted with PBKDF2 (1000 iterations, SHA256)
  • Session-Based Auth: Uses Virtualmin's /session_login.cgi for secure API access
  • HTTPS Enforcement: Required for all non-localhost connections
  • API Key as Password: Dual purpose authentication token and encryption key
  • DNS Validation: Record verification using gethostbyname() and optional dig
  • Session Cleanup: Temporary .webminsesh cookie files automatically removed

Error Responses

JSON responses with detailed error information:

  • 200 OK - Successful DNS operation with response details
  • 400 Bad Request - Missing domain_id, type, name, or value parameters
  • 401 Unauthorized - Invalid or missing API key
  • 500 Internal Server Error - Virtualmin communication or DNS operation failures

Troubleshooting

Common Issues

  1. 401 Unauthorized

    • Verify API key matches generated key from setup
    • Ensure API key is exactly 32 hexadecimal characters
    • Check that all required parameters are provided
  2. 400 Bad Request

    • Verify domain_id is Virtualmin's numeric domain identifier
    • Check record name includes full domain (e.g., "test.example.com")
    • Ensure type and value parameters are valid for DNS record type
  3. Session Authentication Failures

    • Verify Virtualmin URL includes correct port (usually :10000)
    • Check /session_login.cgi endpoint is accessible
    • Ensure virtualmin user credentials are correct
    • Verify encrypted credentials can be decrypted with API key
  4. DNS Operation Failures

    • Check that domain exists in Virtualmin and user has DNS permissions
    • Verify record format matches Virtualmin expectations
    • Review logs/YYYY-MM-DD.log for detailed error messages
    • Test DNS resolution with gethostbyname() or dig if configured

Debug Information

All responses include comprehensive debugging data:

  • HTTP status codes and Virtualmin responses
  • Complete request URLs and parameters
  • Encryption/decryption operations
  • Session management details
  • DNS verification results

Technical Details

Virtualmin Session Integration

For security purposes this server uses session-based authentication instead of Remote API (which requires the Master Administrator credentials):

  • Login Endpoint: /session_login.cgi with POST username/password
  • DNS Endpoint: /save_record.cgi with session cookie authentication
  • Session Management: Temporary .webminsesh cookie files (auto-cleaned)
  • Success Detection: HTTP 302 redirect indicates successful DNS update

DNS Record Operations

Adding Records (via updateRecord method):

$domain_id = "123456789";  // Virtualmin's internal domain ID
$type = "A"; 
$name = "test.example.com";
$value = "192.168.1.100";

Record Format for Virtualmin:

dom=123456789&id=test.%2FA%2F&name=test&value=192.168.1.100&ttl_def=1

Encryption Specifications

  • Algorithm: AES-256-CBC with PBKDF2 key derivation
  • Key Derivation: 1000 iterations, SHA256 digest
  • Salt: 16-byte random salt per encryption
  • IV: Random initialization vector per encryption
  • Output: Base64-encoded (salt + IV + encrypted_data)

File Structure

/ddns/
├── .config              # 5-line encrypted config
├── .webminsesh          # Temporary session cookie (auto-cleaned)
├── ddns.php            # Core API logic
├── cli.php             # Command-line interface  
├── setup.php           # Web setup interface
├── virtualmin.php      # Session management class
├── encrypt.php         # AES-256-CBC encryption
├── log.php             # Daily logging system
├── logs/               # Daily log files (YYYY-MM-DD.log)
└── public_html/        # Web document root
    └── index.php       # Main web endpoint

License

This project is provided as-is for educational and practical use. Modify as needed for your environment.

About

A light-weight PHP-based DDNS server for Virtualmin

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages