mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-07 09:26:24 +02:00
Merge pull request #1664 from master3395/v2.5.5-dev
…tent-type, fix IP validation, and add comprehensive logging - Fixed IP validation logic in blockIPAddress function - Added proper JSON content-type header in firewallManager.py addBannedIP response - Improved error handling with try-catch wrapper - Added comprehensive console logging for debugging - Fixed button onclick handler interference with ng-click - Added $scope.$apply() calls for proper AngularJS view updates - Enhanced error message parsing and display - Fixed duplicate error notification prevention
This commit is contained in:
@@ -1011,8 +1011,84 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
|
||||
};
|
||||
|
||||
$scope.blockIPAddress = function(ipAddress) {
|
||||
if (!$scope.blockingIP) {
|
||||
$scope.blockingIP = ipAddress;
|
||||
try {
|
||||
console.log('========================================');
|
||||
console.log('=== blockIPAddress CALLED ===');
|
||||
console.log('========================================');
|
||||
console.log('blockIPAddress called with:', ipAddress);
|
||||
console.log('ipAddress type:', typeof ipAddress);
|
||||
console.log('ipAddress value:', ipAddress);
|
||||
console.log('$scope:', $scope);
|
||||
console.log('$scope.blockIPAddress:', typeof $scope.blockIPAddress);
|
||||
|
||||
// Validate IP address parameter
|
||||
if (!ipAddress) {
|
||||
console.error('No IP address provided:', ipAddress);
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'No IP address provided',
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure it's a string and trim it
|
||||
ipAddress = String(ipAddress).trim();
|
||||
|
||||
// Validate after trimming
|
||||
if (!ipAddress || ipAddress === '' || ipAddress === 'undefined' || ipAddress === 'null') {
|
||||
console.error('IP address is empty or invalid after trim:', ipAddress);
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'Invalid IP address provided: ' + ipAddress,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic IP format validation
|
||||
var ipPattern = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
|
||||
if (!ipPattern.test(ipAddress)) {
|
||||
console.error('IP address format is invalid:', ipAddress);
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'Invalid IP address format: ' + ipAddress,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent duplicate requests
|
||||
if ($scope.blockingIP === ipAddress) {
|
||||
console.log('Already processing IP:', ipAddress);
|
||||
return; // Already processing this IP
|
||||
}
|
||||
|
||||
// Check if already blocked
|
||||
if ($scope.blockedIPs && $scope.blockedIPs[ipAddress]) {
|
||||
console.log('IP already blocked:', ipAddress);
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Info',
|
||||
text: `IP address ${ipAddress} is already banned`,
|
||||
type: 'info',
|
||||
delay: 3000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Set blocking flag to prevent duplicate requests
|
||||
$scope.blockingIP = ipAddress;
|
||||
|
||||
// Use the new Banned IPs system instead of the old blockIPAddress
|
||||
var data = {
|
||||
@@ -1027,48 +1103,265 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
|
||||
}
|
||||
};
|
||||
|
||||
console.log('Sending ban IP request:', data);
|
||||
console.log('CSRF Token:', getCookie('csrftoken'));
|
||||
console.log('Config:', config);
|
||||
|
||||
$http.post('/firewall/addBannedIP', data, config).then(function (response) {
|
||||
console.log('=== addBannedIP SUCCESS ===');
|
||||
console.log('Full response:', response);
|
||||
console.log('response.data:', response.data);
|
||||
console.log('response.data type:', typeof response.data);
|
||||
console.log('response.status:', response.status);
|
||||
|
||||
// Reset blocking flag
|
||||
$scope.blockingIP = null;
|
||||
if (response.data && response.data.status === 1) {
|
||||
|
||||
// Apply scope changes
|
||||
if (!$scope.$$phase && !$scope.$root.$$phase) {
|
||||
$scope.$apply();
|
||||
}
|
||||
|
||||
// Handle both JSON string and object responses
|
||||
var responseData = response.data;
|
||||
if (typeof responseData === 'string') {
|
||||
try {
|
||||
responseData = JSON.parse(responseData);
|
||||
console.log('Parsed responseData from string:', responseData);
|
||||
} catch (e) {
|
||||
console.error('Failed to parse response as JSON:', e);
|
||||
console.error('Raw response string:', responseData);
|
||||
// Try to extract error from string
|
||||
if (responseData.includes('error')) {
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'Failed to block IP address: ' + responseData,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Final responseData:', responseData);
|
||||
console.log('responseData.status:', responseData ? responseData.status : 'undefined');
|
||||
console.log('responseData.message:', responseData ? responseData.message : 'undefined');
|
||||
console.log('responseData.error_message:', responseData ? responseData.error_message : 'undefined');
|
||||
|
||||
// Check for success (status === 1 or status === '1')
|
||||
if (responseData && (responseData.status === 1 || responseData.status === '1')) {
|
||||
// Mark IP as blocked
|
||||
if (!$scope.blockedIPs) {
|
||||
$scope.blockedIPs = {};
|
||||
}
|
||||
$scope.blockedIPs[ipAddress] = true;
|
||||
|
||||
// Show success notification
|
||||
new PNotify({
|
||||
title: 'IP Address Banned',
|
||||
text: `IP address ${ipAddress} has been permanently banned and added to the firewall. You can manage it in the Firewall > Banned IPs section.`,
|
||||
type: 'success',
|
||||
delay: 5000
|
||||
});
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'IP Address Banned',
|
||||
text: `IP address ${ipAddress} has been permanently banned and added to the firewall. You can manage it in the Firewall > Banned IPs section.`,
|
||||
type: 'success',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh security analysis to update alerts
|
||||
$scope.analyzeSSHSecurity();
|
||||
if ($scope.analyzeSSHSecurity) {
|
||||
$scope.analyzeSSHSecurity();
|
||||
}
|
||||
|
||||
// Apply scope changes
|
||||
if (!$scope.$$phase && !$scope.$root.$$phase) {
|
||||
$scope.$apply();
|
||||
}
|
||||
} else {
|
||||
// Show error notification
|
||||
var errorMsg = 'Failed to block IP address';
|
||||
if (responseData && responseData.error_message) {
|
||||
errorMsg = responseData.error_message;
|
||||
} else if (responseData && responseData.error) {
|
||||
errorMsg = responseData.error;
|
||||
} else if (responseData && responseData.message) {
|
||||
errorMsg = responseData.message;
|
||||
} else if (responseData) {
|
||||
errorMsg = JSON.stringify(responseData);
|
||||
}
|
||||
console.error('Ban IP failed:', errorMsg);
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: errorMsg,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
}
|
||||
}, function (err) {
|
||||
$scope.blockingIP = null;
|
||||
console.error('addBannedIP error:', err);
|
||||
console.error('Error status:', err.status);
|
||||
console.error('Error statusText:', err.statusText);
|
||||
console.error('Error data:', err.data);
|
||||
|
||||
// Prevent showing duplicate error notifications
|
||||
if ($scope.lastErrorIP === ipAddress && $scope.lastErrorTime && (Date.now() - $scope.lastErrorTime) < 2000) {
|
||||
console.log('Skipping duplicate error notification for IP:', ipAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.lastErrorIP = ipAddress;
|
||||
$scope.lastErrorTime = Date.now();
|
||||
|
||||
var errorMessage = 'Failed to block IP address';
|
||||
if (err.data) {
|
||||
var errData = err.data;
|
||||
if (typeof errData === 'string') {
|
||||
try {
|
||||
errData = JSON.parse(errData);
|
||||
} catch (e) {
|
||||
errorMessage = errData || errorMessage;
|
||||
}
|
||||
}
|
||||
if (errData && typeof errData === 'object') {
|
||||
if (errData.error_message) {
|
||||
errorMessage = errData.error_message;
|
||||
} else if (errData.error) {
|
||||
errorMessage = errData.error;
|
||||
} else if (errData.message) {
|
||||
errorMessage = errData.message;
|
||||
}
|
||||
}
|
||||
} else if (err.statusText) {
|
||||
errorMessage = err.statusText;
|
||||
} else if (err.status) {
|
||||
errorMessage = `HTTP ${err.status}: ${err.statusText || 'Unknown error'}`;
|
||||
}
|
||||
|
||||
console.error('Final error message:', errorMessage);
|
||||
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: response.data && response.data.error ? response.data.error : 'Failed to block IP address',
|
||||
text: errorMessage,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
}, function (err) {
|
||||
$scope.blockingIP = null;
|
||||
var errorMessage = 'Failed to block IP address';
|
||||
if (err.data && err.data.error) {
|
||||
errorMessage = err.data.error;
|
||||
} else if (err.data && err.data.message) {
|
||||
errorMessage = err.data.message;
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('========================================');
|
||||
console.error('=== ERROR in blockIPAddress ===');
|
||||
console.error('========================================');
|
||||
console.error('Error:', e);
|
||||
console.error('Error message:', e.message);
|
||||
console.error('Error stack:', e.stack);
|
||||
$scope.blockingIP = null;
|
||||
if (typeof PNotify !== 'undefined') {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'An error occurred while trying to ban the IP address: ' + (e.message || String(e)),
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Ban IP from SSH Logs
|
||||
$scope.banIPFromSSHLog = function(ipAddress) {
|
||||
if (!ipAddress) {
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: 'No IP address provided',
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.blockingIP === ipAddress) {
|
||||
return; // Already processing
|
||||
}
|
||||
|
||||
if ($scope.blockedIPs[ipAddress]) {
|
||||
new PNotify({
|
||||
title: 'Info',
|
||||
text: `IP address ${ipAddress} is already banned`,
|
||||
type: 'info',
|
||||
delay: 3000
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.blockingIP = ipAddress;
|
||||
|
||||
// Use the Banned IPs system
|
||||
var data = {
|
||||
ip: ipAddress,
|
||||
reason: 'Suspicious activity detected from SSH logs',
|
||||
duration: 'permanent'
|
||||
};
|
||||
|
||||
var config = {
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
};
|
||||
|
||||
$http.post('/firewall/addBannedIP', data, config).then(function (response) {
|
||||
$scope.blockingIP = null;
|
||||
if (response.data && response.data.status === 1) {
|
||||
// Mark IP as blocked
|
||||
$scope.blockedIPs[ipAddress] = true;
|
||||
|
||||
// Show success notification
|
||||
new PNotify({
|
||||
title: 'IP Address Banned',
|
||||
text: `IP address ${ipAddress} has been permanently banned and added to the firewall. You can manage it in the Firewall > Banned IPs section.`,
|
||||
type: 'success',
|
||||
delay: 5000
|
||||
});
|
||||
|
||||
// Refresh SSH logs to update the UI
|
||||
$scope.refreshSSHLogs();
|
||||
} else {
|
||||
// Show error notification
|
||||
var errorMsg = 'Failed to ban IP address';
|
||||
if (response.data && response.data.error_message) {
|
||||
errorMsg = response.data.error_message;
|
||||
} else if (response.data && response.data.error) {
|
||||
errorMsg = response.data.error;
|
||||
}
|
||||
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: errorMessage,
|
||||
text: errorMsg,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
}, function (err) {
|
||||
$scope.blockingIP = null;
|
||||
var errorMessage = 'Failed to ban IP address';
|
||||
if (err.data && err.data.error_message) {
|
||||
errorMessage = err.data.error_message;
|
||||
} else if (err.data && err.data.error) {
|
||||
errorMessage = err.data.error;
|
||||
} else if (err.data && err.data.message) {
|
||||
errorMessage = err.data.message;
|
||||
}
|
||||
|
||||
new PNotify({
|
||||
title: 'Error',
|
||||
text: errorMessage,
|
||||
type: 'error',
|
||||
delay: 5000
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Initial fetch
|
||||
|
||||
@@ -972,22 +972,23 @@
|
||||
<strong style="font-size: 12px; color: #1e293b;">Recommendation:</strong>
|
||||
<p style="margin: 4px 0 0 0; font-size: 12px; color: #475569; white-space: pre-line;">{$ alert.recommendation $}</p>
|
||||
</div>
|
||||
<!-- Add to Firewall Button for Brute Force Attacks -->
|
||||
<div ng-if="alert.title === 'Brute Force Attack Detected' && alert.details && alert.details['IP Address']" style="margin-top: 12px;">
|
||||
<button ng-click="blockIPAddress(alert.details['IP Address'])"
|
||||
ng-disabled="blockingIP === alert.details['IP Address']"
|
||||
<!-- Add to Firewall Button for Brute Force Attacks and Root Login Attempts -->
|
||||
<div ng-if="(alert.title === 'Brute Force Attack Detected' && alert.details && alert.details['IP Address']) || (alert.title === 'Root Login Attempts Detected' && alert.details && alert.details['Top IP'])" style="margin-top: 12px;">
|
||||
<button ng-click="blockIPAddress(alert.details['IP Address'] || alert.details['Top IP']); $event.stopPropagation(); return false;"
|
||||
ng-disabled="blockingIP === (alert.details['IP Address'] || alert.details['Top IP'])"
|
||||
style="background: #dc2626; color: white; border: none; padding: 8px 16px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"
|
||||
onmouseover="this.style.background='#b91c1c'"
|
||||
onmouseout="this.style.background='#dc2626'">
|
||||
<i class="fas fa-ban" ng-if="blockingIP !== alert.details['IP Address']"></i>
|
||||
<i class="fas fa-spinner fa-spin" ng-if="blockingIP === alert.details['IP Address']"></i>
|
||||
<span ng-if="blockingIP !== alert.details['IP Address']">Ban IP Permanently</span>
|
||||
<span ng-if="blockingIP === alert.details['IP Address']">Banning...</span>
|
||||
onmouseout="this.style.background='#dc2626'"
|
||||
type="button">
|
||||
<i class="fas fa-ban" ng-if="blockingIP !== (alert.details['IP Address'] || alert.details['Top IP'])"></i>
|
||||
<i class="fas fa-spinner fa-spin" ng-if="blockingIP === (alert.details['IP Address'] || alert.details['Top IP'])"></i>
|
||||
<span ng-if="blockingIP !== (alert.details['IP Address'] || alert.details['Top IP'])">Ban IP</span>
|
||||
<span ng-if="blockingIP === (alert.details['IP Address'] || alert.details['Top IP'])">Banning...</span>
|
||||
</button>
|
||||
<a href="/firewall/" target="_blank" style="margin-left: 10px; color: #5b5fcf; font-size: 12px; text-decoration: none;">
|
||||
<i class="fas fa-external-link-alt"></i> Manage in Firewall
|
||||
</a>
|
||||
<span ng-if="blockedIPs && blockedIPs[alert.details['IP Address']]"
|
||||
<span ng-if="blockedIPs && blockedIPs[alert.details['IP Address'] || alert.details['Top IP']]"
|
||||
style="margin-left: 10px; color: #10b981; font-size: 12px; font-weight: 600;">
|
||||
<i class="fas fa-check-circle"></i> Blocked
|
||||
</span>
|
||||
@@ -1015,12 +1016,43 @@
|
||||
<tr>
|
||||
<th>TIMESTAMP</th>
|
||||
<th>MESSAGE</th>
|
||||
<th>IP ADDRESS</th>
|
||||
<th>ACTIONS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="log in sshLogs">
|
||||
<td>{$ log.timestamp $}</td>
|
||||
<td>{$ log.message $}</td>
|
||||
<td>
|
||||
<span ng-if="log.ip_address" style="font-family: monospace; color: #5b5fcf; font-weight: 600;">
|
||||
{$ log.ip_address $}
|
||||
</span>
|
||||
<span ng-if="!log.ip_address" style="color: #8893a7;">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<button ng-if="log.ip_address && blockingIP !== log.ip_address && !blockedIPs[log.ip_address]"
|
||||
ng-click="banIPFromSSHLog(log.ip_address)"
|
||||
style="background: #dc2626; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 11px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;"
|
||||
onmouseover="this.style.background='#b91c1c'"
|
||||
onmouseout="this.style.background='#dc2626'"
|
||||
title="Ban this IP address permanently">
|
||||
<i class="fas fa-ban"></i>
|
||||
Ban IP
|
||||
</button>
|
||||
<button ng-if="log.ip_address && blockingIP === log.ip_address"
|
||||
disabled
|
||||
style="background: #9ca3af; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 11px; font-weight: 600; cursor: not-allowed; display: inline-flex; align-items: center; gap: 4px;">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
Banning...
|
||||
</button>
|
||||
<span ng-if="log.ip_address && blockedIPs[log.ip_address]"
|
||||
style="color: #10b981; font-size: 11px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px;">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
Banned
|
||||
</span>
|
||||
<span ng-if="!log.ip_address" style="color: #8893a7; font-size: 11px;">-</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -2014,7 +2014,7 @@ class FirewallManager:
|
||||
try:
|
||||
admin = Administrator.objects.get(pk=userID)
|
||||
if admin.acl.adminStatus != 1:
|
||||
return ACLManager.loadError()
|
||||
return ACLManager.loadErrorJson('status', 0)
|
||||
|
||||
ip = data.get('ip', '').strip()
|
||||
reason = data.get('reason', '').strip()
|
||||
@@ -2095,23 +2095,32 @@ class FirewallManager:
|
||||
command = f'chmod 644 {banned_ips_file} && chown root:root {banned_ips_file}'
|
||||
ProcessUtilities.executioner(command, None, True)
|
||||
|
||||
# Apply firewall rule to block the IP
|
||||
# Apply firewall rule to block the IP using ProcessUtilities (handles sudo)
|
||||
try:
|
||||
# Add iptables rule to block the IP
|
||||
if '/' in ip:
|
||||
# CIDR notation
|
||||
subprocess.run(['iptables', '-A', 'INPUT', '-s', ip, '-j', 'DROP'], check=True)
|
||||
else:
|
||||
# Single IP
|
||||
subprocess.run(['iptables', '-A', 'INPUT', '-s', ip, '-j', 'DROP'], check=True)
|
||||
# Check if rule already exists to avoid duplicate rules
|
||||
check_command = f"iptables -C INPUT -s {ip} -j DROP 2>&1"
|
||||
check_result = ProcessUtilities.executioner(check_command, None, True)
|
||||
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Banned IP {ip} with reason: {reason}')
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Failed to add iptables rule for {ip}: {str(e)}')
|
||||
# If rule doesn't exist (check returns non-zero), add it
|
||||
if check_result != 0:
|
||||
# Add iptables rule to block the IP using ProcessUtilities (handles sudo)
|
||||
command = f"iptables -A INPUT -s {ip} -j DROP"
|
||||
result = ProcessUtilities.executioner(command, None, True)
|
||||
|
||||
if result == 0:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Successfully added iptables rule to ban IP {ip} with reason: {reason}')
|
||||
else:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Warning: Failed to add iptables rule for {ip} (exit code: {result}), but IP was added to banned list')
|
||||
# Don't fail the entire operation - IP is still in banned list
|
||||
else:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'IPTables rule already exists for {ip}, skipping')
|
||||
except Exception as e:
|
||||
logging.CyberCPLogFileWriter.writeToFile(f'Error adding iptables rule for {ip}: {str(e)}, but IP was added to banned list')
|
||||
# Don't fail the entire operation - IP is still in banned list
|
||||
|
||||
final_dic = {'status': 1, 'message': f'IP address {ip} has been banned successfully'}
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
return HttpResponse(final_json, content_type='application/json')
|
||||
|
||||
except BaseException as msg:
|
||||
final_dic = {'status': 0, 'error_message': str(msg)}
|
||||
|
||||
Reference in New Issue
Block a user