mirror of
https://github.com/fusionpbx/fusionpbx.git
synced 2026-02-01 13:39:21 +00:00
Update Event Guard version 2.0
- Use the service class - Use object interfaces - Add support for nftables
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
//application details
|
||||
$apps[$x]['name'] = 'Event Guard Logs';
|
||||
$apps[$x]['name'] = 'Event Guard';
|
||||
$apps[$x]['uuid'] = 'c5b86612-1514-40cb-8e2c-3f01a8f6f637';
|
||||
$apps[$x]['category'] = '';
|
||||
$apps[$x]['subcategory'] = '';
|
||||
$apps[$x]['version'] = '';
|
||||
$apps[$x]['category'] = 'Switch';
|
||||
$apps[$x]['subcategory'] = 'Security';
|
||||
$apps[$x]['version'] = '2.0';
|
||||
$apps[$x]['license'] = 'Mozilla Public License 1.1';
|
||||
$apps[$x]['url'] = 'http://www.fusionpbx.com';
|
||||
$apps[$x]['description']['en-us'] = '';
|
||||
|
||||
@@ -83,14 +83,14 @@ class event_guard {
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $setting_array = []) {
|
||||
//set domain and user UUIDs
|
||||
// Set domain and user UUIDs
|
||||
$this->domain_uuid = $setting_array['domain_uuid'] ?? $_SESSION['domain_uuid'] ?? '';
|
||||
$this->user_uuid = $setting_array['user_uuid'] ?? $_SESSION['user_uuid'] ?? '';
|
||||
|
||||
//set objects
|
||||
// Set the objects
|
||||
$this->database = $setting_array['database'] ?? database::new();
|
||||
|
||||
//assign the variables
|
||||
// Assign the variables
|
||||
$this->name = 'event_guard_log';
|
||||
$this->table = 'event_guard_logs';
|
||||
$this->toggle_field = '';
|
||||
@@ -110,11 +110,11 @@ class event_guard {
|
||||
public function delete($records) {
|
||||
if (permission_exists($this->name . '_delete')) {
|
||||
|
||||
//add multi-lingual support
|
||||
// Add multi-lingual support
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
|
||||
//validate the token
|
||||
// Validate the token
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'], 'negative');
|
||||
@@ -122,27 +122,27 @@ class event_guard {
|
||||
exit;
|
||||
}
|
||||
|
||||
//delete multiple records
|
||||
// Delete multiple records
|
||||
if (is_array($records) && @sizeof($records) != 0) {
|
||||
//build the delete array
|
||||
// Build the delete array
|
||||
$x = 0;
|
||||
foreach ($records as $record) {
|
||||
//add to the array
|
||||
// Add to the array
|
||||
if ($record['checked'] == 'true' && is_uuid($record['event_guard_log_uuid'])) {
|
||||
$array[$this->table][$x]['event_guard_log_uuid'] = $record['event_guard_log_uuid'];
|
||||
}
|
||||
|
||||
//increment the id
|
||||
// Increment the id
|
||||
$x++;
|
||||
}
|
||||
|
||||
//delete the checked rows
|
||||
// Delete the checked rows
|
||||
if (is_array($array) && @sizeof($array) != 0) {
|
||||
//execute delete
|
||||
// Execute delete
|
||||
$this->database->delete($array);
|
||||
unset($array);
|
||||
|
||||
//set message
|
||||
// Set the message
|
||||
message::add($text['message-delete']);
|
||||
}
|
||||
unset($records);
|
||||
@@ -160,11 +160,11 @@ class event_guard {
|
||||
public function unblock($records) {
|
||||
if (permission_exists($this->name . '_unblock')) {
|
||||
|
||||
//add multi-lingual support
|
||||
// Add multi-lingual support
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
|
||||
//validate the token
|
||||
// Validate the token
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'], 'negative');
|
||||
@@ -172,7 +172,7 @@ class event_guard {
|
||||
exit;
|
||||
}
|
||||
|
||||
//delete multiple records
|
||||
// Delete multiple records
|
||||
if (is_array($records) && @sizeof($records) != 0) {
|
||||
//build the delete array
|
||||
$x = 0;
|
||||
@@ -187,23 +187,23 @@ class event_guard {
|
||||
$x++;
|
||||
}
|
||||
|
||||
//delete the checked rows
|
||||
// Delete the checked rows
|
||||
if (is_array($array) && @sizeof($array) != 0) {
|
||||
//execute delete
|
||||
// Execute delete
|
||||
$this->database->save($array);
|
||||
unset($array);
|
||||
|
||||
//initialize the settings object
|
||||
// Initialize the settings object
|
||||
$setting = new settings(["category" => 'switch']);
|
||||
|
||||
//send unblock event
|
||||
$cmd = "sendevent CUSTOM\n";
|
||||
$cmd .= "Event-Name: CUSTOM\n";
|
||||
$cmd .= "Event-Subclass: event_guard:unblock\n";
|
||||
$esl = event_socket::create();
|
||||
// Send unblock event
|
||||
$cmd = "sendevent CUSTOM\n";
|
||||
$cmd .= "Event-Name: CUSTOM\n";
|
||||
$cmd .= "Event-Subclass: event_guard:unblock\n";
|
||||
$esl = event_socket::create();
|
||||
$switch_result = event_socket::command($cmd);
|
||||
|
||||
//set message
|
||||
// Set the message
|
||||
message::add($text['message-delete']);
|
||||
}
|
||||
unset($records);
|
||||
@@ -223,11 +223,11 @@ class event_guard {
|
||||
public function toggle($records) {
|
||||
if (permission_exists($this->name . '_edit')) {
|
||||
|
||||
//add multi-lingual support
|
||||
// Add multi-lingual support
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
|
||||
//validate the token
|
||||
// Validate the token
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'], 'negative');
|
||||
@@ -235,9 +235,9 @@ class event_guard {
|
||||
exit;
|
||||
}
|
||||
|
||||
//toggle the checked records
|
||||
// Toggle the checked records
|
||||
if (is_array($records) && @sizeof($records) != 0) {
|
||||
//get current toggle state
|
||||
// Get current toggle state
|
||||
foreach ($records as $record) {
|
||||
if (!empty($record['checked']) && $record['checked'] == 'true' && is_uuid($record['event_guard_log_uuid'])) {
|
||||
$uuids[] = "'" . $record['event_guard_log_uuid'] . "'";
|
||||
@@ -255,25 +255,24 @@ class event_guard {
|
||||
unset($sql, $parameters, $rows, $row);
|
||||
}
|
||||
|
||||
//build update array
|
||||
// Build update array
|
||||
$x = 0;
|
||||
foreach ($states as $uuid => $state) {
|
||||
//create the array
|
||||
// Create the array
|
||||
$array[$this->table][$x][$this->name . '_uuid'] = $uuid;
|
||||
$array[$this->table][$x][$this->toggle_field] = $state == $this->toggle_values[0] ? $this->toggle_values[1] : $this->toggle_values[0];
|
||||
|
||||
//increment the id
|
||||
// Increment the id
|
||||
$x++;
|
||||
}
|
||||
|
||||
//save the changes
|
||||
// Save the changes
|
||||
if (is_array($array) && @sizeof($array) != 0) {
|
||||
//save the array
|
||||
|
||||
// Save the array
|
||||
$this->database->save($array);
|
||||
unset($array);
|
||||
|
||||
//set message
|
||||
// Set the message
|
||||
message::add($text['message-toggle']);
|
||||
}
|
||||
unset($records, $states);
|
||||
@@ -293,11 +292,11 @@ class event_guard {
|
||||
public function copy($records) {
|
||||
if (permission_exists($this->name . '_add')) {
|
||||
|
||||
//add multi-lingual support
|
||||
// Add multi-lingual support
|
||||
$language = new text;
|
||||
$text = $language->get();
|
||||
|
||||
//validate the token
|
||||
// Validate the token
|
||||
$token = new token;
|
||||
if (!$token->validate($_SERVER['PHP_SELF'])) {
|
||||
message::add($text['message-invalid_token'], 'negative');
|
||||
@@ -305,17 +304,17 @@ class event_guard {
|
||||
exit;
|
||||
}
|
||||
|
||||
//copy the checked records
|
||||
// Copy the checked records
|
||||
if (is_array($records) && @sizeof($records) != 0) {
|
||||
|
||||
//get checked records
|
||||
// Get checked records
|
||||
foreach ($records as $record) {
|
||||
if (!empty($record['checked']) && $record['checked'] == 'true' && is_uuid($record['event_guard_log_uuid'])) {
|
||||
$uuids[] = "'" . $record['event_guard_log_uuid'] . "'";
|
||||
}
|
||||
}
|
||||
|
||||
//create the array from existing data
|
||||
// Create the array from existing data
|
||||
if (is_array($uuids) && @sizeof($uuids) != 0) {
|
||||
$sql = "select * from v_" . $this->table . " ";
|
||||
$sql .= "where event_guard_log_uuid in (" . implode(', ', $uuids) . ") ";
|
||||
@@ -323,7 +322,7 @@ class event_guard {
|
||||
if (is_array($rows) && @sizeof($rows) != 0) {
|
||||
$x = 0;
|
||||
foreach ($rows as $row) {
|
||||
//convert boolean values to a string
|
||||
// Convert boolean values to a string
|
||||
foreach ($row as $key => $value) {
|
||||
if (gettype($value) == 'boolean') {
|
||||
$value = $value ? 'true' : 'false';
|
||||
@@ -331,32 +330,30 @@ class event_guard {
|
||||
}
|
||||
}
|
||||
|
||||
//copy data
|
||||
// Copy data
|
||||
$array[$this->table][$x] = $row;
|
||||
|
||||
//add copy to the description
|
||||
// Add copy to the description
|
||||
$array[$this->table][$x]['event_guard_log_uuid'] = uuid();
|
||||
|
||||
//increment the id
|
||||
// Increment the id
|
||||
$x++;
|
||||
}
|
||||
}
|
||||
unset($sql, $parameters, $rows, $row);
|
||||
}
|
||||
|
||||
//save the changes and set the message
|
||||
// Save the changes and set the message
|
||||
if (is_array($array) && @sizeof($array) != 0) {
|
||||
//save the array
|
||||
|
||||
// Save the array
|
||||
$this->database->save($array);
|
||||
unset($array);
|
||||
|
||||
//set message
|
||||
// Set the message
|
||||
message::add($text['message-copy']);
|
||||
}
|
||||
unset($records);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
128
app/event_guard/resources/classes/event_guard_iptables.php
Normal file
128
app/event_guard/resources/classes/event_guard_iptables.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* event_guard_iptables class
|
||||
*
|
||||
*/
|
||||
class event_guard_iptables implements event_guard_interface {
|
||||
|
||||
/**
|
||||
* database object
|
||||
* @var database
|
||||
*/
|
||||
private $database;
|
||||
|
||||
/**
|
||||
* settings object
|
||||
* @var settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* firewall_path string
|
||||
* @var string
|
||||
*/
|
||||
private $firewall_path;
|
||||
|
||||
/**
|
||||
* called when the object is created
|
||||
*/
|
||||
public function __construct(settings $settings) {
|
||||
// Save the settings object
|
||||
$this->settings = $settings;
|
||||
|
||||
// Set the database object from the settings object
|
||||
$this->database = $settings->database();
|
||||
|
||||
// Set firewall path
|
||||
$this->firewall_path = trim(shell_exec('command -v iptables'));
|
||||
|
||||
// Create a chain array
|
||||
$chains[] = 'sip-auth-ip';
|
||||
$chains[] = 'sip-auth-fail';
|
||||
foreach ($chains as $chain) {
|
||||
shell_exec($this->firewall_path.' --new ' . $chain . ' >/dev/null 2>&1 &');
|
||||
shell_exec($this->firewall_path.' -I INPUT -j '.$chain . ' >/dev/null 2>&1 &');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a block command for iptables
|
||||
*
|
||||
* @param string $ip_address The IP address to block
|
||||
* @param string $filter The filter name for nftables, iptables or pf
|
||||
* @param array $event The event data containing 'to-user' and 'to-host'
|
||||
*
|
||||
* @return boolean True if the block command was executed successfully, false otherwise
|
||||
*/
|
||||
public function block_add(string $ip_address, string $filter) : bool {
|
||||
|
||||
// Invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the block command for iptables
|
||||
// Example: iptables -I INPUT -s 127.0.0.1 -j DROP
|
||||
$command = $this->firewall_path.' -I '.$filter.' -s '.$ip_address.' -j DROP';
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a specified IP address from a firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to unblock.
|
||||
* @param string $filter The filter name used in the firewall configuration.
|
||||
*
|
||||
* @return bool True if the IP address was successfully unblocked, false otherwise.
|
||||
*/
|
||||
public function block_delete(string $ip_address, string $filter) : bool {
|
||||
// Invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unblock the address
|
||||
$command = $this->firewall_path.' -L '.$filter.' -n --line-numbers | grep "'.$ip_address.' " | cut -d " " -f1';
|
||||
$line_number = trim(shell_exec($command));
|
||||
echo "\n". $command . " line ".__line__."\n";
|
||||
if (is_numeric($line_number)) {
|
||||
//$result = shell_exec('iptables -D INPUT '.$line_number);
|
||||
$command = $this->firewall_path.' -D '.$filter.' '.$line_number;
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result)) {
|
||||
return false;
|
||||
}
|
||||
echo "Unblock address ".$ip_address ." line ".$line_number." command ".$command." result ".$result."\n";
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IP address is blocked in the configured firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to check
|
||||
*
|
||||
* @return bool True if the address is blocked, False otherwise
|
||||
*/
|
||||
public function block_exists(string $ip_address, string $filter) : bool {
|
||||
// Determine whether to return true or false
|
||||
// Check to see if the address is blocked
|
||||
$command = $this->firewall_path.' -L -n --line-numbers | grep '.$ip_address;
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return false;
|
||||
}
|
||||
}
|
||||
129
app/event_guard/resources/classes/event_guard_nftables.php
Normal file
129
app/event_guard/resources/classes/event_guard_nftables.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* event_guard_nftables class
|
||||
*
|
||||
*/
|
||||
class event_guard_nftables implements event_guard_interface {
|
||||
|
||||
/**
|
||||
* database object
|
||||
* @var database
|
||||
*/
|
||||
private $database;
|
||||
|
||||
/**
|
||||
* settings object
|
||||
* @var settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* firewall_path string
|
||||
* @var string
|
||||
*/
|
||||
private $firewall_path;
|
||||
|
||||
/**
|
||||
* called when the object is created
|
||||
*/
|
||||
public function __construct(settings $settings) {
|
||||
// Save the settings object
|
||||
$this->settings = $settings;
|
||||
|
||||
// Set the database object from the settings object
|
||||
$this->database = $settings->database();
|
||||
|
||||
// Set firewall path
|
||||
$this->firewall_path = trim(shell_exec('command -v nft'));
|
||||
|
||||
// Create a chain array
|
||||
$chains[] = 'sip-auth-ip';
|
||||
$chains[] = 'sip-auth-fail';
|
||||
foreach ($chains as $chain) {
|
||||
shell_exec($this->firewall_path.' add chain inet filter ' . $chain . ' { type filter hook input priority -50 \; }'); // >/dev/null 2>&1 &');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a block command for iptables
|
||||
*
|
||||
* @param string $ip_address The IP address to block
|
||||
* @param string $filter The filter name for nftables, iptables or pf
|
||||
* @param array $event The event data containing 'to-user' and 'to-host'
|
||||
*
|
||||
* @return boolean True if the block command was executed successfully, false otherwise
|
||||
*/
|
||||
public function block_add(string $ip_address, string $filter) : bool {
|
||||
// Invalid IP address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the block command for nftables
|
||||
// Example: nft add element inet filter sip-auth-ip { 192.168.1.100 }
|
||||
$command = $this->firewall_path.' add rule inet filter '.$filter.' ip saddr '.$ip_address.' counter drop';
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a specified IP address from a firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to unblock.
|
||||
* @param string $filter The filter name used in the firewall configuration.
|
||||
*
|
||||
* @return bool True if the IP address was successfully unblocked, false otherwise.
|
||||
*/
|
||||
public function block_delete(string $ip_address, string $filter) : bool {
|
||||
// Invalid IP address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Command used to get the handle
|
||||
$command = $this->firewall_path.' -a list chain inet filter '.$filter.' | grep '.$ip_address;
|
||||
echo $command."\n";
|
||||
$result = trim(shell_exec($command));
|
||||
$rows = explode("\n", $result);
|
||||
|
||||
// Unblock the address
|
||||
foreach ($rows as $row) {
|
||||
$handle = trim(explode("#", $row)[1] ?? '');
|
||||
$command = $this->firewall_path.' delete rule inet filter '.$filter.' '.$handle;
|
||||
echo $command."\n";
|
||||
$result = shell_exec($command);
|
||||
}
|
||||
if (!empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IP address is blocked in the configured firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to check
|
||||
*
|
||||
* @return bool True if the address is blocked, False otherwise
|
||||
*/
|
||||
public function block_exists(string $ip_address, string $filter) : bool {
|
||||
// Determine whether to return true or false
|
||||
// Check to see if the address is blocked
|
||||
$command = $this->firewall_path.' list chain inet filter input | grep "ip saddr '.$ip_address.'"';
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
114
app/event_guard/resources/classes/event_guard_pf.php
Normal file
114
app/event_guard/resources/classes/event_guard_pf.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* event_guard_pf class
|
||||
*
|
||||
*/
|
||||
class event_guard_pf implements event_guard_interface {
|
||||
|
||||
/**
|
||||
* database object
|
||||
* @var database
|
||||
*/
|
||||
private $database;
|
||||
|
||||
/**
|
||||
* settings object
|
||||
* @var settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* firewall_path string
|
||||
* @var string
|
||||
*/
|
||||
private $firewall_path;
|
||||
|
||||
/**
|
||||
* called when the object is created
|
||||
*/
|
||||
public function __construct(settings $settings) {
|
||||
// Save the settings object
|
||||
$this->settings = $settings;
|
||||
|
||||
// Set the database object from the settings object
|
||||
$this->database = $settings->database();
|
||||
|
||||
// Set firewall path
|
||||
$this->firewall_path = trim(shell_exec('command -v pfctl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a block command for iptables
|
||||
*
|
||||
* @param string $ip_address The IP address to block
|
||||
* @param string $filter The filter name for nftables, iptables or pf
|
||||
* @param array $event The event data containing 'to-user' and 'to-host'
|
||||
*
|
||||
* @return boolean True if the block command was executed successfully, false otherwise
|
||||
*/
|
||||
public function block_add(string $ip_address, string $filter) : bool {
|
||||
|
||||
// Invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the block command for pf
|
||||
// Example: pfctl -t sip-auth-ip -T add 127.0.0.5
|
||||
$command = $this->firewall_path.' -t '.$filter.' -T add '.$ip_address;
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a specified IP address from a firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to unblock.
|
||||
* @param string $filter The filter name used in the firewall configuration.
|
||||
*
|
||||
* @return bool True if the IP address was successfully unblocked, false otherwise.
|
||||
*/
|
||||
public function block_delete(string $ip_address, string $filter) : bool {
|
||||
// Invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unblock the address
|
||||
// Example: pfctl -t sip-auth-ip -T delete 127.0.0.5
|
||||
$command = $this->firewall_path.' -t '.$filter.' -T delete '.$ip_address;
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IP address is blocked in the configured firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to check
|
||||
*
|
||||
* @return bool True if the address is blocked, False otherwise
|
||||
*/
|
||||
public function block_exists(string $ip_address, string $filter) : bool {
|
||||
// Determine whether to return true or false
|
||||
// Check to see if the address is blocked
|
||||
$command = $this->firewall_path.' -t ".$filter." -Ts | grep '.$ip_address;
|
||||
$result = shell_exec($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return false;
|
||||
}
|
||||
}
|
||||
517
app/event_guard/resources/classes/event_guard_service.php
Normal file
517
app/event_guard/resources/classes/event_guard_service.php
Normal file
@@ -0,0 +1,517 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Description goes here for event_guard service
|
||||
*/
|
||||
class event_guard_service extends service {
|
||||
|
||||
/**
|
||||
* database object
|
||||
* @var database
|
||||
*/
|
||||
private $database;
|
||||
|
||||
/**
|
||||
* settings object
|
||||
* @var settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* hostname variable
|
||||
* @var string
|
||||
*/
|
||||
private $hostname;
|
||||
|
||||
/**
|
||||
* firewall object
|
||||
* @var event_guard_interface
|
||||
*/
|
||||
private $firewall;
|
||||
|
||||
/**
|
||||
* socket object
|
||||
* @var event_socket
|
||||
*/
|
||||
private $socket;
|
||||
|
||||
/**
|
||||
* Reloads settings from database, config file and websocket server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function reload_settings(): void {
|
||||
// Re-read the config file to get any possible changes
|
||||
parent::$config->read();
|
||||
|
||||
// Connect to the database
|
||||
$this->database = new database(['config' => parent::$config]);
|
||||
|
||||
// Get the settings using global defaults
|
||||
$this->settings = new settings(['database' => $this->database]);
|
||||
|
||||
// Set the php operating system
|
||||
$php_os = strtolower(PHP_OS);
|
||||
|
||||
// Set the firewall name
|
||||
if ($php_os == 'freebsd') {
|
||||
$firewall_name = $this->settings->get('system','firewall_name', 'pf');
|
||||
}
|
||||
if ($php_os == 'linux') {
|
||||
$firewall_name = $this->settings->get('system','firewall_name', 'nftables');
|
||||
}
|
||||
if (empty($firewall_name)) {
|
||||
throw new Exception("No firewall name specified in settings");
|
||||
}
|
||||
|
||||
// Get the settings using global defaults
|
||||
$class_name = 'event_guard_'.$firewall_name;
|
||||
$this->firewall = new $class_name($this->settings);
|
||||
if (!($this->firewall instanceof event_guard_interface)) {
|
||||
throw new Exception("Must be an event_guard_interface firewall");
|
||||
}
|
||||
|
||||
// Get the hostname
|
||||
$this->hostname = gethostname();
|
||||
|
||||
// Connect to event socket
|
||||
$this->socket = new event_socket;
|
||||
if ($this->socket->connect()) {
|
||||
// Loop through the switch events
|
||||
$cmd = "event json ALL";
|
||||
$result = $this->socket->request($cmd);
|
||||
$this->debug('subscribe to ALL events '. print_r($result, true));
|
||||
|
||||
// Filter for specific events
|
||||
$cmd = "filter Event-Name CUSTOM";
|
||||
$result = $this->socket->request($cmd);
|
||||
$this->debug('subscribe to CUSTOM events '. print_r($result, true));
|
||||
}
|
||||
else {
|
||||
$this->warning('Unable to connect to event socket');
|
||||
}
|
||||
}
|
||||
|
||||
public function run(): int {
|
||||
// Reload the settings
|
||||
$this->reload_settings();
|
||||
|
||||
// Service work is handled here
|
||||
while ($this->running) {
|
||||
|
||||
// Initialize the array for switch events
|
||||
$json_array = [];
|
||||
|
||||
// Make sure the database connection is available
|
||||
while (!$this->database->is_connected()) {
|
||||
// Connect to the database
|
||||
$this->database->connect();
|
||||
|
||||
// Reload settings after connection to the database
|
||||
$this->settings = new settings(['database' => $this->database]);
|
||||
|
||||
// Sleep for a moment
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// Reconnect to event socket
|
||||
if (!$this->socket->connected()) {
|
||||
$this->warning('Not connected to even socket');
|
||||
if ($this->socket->connect()) {
|
||||
$cmd = "event json ALL";
|
||||
$result = $this->socket->request($cmd);
|
||||
$this->debug('subscribe to ALL events '. print_r($result, true));
|
||||
|
||||
$cmd = "filter Event-Name CUSTOM";
|
||||
$result = $this->socket->request($cmd);
|
||||
$this->debug('subscribe to CUSTOM events '. print_r($result, true));
|
||||
$this->info('Re-connected to event socket');
|
||||
}
|
||||
else {
|
||||
// Unable to connect to event socket
|
||||
$this->warning('Unable to connect to event socket');
|
||||
|
||||
// Sleep and then attempt to reconnect
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the socket
|
||||
$json_response = $this->socket->read_event();
|
||||
|
||||
// Decode the response
|
||||
if (isset($json_response) && $json_response != '') {
|
||||
$json_array = json_decode($json_response['$'], true);
|
||||
unset($json_response);
|
||||
}
|
||||
|
||||
// Debug the event array
|
||||
$this->debug('Event array '. print_r($json_array, true));
|
||||
|
||||
// Registration failed - block IP address unless they are registered
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'sofia::register_failure') {
|
||||
//not registered so block the address
|
||||
if (!$this->allow_access($json_array['network-ip'])) {
|
||||
$this->block_add($json_array['network-ip'], 'sip-auth-fail', $json_array);
|
||||
}
|
||||
}
|
||||
|
||||
// Sendevent CUSTOM event_guard:unblock
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'event_guard:unblock') {
|
||||
//check the database for pending requests
|
||||
$sql = "select event_guard_log_uuid, log_date, filter, ip_address, extension, user_agent ";
|
||||
$sql .= "from v_event_guard_logs ";
|
||||
$sql .= "where log_status = 'pending' ";
|
||||
$sql .= "and hostname = :hostname ";
|
||||
//$this->debug($sql." ".$this->hostname);
|
||||
$parameters['hostname'] = $this->hostname;
|
||||
$event_guard_logs = $this->database->select($sql, $parameters, 'all');
|
||||
if (is_array($event_guard_logs)) {
|
||||
$x = 0;
|
||||
foreach($event_guard_logs as $row) {
|
||||
//unblock the ip address
|
||||
$this->block_delete($row['ip_address'], $row['filter']);
|
||||
|
||||
//debug info
|
||||
$this->info("unblocked: [ip_address: ".$row['ip_address'].", filter: ".$row['filter'].", to-user: ".$row['extension'].", to-host: ".$row['hostname'].", line: ".__line__);
|
||||
|
||||
//log the blocked ip address to the database
|
||||
$array['event_guard_logs'][$x]['event_guard_log_uuid'] = $row['event_guard_log_uuid'];
|
||||
$array['event_guard_logs'][$x]['log_date'] = 'now()';
|
||||
$array['event_guard_logs'][$x]['log_status'] = 'unblocked';
|
||||
$x++;
|
||||
}
|
||||
if (is_array($array)) {
|
||||
$p = permissions::new();
|
||||
$p->add('event_guard_log_edit', 'temp');
|
||||
$this->database->save($array, false);
|
||||
$p->delete('event_guard_log_edit', 'temp');
|
||||
unset($array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Registration to the IP address
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'sofia::pre_register') {
|
||||
if (isset($json_array['to-host'])) {
|
||||
$is_valid_ip = filter_var($json_array['to-host'], FILTER_VALIDATE_IP);
|
||||
if ($is_valid_ip) {
|
||||
//if not registered block the address
|
||||
if (!$this->allow_access($json_array['network-ip'])) {
|
||||
$this->block_add($json_array['network-ip'], 'sip-auth-ip', $json_array);
|
||||
}
|
||||
|
||||
//debug info
|
||||
$this->debug("network-ip ".$json_array['network-ip'].", to-host ".$json_array['to-host']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug information
|
||||
//if (($json_array['Event-Subclass'] == 'sofia::register_failure' || $json_array['Event-Subclass'] == 'sofia::pre_register')) {
|
||||
//echo "\n";
|
||||
//print_r($json_array);
|
||||
|
||||
//echo "event_name: ".$json_array['Event-Name']."\n";
|
||||
//echo "event_type: ".$json_array['event_type']."\n";
|
||||
//echo "event_subclass: ".$json_array['Event-Subclass']."\n";
|
||||
//echo "status: ".$json_array['status']."\n";
|
||||
//echo "network_ip: ".$json_array['network-ip']."\n";
|
||||
//echo "channel_state: ".$json_array['Channel-State']."\n";
|
||||
//echo "channel_call_state: ".$json_array['Channel-Call-State']."\n";
|
||||
//echo "call_direction: ".$json_array['Call-Direction']."\n";
|
||||
//echo "channel_call_uuid: ".$json_array['Channel-Call-UUID']."\n";
|
||||
//echo "answer_state: ".$json_array['Answer-State']."\n";
|
||||
//echo "hangup_cause: ".$json_array['Hangup-Cause']."\n";
|
||||
//echo "to-host: $json_array['to-host']\n";
|
||||
//echo "\n";
|
||||
//}
|
||||
|
||||
// Sleep for 100 ms
|
||||
usleep(100000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected static function display_version(): void {
|
||||
echo "1.1\n";
|
||||
}
|
||||
|
||||
protected static function set_command_options() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a block command for nftables, iptables or pf based on the firewall type.
|
||||
*
|
||||
* @param string $ip_address The IP address to block
|
||||
* @param string $filter The filter name for nftables, iptables or pf
|
||||
* @param array $event The event data containing 'to-user' and 'to-host'
|
||||
*
|
||||
* @return boolean True if the block command was executed successfully, false otherwise
|
||||
*/
|
||||
public function block_add(string $ip_address, string $filter, array $event) : bool {
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//block the IP address
|
||||
$result = $this->firewall->block_add($ip_address, $filter);
|
||||
if ($result) {
|
||||
//log the blocked ip address to the log
|
||||
$this->warning("blocked: [ip_address: ".$ip_address.", filter: ".$filter.", to-user: ".$event['to-user'].", to-host: ".$event['to-host'].", line: ".__line__."]");
|
||||
|
||||
//log the blocked ip address to the database
|
||||
$array = [];
|
||||
$array['event_guard_logs'][0]['event_guard_log_uuid'] = uuid();
|
||||
$array['event_guard_logs'][0]['hostname'] = gethostname();
|
||||
$array['event_guard_logs'][0]['log_date'] = 'now()';
|
||||
$array['event_guard_logs'][0]['filter'] = $filter;
|
||||
$array['event_guard_logs'][0]['ip_address'] = $ip_address;
|
||||
$array['event_guard_logs'][0]['extension'] = $event['to-user'].'@'.$event['to-host'];
|
||||
$array['event_guard_logs'][0]['user_agent'] = $event['user-agent'];
|
||||
$array['event_guard_logs'][0]['log_status'] = 'blocked';
|
||||
$p = permissions::new();
|
||||
$p->add('event_guard_log_add', 'temp');
|
||||
$this->database->save($array, false);
|
||||
$p->delete('event_guard_log_add', 'temp');
|
||||
|
||||
//send debug information to the console
|
||||
$this->info("blocked address " . $ip_address . ", line " . __line__);
|
||||
}
|
||||
|
||||
//return the result
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function block_delete(string $ip_address, string $filter) : bool {
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//unblock the IP address
|
||||
$result = $this->firewall->block_delete($ip_address, $filter);
|
||||
if ($result) {
|
||||
//send debug information to the console
|
||||
$this->info("Unblock address " . $ip_address . ", line " . __line__);
|
||||
}
|
||||
|
||||
//return the result
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function block_exists(string $ip_address, string $filter) : bool {
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if the address is blocked
|
||||
$result = $this->firewall->block_exists($ip_address, $filter);
|
||||
|
||||
//send debug information to the console
|
||||
$this->debug("Address Exists " . $ip_address . ", line " . __line__);
|
||||
|
||||
//return the result
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if access is allowed for a given IP address.
|
||||
*
|
||||
* This method checks the IP address is inside the cache, user logs, event guard logs, access controls,
|
||||
* and registration to determine if access should be allowed. If the IP address is found
|
||||
* in the access control list, user logs with result success, or valid registrations
|
||||
* is found then the address is automatically allowed.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for access.
|
||||
*
|
||||
* @return boolean True if access is allowed, false otherwise.
|
||||
*/
|
||||
private function allow_access($ip_address) {
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check the cache to see if the address is allowed
|
||||
$cache = new cache;
|
||||
if ($cache->get("switch:allowed:".$ip_address) === 'true') {
|
||||
//debug info
|
||||
$this->debug("address: ".$ip_address." allowed by: cache");
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//allow access for addresses with authentication status success
|
||||
if ($this->allow_user_log_success($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
$this->debug("address: ".$ip_address." allowed by: user logs");
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//allow access for addresses that have been unblocked
|
||||
/*
|
||||
if (event_guard_log_allowed($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
$this->debug("address: ".$ip_address." allowed by: unblocked");
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//allow access if the cidr address is allowed
|
||||
if ($this->allow_access_control($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
$this->debug("address: ".$ip_address." allowed by: access controls");
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//allow if there is a registration from the same IP address
|
||||
if ($this->allow_registered($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
$this->debug("address: ".$ip_address." allowed by: registration");
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//return
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given IP address is authorized by any access control node.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for authorization.
|
||||
*
|
||||
* @return bool True if the IP address is authorized, false otherwise.
|
||||
*/
|
||||
private function allow_access_control($ip_address) {
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the access control allowed nodes
|
||||
$sql = "select access_control_node_uuid, access_control_uuid, node_cidr, node_description ";
|
||||
$sql .= "from v_access_control_nodes ";
|
||||
$sql .= "where node_type = 'allow' ";
|
||||
$sql .= "and length(node_cidr) > 0 ";
|
||||
$parameters = null;
|
||||
$allowed_nodes = $this->database->select($sql, $parameters, 'all');
|
||||
|
||||
//default authorized to false
|
||||
$allowed = false;
|
||||
|
||||
//use the ip address to get the authorized nodes
|
||||
if (is_array($allowed_nodes)) {
|
||||
foreach($allowed_nodes as $row) {
|
||||
if (check_cidr($row['node_cidr'], $ip_address)) {
|
||||
//debug info
|
||||
// print_r($row);
|
||||
// $this->debug("Authorized: ".$ip_address);
|
||||
|
||||
//set the allowed to true
|
||||
$allowed = true;
|
||||
|
||||
//exit the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a user's IP address is allowed based on their login history.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for access.
|
||||
*
|
||||
* @return bool True if the IP address is allowed, false otherwise.
|
||||
*/
|
||||
private function allow_user_log_success($ip_address) {
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check to see if the address was authenticated successfully
|
||||
$sql = "select count(user_log_uuid) ";
|
||||
$sql .= "from v_user_logs ";
|
||||
$sql .= "where remote_address = :remote_address ";
|
||||
$sql .= "and result = 'success' ";
|
||||
$sql .= "and timestamp > NOW() - INTERVAL '8 days' ";
|
||||
$parameters['remote_address'] = $ip_address;
|
||||
$user_log_count = $this->database->select($sql, $parameters, 'column');
|
||||
|
||||
//debug info
|
||||
$this->debug("address ".$ip_address." count ".$user_log_count);
|
||||
|
||||
//default authorized to false
|
||||
$allowed = false;
|
||||
|
||||
//use the ip address to get the authorized nodes
|
||||
if (!empty($user_log_count) && $user_log_count > 0) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
//return
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given IP address is registered on the network.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for registration.
|
||||
*
|
||||
* @return bool True if the IP address is registered, false otherwise.
|
||||
*/
|
||||
private function allow_registered($ip_address) {
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$registered = false;
|
||||
$command = "fs_cli -x 'show registrations as json' ";
|
||||
$result = shell_exec($command);
|
||||
$array = json_decode($result, true);
|
||||
if (is_array($array['rows'])) {
|
||||
foreach ($array['rows'] as $row) {
|
||||
if ($row['network_ip'] == $ip_address) {
|
||||
$registered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return registered boolean
|
||||
return $registered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* event_guard_interface class
|
||||
*
|
||||
*/
|
||||
interface event_guard_interface {
|
||||
public function block_add(string $ip_address, string $filter) : bool;
|
||||
public function block_delete(string $ip_address, string $filter) : bool;
|
||||
public function block_exists(string $ip_address, string $filter) : bool;
|
||||
}
|
||||
@@ -16,6 +16,9 @@ StartLimitIntervalSec=0
|
||||
[Service]
|
||||
WorkingDirectory=/var/www/fusionpbx
|
||||
ExecStart=/usr/bin/php /var/www/fusionpbx/app/event_guard/resources/service/event_guard.php
|
||||
RuntimeDirectory=fusionpbx
|
||||
RuntimeDirectoryMode=0755
|
||||
RuntimeDirectoryPreserve=yes
|
||||
User=root
|
||||
Group=root
|
||||
TimeoutSec=55s
|
||||
@@ -23,3 +26,4 @@ Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
|
||||
@@ -1,884 +1,17 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright (C) 2022-2024 Mark J Crane <markjcrane@fusionpbx.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
require_once dirname(__DIR__, 4) . '/resources/require.php';
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
try {
|
||||
// Create the service
|
||||
$service = event_guard_service::create();
|
||||
|
||||
//check the permission
|
||||
if (defined('STDIN')) {
|
||||
//includes files
|
||||
require_once dirname(__DIR__, 4) . "/resources/require.php";
|
||||
}
|
||||
else {
|
||||
//only allow running this from command line
|
||||
exit;
|
||||
}
|
||||
// Exit using the status run method returns
|
||||
exit($service->run());
|
||||
} catch (Throwable $ex) {
|
||||
// Show the details of the error
|
||||
echo "Error occurred in " . $ex->getFile() . ' (' . $ex->getLine() . '):' . $ex->getMessage();
|
||||
|
||||
//increase limits
|
||||
set_time_limit(0);
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('memory_limit', '256M');
|
||||
|
||||
//save the arguments to variables
|
||||
$script_name = $argv[0];
|
||||
if (!empty($argv[1])) {
|
||||
parse_str($argv[1], $_GET);
|
||||
}
|
||||
|
||||
//set the variables
|
||||
if (!empty($_GET['hostname'])) {
|
||||
$hostname = urldecode($_GET['hostname']);
|
||||
}
|
||||
$debug = false;
|
||||
if (!empty($_GET['debug'])) {
|
||||
if (is_numeric($_GET['debug'])) {
|
||||
$debug_level = $_GET['debug'];
|
||||
}
|
||||
$debug = true;
|
||||
}
|
||||
|
||||
//get the hostname
|
||||
if (empty($hostname)) {
|
||||
$hostname = gethostname();
|
||||
}
|
||||
|
||||
//set the php operating system
|
||||
$php_os = strtolower(PHP_OS);
|
||||
|
||||
//define the firewall command
|
||||
if ($php_os == 'freebsd') {
|
||||
$firewall_name = 'pf';
|
||||
if (file_exists('/sbin/pfctl')) {
|
||||
$firewall_path = '/sbin';
|
||||
}
|
||||
}
|
||||
if ($php_os == 'linux') {
|
||||
$firewall_name = 'iptables';
|
||||
|
||||
//find the firewall path
|
||||
if (file_exists('/usr/sbin/iptables')) {
|
||||
$firewall_path = '/usr/sbin';
|
||||
}
|
||||
if (empty($firewall_path) && file_exists('/sbin/iptables')) {
|
||||
$firewall_path = '/sbin';
|
||||
}
|
||||
}
|
||||
|
||||
//check if the firewall command was found
|
||||
if (empty($firewall_path)) {
|
||||
echo $firewall_name." command not found\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
//add pf tables into your pf.conf file
|
||||
//if ($firewall_name == 'pf') {
|
||||
// table <sip-auth-ip> persist
|
||||
// table <sip-auth-fail> persist
|
||||
// block in quick from <sip-auth-ip>
|
||||
// block in quick from <sip-auth-fail>
|
||||
//}
|
||||
|
||||
//add the iptables chains
|
||||
if ($firewall_name == 'iptables') {
|
||||
//create a chain array
|
||||
$chains[] = 'sip-auth-ip';
|
||||
$chains[] = 'sip-auth-fail';
|
||||
|
||||
//loop through the chains
|
||||
if (is_array($chains)) {
|
||||
foreach ($chains as $chain) {
|
||||
iptables_chain_add($chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//define the process id file
|
||||
$pid_file = "/var/run/fusionpbx/".basename($argv[0], ".php") .".pid";
|
||||
echo "pid_file: ".$pid_file."\n";
|
||||
|
||||
//function to check if the process exists
|
||||
/**
|
||||
* Checks if a process exists.
|
||||
*
|
||||
* @param string $file Path to the file containing the process ID (PID)
|
||||
*
|
||||
* @return bool True if the process exists, false otherwise
|
||||
*/
|
||||
function process_exists($file) {
|
||||
|
||||
//set the default exists to false
|
||||
$exists = false;
|
||||
|
||||
//check to see if the process is running
|
||||
if (file_exists($file)) {
|
||||
$pid = file_get_contents($file);
|
||||
if (function_exists('posix_getsid')) {
|
||||
if (posix_getsid($pid) === false) {
|
||||
//process is not running
|
||||
$exists = false;
|
||||
}
|
||||
else {
|
||||
//process is running
|
||||
$exists = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (file_exists('/proc/'.$pid)) {
|
||||
//process is running
|
||||
$exists = true;
|
||||
}
|
||||
else {
|
||||
//process is not running
|
||||
$exists = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return the result
|
||||
return $exists;
|
||||
}
|
||||
|
||||
//check to see if the process exists
|
||||
$pid_exists = process_exists($pid_file);
|
||||
|
||||
//prevent the process running more than once
|
||||
if ($pid_exists) {
|
||||
echo "Cannot lock pid file {$pid_file}\n";
|
||||
exit;
|
||||
}
|
||||
else {
|
||||
echo "pid file exists\n";
|
||||
}
|
||||
|
||||
//create the process id file if the process doesn't exist
|
||||
if (!$pid_exists) {
|
||||
//remove the old pid file
|
||||
if (file_exists($pid_file)) {
|
||||
unlink($pid_file);
|
||||
}
|
||||
|
||||
//show the details to the user
|
||||
if (isset($debug) && $debug == true) {
|
||||
echo "\n";
|
||||
echo "Service: ".basename( $argv[0], ".php")."\n";
|
||||
echo "Process ID: ".getmypid()."\n";
|
||||
echo "PID File: ".$pid_file."\n";
|
||||
}
|
||||
|
||||
//save the pid file
|
||||
file_put_contents($pid_file, getmypid());
|
||||
}
|
||||
|
||||
//connect to the database
|
||||
$database = database::new();
|
||||
|
||||
//test a specific address
|
||||
//$ip_address = '10.7.0.253';
|
||||
//$result = access_allowed($ip_address);
|
||||
|
||||
//connect to event socket
|
||||
$socket = new event_socket;
|
||||
if (!$socket->connect()) {
|
||||
echo "Unable to connect to event socket\n";
|
||||
}
|
||||
|
||||
//preset values
|
||||
//$interval_seconds = 30;
|
||||
//$previous_time = time() - $interval_seconds;
|
||||
|
||||
//loop through the switch events
|
||||
$cmd = "event json ALL";
|
||||
$result = $socket->request($cmd);
|
||||
if ($debug) { print_r($result); }
|
||||
|
||||
//filter for specific events
|
||||
$cmd = "filter Event-Name CUSTOM";
|
||||
$result = $socket->request($cmd);
|
||||
if ($debug) { print_r($result); }
|
||||
|
||||
while (true) {
|
||||
|
||||
//check pending unblock requests
|
||||
/*
|
||||
if ((time() - $previous_time) > $interval_seconds) {
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "time difference: ". (time() - $previous_time)."\n";
|
||||
}
|
||||
|
||||
//update the time
|
||||
$previous_time = time();
|
||||
}
|
||||
*/
|
||||
|
||||
//reconnect to event socket
|
||||
if (!$socket->connected()) {
|
||||
//echo "Not connected to even socket\n";
|
||||
if ($socket->connect()) {
|
||||
$cmd = "event json ALL";
|
||||
$result = $socket->request($cmd);
|
||||
if ($debug) { print_r($result); }
|
||||
|
||||
$cmd = "filter Event-Name CUSTOM";
|
||||
$result = $socket->request($cmd);
|
||||
if ($debug) { print_r($result); }
|
||||
echo "Re-connected to event socket\n";
|
||||
}
|
||||
else {
|
||||
//unable to connect to event socket
|
||||
echo "Unable to connect to event socket\n";
|
||||
|
||||
//sleep and then attempt to reconnect
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//read the socket
|
||||
$json_response = $socket->read_event();
|
||||
|
||||
//decode the response
|
||||
if (isset($json_response) && $json_response != '') {
|
||||
$json_array = json_decode($json_response['$'], true);
|
||||
unset($json_response);
|
||||
}
|
||||
|
||||
//debug info
|
||||
//if ($debug) {
|
||||
// print_r($json_array);
|
||||
//}
|
||||
|
||||
//registration failed - block IP address unless they are registered
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'sofia::register_failure') {
|
||||
//not registered so block the address
|
||||
if (!access_allowed($json_array['network-ip'])) {
|
||||
block($json_array['network-ip'], 'sip-auth-fail', $json_array);
|
||||
}
|
||||
}
|
||||
|
||||
//sendevent CUSTOM event_guard:unblock
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'event_guard:unblock') {
|
||||
//check the database for pending requests
|
||||
$sql = "select event_guard_log_uuid, log_date, filter, ip_address, extension, user_agent ";
|
||||
$sql .= "from v_event_guard_logs ";
|
||||
$sql .= "where log_status = 'pending' ";
|
||||
$sql .= "and hostname = :hostname ";
|
||||
//if ($debug) { echo $sql." ".$hostname."\n"; }
|
||||
$parameters['hostname'] = $hostname;
|
||||
$event_guard_logs = $database->select($sql, $parameters, 'all');
|
||||
if (is_array($event_guard_logs)) {
|
||||
foreach($event_guard_logs as $row) {
|
||||
//unblock the ip address
|
||||
unblock($row['ip_address'], $row['filter']);
|
||||
|
||||
//log the blocked ip address to the syslog
|
||||
openlog("fusionpbx", LOG_PID | LOG_PERROR, LOG_AUTH);
|
||||
syslog(LOG_WARNING, "fusionpbx: unblocked: [ip_address: ".$row['ip_address'].", filter: ".$row['filter'].", to-user: ".$row['extension'].", to-host: ".$row['hostname'].", line: ".__line__."]");
|
||||
closelog();
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "unblocked: [ip_address: ".$row['ip_address'].", filter: ".$row['filter'].", to-user: ".$row['extension'].", to-host: ".$row['hostname'].", line: ".__line__."]\n";
|
||||
}
|
||||
|
||||
//log the blocked ip address to the database
|
||||
$array['event_guard_logs'][$x]['event_guard_log_uuid'] = $row['event_guard_log_uuid'];
|
||||
$array['event_guard_logs'][$x]['log_date'] = 'now()';
|
||||
$array['event_guard_logs'][$x]['log_status'] = 'unblocked';
|
||||
$x++;
|
||||
}
|
||||
if (is_array($array)) {
|
||||
$p = permissions::new();
|
||||
$p->add('event_guard_log_edit', 'temp');
|
||||
$database->app_name = 'event guard';
|
||||
$database->app_uuid = 'c5b86612-1514-40cb-8e2c-3f01a8f6f637';
|
||||
$database->save($array, false);
|
||||
//$message = $database->message;
|
||||
$p->delete('event_guard_log_edit', 'temp');
|
||||
unset($array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//registration to the IP address
|
||||
if (is_array($json_array) && $json_array['Event-Subclass'] == 'sofia::pre_register') {
|
||||
if (isset($json_array['to-host'])) {
|
||||
$is_valid_ip = filter_var($json_array['to-host'], FILTER_VALIDATE_IP);
|
||||
if ($is_valid_ip) {
|
||||
//if not registered block the address
|
||||
if (!access_allowed($json_array['network-ip'])) {
|
||||
block($json_array['network-ip'], 'sip-auth-ip', $json_array);
|
||||
}
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "network-ip ".$json_array['network-ip']."\n";
|
||||
echo "to-host ".$json_array['to-host']."\n";
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug information
|
||||
//if ($debug && ($json_array['Event-Subclass'] == 'sofia::register_failure' || $json_array['Event-Subclass'] == 'sofia::pre_register')) {
|
||||
|
||||
//echo "\n";
|
||||
//print_r($json_array);
|
||||
|
||||
//echo "event_name: ".$json_array['Event-Name']."\n";
|
||||
//echo "event_type: ".$json_array['event_type']."\n";
|
||||
//echo "event_subclass: ".$json_array['Event-Subclass']."\n";
|
||||
//echo "status: ".$json_array['status']."\n";
|
||||
//echo "network_ip: ".$json_array['network-ip']."\n";
|
||||
//echo "channel_state: ".$json_array['Channel-State']."\n";
|
||||
//echo "channel_call_state: ".$json_array['Channel-Call-State']."\n";
|
||||
//echo "call_direction: ".$json_array['Call-Direction']."\n";
|
||||
//echo "channel_call_uuid: ".$json_array['Channel-Call-UUID']."\n";
|
||||
//echo "answer_state: ".$json_array['Answer-State']."\n";
|
||||
//echo "hangup_cause: ".$json_array['Hangup-Cause']."\n";
|
||||
//echo "to-host: $json_array['to-host']\n";
|
||||
//echo "\n";
|
||||
//}
|
||||
|
||||
//unset the array
|
||||
if (is_array($json_array)) {
|
||||
unset($json_array);
|
||||
}
|
||||
|
||||
//debug info
|
||||
if ($debug && $debug_level == '2') {
|
||||
//current memory
|
||||
$memory_usage = memory_get_usage();
|
||||
|
||||
//peak memory
|
||||
$memory_peak = memory_get_peak_usage();
|
||||
echo "\n";
|
||||
echo 'Current memory: ' . round($memory_usage / 1024) . " KB\n";
|
||||
echo 'Peak memory: ' . round($memory_peak / 1024) . " KB\n\n";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//run command and capture standard output
|
||||
/**
|
||||
* Execute a shell command and capture its output.
|
||||
*
|
||||
* @param string $command The shell command to execute
|
||||
*
|
||||
* @return string The output of the executed command
|
||||
*/
|
||||
function shell($command) {
|
||||
ob_start();
|
||||
$result = system($command);
|
||||
ob_get_clean();
|
||||
return $result;
|
||||
}
|
||||
|
||||
//block an ip address
|
||||
/**
|
||||
* Execute a block command for iptables or pf based on the firewall type.
|
||||
*
|
||||
* @param string $ip_address The IP address to block
|
||||
* @param string $filter The filter name for iptables or pf
|
||||
* @param array $event The event data containing 'to-user' and 'to-host'
|
||||
*
|
||||
* @return boolean True if the block command was executed successfully, false otherwise
|
||||
*/
|
||||
function block($ip_address, $filter, $event) {
|
||||
//define the global variables
|
||||
global $database, $debug, $firewall_path, $firewall_name;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//run the block command for iptables
|
||||
if ($firewall_name == 'iptables') {
|
||||
//example: iptables -I INPUT -s 127.0.0.1 -j DROP
|
||||
$command = $firewall_path.'/./iptables -I '.$filter.' -s '.$ip_address.' -j DROP';
|
||||
$result = shell($command);
|
||||
}
|
||||
|
||||
//run the block command for pf
|
||||
if ($firewall_name == 'pf') {
|
||||
//example: pfctl -t sip-auth-ip -T add 127.0.0.5
|
||||
$command = $firewall_path.'/pfctl -t '.$filter.' -T add '.$ip_address;
|
||||
$result = shell($command);
|
||||
}
|
||||
|
||||
//log the blocked ip address to the syslog
|
||||
openlog("fusionpbx", LOG_PID | LOG_PERROR, LOG_AUTH);
|
||||
syslog(LOG_WARNING, "fusionpbx: blocked: [ip_address: ".$ip_address.", filter: ".$filter.", to-user: ".$event['to-user'].", to-host: ".$event['to-host'].", line: ".__line__."]");
|
||||
closelog();
|
||||
|
||||
//log the blocked ip address to the database
|
||||
$array = [];
|
||||
$array['event_guard_logs'][0]['event_guard_log_uuid'] = uuid();
|
||||
$array['event_guard_logs'][0]['hostname'] = gethostname();
|
||||
$array['event_guard_logs'][0]['log_date'] = 'now()';
|
||||
$array['event_guard_logs'][0]['filter'] = $filter;
|
||||
$array['event_guard_logs'][0]['ip_address'] = $ip_address;
|
||||
$array['event_guard_logs'][0]['extension'] = $event['to-user'].'@'.$event['to-host'];
|
||||
$array['event_guard_logs'][0]['user_agent'] = $event['user-agent'];
|
||||
$array['event_guard_logs'][0]['log_status'] = 'blocked';
|
||||
$p = permissions::new();
|
||||
$p->add('event_guard_log_add', 'temp');
|
||||
$database->app_name = 'event guard';
|
||||
$database->app_uuid = 'c5b86612-1514-40cb-8e2c-3f01a8f6f637';
|
||||
$database->save($array, false);
|
||||
$p->delete('event_guard_log_add', 'temp');
|
||||
|
||||
//send debug information to the console
|
||||
if ($debug) {
|
||||
echo "blocked address ".$ip_address .", line ".__line__."\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//unblock the ip address
|
||||
/**
|
||||
* Unblock a specified IP address from a firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to unblock.
|
||||
* @param string $filter The filter name used in the firewall configuration.
|
||||
*
|
||||
* @return bool True if the IP address was successfully unblocked, false otherwise.
|
||||
*/
|
||||
function unblock($ip_address, $filter) {
|
||||
//define the global variables
|
||||
global $debug, $firewall_path, $firewall_name;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//unblock the address
|
||||
if ($firewall_name == 'iptables') {
|
||||
$command = $firewall_path.'/./iptables -L '.$filter.' -n --line-numbers | grep "'.$ip_address.' " | cut -d " " -f1';
|
||||
$line_number = trim(shell($command));
|
||||
echo "\n". $command . " line ".__line__."\n";
|
||||
if (is_numeric($line_number)) {
|
||||
//$result = shell('iptables -D INPUT '.$line_number);
|
||||
$command = $firewall_path.'/./iptables -D '.$filter.' '.$line_number;
|
||||
$result = shell($command);
|
||||
echo "Unblock address ".$ip_address ." line ".$line_number." command ".$command." result ".$result."\n";
|
||||
}
|
||||
}
|
||||
|
||||
//unblock the address
|
||||
if ($firewall_name == 'pf') {
|
||||
//example: pfctl -t sip-auth-ip -T delete 127.0.0.5
|
||||
$command = $firewall_path.'/pfctl -t '.$filter.' -T delete '.$ip_address;
|
||||
$result = shell($command);
|
||||
}
|
||||
|
||||
//send debug information to the console
|
||||
if ($debug) {
|
||||
echo "Unblock address ".$ip_address ."\n";
|
||||
}
|
||||
}
|
||||
|
||||
//is the ip address blocked
|
||||
/**
|
||||
* Check if an IP address is blocked in the configured firewall.
|
||||
*
|
||||
* @param string $ip_address The IP address to check
|
||||
*
|
||||
* @return bool True if the address is blocked, False otherwise
|
||||
*/
|
||||
function is_blocked($ip_address) {
|
||||
//define the global variables
|
||||
global $firewall_path, $firewall_name;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//determine whether to return true or false
|
||||
if ($firewall_name == 'iptables') {
|
||||
//check to see if the address is blocked
|
||||
$command = $firewall_path.'/./iptables -L -n --line-numbers | grep '.$ip_address;
|
||||
$result = shell($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
elseif ($firewall_name == 'pf') {
|
||||
//check to see if the address is blocked
|
||||
$command = $firewall_path.'/pfctl -t ".$filter." -Ts | grep '.$ip_address;
|
||||
$result = shell($command);
|
||||
if (!empty($result) && strlen($result) > 3) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//determine if the IP address has been allowed by the access control list node cidr
|
||||
/**
|
||||
* Determine if access is allowed for a given IP address.
|
||||
*
|
||||
* This method checks the cache, user logs, event guard logs, access controls,
|
||||
* and registration to determine if access should be granted. If no valid reason
|
||||
* is found to deny access, it will be automatically allowed.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for access.
|
||||
*
|
||||
* @return boolean True if access is allowed, false otherwise.
|
||||
*/
|
||||
function access_allowed($ip_address) {
|
||||
//define global variables
|
||||
global $debug;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check the cache to see if the address is allowed
|
||||
$cache = new cache;
|
||||
if ($cache->get("switch:allowed:".$ip_address) === 'true') {
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address: ".$ip_address." allowed by: cache\n";
|
||||
}
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//allow access for addresses with authentication status success
|
||||
if (user_log_allowed($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address: ".$ip_address." allowed by: user logs\n";
|
||||
}
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//allow access for addresses that have been unblocked
|
||||
/*
|
||||
if (event_guard_log_allowed($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address: ".$ip_address." allowed by: unblocked\n";
|
||||
}
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//allow access if the cidr address is allowed
|
||||
if (access_control_allowed($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address: ".$ip_address." allowed by: access controls\n";
|
||||
}
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//auto allow if there is a registration from the same IP address
|
||||
if (is_registered($ip_address)) {
|
||||
//save address to the cache as allowed
|
||||
$cache->set("switch:allowed:".$ip_address, 'true');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address: ".$ip_address." allowed by: registration\n";
|
||||
}
|
||||
|
||||
//return boolean true
|
||||
return true;
|
||||
}
|
||||
|
||||
//return
|
||||
return false;
|
||||
}
|
||||
|
||||
//is the ip address registered
|
||||
/**
|
||||
* Checks if the given IP address is registered on the network.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for registration.
|
||||
*
|
||||
* @return bool True if the IP address is registered, false otherwise.
|
||||
*/
|
||||
function is_registered($ip_address) {
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$registered = false;
|
||||
$command = "fs_cli -x 'show registrations as json' ";
|
||||
$result = shell($command);
|
||||
$array = json_decode($result, true);
|
||||
if (is_array($array['rows'])) {
|
||||
foreach ($array['rows'] as $row) {
|
||||
if ($row['network_ip'] == $ip_address) {
|
||||
$registered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return registered boolean
|
||||
return $registered;
|
||||
}
|
||||
|
||||
//determine if the IP address has been allowed by the access control list node cidr
|
||||
/**
|
||||
* Checks if the given IP address is authorized by any access control node.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for authorization.
|
||||
*
|
||||
* @return bool True if the IP address is authorized, false otherwise.
|
||||
*/
|
||||
function access_control_allowed($ip_address) {
|
||||
|
||||
global $database;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the access control allowed nodes
|
||||
$sql = "select access_control_node_uuid, access_control_uuid, node_cidr, node_description ";
|
||||
$sql .= "from v_access_control_nodes ";
|
||||
$sql .= "where node_type = 'allow' ";
|
||||
$sql .= "and length(node_cidr) > 0 ";
|
||||
$parameters = null;
|
||||
$allowed_nodes = $database->select($sql, $parameters, 'all');
|
||||
|
||||
//default authorized to false
|
||||
$allowed = false;
|
||||
|
||||
//use the ip address to get the authorized nodes
|
||||
if (is_array($allowed_nodes)) {
|
||||
foreach($allowed_nodes as $row) {
|
||||
if (check_cidr($row['node_cidr'], $ip_address)) {
|
||||
//debug info
|
||||
//if ($debug) {
|
||||
// print_r($row);
|
||||
// echo $ip_address."\n";
|
||||
//}
|
||||
|
||||
//set the allowed to true
|
||||
$allowed = true;
|
||||
|
||||
//exit the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
//determine if the IP address has been allowed by a successful authentication
|
||||
/**
|
||||
* Determines if a user's IP address is allowed based on their login history.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for access.
|
||||
*
|
||||
* @return bool True if the IP address is allowed, false otherwise.
|
||||
*/
|
||||
function user_log_allowed($ip_address) {
|
||||
|
||||
global $database, $debug;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check to see if the address was authenticated successfully
|
||||
$sql = "select count(user_log_uuid) ";
|
||||
$sql .= "from v_user_logs ";
|
||||
$sql .= "where remote_address = :remote_address ";
|
||||
$sql .= "and result = 'success' ";
|
||||
$sql .= "and timestamp > NOW() - INTERVAL '8 days' ";
|
||||
$parameters['remote_address'] = $ip_address;
|
||||
$user_log_count = $database->select($sql, $parameters, 'column');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address ".$ip_address." count ".$user_log_count."\n";
|
||||
}
|
||||
|
||||
//default authorized to false
|
||||
$allowed = false;
|
||||
|
||||
//use the ip address to get the authorized nodes
|
||||
if (!empty($user_log_count) && $user_log_count > 0) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
//return
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
//determine if the IP address has been unblocked in the event guard log
|
||||
/**
|
||||
* Determines if an IP address is allowed based on event guard logs.
|
||||
*
|
||||
* @param string $ip_address The IP address to check for access.
|
||||
*
|
||||
* @return bool True if the IP address is allowed, false otherwise.
|
||||
*/
|
||||
function event_guard_log_allowed($ip_address) {
|
||||
|
||||
global $database, $debug;
|
||||
|
||||
//invalid ip address
|
||||
if (!filter_var($ip_address, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the access control allowed nodes
|
||||
$sql = "select count(event_guard_log_uuid) ";
|
||||
$sql .= "from v_event_guard_logs ";
|
||||
$sql .= "where ip_address = :ip_address ";
|
||||
$sql .= "and log_status = 'unblocked' ";
|
||||
$parameters['ip_address'] = $ip_address;
|
||||
$user_log_count = $database->select($sql, $parameters, 'column');
|
||||
|
||||
//debug info
|
||||
if ($debug) {
|
||||
echo "address ".$ip_address." count ".$user_log_count."\n";
|
||||
}
|
||||
|
||||
//default authorized to false
|
||||
$allowed = false;
|
||||
|
||||
//use the ip address to get the authorized nodes
|
||||
if ($user_log_count > 0) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
//return
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
//check if the iptables chain exists
|
||||
/**
|
||||
* Determines if a pf table exists in the firewall configuration.
|
||||
*
|
||||
* @param string $table The name of the pf table to check for existence.
|
||||
*
|
||||
* @return bool True if the pf table exists, false otherwise.
|
||||
*/
|
||||
function pf_table_exists($table) {
|
||||
//define the global variables
|
||||
global $firewall_path, $firewall_name;
|
||||
|
||||
//build the command to check if the pf table exists
|
||||
$command = $firewall_path."/./pfctl -t ".$table." -T show | grep error";
|
||||
//if ($debug) { echo $command."\n"; }
|
||||
$response = shell($command);
|
||||
if (!empty($response)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//add IP table chains
|
||||
/**
|
||||
* Adds a new IPtables chain and inserts it into the INPUT table.
|
||||
*
|
||||
* @param string $chain The name of the IPtables chain to add.
|
||||
*
|
||||
* @return bool True if the chain was successfully added, false otherwise.
|
||||
*/
|
||||
function iptables_chain_add($chain) {
|
||||
//define the global variables
|
||||
global $firewall_path;
|
||||
|
||||
//if the chain exists return true
|
||||
if (iptables_chain_exists($chain)) {
|
||||
echo "IPtables ".$chain." chain already exists\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
//log info to the console
|
||||
echo "Add iptables ".$chain." chain\n";
|
||||
|
||||
//add the chain
|
||||
system($firewall_path.'/./iptables --new '.$chain);
|
||||
system($firewall_path.'/./iptables -I INPUT -j '.$chain);
|
||||
|
||||
//check if the chain exists
|
||||
if (iptables_chain_exists($chain)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
sleep(1);
|
||||
iptables_chain_add($chain);
|
||||
}
|
||||
}
|
||||
|
||||
//check if the iptables chain exists
|
||||
/**
|
||||
* Determines if a specified iptables chain exists.
|
||||
*
|
||||
* @param string $chain The name of the iptables chain to check for existence.
|
||||
*
|
||||
* @return bool True if the iptables chain exists, false otherwise.
|
||||
*/
|
||||
function iptables_chain_exists($chain) {
|
||||
//define the global variables
|
||||
global $firewall_path;
|
||||
|
||||
//build the command to check if the iptables chain exists
|
||||
$command = $firewall_path."/./iptables --list INPUT --numeric | grep ".$chain." | awk '{print \$1}' | sed ':a;N;\$!ba;s/\\n/,/g' ";
|
||||
//if ($debug) { echo $command."\n"; }
|
||||
$response = shell($command);
|
||||
if (in_array($chain, explode(",", $response))) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Exit with error code
|
||||
exit($ex->getCode());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user