It is your script. Its weird because now script sent 2 rules to Mikrotik but in third test, script has stopped. Some is killing that script which I can’t see what neither why.
Here output file php (which its always showing but doesn’t matter because with that error if I don’t leave shell, Mikrotik receive alerts) →
Notice: Array to string conversion in /opt/mikrotik-ips-suricata/suricata_block.php on line 41
Array
Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, boolean given in /opt/mikrotik-ips-suricata/suricata_block.php on line 139
Here script:
# cat /opt/mikrotik-ips-suricata/suricata_block.php
<?php
require('routeros_api.class.php');
/* Set your specific configuration below */
$user_name = "snorby";
$password = "XXXXXX";
$database = "snorby";
$server = "localhost";
$mikrotik_addr = "192.168.X.X";
$mikrotik_user = "admin";
$mikrotik_pwd = "XXXXX";
$local_ip_prefix = "192.168.";
$email_to = "MYEMAIL";
$email_from = "MYEMAIL";
header('Content-Type: text/plain');
$API = new RouterosAPI();
function UptimeInSeconds($uptime) {
$mark1=strpos($uptime, "d");
$days=substr($uptime, 0, $mark1);
if ($mark1) $uptime=substr($uptime, $mark1 + 1);
$mark1=strpos($uptime, "h");
$hours=substr($uptime, 0, $mark1);
if ($mark1) $uptime=substr($uptime, $mark1 + 1);
$mark1=strpos($uptime, "m");
$minutes=substr($uptime, 0, $mark1);
if ($mark1) $uptime=substr($uptime, $mark1 + 1);
$mark1=strpos($uptime, "s");
$seconds=substr($uptime, 0, $mark1);
if ($mark1) $uptime=substr($uptime, $mark1 + 1);
$total=($days * 86400) + ($hours * 3600) + ($minutes * 60) + $seconds;
return $total;
}
function AddToFirewall($thisrow) {
echo $thisrow;
global $local_ip_prefix, $API, $mikrotik_addr, $mikrotik_user, $mikrotik_pwd, $email_to, $email_from;
if (strpos($thisrow['que_ip_adr'], $local_ip_prefix) !== true) {
/* Does not match local address... */
/* See if the address is already in the firewall list, if so delete it so we can readd it with a new timeout */
try {
$API->connect($mikrotik_addr, $mikrotik_user, $mikrotik_pwd);
} catch (Exception $e) {
die('Unable to connect to RouterOS. Error:' . $e);
}
$ARRAY = $API->comm("/ip/firewall/address-list/print", array(
".proplist"=> ".id",
"?address" => $thisrow['que_ip_adr'],));
foreach ($ARRAY as $a) {
foreach ($a as $name => $value) {
$API->write("/ip/firewall/address-list/remove",false);
$API->write("=.id=$value",true);
$API->read();
}
}
if (array_key_exists('que_remaining', $thisrow))
{ $timeremaining = $thisrow['que_remaining']; }
else
{ $timeremaining = $thisrow['que_timeout']; }
$API->comm("/ip/firewall/address-list/add", array(
"list" => "Blocked",
"address" => $thisrow['que_ip_adr'],
"timeout" => $timeremaining,
"comment" => "From suricata, " . $thisrow['que_sig_name'] . " => " . $thisrow['que_sig_gid'] . ":" . $thisrow['que_sig_sid'] .
" => event timestamp: " . $thisrow['que_event_timestamp'],));
$API->disconnect();
} else {
/* Send email indicating bad block attempt*/
$to = $email_to;
$subject = 'Suricata on ' . gethostname() . ': attempted block on local address';
$message = 'A record in the block_queue indicated a block on a local IP Address (' . $row['que_ip_adr'] . ")\r\n";
$message = $message . "\r\n";
$message = $message . "The signature ID is " . $row['que_sig_id'] . " named: " . $row['que_sig_name'] . "\r\n";
$message = $message . " with a que_id of " . $row['que_id'] . "\r\n\r\n";
$message = $message . "Check the src_or_dst field in events_to_block for the signature to make sure it is correct (src/dst).\r\n\r\n";
$message = $message . "The record was not processed but marked as completed.\r\n";
$headers = 'From: ' . $email_from . "\r\n" .
'Reply-To: ' . $email_from . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
}
return true;
}
/* Connect to database, if unsuccessful keep trying for 100 seconds */
$i = 0;
while ( $i < 100 ) {
$db = new mysqli($server, $user_name, $password, $database);
if ($db->connect_errno > 0) {
print('Unable to connect to database [' . $db->connect_error . ']');
sleep(10);
$i = $i + 10;
}
else {
$i = 100;
}
}
/* Check to see how long the mikrotik has been up. If less than 5 minutes then rebuild firewall list */
try {
$API->connect($mikrotik_addr, $mikrotik_user, $mikrotik_pwd);
} catch (Exception $e) {
die('Unable to connect to RouterOS. Error:' . $e);
}
$ARRAY = $API->comm("/system/resource/print", false);
$upsecs = UptimeInSeconds($ARRAY[0]['uptime']);
$API->disconnect();
if ($upsecs < 300) {
/* This SELECT statement will ignore any entries that had 2 minutes or less remaining */
$SQL = "SELECT *,DATE_FORMAT(TIMEDIFF(ADDTIME(que_added,que_timeout), CURRENT_TIMESTAMP), '%H:%i:%s') as que_remaining " .
"FROM block_queue where ADDTIME(que_added, que_timeout) > TIMESTAMPADD(MINUTE, 2, CURRENT_TIMESTAMP) order by que_remaining;";
if (!$result = $db->query($SQL)) {
die('There was an error running the query [' . $db->error . ']');
}
while ($row = $result->fetch_assoc()) {
$x = AddToFirewall($row);
}
$rslt = mysqli_free_result($result);
}
/* Main program loop */
while ( 1 == 1 ) {
$SQL = "SELECT * FROM block_queue WHERE que_processed = 0;";
if(!$result = $db->query($SQL)) {
die('There was an error running the query [' . $db->error . ']');
}
while($row = $result->fetch_assoc()) {
$x = AddToFirewall($row);
$SQL2 = "UPDATE block_queue set que_processed = 1 WHERE que_id = " . $row['que_id'] . ";";
if (!$result2 = $db->query($SQL2)) {
die('There was an error running the query [' . $db->error . ']');
}
$rslt = mysqli_free_result($result2);
}
$rslt = mysqli_free_result($result);
sleep(5); /* Sleep 5 seconds then do again */
mysqli_ping($db);
}
$db->close();
?>
Sorry for so many post converting the post (a great job and an excellent tool) in my troubleshooting. Thanks.