mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-10-26 00:36:34 +02:00
Remove deprecated files and enhance IP blocking feature
- Deleted obsolete files: SECURITY_INSTALLATION.md, test.php, and test.sh. - Improved IP blocking functionality in views.py by adding validation for private and reserved IP addresses, enhancing security against self-blocking. - Updated error handling to capture specific issues related to IP validation and command execution. - Revised FIREWALL_BLOCKING_FEATURE.md to reflect new validation and security measures.
This commit is contained in:
@@ -1,193 +0,0 @@
|
||||
# CyberPanel Secure Installation Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration.
|
||||
|
||||
## Security Improvements
|
||||
|
||||
### ✅ **Fixed Security Vulnerabilities**
|
||||
|
||||
1. **Hardcoded Database Passwords** - Now generated securely during installation
|
||||
2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation
|
||||
3. **Environment Variables** - All sensitive configuration moved to `.env` file
|
||||
4. **File Permissions** - `.env` file set to 600 (owner read/write only)
|
||||
|
||||
### 🔐 **Security Features**
|
||||
|
||||
- **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation
|
||||
- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code
|
||||
- **Secure File Permissions**: Environment files protected with 600 permissions
|
||||
- **Credential Backup**: Automatic backup of credentials for recovery
|
||||
- **Fallback Security**: Maintains backward compatibility with fallback method
|
||||
|
||||
## Installation Process
|
||||
|
||||
### 1. **Automatic Secure Installation**
|
||||
|
||||
The installation script now automatically:
|
||||
|
||||
1. Generates secure random passwords for:
|
||||
- MySQL root user
|
||||
- CyberPanel database user
|
||||
- Django secret key
|
||||
|
||||
2. Creates `.env` file with secure configuration:
|
||||
```bash
|
||||
# Generated during installation
|
||||
SECRET_KEY=your_64_character_secure_key
|
||||
DB_PASSWORD=your_24_character_secure_password
|
||||
ROOT_DB_PASSWORD=your_24_character_secure_password
|
||||
```
|
||||
|
||||
3. Creates `.env.backup` file for credential recovery
|
||||
4. Sets secure file permissions (600) on all environment files
|
||||
|
||||
### 2. **Manual Installation** (if needed)
|
||||
|
||||
If you need to manually generate environment configuration:
|
||||
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
/usr/local/CyberCP/
|
||||
├── .env # Main environment configuration (600 permissions)
|
||||
├── .env.backup # Credential backup (600 permissions)
|
||||
├── .env.template # Template for manual configuration
|
||||
├── .gitignore # Prevents .env files from being committed
|
||||
└── CyberCP/
|
||||
└── settings.py # Updated to use environment variables
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### ✅ **Do's**
|
||||
|
||||
- Keep `.env` and `.env.backup` files secure
|
||||
- Record credentials from `.env.backup` and delete the file after installation
|
||||
- Use strong, unique passwords for production deployments
|
||||
- Regularly rotate database passwords
|
||||
- Monitor access to environment files
|
||||
|
||||
### ❌ **Don'ts**
|
||||
|
||||
- Never commit `.env` files to version control
|
||||
- Don't share `.env` files via insecure channels
|
||||
- Don't use default passwords in production
|
||||
- Don't leave `.env.backup` files on the system after recording credentials
|
||||
|
||||
## Recovery
|
||||
|
||||
### **Lost Credentials**
|
||||
|
||||
If you lose your database credentials:
|
||||
|
||||
1. Check if `.env.backup` file exists:
|
||||
```bash
|
||||
sudo cat /usr/local/CyberCP/.env.backup
|
||||
```
|
||||
|
||||
2. If backup doesn't exist, you'll need to reset MySQL passwords using MySQL recovery procedures
|
||||
|
||||
### **Regenerate Environment**
|
||||
|
||||
To regenerate environment configuration:
|
||||
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
sudo python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### **Environment Variables**
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SECRET_KEY` | Django secret key | Generated (64 chars) |
|
||||
| `DB_PASSWORD` | CyberPanel DB password | Generated (24 chars) |
|
||||
| `ROOT_DB_PASSWORD` | MySQL root password | Generated (24 chars) |
|
||||
| `DEBUG` | Debug mode | False |
|
||||
| `ALLOWED_HOSTS` | Allowed hosts | localhost,127.0.0.1,hostname |
|
||||
|
||||
### **Custom Configuration**
|
||||
|
||||
To use custom passwords during installation:
|
||||
|
||||
```bash
|
||||
python install/env_generator.py /usr/local/CyberCP "your_root_password" "your_db_password"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### **Installation Fails**
|
||||
|
||||
If the new secure installation fails:
|
||||
|
||||
1. Check installation logs for error messages
|
||||
2. The system will automatically fallback to the original installation method
|
||||
3. Verify Python dependencies are installed:
|
||||
```bash
|
||||
pip install python-dotenv
|
||||
```
|
||||
|
||||
### **Environment Loading Issues**
|
||||
|
||||
If Django can't load environment variables:
|
||||
|
||||
1. Ensure `.env` file exists and has correct permissions:
|
||||
```bash
|
||||
ls -la /usr/local/CyberCP/.env
|
||||
# Should show: -rw------- 1 root root
|
||||
```
|
||||
|
||||
2. Install python-dotenv if missing:
|
||||
```bash
|
||||
pip install python-dotenv
|
||||
```
|
||||
|
||||
## Migration from Old Installation
|
||||
|
||||
### **Existing Installations**
|
||||
|
||||
For existing CyberPanel installations with hardcoded passwords:
|
||||
|
||||
1. **Backup current configuration**:
|
||||
```bash
|
||||
cp /usr/local/CyberCP/CyberCP/settings.py /usr/local/CyberCP/CyberCP/settings.py.backup
|
||||
```
|
||||
|
||||
2. **Generate new environment configuration**:
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python install/env_generator.py /usr/local/CyberCP
|
||||
```
|
||||
|
||||
3. **Update settings.py** (already done in new installations):
|
||||
- The settings.py file now supports environment variables
|
||||
- It will fallback to hardcoded values if .env is not available
|
||||
|
||||
4. **Test the configuration**:
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python manage.py check
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For issues with the secure installation:
|
||||
|
||||
1. Check the installation logs
|
||||
2. Verify file permissions
|
||||
3. Ensure all dependencies are installed
|
||||
4. Review the fallback installation method if needed
|
||||
|
||||
---
|
||||
|
||||
**Security Notice**: This installation method significantly improves security by eliminating hardcoded credentials. Always ensure proper file permissions and secure handling of environment files.
|
||||
|
||||
@@ -1129,8 +1129,9 @@ def blockIPAddress(request):
|
||||
'error': 'IP address is required'
|
||||
}), content_type='application/json', status=400)
|
||||
|
||||
# Validate IP address format
|
||||
# Validate IP address format and check for private/reserved ranges
|
||||
import re
|
||||
import ipaddress
|
||||
ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
|
||||
if not re.match(ip_pattern, ip_address):
|
||||
return HttpResponse(json.dumps({
|
||||
@@ -1138,39 +1139,78 @@ def blockIPAddress(request):
|
||||
'error': 'Invalid IP address format'
|
||||
}), content_type='application/json', status=400)
|
||||
|
||||
# Check for private/reserved IP ranges to prevent self-blocking
|
||||
try:
|
||||
ip_obj = ipaddress.ip_address(ip_address)
|
||||
if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local or ip_obj.is_reserved:
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': 'Cannot block private, loopback, link-local, or reserved IP addresses'
|
||||
}), content_type='application/json', status=400)
|
||||
|
||||
# Additional check for common problematic ranges
|
||||
if (ip_address.startswith('127.') or # Loopback
|
||||
ip_address.startswith('169.254.') or # Link-local
|
||||
ip_address.startswith('224.') or # Multicast
|
||||
ip_address.startswith('255.') or # Broadcast
|
||||
ip_address in ['0.0.0.0', '::1']): # Invalid/loopback
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': 'Cannot block system or reserved IP addresses'
|
||||
}), content_type='application/json', status=400)
|
||||
|
||||
except ValueError:
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': 'Invalid IP address'
|
||||
}), content_type='application/json', status=400)
|
||||
|
||||
# Use firewalld (CSF has been discontinued)
|
||||
firewall_cmd = 'firewalld'
|
||||
try:
|
||||
# Verify firewalld is active
|
||||
firewalld_check = ProcessUtilities.outputExecutioner('systemctl is-active firewalld')
|
||||
if not (firewalld_check and 'active' in firewalld_check):
|
||||
# Verify firewalld is active using subprocess for better security
|
||||
import subprocess
|
||||
firewalld_check = subprocess.run(['systemctl', 'is-active', 'firewalld'],
|
||||
capture_output=True, text=True, timeout=10)
|
||||
if not (firewalld_check.returncode == 0 and 'active' in firewalld_check.stdout):
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': 'Firewalld is not active. Please enable firewalld service.'
|
||||
}), content_type='application/json', status=500)
|
||||
except subprocess.TimeoutExpired:
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': 'Timeout checking firewalld status'
|
||||
}), content_type='application/json', status=500)
|
||||
except Exception as e:
|
||||
return HttpResponse(json.dumps({
|
||||
'status': 0,
|
||||
'error': f'Cannot check firewalld status: {str(e)}'
|
||||
}), content_type='application/json', status=500)
|
||||
|
||||
# Block the IP address using firewalld
|
||||
# Block the IP address using firewalld with subprocess for better security
|
||||
success = False
|
||||
error_message = ''
|
||||
|
||||
try:
|
||||
# Use firewalld to block IP
|
||||
command = f'firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address={ip_address} drop"'
|
||||
result = ProcessUtilities.executioner(command)
|
||||
if result == 0:
|
||||
# Use subprocess with explicit argument lists to prevent injection
|
||||
rich_rule = f'rule family=ipv4 source address={ip_address} drop'
|
||||
add_rule_cmd = ['firewall-cmd', '--permanent', '--add-rich-rule', rich_rule]
|
||||
|
||||
# Execute the add rule command
|
||||
result = subprocess.run(add_rule_cmd, capture_output=True, text=True, timeout=30)
|
||||
if result.returncode == 0:
|
||||
# Reload firewall rules
|
||||
reload_result = ProcessUtilities.executioner('firewall-cmd --reload')
|
||||
if reload_result == 0:
|
||||
reload_cmd = ['firewall-cmd', '--reload']
|
||||
reload_result = subprocess.run(reload_cmd, capture_output=True, text=True, timeout=30)
|
||||
if reload_result.returncode == 0:
|
||||
success = True
|
||||
else:
|
||||
error_message = 'Failed to reload firewall rules'
|
||||
error_message = f'Failed to reload firewall rules: {reload_result.stderr}'
|
||||
else:
|
||||
error_message = 'Failed to add firewall rule'
|
||||
error_message = f'Failed to add firewall rule: {result.stderr}'
|
||||
except subprocess.TimeoutExpired:
|
||||
error_message = 'Firewall command timed out'
|
||||
except Exception as e:
|
||||
error_message = f'Firewall command failed: {str(e)}'
|
||||
|
||||
|
||||
@@ -80,23 +80,56 @@ firewall-cmd --reload
|
||||
|
||||
1. **Admin-Only Access**: Feature restricted to administrators
|
||||
2. **Premium Feature**: Requires CyberPanel addons
|
||||
3. **IP Validation**: Validates IP address format before blocking
|
||||
4. **Firewalld Verification**: Ensures firewalld service is active
|
||||
5. **Audit Logging**: All blocking actions are logged
|
||||
6. **Error Handling**: Comprehensive error handling and user feedback
|
||||
3. **Enhanced IP Validation**: Validates IP address format and prevents blocking private/reserved ranges
|
||||
4. **Command Injection Protection**: Uses subprocess with explicit argument lists
|
||||
5. **Timeout Protection**: Prevents hanging processes with configurable timeouts
|
||||
6. **Firewalld Verification**: Ensures firewalld service is active
|
||||
7. **Audit Logging**: All blocking actions are logged
|
||||
8. **Comprehensive Error Handling**: Detailed error messages with captured stderr
|
||||
|
||||
## Error Handling
|
||||
|
||||
The feature includes robust error handling for:
|
||||
- Invalid IP addresses
|
||||
- Invalid IP addresses and formats
|
||||
- Private/reserved IP address ranges
|
||||
- Firewalld service not active
|
||||
- Firewall command failures
|
||||
- Firewall command failures and timeouts
|
||||
- Network connectivity issues
|
||||
- Permission errors
|
||||
- Command injection attempts
|
||||
- Process timeouts
|
||||
|
||||
## Testing
|
||||
|
||||
A test script is provided (`test_firewall_blocking.py`) for manual testing, though the feature is best tested through the web interface.
|
||||
A test script is provided for basic functionality testing:
|
||||
- `test_firewall_blocking.py` - Basic functionality testing
|
||||
|
||||
The feature is best tested through the web interface with various IP address types.
|
||||
|
||||
## Enhanced Security Features
|
||||
|
||||
### IP Range Validation
|
||||
The system now prevents blocking of:
|
||||
- **Private IP ranges**: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
|
||||
- **Loopback addresses**: 127.0.0.0/8
|
||||
- **Link-local addresses**: 169.254.0.0/16
|
||||
- **Multicast addresses**: 224.0.0.0/4
|
||||
- **Broadcast addresses**: 255.255.255.255
|
||||
- **Reserved addresses**: 0.0.0.0
|
||||
|
||||
### Command Execution Security
|
||||
- **Subprocess with explicit arguments**: Prevents command injection
|
||||
- **Timeout protection**: 10s for status checks, 30s for firewall commands
|
||||
- **Error capture**: Captures both stdout and stderr for better debugging
|
||||
- **No shell interpretation**: Eliminates shell injection vulnerabilities
|
||||
|
||||
### Example Error Messages
|
||||
```
|
||||
"Cannot block private, loopback, link-local, or reserved IP addresses"
|
||||
"Cannot block system or reserved IP addresses"
|
||||
"Timeout checking firewalld status"
|
||||
"Firewall command timed out"
|
||||
```
|
||||
|
||||
## Browser Compatibility
|
||||
|
||||
|
||||
Reference in New Issue
Block a user