This document outlines security considerations, best practices, and guidelines for deploying and maintaining the WireGuard Management System.
The system implements multiple layers of security:
βββββββββββββββββββββββββββββββββββββββββββ
β Internet β
βββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββββββ
β Reverse Proxy β β SSL/TLS, Rate Limiting
β (nginx/Traefik) β
βββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββββββ
β Application Layer β β Input Validation, CSRF
β (Flask + WebSocket) β
βββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββββββ
β System Layer β β iptables, Containers
β (Docker + WireGuard) β
βββββββββββββββββββββββββββββββββββββββββββ
- No built-in authentication - designed for private networks
- Network-level security through VPN access
- iptables integration for traffic control
For production deployments, consider implementing:
# Example: Add basic authentication
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import check_password_hash
auth = HTTPBasicAuth()
@auth.verify_password
def verify_password(username, password):
if username == 'admin':
return check_password_hash(os.environ.get('ADMIN_PASSWORD_HASH'), password)
return False
@app.route('/admin')
@auth.login_required
def admin_panel():
return render_template('admin.html')# All database queries use parameterized statements
peer = Peer.query.filter_by(name=peer_name).first()
# Automatically prevents SQL injection# Input validation for peer creation
def validate_peer_data(data):
errors = []
# Name validation
if not data.get('name') or len(data['name']) > 50:
errors.append('Invalid peer name')
# Public key validation
if not is_valid_wireguard_key(data.get('public_key')):
errors.append('Invalid WireGuard public key')
return errorsimport ipaddress
def validate_ip_network(network):
try:
ipaddress.ip_network(network, strict=False)
return True
except ipaddress.AddressValueError:
return FalseAdd these headers for enhanced security:
# Add to Flask app
from flask_talisman import Talisman
Talisman(app,
force_https=True,
strict_transport_security=True,
content_security_policy={
'default-src': "'self'",
'script-src': "'self' 'unsafe-inline' cdn.socket.io cdn.jsdelivr.net",
'style-src': "'self' 'unsafe-inline'",
'img-src': "'self' data:",
}
)# Server keys (do this once)
wg genkey | tee server_private_key | wg pubkey > server_public_key
# Client keys (for each peer)
wg genkey | tee client_private_key | wg pubkey > client_public_key# Secure key storage
chmod 600 server_private_key
chown root:root server_private_key
# Environment variables (never commit)
export SERVER_PRIVATE_KEY=$(cat server_private_key)
export SERVER_PUBLIC_KEY=$(cat server_public_key)# Planned: Automated key rotation
def rotate_server_keys():
# Generate new keypair
new_private, new_public = generate_wireguard_keypair()
# Update server configuration
update_server_config(new_private, new_public)
# Notify all peers of new public key
notify_peers_key_change(new_public)
# Archive old keys with timestamp
archive_old_keys(current_private, current_public)# Planned: Database encryption
from cryptography.fernet import Fernet
class EncryptedField(db.TypeDecorator):
impl = db.Text
def process_bind_param(self, value, dialect):
if value is not None:
return fernet.encrypt(value.encode()).decode()
return value
def process_result_value(self, value, dialect):
if value is not None:
return fernet.decrypt(value.encode()).decode()
return value# Basic host protection
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 51820/udp
sudo ufw enable# Automated by the application
iptables -A FORWARD -i wg0 -j wireguard_rules
iptables -A wireguard_rules -s 10.0.0.0/24 -d 192.168.1.0/24 -j ACCEPT
iptables -A wireguard_rules -j DROP# Separate VPN clients from host network
iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o wg0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i wg0 -o wg0 -j DROP # Prevent peer-to-peer communication# Planned: API rate limiting
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["100 per hour"]
)
@app.route('/api/v1/peers', methods=['POST'])
@limiter.limit("5 per minute")
def create_peer():
# Limited to prevent abuse
pass# Use specific version tags
FROM ubuntu:22.04
# Create non-root user (when possible)
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Set proper permissions
COPY --chown=appuser:appuser . /app
USER appuser
# Health checks
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost:5000/ || exit 1# docker-compose.yml security options
services:
vpn-manager:
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_ADMIN # Only what's needed
- SYS_MODULE
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=100M# Use Docker secrets for production
secrets:
server_private_key:
file: ./secrets/server_private_key
services:
vpn-manager:
secrets:
- server_private_key
environment:
- SERVER_PRIVATE_KEY_FILE=/run/secrets/server_private_key# Security event logging
import logging
security_logger = logging.getLogger('security')
security_logger.addHandler(logging.FileHandler('/app/logs/security.log'))
def log_security_event(event_type, details):
security_logger.warning(f"Security Event: {event_type} - {details}")
# Usage
log_security_event("UNAUTHORIZED_ACCESS", f"IP: {request.remote_addr}")
log_security_event("PEER_CREATED", f"Name: {peer.name}, IP: {peer.assigned_ip}")# Monitor for suspicious patterns
tail -f /app/logs/security.log | grep -E "(UNAUTHORIZED|FAILED|SUSPICIOUS)"
# Alert on multiple failed attempts
awk '/FAILED_LOGIN/{count[$1]++} END{for(ip in count) if(count[ip]>5) print ip, count[ip]}' /app/logs/access.log# Application health checks
@app.route('/health')
def health_check():
checks = {
'database': check_database_connection(),
'wireguard': check_wireguard_interface(),
'disk_space': check_disk_space(),
'memory': check_memory_usage()
}
if all(checks.values()):
return jsonify(checks), 200
else:
return jsonify(checks), 503# Check for suspicious activity
grep -E "(UNAUTHORIZED|FAILED|SUSPICIOUS)" /app/logs/security.log
netstat -tulpn | grep LISTEN
ps aux | grep -v grep | grep -E "(nc|netcat|wget|curl)"# Isolate the system
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
# Stop services
docker compose down
# Backup evidence
tar -czf incident-$(date +%Y%m%d-%H%M).tar.gz /app/logs /app/instance# Rotate all keys
wg genkey | tee new_server_private | wg pubkey > new_server_public
# Update configuration
# Rebuild containers
docker compose build --no-cache
docker compose up -d
# Verify security
docker compose exec vpn-manager wg show
curl -f http://localhost:5000/health# Docker image scanning
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image vpn-vpn-manager
# Dependency scanning
pip install safety
safety check
# Code security analysis
pip install bandit
bandit -r app/# Network scanning
nmap -sS -O -p 1-65535 your-server-ip
# Web application scanning
nikto -h http://your-server:5000
sqlmap -u "http://your-server:5000/api/v1/peers" --batch
# SSL/TLS testing
sslscan your-server.com:443
testssl.sh your-server.com- Generate strong WireGuard keys
- Configure environment variables
- Set up reverse proxy with SSL/TLS
- Configure host firewall
- Review Docker security settings
- Test backup and restore procedures
- Verify SSL/TLS configuration
- Test WireGuard connectivity
- Validate firewall rules
- Check application logs
- Perform security scans
- Document configuration
- Regular security updates
- Log monitoring and analysis
- Key rotation procedures
- Backup verification
- Performance monitoring
- Incident response testing
If you discover a security vulnerability, please:
- Do not create a public issue
- Email security@your-domain.com
- Include detailed reproduction steps
- Allow reasonable time for fixes
- Coordinate disclosure timeline
We'll acknowledge receipt within 48 hours and work to resolve critical vulnerabilities within 7 days.
- OWASP Top 10
- Docker Security Best Practices
- WireGuard Security Documentation
- Flask Security Guidelines
Remember: Security is a continuous process, not a one-time setup!