Enhance reverse DNS lookup functionality in mailUtilities

- Added detailed error handling and logging for reverse DNS lookups, improving robustness against network issues and invalid responses.
- Updated virtualHostUtilities to handle cases where reverse DNS lookups fail, providing clearer error messages and guidance for users.
- Ensured that the results from DNS queries are validated before processing, enhancing the reliability of the rDNS checks.

These changes improve the overall reliability and user experience of the reverse DNS lookup feature within the CyberPanel environment.
This commit is contained in:
Master3395 2025-12-09 18:32:52 +01:00
parent 4fe142ad8e
commit b9162b10cc
10 changed files with 1371 additions and 26 deletions

View File

@ -0,0 +1,60 @@
# CyberPanel rDNS Fix Mod for v2.4.4
## Overview
This mod fixes critical bugs and issues in the rDNS (reverse DNS) validation system in CyberPanel 2.4.4.
## Files in This Mod
### Documentation
- **`rDNS-Fix-README.md`** - Comprehensive documentation of all fixes and issues
- **`INSTALL.md`** - Step-by-step installation guide
- **`INDEX.md`** - This file, mod overview and quick reference
### Installation Scripts
- **`apply-rdns-fix.sh`** - Automatic installation script (recommended)
### Fixed Code Files
- **`mailUtilities_fixed.py`** - Complete fixed `reverse_dns_lookup()` function
- **`virtualHostUtilities_fixed.py`** - Fixed code sections for `OnBoardingHostName()` function
## Quick Start
### One-Liner (Recommended)
```bash
sh <(curl https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh || wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
### Local Installation
```bash
cd cyberpanel-mods/rdns
chmod +x rdns-fix.sh
sudo ./rdns-fix.sh
```
## Issues Fixed
1. ✅ **NameError Bug** - Fixed undefined variable `msg``e`
2. ✅ **Empty List Handling** - Proper validation of empty rDNS results
3. ✅ **Silent Exception Swallowing** - Replaced with specific error handling
4. ✅ **API Failure Handling** - Comprehensive error handling for DNS server failures
5. ✅ **Logic Flow Issues** - Fixed validation flow when rDNS lookup fails
6. ✅ **Error Messages** - Enhanced with debugging information
## Compatibility
- **CyberPanel Version**: 2.4.4
- **Python**: 3.6+ (compatible with CyberPanel 2.4.4)
- **OS**: All supported by CyberPanel 2.4.4
## Related Links
- [CyberPanel v2.4.4 Repository](https://github.com/usmannasir/cyberpanel/tree/v2.4.4)
- [CyberPanel Documentation](https://cyberpanel.net/docs/)
## Support
See `rDNS-Fix-README.md` for detailed troubleshooting and support information.

View File

@ -0,0 +1,170 @@
# Installation Guide - rDNS Fix for CyberPanel 2.4.4
## Quick Installation
### Option 1: One-Liner SSH Command (Easiest - Recommended)
Run this single command via SSH:
```bash
sh <(curl https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh || wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
Or using bash:
```bash
bash <(curl -s https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh) || bash <(wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
### Option 2: Local Installation
```bash
cd /path/to/cyberpanel/cyberpanel-mods/rdns
chmod +x rdns-fix.sh
sudo ./rdns-fix.sh
```
### Option 3: Manual Installation
Follow the step-by-step guide below.
## Manual Installation Steps
### Step 1: Backup Original Files
```bash
# Create backup directory
sudo mkdir -p /usr/local/CyberCP/backup_rdns_fix_$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/usr/local/CyberCP/backup_rdns_fix_$(date +%Y%m%d_%H%M%S)"
# Backup files
sudo cp /usr/local/CyberCP/plogical/mailUtilities.py "$BACKUP_DIR/mailUtilities.py"
sudo cp /usr/local/CyberCP/plogical/virtualHostUtilities.py "$BACKUP_DIR/virtualHostUtilities.py"
echo "Backup created at: $BACKUP_DIR"
```
### Step 2: Apply Fix to mailUtilities.py
#### Method A: Using sed (Quick Fix for NameError only)
```bash
# Fix the critical NameError bug
sudo sed -i 's/str(msg)/str(e)/g' /usr/local/CyberCP/plogical/mailUtilities.py
```
#### Method B: Replace the entire function (Comprehensive Fix)
1. Locate the `reverse_dns_lookup` function in `/usr/local/CyberCP/plogical/mailUtilities.py` (around line 1637)
2. Replace the entire function with the content from `mailUtilities_fixed.py` in this mod directory
3. Or use Python to apply the fix:
```python
# Run as root
import re
file_path = '/usr/local/CyberCP/plogical/mailUtilities.py'
with open(file_path, 'r') as f:
content = f.read()
# Find and replace the function
# (You'll need to manually copy the fixed function from mailUtilities_fixed.py)
with open(file_path, 'w') as f:
f.write(content)
```
### Step 3: Apply Fix to virtualHostUtilities.py
1. Open `/usr/local/CyberCP/plogical/virtualHostUtilities.py`
2. Find the `OnBoardingHostName` function
3. Replace the rDNS lookup section (around lines 119-137) with Section 1 from `virtualHostUtilities_fixed.py`
4. Replace the domain validation section (around lines 333-343) with Section 2 from `virtualHostUtilities_fixed.py`
### Step 4: Verify Changes
```bash
# Check if NameError fix is applied
grep -n "str(e)" /usr/local/CyberCP/plogical/mailUtilities.py | grep "Error in fetch rDNS"
# Should show the fixed line, not "str(msg)"
```
### Step 5: Restart CyberPanel
```bash
sudo systemctl restart lscpd
```
### Step 6: Test
1. Access CyberPanel web interface
2. Go to Onboarding page
3. Try configuring a hostname
4. Check that error messages are more descriptive
5. Review logs: `tail -f /home/cyberpanel/cyberpanel.log`
## Verification Checklist
- [ ] Backup created successfully
- [ ] NameError bug fixed (no `str(msg)` in mailUtilities.py)
- [ ] Empty rDNS result handling added
- [ ] Error messages include IP and domain information
- [ ] CyberPanel restarted successfully
- [ ] Tested onboarding process
- [ ] Logs show improved error messages
## Rollback Instructions
If you need to rollback:
```bash
# Find your backup directory
ls -la /usr/local/CyberCP/backup_rdns_fix_*
# Restore files (replace YYYYMMDD_HHMMSS with your backup timestamp)
sudo cp /usr/local/CyberCP/backup_rdns_fix_YYYYMMDD_HHMMSS/mailUtilities.py /usr/local/CyberCP/plogical/mailUtilities.py
sudo cp /usr/local/CyberCP/backup_rdns_fix_YYYYMMDD_HHMMSS/virtualHostUtilities.py /usr/local/CyberCP/plogical/virtualHostUtilities.py
# Restart CyberPanel
sudo systemctl restart lscpd
```
## Troubleshooting
### Issue: Permission Denied
```bash
# Ensure you're running as root
sudo su -
# Check file ownership
ls -la /usr/local/CyberCP/plogical/mailUtilities.py
```
### Issue: Changes Not Applied
1. Verify file paths are correct
2. Check if files were modified: `stat /usr/local/CyberCP/plogical/mailUtilities.py`
3. Ensure CyberPanel was restarted
4. Check for syntax errors: `python3 -m py_compile /usr/local/CyberCP/plogical/mailUtilities.py`
### Issue: Still Getting Errors
1. Check logs: `tail -100 /home/cyberpanel/cyberpanel.log`
2. Verify DNS server availability: `curl https://cyberpanel.net/dnsServers.txt`
3. Test rDNS manually: `dig -x YOUR_IP_ADDRESS`
## Support
For issues or questions:
1. Check the README.md for detailed information
2. Review log files for specific error messages
3. Verify all steps were completed correctly

View File

@ -0,0 +1,51 @@
# Quick Install - rDNS Fix for CyberPanel 2.4.4
## One-Liner SSH Command
Copy and paste this command into your SSH terminal:
```bash
sh <(curl https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh || wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
## Alternative: Using bash
```bash
bash <(curl -s https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh) || bash <(wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
## What It Does
1. ✅ Creates automatic backups
2. ✅ Fixes NameError bug (`str(msg)` → `str(e)`)
3. ✅ Replaces `reverse_dns_lookup()` with improved version
4. ✅ Adds empty rDNS result validation
5. ✅ Improves error messages with debugging info
6. ✅ Restarts CyberPanel automatically
## Requirements
- Root/sudo access
- CyberPanel 2.4.4 installed
- Internet connection (to download script)
## After Installation
1. Test the onboarding process in CyberPanel
2. Check that error messages are more descriptive
3. Review logs if needed: `tail -f /home/cyberpanel/cyberpanel.log`
## Rollback
If needed, restore from backup:
```bash
# Find backup directory
ls -la /usr/local/CyberCP/backup_rdns_fix_*
# Restore (replace TIMESTAMP with actual backup timestamp)
sudo cp /usr/local/CyberCP/backup_rdns_fix_TIMESTAMP/mailUtilities.py /usr/local/CyberCP/plogical/mailUtilities.py
sudo cp /usr/local/CyberCP/backup_rdns_fix_TIMESTAMP/virtualHostUtilities.py /usr/local/CyberCP/plogical/virtualHostUtilities.py
sudo systemctl restart lscpd
```

View File

@ -0,0 +1,180 @@
#!/bin/bash
###############################################################################
# CyberPanel rDNS System Fix for v2.4.4
# This script applies fixes to the rDNS validation system
###############################################################################
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# CyberPanel paths
CYBERCP_PATH="/usr/local/CyberCP"
MAIL_UTILITIES="${CYBERCP_PATH}/plogical/mailUtilities.py"
VIRTUAL_HOST_UTILITIES="${CYBERCP_PATH}/plogical/virtualHostUtilities.py"
# Backup directory
BACKUP_DIR="${CYBERCP_PATH}/backup_rdns_fix_$(date +%Y%m%d_%H%M%S)"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}CyberPanel rDNS System Fix v1.0${NC}"
echo -e "${GREEN}For CyberPanel 2.4.4${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Please run as root${NC}"
exit 1
fi
# Check if CyberPanel is installed
if [ ! -d "$CYBERCP_PATH" ]; then
echo -e "${RED}CyberPanel not found at ${CYBERCP_PATH}${NC}"
exit 1
fi
# Check if files exist
if [ ! -f "$MAIL_UTILITIES" ]; then
echo -e "${RED}File not found: ${MAIL_UTILITIES}${NC}"
exit 1
fi
if [ ! -f "$VIRTUAL_HOST_UTILITIES" ]; then
echo -e "${RED}File not found: ${VIRTUAL_HOST_UTILITIES}${NC}"
exit 1
fi
# Create backup directory
echo -e "${YELLOW}Creating backup...${NC}"
mkdir -p "$BACKUP_DIR"
cp "$MAIL_UTILITIES" "${BACKUP_DIR}/mailUtilities.py"
cp "$VIRTUAL_HOST_UTILITIES" "${BACKUP_DIR}/virtualHostUtilities.py"
echo -e "${GREEN}Backup created at: ${BACKUP_DIR}${NC}"
echo ""
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Check if patch files exist
PATCH_MAIL="${SCRIPT_DIR}/mailUtilities.py.patch"
PATCH_VHOST="${SCRIPT_DIR}/virtualHostUtilities.py.patch"
# Function to apply Python code fix
apply_mail_utilities_fix() {
echo -e "${YELLOW}Applying fix to mailUtilities.py...${NC}"
# Create temporary Python script to apply the fix
python3 << 'PYTHON_SCRIPT'
import re
import sys
file_path = sys.argv[1]
try:
with open(file_path, 'r') as f:
content = f.read()
# Fix 1: Replace str(msg) with str(e) in exception handler
content = re.sub(
r"logging\.CyberCPLogFileWriter\.writeToFile\(f'Error in fetch rDNS \{str\(msg\)\}'\)",
"logging.CyberCPLogFileWriter.writeToFile(f'Error in fetch rDNS {str(e)}')",
content
)
# Fix 2: Check if reverse_dns_lookup function needs comprehensive fix
# This is a more complex fix that requires the full function replacement
# We'll use a marker-based approach
# Check if the old buggy version exists
if "str(msg)" in content and "reverse_dns_lookup" in content:
print("Found buggy version, applying comprehensive fix...")
# Read the fixed version from a separate file or embed it
# For now, we'll do a targeted fix
pass
with open(file_path, 'w') as f:
f.write(content)
print("Fix applied successfully")
except Exception as e:
print(f"Error applying fix: {e}")
sys.exit(1)
PYTHON_SCRIPT
"$MAIL_UTILITIES"
if [ $? -eq 0 ]; then
echo -e "${GREEN}mailUtilities.py fix applied${NC}"
else
echo -e "${RED}Failed to apply fix to mailUtilities.py${NC}"
return 1
fi
}
# Function to check if fix is already applied
check_if_fixed() {
if grep -q "str(e)" "$MAIL_UTILITIES" && ! grep -q "str(msg)" "$MAIL_UTILITIES"; then
return 0 # Fixed
else
return 1 # Not fixed
fi
}
# Main installation
echo -e "${YELLOW}Checking current state...${NC}"
if check_if_fixed; then
echo -e "${GREEN}Fix appears to already be applied${NC}"
read -p "Do you want to reapply? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}Aborted${NC}"
exit 0
fi
fi
# Apply fixes
echo ""
echo -e "${YELLOW}Applying fixes...${NC}"
# Fix 1: mailUtilities.py - NameError bug
if grep -q "str(msg)" "$MAIL_UTILITIES"; then
sed -i 's/str(msg)/str(e)/g' "$MAIL_UTILITIES"
echo -e "${GREEN}✓ Fixed NameError bug in mailUtilities.py${NC}"
else
echo -e "${YELLOW}⚠ NameError fix not needed (may already be fixed)${NC}"
fi
# Note: The comprehensive fixes require full function replacement
# which is better done manually or with a proper patch file
echo ""
echo -e "${YELLOW}Note: This script applies the critical NameError fix.${NC}"
echo -e "${YELLOW}For comprehensive fixes (error handling improvements),${NC}"
echo -e "${YELLOW}please refer to the README.md for manual installation steps.${NC}"
echo ""
# Restart CyberPanel
echo -e "${YELLOW}Restarting CyberPanel...${NC}"
if systemctl is-active --quiet lscpd; then
systemctl restart lscpd
echo -e "${GREEN}CyberPanel restarted${NC}"
else
echo -e "${YELLOW}CyberPanel service not running, skipping restart${NC}"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Fix applied successfully!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${YELLOW}Backup location: ${BACKUP_DIR}${NC}"
echo -e "${YELLOW}Please test the rDNS functionality and review logs if needed.${NC}"
echo ""

View File

@ -0,0 +1,134 @@
# Fixed reverse_dns_lookup function for CyberPanel 2.4.4
# Replace the reverse_dns_lookup function in /usr/local/CyberCP/plogical/mailUtilities.py
#
# Original function location: around line 1637
# This is the complete fixed function to replace the original
@staticmethod
def reverse_dns_lookup(ip_address):
"""
Perform reverse DNS lookup for the given IP address using external DNS servers.
Args:
ip_address: The IP address to perform reverse DNS lookup on
Returns:
list: List of rDNS hostnames found, or empty list if lookup fails
"""
try:
import requests
from requests.exceptions import RequestException, Timeout, ConnectionError
# Fetch DNS server URLs with proper error handling
try:
fetchURLs = requests.get('https://cyberpanel.net/dnsServers.txt', timeout=10)
except (ConnectionError, Timeout) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list from cyberpanel.net: {str(e)}')
return []
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while fetching DNS server list: {str(e)}')
return []
if fetchURLs.status_code != 200:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list: HTTP {fetchURLs.status_code}')
return []
try:
urls_data = fetchURLs.json()
if 'urls' not in urls_data:
logging.CyberCPLogFileWriter.writeToFile('DNS server list response missing "urls" key')
return []
urls = urls_data['urls']
except (ValueError, KeyError) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse DNS server list JSON: {str(e)}')
return []
if not isinstance(urls, list) or len(urls) == 0:
logging.CyberCPLogFileWriter.writeToFile('DNS server list is empty or invalid')
return []
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS urls {urls}.')
results = []
successful_queries = 0
# Query each DNS server
for url in urls:
try:
response = requests.get(f'{url}/index.php?ip={ip_address}', timeout=5)
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'url to call {ip_address} is {url}')
if response.status_code == 200:
try:
data = response.json()
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'response from dns system {str(data)}')
# Validate response structure
if not isinstance(data, dict):
logging.CyberCPLogFileWriter.writeToFile(f'Invalid response format from {url}: not a dictionary')
continue
if 'status' not in data:
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing "status" key')
continue
if data['status'] == 1:
# Validate results structure
if 'results' not in data or not isinstance(data['results'], dict):
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing or invalid "results" key')
continue
results_dict = data['results']
# Safely extract results from different DNS servers
dns_servers = ['8.8.8.8', '1.1.1.1', '9.9.9.9']
for dns_server in dns_servers:
if dns_server in results_dict:
result_value = results_dict[dns_server]
if result_value and result_value not in results:
results.append(result_value)
successful_queries += 1
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned status != 1: {data.get("status", "unknown")}')
except ValueError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse JSON response from {url}: {str(e)}')
continue
except KeyError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Missing key in response from {url}: {str(e)}')
continue
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned HTTP {response.status_code}')
except Timeout as e:
logging.CyberCPLogFileWriter.writeToFile(f'Timeout while querying DNS server {url}: {str(e)}')
continue
except ConnectionError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Connection error while querying DNS server {url}: {str(e)}')
continue
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while querying DNS server {url}: {str(e)}')
continue
except Exception as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error while querying DNS server {url}: {str(e)}')
continue
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'rDNS result of {ip_address} is {str(results)} (successful queries: {successful_queries}/{len(urls)})')
# Return results (empty list if no successful queries)
return results
except ImportError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to import requests library: {str(e)}')
return []
except BaseException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error in reverse_dns_lookup for IP {ip_address}: {str(e)}')
return []

View File

@ -0,0 +1,223 @@
# CyberPanel rDNS System Fix for v2.4.4
## Overview
This fix addresses critical bugs and issues in the rDNS (reverse DNS) validation system in CyberPanel 2.4.4. The problems typically occur during the onboarding process when configuring a hostname, causing errors like:
- `Domain that you have provided is not configured as rDNS for your server IP. [404]`
- `Failed to perform reverse DNS lookup: [404]`
- Silent failures when DNS lookup services are unavailable
## Issues Fixed
### 1. Critical NameError Bug (`mailUtilities.reverse_dns_lookup()`)
- **Problem**: Line 1681 used undefined variable `msg` instead of `e` in exception handler, causing NameError
- **Fix**: Changed `str(msg)` to `str(e)` to correctly reference the exception object
### 2. Empty List Handling
- **Problem**: When `reverse_dns_lookup()` returns empty list (network/API failures), validation always fails even if domain is correctly configured
- **Fix**: Added proper validation to distinguish between "lookup failed" and "domain not found in rDNS"
### 3. Silent Exception Swallowing
- **Problem**: Broad `except: pass` blocks hide errors and make debugging impossible
- **Fix**: Replaced with specific exception handling (Timeout, ConnectionError, RequestException) with proper logging
### 4. Missing API Failure Handling
- **Problem**: No proper error handling when `https://cyberpanel.net/dnsServers.txt` is unavailable
- **Fix**: Added comprehensive error handling for network failures, invalid responses, and missing JSON keys
### 5. Logic Flow Issue
- **Problem**: When rDNS lookup fails but `skipRDNSCheck` is False, code still validates against empty list
- **Fix**: Added validation to check if rDNS results are empty before domain validation
### 6. Improved Error Messages
- **Problem**: Generic error messages don't provide enough information for debugging
- **Fix**: Enhanced error messages include server IP, domain name, current rDNS records, and actionable guidance
## Files Modified
1. **`cyberpanel/plogical/mailUtilities.py`**
- Fixed `reverse_dns_lookup()` function (lines 1637-1683)
- Added comprehensive error handling and logging
- Added API response validation
- Improved timeout and connection error handling
2. **`cyberpanel/plogical/virtualHostUtilities.py`**
- Enhanced `OnBoardingHostName()` function (lines 119-343)
- Added empty rDNS result validation
- Improved error messages with debugging information
- Better distinction between lookup failures and domain mismatches
## Installation
### One-Liner SSH Command (Easiest - Recommended)
Run this single command via SSH:
```bash
sh <(curl https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh || wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
Or using bash:
```bash
bash <(curl -s https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh) || bash <(wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
```
### Local Installation
```bash
# Make the script executable
chmod +x cyberpanel/cyberpanel-mods/rdns/rdns-fix.sh
# Run the fix script
sudo ./cyberpanel/cyberpanel-mods/rdns/rdns-fix.sh
```
### Manual Installation
#### Step 1: Backup Original Files
```bash
# Backup mailUtilities.py
cp /usr/local/CyberCP/plogical/mailUtilities.py /usr/local/CyberCP/plogical/mailUtilities.py.backup.$(date +%Y%m%d_%H%M%S)
# Backup virtualHostUtilities.py
cp /usr/local/CyberCP/plogical/virtualHostUtilities.py /usr/local/CyberCP/plogical/virtualHostUtilities.py.backup.$(date +%Y%m%d_%H%M%S)
```
#### Step 2: Apply Fixes
Copy the fixed code from this mod to the respective files:
1. Replace `reverse_dns_lookup()` function in `/usr/local/CyberCP/plogical/mailUtilities.py`
2. Update `OnBoardingHostName()` function in `/usr/local/CyberCP/plogical/virtualHostUtilities.py`
#### Step 3: Restart CyberPanel
```bash
systemctl restart lscpd
```
## Verification
After applying the fix:
1. **Test rDNS Lookup**: Try the onboarding process with a valid domain
2. **Check Error Messages**: Error messages should now be more descriptive
3. **Test Empty Results**: System should properly handle DNS lookup failures
4. **Check Logs**: Review `/home/cyberpanel/cyberpanel.log` for detailed error information
## Code Changes Summary
### mailUtilities.py - reverse_dns_lookup()
**Before:**
```python
except BaseException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Error in fetch rDNS {str(msg)}') # BUG: msg undefined
return []
```
**After:**
```python
except BaseException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error in reverse_dns_lookup for IP {ip_address}: {str(e)}')
return []
```
### virtualHostUtilities.py - OnBoardingHostName()
**Before:**
```python
rDNS = mailUtilities.reverse_dns_lookup(serverIP)
# ... later ...
if Domain not in rDNS:
message = 'Domain that you have provided is not configured as rDNS for your server IP. [404]'
```
**After:**
```python
rDNS = mailUtilities.reverse_dns_lookup(serverIP)
if not rDNS or len(rDNS) == 0:
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}...'
return 0
# ... later ...
if Domain not in rDNS:
rDNS_list_str = ', '.join(rDNS) if rDNS else 'none'
message = f'Domain "{Domain}" that you have provided is not configured as rDNS for your server IP {serverIP}. Current rDNS records: {rDNS_list_str}...'
```
## Troubleshooting
### Common Issues
1. **Fix not applying**
- Verify file paths: `/usr/local/CyberCP/plogical/`
- Check file permissions: `ls -la /usr/local/CyberCP/plogical/mailUtilities.py`
- Ensure CyberPanel is restarted: `systemctl restart lscpd`
2. **Still getting errors**
- Check logs: `tail -f /home/cyberpanel/cyberpanel.log`
- Verify DNS server availability: `curl https://cyberpanel.net/dnsServers.txt`
- Test rDNS manually: `dig -x YOUR_IP_ADDRESS`
3. **Empty rDNS results**
- Verify your IP has rDNS configured: Contact your hosting provider
- Check if DNS servers are accessible: Review network connectivity
- Consider using "Skip rDNS/PTR Check" if email services aren't needed
### Log Files
- **CyberPanel Log**: `/home/cyberpanel/cyberpanel.log`
- **Debug Log**: Check if `/home/cyberpanel/debug` exists for detailed logging
- **LiteSpeed Error Log**: `/usr/local/lsws/logs/error.log`
## Compatibility
- **CyberPanel Version**: 2.4.4
- **Python Version**: 3.6+ (compatible with CyberPanel 2.4.4 requirements)
- **Operating Systems**: All supported by CyberPanel 2.4.4 (Ubuntu, AlmaLinux, RockyLinux, RHEL, CloudLinux, CentOS)
## Rollback
If you need to rollback the changes:
```bash
# Restore from backup
cp /usr/local/CyberCP/plogical/mailUtilities.py.backup.* /usr/local/CyberCP/plogical/mailUtilities.py
cp /usr/local/CyberCP/plogical/virtualHostUtilities.py.backup.* /usr/local/CyberCP/plogical/virtualHostUtilities.py
# Restart CyberPanel
systemctl restart lscpd
```
## Security Considerations
1. **Error Messages**: Enhanced error messages may reveal server IP addresses - this is intentional for debugging but be aware in production
2. **Network Requests**: The fix adds proper timeout handling to prevent hanging requests
3. **Logging**: More detailed logging helps with debugging but may increase log file size
## Support
If you encounter issues after applying this fix:
1. Check the troubleshooting section above
2. Review log files for specific error messages
3. Verify all file permissions and ownership
4. Test with a simple rDNS configuration first
## Changelog
- **v1.0**: Initial fix for rDNS system issues in CyberPanel 2.4.4
- Fixed NameError bug in `reverse_dns_lookup()`
- Added comprehensive error handling
- Improved empty result validation
- Enhanced error messages with debugging information
## References
- [CyberPanel GitHub Repository v2.4.4](https://github.com/usmannasir/cyberpanel/tree/v2.4.4)
- [CyberPanel Documentation](https://cyberpanel.net/docs/)
- [CyberPanel Mods Repository](https://github.com/master3395/cyberpanel-mods)

View File

@ -0,0 +1,367 @@
#!/bin/bash
###############################################################################
# CyberPanel rDNS System Fix for v2.4.4
# Standalone script that can be run via:
# sh <(curl https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh || wget -O - https://raw.githubusercontent.com/master3395/cyberpanel-mods/main/rdns/rdns-fix.sh)
###############################################################################
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# CyberPanel paths
CYBERCP_PATH="/usr/local/CyberCP"
MAIL_UTILITIES="${CYBERCP_PATH}/plogical/mailUtilities.py"
VIRTUAL_HOST_UTILITIES="${CYBERCP_PATH}/plogical/virtualHostUtilities.py"
# Backup directory
BACKUP_DIR="${CYBERCP_PATH}/backup_rdns_fix_$(date +%Y%m%d_%H%M%S)"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}CyberPanel rDNS System Fix v1.0${NC}"
echo -e "${GREEN}For CyberPanel 2.4.4${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Please run as root (use sudo)${NC}"
exit 1
fi
# Check if CyberPanel is installed
if [ ! -d "$CYBERCP_PATH" ]; then
echo -e "${RED}CyberPanel not found at ${CYBERCP_PATH}${NC}"
exit 1
fi
# Check if files exist
if [ ! -f "$MAIL_UTILITIES" ]; then
echo -e "${RED}File not found: ${MAIL_UTILITIES}${NC}"
exit 1
fi
if [ ! -f "$VIRTUAL_HOST_UTILITIES" ]; then
echo -e "${RED}File not found: ${VIRTUAL_HOST_UTILITIES}${NC}"
exit 1
fi
# Create backup directory
echo -e "${YELLOW}Creating backup...${NC}"
mkdir -p "$BACKUP_DIR"
cp "$MAIL_UTILITIES" "${BACKUP_DIR}/mailUtilities.py"
cp "$VIRTUAL_HOST_UTILITIES" "${BACKUP_DIR}/virtualHostUtilities.py"
echo -e "${GREEN}Backup created at: ${BACKUP_DIR}${NC}"
echo ""
# Apply fixes using Python
echo -e "${YELLOW}Applying comprehensive fixes...${NC}"
python3 << 'PYTHON_FIX'
import re
import sys
import os
# File paths
mail_utils = "/usr/local/CyberCP/plogical/mailUtilities.py"
vhost_utils = "/usr/local/CyberCP/plogical/virtualHostUtilities.py"
def fix_mail_utilities():
"""Fix mailUtilities.py - reverse_dns_lookup function"""
try:
with open(mail_utils, 'r') as f:
content = f.read()
original_content = content
# Fix 1: Replace str(msg) with str(e) - Critical NameError bug
content = re.sub(
r"logging\.CyberCPLogFileWriter\.writeToFile\(f'Error in fetch rDNS \{str\(msg\)\}'\)",
"logging.CyberCPLogFileWriter.writeToFile(f'Error in fetch rDNS {str(e)}')",
content
)
# Fix 2: Replace the entire reverse_dns_lookup function with improved version
# Find the function start
func_start_pattern = r'(@staticmethod\s+def reverse_dns_lookup\(ip_address\):.*?)(?=\n @staticmethod|\n def |\Z)'
fixed_function = ''' @staticmethod
def reverse_dns_lookup(ip_address):
"""
Perform reverse DNS lookup for the given IP address using external DNS servers.
Args:
ip_address: The IP address to perform reverse DNS lookup on
Returns:
list: List of rDNS hostnames found, or empty list if lookup fails
"""
try:
import requests
from requests.exceptions import RequestException, Timeout, ConnectionError
# Fetch DNS server URLs with proper error handling
try:
fetchURLs = requests.get('https://cyberpanel.net/dnsServers.txt', timeout=10)
except (ConnectionError, Timeout) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list from cyberpanel.net: {str(e)}')
return []
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while fetching DNS server list: {str(e)}')
return []
if fetchURLs.status_code != 200:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list: HTTP {fetchURLs.status_code}')
return []
try:
urls_data = fetchURLs.json()
if 'urls' not in urls_data:
logging.CyberCPLogFileWriter.writeToFile('DNS server list response missing "urls" key')
return []
urls = urls_data['urls']
except (ValueError, KeyError) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse DNS server list JSON: {str(e)}')
return []
if not isinstance(urls, list) or len(urls) == 0:
logging.CyberCPLogFileWriter.writeToFile('DNS server list is empty or invalid')
return []
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS urls {urls}.')
results = []
successful_queries = 0
# Query each DNS server
for url in urls:
try:
response = requests.get(f'{url}/index.php?ip={ip_address}', timeout=5)
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'url to call {ip_address} is {url}')
if response.status_code == 200:
try:
data = response.json()
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'response from dns system {str(data)}')
# Validate response structure
if not isinstance(data, dict):
logging.CyberCPLogFileWriter.writeToFile(f'Invalid response format from {url}: not a dictionary')
continue
if 'status' not in data:
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing "status" key')
continue
if data['status'] == 1:
# Validate results structure
if 'results' not in data or not isinstance(data['results'], dict):
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing or invalid "results" key')
continue
results_dict = data['results']
# Safely extract results from different DNS servers
dns_servers = ['8.8.8.8', '1.1.1.1', '9.9.9.9']
for dns_server in dns_servers:
if dns_server in results_dict:
result_value = results_dict[dns_server]
if result_value and result_value not in results:
results.append(result_value)
successful_queries += 1
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned status != 1: {data.get("status", "unknown")}')
except ValueError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse JSON response from {url}: {str(e)}')
continue
except KeyError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Missing key in response from {url}: {str(e)}')
continue
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned HTTP {response.status_code}')
except Timeout as e:
logging.CyberCPLogFileWriter.writeToFile(f'Timeout while querying DNS server {url}: {str(e)}')
continue
except ConnectionError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Connection error while querying DNS server {url}: {str(e)}')
continue
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while querying DNS server {url}: {str(e)}')
continue
except Exception as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error while querying DNS server {url}: {str(e)}')
continue
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'rDNS result of {ip_address} is {str(results)} (successful queries: {successful_queries}/{len(urls)})')
# Return results (empty list if no successful queries)
return results
except ImportError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to import requests library: {str(e)}')
return []
except BaseException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error in reverse_dns_lookup for IP {ip_address}: {str(e)}')
return []'''
# Try to replace the function
if re.search(func_start_pattern, content, re.DOTALL):
content = re.sub(func_start_pattern, fixed_function + '\n', content, flags=re.DOTALL)
print("✓ Replaced entire reverse_dns_lookup function")
elif "str(msg)" in content:
# Fallback: just fix the NameError if function replacement didn't work
content = content.replace("str(msg)", "str(e)")
print("✓ Fixed NameError bug (str(msg) -> str(e))")
else:
print("⚠ Function may already be fixed or structure differs")
if content != original_content:
with open(mail_utils, 'w') as f:
f.write(content)
print("✓ mailUtilities.py updated successfully")
return True
else:
print("⚠ No changes needed in mailUtilities.py")
return False
except Exception as e:
print(f"✗ Error fixing mailUtilities.py: {e}")
return False
def fix_virtual_host_utilities():
"""Fix virtualHostUtilities.py - OnBoardingHostName function"""
try:
with open(vhost_utils, 'r') as f:
content = f.read()
original_content = content
changes_made = False
# Fix 1: Add empty rDNS result check after reverse_dns_lookup call
# Find the pattern: rDNS = mailUtilities.reverse_dns_lookup(serverIP)
pattern1 = r'(rDNS = mailUtilities\.reverse_dns_lookup\(serverIP\))\s*\n(\s*except Exception as e:)'
replacement1 = r'''\1
# Check if rDNS lookup returned empty results (indicating lookup failure)
if not rDNS or len(rDNS) == 0:
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}. The DNS lookup service may be unavailable or the IP address may not have rDNS configured. Please verify your rDNS settings with your hosting provider or check the "Skip rDNS/PTR Check" option if you do not need email services. [404]'
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
return 0
\2'''
if re.search(pattern1, content):
content = re.sub(pattern1, replacement1, content)
print("✓ Added empty rDNS result validation")
changes_made = True
# Fix 2: Improve error message in exception handler
pattern2 = r"message = f'Failed to perform reverse DNS lookup: \{str\(e\)\} \[404\]'"
replacement2 = "message = f'Failed to perform reverse DNS lookup for server IP {serverIP}: {str(e)}. Please verify your rDNS settings with your hosting provider or check the \\\"Skip rDNS/PTR Check\\\" option if you do not need email services. [404]'"
if re.search(pattern2, content):
content = re.sub(pattern2, replacement2, content)
print("✓ Improved error message in exception handler")
changes_made = True
# Fix 3: Add validation before domain check and improve error message
pattern3 = r'(#first check if hostname is already configured as rDNS, if not return error\s*\n\s*\n\s*if Domain not in rDNS:)'
replacement3 = r'''#first check if hostname is already configured as rDNS, if not return error
# Validate that we have rDNS results before checking
if not rDNS or len(rDNS) == 0:
message = f'Reverse DNS lookup failed for server IP {serverIP}. Unable to verify if domain "{Domain}" is configured as rDNS. Please check your rDNS configuration with your hosting provider or select "Skip rDNS/PTR Check" if you do not need email services. [404]'
print(message)
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
config['hostname'] = Domain
config['onboarding'] = 3
config['skipRDNSCheck'] = skipRDNSCheck
admin.config = json.dumps(config)
admin.save()
return 0
if Domain not in rDNS:'''
if re.search(pattern3, content):
content = re.sub(pattern3, replacement3, content)
print("✓ Added rDNS validation before domain check")
changes_made = True
# Fix 4: Improve domain mismatch error message
pattern4 = r"message = 'Domain that you have provided is not configured as rDNS for your server IP\. \[404\]'"
replacement4 = r'''rDNS_list_str = ', '.join(rDNS) if rDNS else 'none'
message = f'Domain "{Domain}" that you have provided is not configured as rDNS for your server IP {serverIP}. Current rDNS records: {rDNS_list_str}. Please configure rDNS (PTR record) for your IP address to point to "{Domain}" with your hosting provider, or select "Skip rDNS/PTR Check" if you do not need email services. [404]''''
if re.search(pattern4, content):
content = re.sub(pattern4, replacement4, content)
print("✓ Improved domain mismatch error message")
changes_made = True
if changes_made and content != original_content:
with open(vhost_utils, 'w') as f:
f.write(content)
print("✓ virtualHostUtilities.py updated successfully")
return True
else:
print("⚠ No changes needed in virtualHostUtilities.py")
return False
except Exception as e:
print(f"✗ Error fixing virtualHostUtilities.py: {e}")
return False
# Apply fixes
print("\nFixing mailUtilities.py...")
fix_mail_utilities()
print("\nFixing virtualHostUtilities.py...")
fix_virtual_host_utilities()
print("\n✓ All fixes applied!")
PYTHON_FIX
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ All fixes applied successfully${NC}"
else
echo -e "${RED}✗ Some fixes may have failed. Check output above.${NC}"
exit 1
fi
# Restart CyberPanel
echo ""
echo -e "${YELLOW}Restarting CyberPanel...${NC}"
if systemctl is-active --quiet lscpd 2>/dev/null || systemctl is-active --quiet cyberpanel 2>/dev/null; then
if systemctl restart lscpd 2>/dev/null; then
echo -e "${GREEN}✓ CyberPanel restarted${NC}"
elif systemctl restart cyberpanel 2>/dev/null; then
echo -e "${GREEN}✓ CyberPanel restarted${NC}"
else
echo -e "${YELLOW}⚠ Could not restart CyberPanel automatically. Please restart manually.${NC}"
fi
else
echo -e "${YELLOW}⚠ CyberPanel service not running, skipping restart${NC}"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Fix applied successfully!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${YELLOW}Backup location: ${BACKUP_DIR}${NC}"
echo -e "${YELLOW}Please test the rDNS functionality in CyberPanel onboarding.${NC}"
echo ""

View File

@ -0,0 +1,62 @@
# Fixed OnBoardingHostName function sections for CyberPanel 2.4.4
# Replace the relevant sections in /usr/local/CyberCP/plogical/virtualHostUtilities.py
#
# Section 1: Replace the rDNS lookup section (around line 119-137)
# Section 2: Replace the domain validation section (around line 333-343)
# ============================================================================
# SECTION 1: Replace lines 119-137 in OnBoardingHostName function
# ============================================================================
### if skipRDNSCheck == 1, it means we need to skip checking for rDNS
if skipRDNSCheck:
### When skipping rDNS check, include both current hostname and the domain being set up
### This ensures both code paths work correctly
rDNS = [CurrentHostName, Domain]
else:
try:
rDNS = mailUtilities.reverse_dns_lookup(serverIP)
# Check if rDNS lookup returned empty results (indicating lookup failure)
if not rDNS or len(rDNS) == 0:
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}. The DNS lookup service may be unavailable or the IP address may not have rDNS configured. Please verify your rDNS settings with your hosting provider or check the "Skip rDNS/PTR Check" option if you do not need email services. [404]'
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
return 0
except Exception as e:
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}: {str(e)}. Please verify your rDNS settings with your hosting provider or check the "Skip rDNS/PTR Check" option if you do not need email services. [404]'
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
return 0
# ============================================================================
# SECTION 2: Replace lines 333-343 in OnBoardingHostName function
# ============================================================================
#first check if hostname is already configured as rDNS, if not return error
# Validate that we have rDNS results before checking
if not rDNS or len(rDNS) == 0:
message = f'Reverse DNS lookup failed for server IP {serverIP}. Unable to verify if domain "{Domain}" is configured as rDNS. Please check your rDNS configuration with your hosting provider or select "Skip rDNS/PTR Check" if you do not need email services. [404]'
print(message)
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
config['hostname'] = Domain
config['onboarding'] = 3
config['skipRDNSCheck'] = skipRDNSCheck
admin.config = json.dumps(config)
admin.save()
return 0
if Domain not in rDNS:
rDNS_list_str = ', '.join(rDNS) if rDNS else 'none'
message = f'Domain "{Domain}" that you have provided is not configured as rDNS for your server IP {serverIP}. Current rDNS records: {rDNS_list_str}. Please configure rDNS (PTR record) for your IP address to point to "{Domain}" with your hosting provider, or select "Skip rDNS/PTR Check" if you do not need email services. [404]'
print(message)
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
config['hostname'] = Domain
config['onboarding'] = 3
config['skipRDNSCheck'] = skipRDNSCheck
admin.config = json.dumps(config)
admin.save()
return 0

View File

@ -1635,51 +1635,130 @@ LogFile /var/log/clamav/clamav.log
@staticmethod
def reverse_dns_lookup(ip_address):
"""
Perform reverse DNS lookup for the given IP address using external DNS servers.
Args:
ip_address: The IP address to perform reverse DNS lookup on
Returns:
list: List of rDNS hostnames found, or empty list if lookup fails
"""
try:
import requests
from requests.exceptions import RequestException, Timeout, ConnectionError
fetchURLs = requests.get('https://cyberpanel.net/dnsServers.txt')
# Fetch DNS server URLs with proper error handling
try:
fetchURLs = requests.get('https://cyberpanel.net/dnsServers.txt', timeout=10)
except (ConnectionError, Timeout) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list from cyberpanel.net: {str(e)}')
return []
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while fetching DNS server list: {str(e)}')
return []
if fetchURLs.status_code == 200:
if fetchURLs.status_code != 200:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to fetch DNS server list: HTTP {fetchURLs.status_code}')
return []
urls = fetchURLs.json()['urls']
try:
urls_data = fetchURLs.json()
if 'urls' not in urls_data:
logging.CyberCPLogFileWriter.writeToFile('DNS server list response missing "urls" key')
return []
urls = urls_data['urls']
except (ValueError, KeyError) as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse DNS server list JSON: {str(e)}')
return []
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS urls {urls}.')
if not isinstance(urls, list) or len(urls) == 0:
logging.CyberCPLogFileWriter.writeToFile('DNS server list is empty or invalid')
return []
results = []
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS urls {urls}.')
###
results = []
successful_queries = 0
for url in urls:
try:
response = requests.get(f'{url}/index.php?ip={ip_address}', timeout=5)
# Query each DNS server
for url in urls:
try:
response = requests.get(f'{url}/index.php?ip={ip_address}', timeout=5)
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'url to call {ip_address} is {url}')
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'url to call {ip_address} is {url}')
if response.status_code == 200:
if response.status_code == 200:
try:
data = response.json()
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'response from dns system {str(data)}')
# Validate response structure
if not isinstance(data, dict):
logging.CyberCPLogFileWriter.writeToFile(f'Invalid response format from {url}: not a dictionary')
continue
if 'status' not in data:
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing "status" key')
continue
if data['status'] == 1:
results.append(data['results']['8.8.8.8'])
results.append(data['results']['1.1.1.1'])
results.append(data['results']['9.9.9.9'])
except:
pass
# Validate results structure
if 'results' not in data or not isinstance(data['results'], dict):
logging.CyberCPLogFileWriter.writeToFile(f'Response from {url} missing or invalid "results" key')
continue
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'rDNS result of {ip_address} is {str(results)}')
results_dict = data['results']
# Safely extract results from different DNS servers
dns_servers = ['8.8.8.8', '1.1.1.1', '9.9.9.9']
for dns_server in dns_servers:
if dns_server in results_dict:
result_value = results_dict[dns_server]
if result_value and result_value not in results:
results.append(result_value)
successful_queries += 1
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned status != 1: {data.get("status", "unknown")}')
except ValueError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to parse JSON response from {url}: {str(e)}')
continue
except KeyError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Missing key in response from {url}: {str(e)}')
continue
else:
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'DNS server {url} returned HTTP {response.status_code}')
except Timeout as e:
logging.CyberCPLogFileWriter.writeToFile(f'Timeout while querying DNS server {url}: {str(e)}')
continue
except ConnectionError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Connection error while querying DNS server {url}: {str(e)}')
continue
except RequestException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Request error while querying DNS server {url}: {str(e)}')
continue
except Exception as e:
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error while querying DNS server {url}: {str(e)}')
continue
###
if os.path.exists(ProcessUtilities.debugPath):
logging.CyberCPLogFileWriter.writeToFile(f'rDNS result of {ip_address} is {str(results)} (successful queries: {successful_queries}/{len(urls)})')
return results
# Return results (empty list if no successful queries)
return results
except ImportError as e:
logging.CyberCPLogFileWriter.writeToFile(f'Failed to import requests library: {str(e)}')
return []
except BaseException as e:
logging.CyberCPLogFileWriter.writeToFile(f'Error in fetch rDNS {str(msg)}')
# Handle errors, e.g., if reverse DNS lookup fails
logging.CyberCPLogFileWriter.writeToFile(f'Unexpected error in reverse_dns_lookup for IP {ip_address}: {str(e)}')
return []
@staticmethod

View File

@ -124,8 +124,14 @@ class virtualHostUtilities:
else:
try:
rDNS = mailUtilities.reverse_dns_lookup(serverIP)
# Check if rDNS lookup returned empty results (indicating lookup failure)
if not rDNS or len(rDNS) == 0:
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}. The DNS lookup service may be unavailable or the IP address may not have rDNS configured. Please verify your rDNS settings with your hosting provider or check the "Skip rDNS/PTR Check" option if you do not need email services. [404]'
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
return 0
except Exception as e:
message = f'Failed to perform reverse DNS lookup: {str(e)} [404]'
message = f'Failed to perform reverse DNS lookup for server IP {serverIP}: {str(e)}. Please verify your rDNS settings with your hosting provider or check the "Skip rDNS/PTR Check" option if you do not need email services. [404]'
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
return 0
@ -329,9 +335,22 @@ class virtualHostUtilities:
#first check if hostname is already configured as rDNS, if not return error
# Validate that we have rDNS results before checking
if not rDNS or len(rDNS) == 0:
message = f'Reverse DNS lookup failed for server IP {serverIP}. Unable to verify if domain "{Domain}" is configured as rDNS. Please check your rDNS configuration with your hosting provider or select "Skip rDNS/PTR Check" if you do not need email services. [404]'
print(message)
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)
config['hostname'] = Domain
config['onboarding'] = 3
config['skipRDNSCheck'] = skipRDNSCheck
admin.config = json.dumps(config)
admin.save()
return 0
if Domain not in rDNS:
message = 'Domain that you have provided is not configured as rDNS for your server IP. [404]'
rDNS_list_str = ', '.join(rDNS) if rDNS else 'none'
message = f'Domain "{Domain}" that you have provided is not configured as rDNS for your server IP {serverIP}. Current rDNS records: {rDNS_list_str}. Please configure rDNS (PTR record) for your IP address to point to "{Domain}" with your hosting provider, or select "Skip rDNS/PTR Check" if you do not need email services. [404]'
print(message)
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
logging.CyberCPLogFileWriter.writeToFile(message)