Skip to content

awkto/bind-frontend

Repository files navigation

BIND DNS Manager

A modern, web-based interface for managing multiple BIND DNS servers with comprehensive zone management and detailed service configuration.

BIND DNS Manager Python Flask Docker SSH

✨ What's New - Multi-Server Management

  • πŸ–₯️ Manage Multiple BIND Servers: Add unlimited DNS servers, switch between them with one click
  • βš™οΈ BIND Service Configuration: Configure recursion, forwarding, caching, access control, and more
  • 🎯 Server-Specific Settings: Each server has independent BIND options and zone configurations
  • πŸ”„ Automatic Migration: Legacy single-server configs automatically migrate to multi-server format
  • πŸ“‹ Separate Pages: "Edit Connection" for server setup, "BIND Config" for service settings

Features

πŸ–₯️ Multi-Server Management

  • Manage unlimited BIND DNS servers from a single interface
  • Quick server switching with active server selection
  • Independent configuration for each server
  • Automatic legacy configuration migration

🌐 DNS Zone Management

  • οΏ½ Auto-Discovery: Zones and zone files automatically detected from named.conf
  • 🎯 Zone Selector: Easy dropdown to switch between different DNS zones
  • βž• Add new DNS records (A, AAAA, CNAME, MX, TXT, NS, etc.)
  • ✏️ Edit existing DNS records
  • πŸ—‘οΈ Delete DNS records
  • βœ… Automatic zone validation with named-checkzone
  • ⚑ Zone reload via rndc after changes
  • πŸ’Ύ Remembers your last selected zone

βš™οΈ BIND Service Configuration (New!)

  • Recursion & Forwarding: Configure recursive DNS with upstream forwarders (Google, Cloudflare, etc.)
  • Caching: Set TTLs for positive and negative responses
  • Access Control: Define allow-query and allow-recursion ACLs
  • DNSSEC: Enable validation for enhanced security
  • Rate Limiting: Configure query limits and client connections
  • Logging: Enable query logging for troubleshooting
  • Network Settings: Configure IPv4/IPv6 listen addresses

πŸš€ Additional Features

  • 🎨 Modern, responsive web interface with dark mode
  • πŸ” Advanced search and filtering by record type
  • οΏ½ Secure SSH authentication (key-based or password)
  • πŸ“Š Real-time BIND installation progress
  • 🐳 Docker support for easy deployment

Architecture

Server β†’ BIND Options β†’ DNS Zones β†’ DNS Records

Data Model Hierarchy

  • Server Level: Connection settings, BIND service options
  • Zone Level: Zone configurations per server
  • Record Level: DNS records within each zone

Pages

  • Main Page (/): Manage zones and records for active server
  • Manage Servers (/servers.html): Add, edit, activate servers
  • BIND Config (/bind-options.html): Configure BIND service settings per server
  • Edit Connection (/settings.html): Edit server connection details

See ARCHITECTURE.md and PAGE_STRUCTURE.md for detailed documentation.

Quick Start with Docker

The easiest way to run BIND DNS Manager is using Docker:

docker run -d -p 5000:5000 \
  -e BIND_HOST=your-dns-server.com \
  -e BIND_USER=root \
  -e BIND_SSH_KEY=/root/.ssh/id_rsa \
  -e BIND_CONFIG_PATH=/etc/bind/named.conf \
  -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
  --name bind-dns-manager \
  yourusername/bind-dns-gui:latest

Then open http://localhost:5000 in your browser. The application will automatically discover all zones from your BIND configuration.

Architecture

  • Backend: Python Flask REST API connecting via SSH to BIND server
  • Frontend: Vanilla HTML/CSS/JavaScript with zone selector
  • Authentication: SSH key-based or password authentication
  • DNS Management: Direct zone file manipulation with validation and reload
  • Zone Discovery: Automatic parsing of named.conf and included configuration files
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Web Browser   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ HTTP
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Flask Server   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ SSH (Paramiko)
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  BIND Server    β”‚
β”‚  β”œβ”€ Zone Files  β”‚
β”‚  β”œβ”€ rndc        β”‚
β”‚  └─ named-check β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Prerequisites

  1. Python 3.11 or higher (for local development)
  2. Docker (optional, for containerized deployment)
  3. BIND DNS Server with SSH access
  4. SSH Credentials (private key or password)
  5. BIND Server Requirements:
    • SSH access to the server
    • Read/write permissions to zone files
    • Ability to execute named-checkzone command
    • Ability to execute rndc reload command

Setting Up SSH Access to BIND Server

Option 1: SSH Key Authentication (Recommended)

  1. Generate an SSH key pair (if you don't have one):
ssh-keygen -t rsa -b 4096 -f ~/.ssh/bind_dns_key
  1. Copy your public key to the BIND server:
ssh-copy-id -i ~/.ssh/bind_dns_key.pub user@your-bind-server.com
  1. Test the connection:
ssh -i ~/.ssh/bind_dns_key user@your-bind-server.com

Option 2: Password Authentication

Simply use your SSH username and password in the configuration.

BIND Server User Permissions

The SSH user needs proper permissions on the BIND server:

# On your BIND server, ensure the user can read zone files
sudo usermod -a -G bind your-ssh-user

# Set proper permissions on zone files
sudo chmod 640 /etc/bind/zones/db.example.com
sudo chown root:bind /etc/bind/zones/db.example.com

# Test if user can read zone files
cat /etc/bind/zones/db.example.com

# Test if user can run rndc
rndc reload example.com

Deployment Options

Option 1: Docker (Recommended)

Pull and Run from Docker Hub

# Pull the latest image
docker pull yourusername/bind-dns-gui:latest

# Run with environment variables (SSH key authentication)
docker run -d \
  --name bind-dns-manager \
  -p 5000:5000 \
  -e BIND_HOST=dns.example.com \
  -e BIND_PORT=22 \
  -e BIND_USER=root \
  -e BIND_SSH_KEY=/root/.ssh/id_rsa \
  -e BIND_CONFIG_PATH=/etc/bind/named.conf \
  -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
  yourusername/bind-dns-gui:latest

# Or use password authentication
docker run -d \
  --name bind-dns-manager \
  -p 5000:5000 \
  -e BIND_HOST=dns.example.com \
  -e BIND_USER=root \
  -e BIND_PASSWORD=your-password \
  -e BIND_CONFIG_PATH=/etc/bind/named.conf \
  yourusername/bind-dns-gui:latest

# Or use a .env file
docker run -d \
  --name bind-dns-manager \
  -p 5000:5000 \
  --env-file .env \
  -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
  yourusername/bind-dns-gui:latest

All zones configured in your BIND server will be automatically discovered and available in the zone selector dropdown.

Build Docker Image Locally

# Clone the repository
git clone https://github.com/awkto/bind-frontend.git
cd bind-frontend

# Build the image
docker build -t bind-dns-manager .

# Run the container
docker run -d -p 5000:5000 \
  --env-file .env \
  -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
  bind-dns-manager

Docker Compose

Create a docker-compose.yml:

version: '3.8'

services:
  bind-dns-manager:
    image: yourusername/bind-dns-gui:latest
    container_name: bind-dns-manager
    ports:
      - "5000:5000"
    environment:
      - BIND_HOST=${BIND_HOST}
      - BIND_PORT=${BIND_PORT:-22}
      - BIND_USER=${BIND_USER}
      - BIND_SSH_KEY=${BIND_SSH_KEY}
      - DNS_ZONE=${DNS_ZONE}
      - ZONE_FILE_PATH=${ZONE_FILE_PATH}
    volumes:
      - ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:5000/api/health')"]
      interval: 30s
      timeout: 10s
      retries: 3

Then run:

docker-compose up -d

Option 2: Local Python Installation

1. Clone the Repository

git clone https://github.com/awkto/bind-frontend.git
cd bind-frontend

2. Install Python Dependencies

pip install -r requirements.txt

3. Configure Environment Variables

Copy the example environment file and fill in your BIND server details:

cp .env.example .env

Edit .env with your values:

# BIND Server Connection
BIND_HOST=dns.example.com
BIND_PORT=22
BIND_USER=root

# Authentication (choose ONE)
BIND_SSH_KEY=/root/.ssh/id_rsa
# BIND_PASSWORD=your-ssh-password

# BIND Configuration (zones will be auto-discovered)
BIND_CONFIG_PATH=/etc/bind/named.conf

Important: Never commit the .env file to version control!

Note: The application will automatically discover all zones from your BIND configuration file. You no longer need to specify individual zone names or file paths.

4. Test Your Connection (Optional)

python test_connection.py

5. Run the Application

python app.py

The application will start on http://localhost:5000

6. Access the GUI

Open your web browser and navigate to:

http://localhost:5000

Configuration

First-Time Setup

When you first access the application:

  1. If BIND credentials are not configured, you'll be automatically redirected to the Settings page
  2. Enter your BIND server connection details:
    • BIND Server Host: Hostname or IP address of your DNS server
    • SSH Port: SSH port (default: 22)
    • SSH User: Username with access to BIND zone files
    • SSH Private Key Path: Path to SSH key OR password
    • DNS Zone: Domain name (e.g., example.com)
    • Zone File Path: Full path to zone file (e.g., /etc/bind/zones/db.example.com)
  3. Click Test Connection to verify your credentials
  4. Click Save Configuration to persist the settings
  5. You'll be redirected to the main page with your DNS records

Updating Configuration

To update your BIND server credentials later:

  1. Click the βš™οΈ Settings button in the header
  2. Update the required fields
  3. Test and save the new configuration

Environment Variables

All configuration can be provided via environment variables (useful for Docker):

BIND_HOST=dns.example.com
BIND_PORT=22
BIND_USER=root
BIND_SSH_KEY=/root/.ssh/id_rsa
# BIND_PASSWORD=your-password
DNS_ZONE=example.com
ZONE_FILE_PATH=/etc/bind/zones/db.example.com

Usage Guide

Viewing DNS Records

The main page displays all DNS records from your BIND zone file in a table format showing:

  • Record name and FQDN
  • Record type (A, AAAA, CNAME, MX, TXT, NS, etc.)
  • TTL (Time To Live)
  • Record values

Adding a New Record

  1. Click Add New Record button

  2. Fill in the form:

    • Record Name: Enter the subdomain name (e.g., www, mail) or @ for the root domain
    • Record Type: Select from A, AAAA, CNAME, MX, or TXT
    • TTL: Set Time To Live in seconds (default: 3600)
    • Values: Enter record values (one per line)
      • For A records: IP addresses (e.g., 192.168.1.1)
      • For AAAA records: IPv6 addresses
      • For CNAME: Target domain (e.g., target.example.com)
      • For MX: Priority and exchange (e.g., 10 mail.example.com)
      • For TXT: Text values (e.g., v=spf1 include:_spf.google.com ~all)
  3. Click Add Record

  4. The zone file will be validated and reloaded automatically

Editing a Record

  1. Click the ✏️ Edit button next to any record
  2. Modify the TTL or values in the modal dialog
  3. Click Update Record
  4. Zone will be validated and reloaded

Note: Update/Delete functionality is partially implemented. For now, you may need to edit the zone file directly for complex changes.

Deleting a Record

  1. Click the πŸ—‘οΈ Delete button next to any record
  2. Confirm the deletion in the dialog

Note: Delete functionality returns 501 (coming soon). Use the BIND server directly for deletions.

Refreshing Records

Click the πŸ”„ Refresh button in the header to reload all records from the BIND server.

API Endpoints

The backend provides the following REST API endpoints:

Method Endpoint Description
GET /api/health Health check and zone info
GET /api/config/status Check if configuration is complete
GET /api/config Get current configuration (masked)
POST /api/config Save BIND server configuration
POST /api/config/test Test BIND server connection
GET /api/records List all DNS records from zone file
POST /api/records Create a new DNS record
PUT /api/records/<type>/<name> Update a DNS record (501 - coming soon)
DELETE /api/records/<type>/<name> Delete a DNS record (501 - coming soon)

Project Structure

bind-frontend/
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ index.html               # Main DNS records page
β”‚   β”œβ”€β”€ settings.html            # Configuration page
β”‚   β”œβ”€β”€ app.js                   # Main page JavaScript
β”‚   β”œβ”€β”€ settings.js              # Settings page JavaScript (needs update)
β”‚   └── styles.css               # Modern CSS with dark mode
β”œβ”€β”€ app.py                       # Flask backend with SSH/BIND integration
β”œβ”€β”€ test_connection.py           # Connection test script
β”œβ”€β”€ requirements.txt             # Python dependencies (paramiko, dnspython)
β”œβ”€β”€ Dockerfile                   # Docker image definition
β”œβ”€β”€ docker-compose.yml           # Docker Compose configuration
β”œβ”€β”€ .dockerignore               # Docker build exclusions
β”œβ”€β”€ .env.example                # Example environment variables
β”œβ”€β”€ .env                        # Your configuration (not in git)
β”œβ”€β”€ .gitignore                  # Git ignore rules
β”œβ”€β”€ CONVERSION_SUMMARY.md       # Conversion notes from DigitalOcean
└── README.md                   # This file

Security Considerations

  • ⚠️ This application does not include user authentication for the web interface
  • πŸ” SSH credentials are stored in environment variables (never commit .env to git)
  • πŸ”‘ SSH key-based authentication is strongly recommended over passwords
  • 🌐 By default, the app runs on all interfaces (0.0.0.0) - consider restricting this in production
  • πŸ”’ Ensure your SSH user has minimal required permissions
  • 🚫 Do not expose this application directly to the internet without proper security measures
  • πŸ›‘οΈ Consider using a reverse proxy (nginx/traefik) with authentication
  • πŸ“ All zone changes are validated with named-checkzone before applying
  • πŸ”„ Failed zone validations are rejected to prevent breaking DNS

Troubleshooting

Docker Issues

Container won't start

# Check container logs
docker logs bind-dns-manager

# Check if port is already in use
netstat -an | grep 5000  # Linux/Mac
netstat -ano | findstr :5000  # Windows

SSH key mount issues

# Ensure SSH key has correct permissions
chmod 600 ~/.ssh/id_rsa

# Check if key is mounted correctly in container
docker exec bind-dns-manager ls -la /root/.ssh/

Configuration not persisting

  • For Docker: Use environment variables or mount a volume for the .env file
docker run -d -p 5000:5000 -v $(pwd)/.env:/app/.env bind-dns-manager

Local Development Issues

"Module not found" errors

pip install -r requirements.txt

"Missing required environment variables" error Make sure you've created a .env file with all required values or configured via the Settings page.

BIND Server Connection Issues

"Authentication failed" error

  • Verify SSH credentials are correct
  • Test SSH connection manually: ssh -i /path/to/key user@host
  • Ensure SSH key has correct permissions (600)
  • Check if password authentication is enabled on server if using password

"Zone file not found" error

  • Verify the zone file path is correct on the BIND server
  • Check if SSH user has read permissions to the zone file
  • Common locations:
    • Debian/Ubuntu: /etc/bind/zones/db.example.com
    • RHEL/CentOS: /var/named/example.com.zone

"Permission denied" when updating records

  • SSH user needs write permissions to zone files
  • User must be able to execute rndc reload
  • Consider adding user to bind group: sudo usermod -a -G bind your-user

"named-checkzone command not found"

  • Ensure BIND is installed on the server
  • Verify the SSH user's PATH includes BIND binaries
  • Try full path: /usr/sbin/named-checkzone

Cannot connect to the application

  • Check that the application is running on port 5000
  • Verify no firewall is blocking the connection
  • Try accessing via http://127.0.0.1:5000 instead

Known Limitations

  • Update/Delete records: Currently returns 501 (Not Implemented)
    • Records can be added, but updates/deletes require zone file editing
    • Full implementation coming in future release
  • SOA Serial: Serial number is not automatically incremented
    • Manual increment required after changes
  • Single Zone: Currently supports one zone at a time
    • Multi-zone support planned for future
  • No DNSSEC UI: DNSSEC records can be viewed but not managed via UI

Future Enhancements

  • Complete update/delete record functionality
  • Auto-increment SOA serial number on changes
  • Multi-zone support (manage multiple domains)
  • DNSSEC record management
  • Zone file backup before changes
  • Change history and audit logging
  • User authentication and authorization
  • HTTPS/TLS support
  • Batch operations
  • Record import/export (CSV, JSON, BIND format)
  • Zone transfer functionality
  • Support for views and split-horizon DNS
  • Kubernetes deployment manifests
  • Webhook notifications for changes

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is open source and available under the MIT License.

Acknowledgments

  • Built with Flask
  • SSH connectivity via Paramiko
  • DNS parsing with dnspython
  • Inspired by the need for a modern BIND management interface

Support


Note: This is primarily a development/management tool. For production use, implement proper security measures including user authentication, HTTPS, access controls, and consider running it on an isolated management network.