Ban IP: close connections when already banned; install conntrack-tools on all OS

- firewallUtilities: add closeConnectionsFromIP() using conntrack -D -s IP
- addBannedIP: when IP already banned, close connections and return success message
- Frontend: always call API on Ban IP so backend can close connections; show server message
- Install: add conntrack-tools (RHEL) / conntrack (Debian/Ubuntu) to all install paths
  (rhel_deps, debian_deps, install_modules/01_verify_deps, install.py, venvsetup)
This commit is contained in:
master3395
2026-02-16 19:54:37 +01:00
parent 68e59ccccf
commit dbbcd945d2
10 changed files with 80 additions and 86 deletions

View File

@@ -1162,19 +1162,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
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;
}
// Do not early-return when IP is already in blockedIPs: still call the API so the
// backend can close any active connections from this IP (already-banned path).
// Set blocking flag to prevent duplicate requests
$scope.blockingIP = ipAddress;
@@ -1241,11 +1230,12 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
}
$scope.blockedIPs[ipAddress] = true;
// Show success notification
// Show success notification (use server message when present, e.g. already-banned + connections closed)
if (typeof PNotify !== 'undefined') {
var successText = (responseData.message && responseData.message.length) ? responseData.message : `IP address ${ipAddress} has been permanently banned and added to the firewall. You can manage it in the Firewall > Banned IPs section.`;
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.`,
text: successText,
type: 'success',
delay: 5000
});
@@ -1361,14 +1351,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
return; // Already processing
}
if ($scope.blockedIPs[ipAddress]) {
new PNotify({
title: 'Info',
text: `IP address ${ipAddress} is already banned`,
type: 'info',
delay: 3000
});
return;
// Still call API when already in blockedIPs so backend can close active connections
if (!$scope.blockedIPs) {
$scope.blockedIPs = {};
}
$scope.blockingIP = ipAddress;
@@ -1454,14 +1439,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
return; // Already processing
}
if ($scope.blockedIPs[ipAddress]) {
new PNotify({
title: 'Info',
text: `IP address ${ipAddress} is already banned`,
type: 'info',
delay: 3000
});
return;
// Still call API when already in blockedIPs so backend can close active connections
if (!$scope.blockedIPs) {
$scope.blockedIPs = {};
}
$scope.blockingIP = ipAddress;

View File

@@ -2132,8 +2132,13 @@ class FirewallManager:
# Primary path: save to database
existing = BannedIP.objects.filter(ip_address=ip, active=True).first()
if existing:
msg = 'IP address %s is already banned' % ip
final_dic = {'status': 0, 'error_message': msg, 'error': msg}
# IP already banned: close any active connections from this IP so they cannot keep trying
try:
FirewallUtilities.closeConnectionsFromIP(ip)
except Exception as close_err:
logging.CyberCPLogFileWriter.writeToFile('addBannedIP: closeConnectionsFromIP %s: %s' % (ip, str(close_err)))
msg = 'IP address %s was already banned; any active connections from this IP have been terminated.' % ip
final_dic = {'status': 1, 'message': msg}
return HttpResponse(json.dumps(final_dic), content_type='application/json')
try:
new_ban = BannedIP(
@@ -2153,8 +2158,13 @@ class FirewallManager:
banned_ips, _ = self._load_banned_ips_store()
for banned_ip in banned_ips:
if banned_ip.get('ip') == ip and banned_ip.get('active', True):
msg = 'IP address %s is already banned' % ip
final_dic = {'status': 0, 'error_message': msg, 'error': msg}
# IP already banned: close any active connections from this IP so they cannot keep trying
try:
FirewallUtilities.closeConnectionsFromIP(ip)
except Exception as close_err:
logging.CyberCPLogFileWriter.writeToFile('addBannedIP: closeConnectionsFromIP %s: %s' % (ip, str(close_err)))
msg = 'IP address %s was already banned; any active connections from this IP have been terminated.' % ip
final_dic = {'status': 1, 'message': msg}
return HttpResponse(json.dumps(final_dic), content_type='application/json')
new_banned_ip = {
'id': int(current_time),

View File

@@ -486,7 +486,7 @@ class preFlightsChecks:
except Exception as e:
self.stdOut(f"Warning: Graphics library fixes failed: {str(e)}", 1)
# Install common dependencies
# Install common dependencies (conntrack-tools for firewall/SSH security connection termination)
self.stdOut("Installing common RHEL dependencies...", 1)
common_deps = [
'curl',
@@ -500,7 +500,8 @@ class preFlightsChecks:
'cmake',
'pcre2-devel',
'openssl-devel',
'zlib-devel'
'zlib-devel',
'conntrack-tools'
]
for dep in common_deps:
@@ -706,7 +707,7 @@ class preFlightsChecks:
try:
self.stdOut("Applying Ubuntu-specific fixes...", 1)
# Install required dependencies
# Install required dependencies (conntrack for firewall/SSH security connection termination)
self.stdOut("Installing Ubuntu dependencies...", 1)
ubuntu_deps = [
'software-properties-common',
@@ -714,7 +715,8 @@ class preFlightsChecks:
'curl',
'wget',
'gnupg',
'lsb-release'
'lsb-release',
'conntrack'
]
for dep in ubuntu_deps:
@@ -748,7 +750,7 @@ class preFlightsChecks:
try:
self.stdOut("Applying Debian-specific fixes...", 1)
# Install required dependencies
# Install required dependencies (conntrack for firewall/SSH security connection termination)
self.stdOut("Installing Debian dependencies...", 1)
debian_deps = [
'software-properties-common',
@@ -756,7 +758,8 @@ class preFlightsChecks:
'curl',
'wget',
'gnupg',
'lsb-release'
'lsb-release',
'conntrack'
]
for dep in debian_deps:

View File

@@ -384,7 +384,7 @@ if [[ $SERVER_OS == "CentOS" ]] ; then
yum clean all
yum update -y
yum install epel-release -y
yum install -y wget strace htop net-tools telnet curl which bc telnet htop libevent-devel gcc python-devel libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel python-pip git
yum install -y wget strace htop net-tools telnet curl which bc telnet htop libevent-devel gcc python-devel libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel python-pip git conntrack-tools
if [[ $DEV == "ON" ]] ; then
yum -y install yum-utils
yum -y groupinstall development
@@ -402,17 +402,17 @@ if [[ $SERVER_OS == "Ubuntu" ]] ; then
DEBIAN_VERSION=$(cat /etc/debian_version | cut -d'.' -f1)
if [[ $DEBIAN_VERSION -ge 13 ]]; then
# Debian 13 (Trixie) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git conntrack
elif [[ $DEBIAN_VERSION -ge 12 ]]; then
# Debian 12 (Bookworm) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git conntrack
else
# Older Debian versions
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git conntrack
fi
else
# Ubuntu or older Debian with compatible package names
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git conntrack
fi
if [[ $DEV == "ON" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install -y python3-pip

View File

@@ -382,7 +382,7 @@ if [[ $SERVER_OS == "CentOS" ]] ; then
yum clean all
yum update -y
yum install epel-release -y
yum install -y wget strace htop net-tools telnet curl which bc telnet htop libevent-devel gcc python-devel libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel python-pip git
yum install -y wget strace htop net-tools telnet curl which bc telnet htop libevent-devel gcc python-devel libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel python-pip git conntrack-tools
if [[ $DEV == "ON" ]] ; then
yum -y install yum-utils
yum -y groupinstall development
@@ -400,17 +400,17 @@ if [[ $SERVER_OS == "Ubuntu" ]] ; then
DEBIAN_VERSION=$(cat /etc/debian_version | cut -d'.' -f1)
if [[ $DEBIAN_VERSION -ge 13 ]]; then
# Debian 13 (Trixie) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git conntrack
elif [[ $DEBIAN_VERSION -ge 12 ]]; then
# Debian 12 (Bookworm) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git conntrack
else
# Older Debian versions
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git conntrack
fi
else
# Ubuntu or older Debian with compatible package names
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git conntrack
fi
if [[ $DEV == "ON" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install -y python3-pip

View File

@@ -92,6 +92,7 @@ install_dependencies() {
# AlmaLinux 8 / CentOS 8 / Rocky Linux 8
$PACKAGE_MANAGER install -y ImageMagick gd libicu oniguruma aspell libc-client-devel python3 python3-pip python3-devel 2>/dev/null || true
fi
$PACKAGE_MANAGER install -y conntrack-tools 2>/dev/null || print_status "WARNING: conntrack-tools not available, skipping..."
echo " ✓ Core packages installed"
echo ""
@@ -118,6 +119,7 @@ install_dependencies() {
apt install -y -qq imagemagick php-gd libicu-dev libonig-dev 2>/dev/null || true
apt install -y -qq aspell 2>/dev/null || print_status "WARNING: aspell not available, skipping..."
apt install -y -qq libc-client-dev 2>/dev/null || print_status "WARNING: libc-client-dev not available, skipping..."
apt install -y -qq conntrack 2>/dev/null || print_status "WARNING: conntrack not available, skipping..."
echo " ✓ Core packages installed"
;;
esac

View File

@@ -41,8 +41,8 @@ install_essential_packages() {
print_status "$BLUE" "Installing essential packages..."
# Common essential packages for all Debian variants
local essential_packages="curl wget git unzip tar gzip bzip2"
# Common essential packages for all Debian variants (conntrack for firewall/SSH security connection termination)
local essential_packages="curl wget git unzip tar gzip bzip2 conntrack"
apt install -y -qq $essential_packages 2>/dev/null || {
print_status "$YELLOW" "Some essential packages failed to install, continuing..."

View File

@@ -133,8 +133,8 @@ install_additional_packages() {
print_status "$BLUE" "Installing additional packages..."
# Additional packages that might be needed
local additional_packages="git wget curl unzip tar gzip bzip2"
# Additional packages that might be needed (conntrack-tools for firewall/SSH security connection termination)
local additional_packages="git wget curl unzip tar gzip bzip2 conntrack-tools"
$package_manager install -y $additional_packages 2>/dev/null || {
print_status "$YELLOW" "Some additional packages not available, continuing..."

View File

@@ -182,6 +182,25 @@ class FirewallUtilities:
logging.CyberCPLogFileWriter.writeToFile(f"Error checking if IP {ip_address} is blocked: {str(e)}")
return False
@staticmethod
def closeConnectionsFromIP(ip_address):
"""
Try to close/drop existing connections from the given IP so the remote host
cannot keep trying (e.g. when IP is already banned and admin clicks Ban again).
Uses conntrack when available; safe to call even if no connections exist.
"""
try:
# conntrack -D -s IP deletes connection tracking entries from this source IP,
# which drops existing TCP connections from that IP (kernel sends RST or they time out).
command = "conntrack -D -s %s 2>/dev/null" % ip_address
result = ProcessUtilities.executioner(command)
logging.CyberCPLogFileWriter.writeToFile("closeConnectionsFromIP %s: conntrack returned %s" % (ip_address, result))
# executioner returns 1 on success; conntrack may also return 0 when no entries found (still ok)
return True, "Connections from %s have been closed" % ip_address
except Exception as e:
logging.CyberCPLogFileWriter.writeToFile("closeConnectionsFromIP error for %s: %s" % (ip_address, str(e)))
return False, str(e)
@staticmethod
def getBlockedIPs():
"""

View File

@@ -1162,19 +1162,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
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;
}
// Do not early-return when IP is already in blockedIPs: still call the API so the
// backend can close any active connections from this IP (already-banned path).
// Set blocking flag to prevent duplicate requests
$scope.blockingIP = ipAddress;
@@ -1241,11 +1230,12 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
}
$scope.blockedIPs[ipAddress] = true;
// Show success notification
// Show success notification (use server message when present, e.g. already-banned + connections closed)
if (typeof PNotify !== 'undefined') {
var successText = (responseData.message && responseData.message.length) ? responseData.message : `IP address ${ipAddress} has been permanently banned and added to the firewall. You can manage it in the Firewall > Banned IPs section.`;
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.`,
text: successText,
type: 'success',
delay: 5000
});
@@ -1361,14 +1351,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
return; // Already processing
}
if ($scope.blockedIPs[ipAddress]) {
new PNotify({
title: 'Info',
text: `IP address ${ipAddress} is already banned`,
type: 'info',
delay: 3000
});
return;
// Still call API when already in blockedIPs so backend can close active connections
if (!$scope.blockedIPs) {
$scope.blockedIPs = {};
}
$scope.blockingIP = ipAddress;
@@ -1454,14 +1439,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
return; // Already processing
}
if ($scope.blockedIPs[ipAddress]) {
new PNotify({
title: 'Info',
text: `IP address ${ipAddress} is already banned`,
type: 'info',
delay: 3000
});
return;
// Still call API when already in blockedIPs so backend can close active connections
if (!$scope.blockedIPs) {
$scope.blockedIPs = {};
}
$scope.blockingIP = ipAddress;