From 26425dd3979d0bd2da2d70d1f938249a72c2ba8d Mon Sep 17 00:00:00 2001 From: usmannasir Date: Mon, 15 Sep 2025 12:07:15 +0500 Subject: [PATCH] bug fix: allowed host issue --- .env.template | 2 +- CyberCP/settings.py | 9 +--- install/env_generator.py | 90 ++++++++++++++++++++++++++++--- install/setup_env.py | 112 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 16 deletions(-) create mode 100644 install/setup_env.py diff --git a/.env.template b/.env.template index 71c488291..f553174ac 100644 --- a/.env.template +++ b/.env.template @@ -5,7 +5,7 @@ # Django Configuration SECRET_KEY=your_very_long_random_secret_key_here_minimum_50_characters DEBUG=False -ALLOWED_HOSTS=localhost,127.0.0.1,yourdomain.com +ALLOWED_HOSTS=* # Database Configuration - CyberPanel Database DB_NAME=cyberpanel diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 4d827169f..4587e58eb 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -33,13 +33,8 @@ SECRET_KEY = os.getenv('SECRET_KEY', 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmj # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.getenv('DEBUG', 'False').lower() == 'true' -# Allow configuration via environment variable, with dynamic host detection -allowed_hosts_env = os.getenv('ALLOWED_HOSTS', '') -if allowed_hosts_env: - ALLOWED_HOSTS = allowed_hosts_env.split(',') -else: - # Default to localhost and auto-detect server IP from request - ALLOWED_HOSTS = ['localhost', '127.0.0.1', '*'] +# Allow configuration via environment variable, with wildcard fallback for universal compatibility +ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '*').split(',') # Application definition diff --git a/install/env_generator.py b/install/env_generator.py index 47f6cac64..0edb1d7f4 100644 --- a/install/env_generator.py +++ b/install/env_generator.py @@ -8,6 +8,9 @@ import os import sys import secrets import string +import socket +import urllib.request +import re from pathlib import Path def generate_secure_password(length=24): @@ -27,16 +30,53 @@ def generate_secure_password(length=24): def generate_secret_key(length=64): """ Generate a cryptographically secure Django secret key - + Args: length: Length of the secret key to generate (default 64) - + Returns: str: Random secret key """ chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)' return ''.join(secrets.choice(chars) for _ in range(length)) +def get_public_ip(): + """Get the public IP address of the server using multiple methods""" + methods = [ + 'https://ipv4.icanhazip.com', + 'https://api.ipify.org', + 'https://checkip.amazonaws.com', + 'https://ipecho.net/plain' + ] + + for url in methods: + try: + with urllib.request.urlopen(url, timeout=10) as response: + ip = response.read().decode('utf-8').strip() + # Validate IP format + if re.match(r'^(\d{1,3}\.){3}\d{1,3}$', ip): + print(f"✓ Detected public IP: {ip}") + return ip + except Exception as e: + print(f"Failed to get IP from {url}: {e}") + continue + + print("⚠️ Could not detect public IP address") + return None + +def get_local_ip(): + """Get the local IP address of the server""" + try: + # Connect to a remote address to determine the local IP + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.connect(("8.8.8.8", 80)) + local_ip = s.getsockname()[0] + print(f"✓ Detected local IP: {local_ip}") + return local_ip + except Exception as e: + print(f"Failed to detect local IP: {e}") + return None + def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_password=None): """ Create .env file with generated secure credentials @@ -56,15 +96,49 @@ def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_pas secret_key = generate_secret_key(64) - # Get hostname for ALLOWED_HOSTS - import socket + # Auto-detect IP addresses for ALLOWED_HOSTS + print("🔍 Auto-detecting server IP addresses...") + + # Get hostname and local hostname resolution try: hostname = socket.gethostname() - local_ip = socket.gethostbyname(hostname) + hostname_ip = socket.gethostbyname(hostname) except: hostname = 'localhost' - local_ip = '127.0.0.1' - + hostname_ip = '127.0.0.1' + + # Get actual local IP address + local_ip = get_local_ip() + + # Get public IP address + public_ip = get_public_ip() + + # Build ALLOWED_HOSTS list with all detected IPs + allowed_hosts = ['localhost', '127.0.0.1'] + + # Add hostname if different from localhost + if hostname and hostname != 'localhost': + allowed_hosts.append(hostname) + + # Add hostname IP if different from localhost + if hostname_ip and hostname_ip not in allowed_hosts: + allowed_hosts.append(hostname_ip) + + # Add local IP if detected and different + if local_ip and local_ip not in allowed_hosts: + allowed_hosts.append(local_ip) + + # Add public IP if detected and different + if public_ip and public_ip not in allowed_hosts: + allowed_hosts.append(public_ip) + + # Add wildcard for maximum compatibility (allows any host) + # This ensures CyberPanel works regardless of how the server is accessed + allowed_hosts.append('*') + + allowed_hosts_str = ','.join(allowed_hosts) + print(f"✓ ALLOWED_HOSTS configured: {allowed_hosts_str}") + # Create .env content env_content = f"""# CyberPanel Environment Configuration # Generated automatically during installation - DO NOT EDIT MANUALLY @@ -73,7 +147,7 @@ def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_pas # Django Configuration SECRET_KEY={secret_key} DEBUG=False -ALLOWED_HOSTS=localhost,127.0.0.1,{hostname},{local_ip} +ALLOWED_HOSTS={allowed_hosts_str} # Database Configuration - CyberPanel Database DB_NAME=cyberpanel diff --git a/install/setup_env.py b/install/setup_env.py new file mode 100644 index 000000000..5207d5b86 --- /dev/null +++ b/install/setup_env.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +""" +Environment setup script for CyberPanel +Automatically detects server IP and configures .env file +""" + +import os +import socket +import urllib.request +import re +import shutil +from pathlib import Path + +def get_public_ip(): + """Get the public IP address of the server using multiple methods""" + methods = [ + 'https://ipv4.icanhazip.com', + 'https://api.ipify.org', + 'https://checkip.amazonaws.com', + 'https://ipecho.net/plain' + ] + + for url in methods: + try: + with urllib.request.urlopen(url, timeout=10) as response: + ip = response.read().decode('utf-8').strip() + # Validate IP format + if re.match(r'^(\d{1,3}\.){3}\d{1,3}$', ip): + return ip + except Exception: + continue + + return None + +def get_local_ip(): + """Get the local IP address of the server""" + try: + # Connect to a remote address to determine the local IP + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.connect(("8.8.8.8", 80)) + return s.getsockname()[0] + except Exception: + return None + +def setup_env_file(cyberpanel_root="/usr/local/CyberCP"): + """Set up the .env file with auto-detected IP addresses""" + env_template_path = os.path.join(cyberpanel_root, ".env.template") + env_path = os.path.join(cyberpanel_root, ".env") + + # Get IPs + public_ip = get_public_ip() + local_ip = get_local_ip() + + # Build ALLOWED_HOSTS list + allowed_hosts = ['localhost', '127.0.0.1'] + + if local_ip and local_ip not in allowed_hosts: + allowed_hosts.append(local_ip) + + if public_ip and public_ip not in allowed_hosts: + allowed_hosts.append(public_ip) + + # For maximum compatibility, also include wildcard + # This ensures the server works regardless of how it's accessed + allowed_hosts.append('*') + + allowed_hosts_str = ','.join(allowed_hosts) + + print(f"Auto-detected public IP: {public_ip}") + print(f"Auto-detected local IP: {local_ip}") + print(f"Setting ALLOWED_HOSTS to: {allowed_hosts_str}") + + # If .env doesn't exist, copy from template + if not os.path.exists(env_path): + if os.path.exists(env_template_path): + shutil.copy2(env_template_path, env_path) + print(f"Created .env file from template") + else: + print(f"Warning: Template file not found at {env_template_path}") + return False + + # Update ALLOWED_HOSTS in .env file + try: + with open(env_path, 'r') as f: + content = f.read() + + # Update ALLOWED_HOSTS line + content = re.sub( + r'^ALLOWED_HOSTS=.*$', + f'ALLOWED_HOSTS={allowed_hosts_str}', + content, + flags=re.MULTILINE + ) + + with open(env_path, 'w') as f: + f.write(content) + + print(f"Updated ALLOWED_HOSTS in {env_path}") + return True + + except Exception as e: + print(f"Error updating .env file: {e}") + return False + +if __name__ == "__main__": + import sys + + # Allow custom path as argument + cyberpanel_root = sys.argv[1] if len(sys.argv) > 1 else "/usr/local/CyberCP" + + success = setup_env_file(cyberpanel_root) + sys.exit(0 if success else 1) \ No newline at end of file