Rocky 9: Difference between revisions

From VoIPmonitor.org
(Add post-installation tasks: timezone, Postfix MTA, MySQL data directory relocation)
(Review: oprava formátování (syntaxhighlight pro všechny kódové bloky), přidání hlavního nadpisu, oprava odkazů na wiki stránky, přidání AI Summary for RAG sekce)
Line 1: Line 1:
= Rocky Linux 9 Installation Guide =
This guide describes the installation of VoIPmonitor on '''Rocky Linux 9''' with PHP 8.2 and MySQL 8.0. The installation consists of three main components: MySQL database, Web GUI, and the Sensor (sniffer).
This guide describes the installation of VoIPmonitor on '''Rocky Linux 9''' with PHP 8.2 and MySQL 8.0. The installation consists of three main components: MySQL database, Web GUI, and the Sensor (sniffer).


Line 9: Line 11:


'''1. Install MySQL server:'''
'''1. Install MySQL server:'''
dnf install mysql-server
 
<syntaxhighlight lang="bash">
dnf install mysql-server
</syntaxhighlight>


'''2. Configure MySQL:'''
'''2. Configure MySQL:'''


Edit <code>/etc/my.cnf.d/mysql-server.cnf</code> and add:
Edit <code>/etc/my.cnf.d/mysql-server.cnf</code> and add:
innodb_flush_log_at_trx_commit = 2
 
innodb_buffer_pool_size = 8GB
<syntaxhighlight lang="ini">
skip-log-bin
innodb_flush_log_at_trx_commit = 2
innodb_buffer_pool_size = 8GB
skip-log-bin
</syntaxhighlight>


'''Note on MySQL Authentication Methods:'''
'''Note on MySQL Authentication Methods:'''
Line 25: Line 33:


If you must configure mysql_native_password for compatibility reasons (not recommended):
If you must configure mysql_native_password for compatibility reasons (not recommended):
echo 'default-authentication-plugin=mysql_native_password' >> /etc/my.cnf.d/mysql-server.cnf
 
<syntaxhighlight lang="bash">
echo 'default-authentication-plugin=mysql_native_password' >> /etc/my.cnf.d/mysql-server.cnf
</syntaxhighlight>


{{Note|Set <code>innodb_buffer_pool_size</code> to approximately half of your available RAM. See the [[Scaling]] guide for more details.}}
{{Note|Set <code>innodb_buffer_pool_size</code> to approximately half of your available RAM. See the [[Scaling]] guide for more details.}}


'''3. Start MySQL and configure authentication:'''
'''3. Start MySQL and configure authentication:'''
systemctl start mysqld
 
systemctl enable mysqld
<syntaxhighlight lang="bash">
systemctl start mysqld
systemctl enable mysqld
</syntaxhighlight>


Set root password for MySQL (can be empty):
Set root password for MySQL (can be empty):
mysql
 
mysql> ALTER USER root@localhost IDENTIFIED BY '' OR REPLACE;
<syntaxhighlight lang="sql">
mysql> FLUSH PRIVILEGES;
mysql> ALTER USER root@localhost IDENTIFIED BY '' OR REPLACE;
mysql> exit
mysql> FLUSH PRIVILEGES;
</syntaxhighlight>


'''4. Run security configuration:'''
'''4. Run security configuration:'''
mysql_secure_installation
 
<syntaxhighlight lang="bash">
mysql_secure_installation
</syntaxhighlight>


== Web GUI Installation ==
== Web GUI Installation ==
Line 47: Line 65:


Rocky 9 ships with PHP 8.0, but IonCube requires PHP 8.2:
Rocky 9 ships with PHP 8.0, but IonCube requires PHP 8.2:
dnf install epel-release
 
dnf install http://rpms.remirepo.net/enterprise/remi-release-9.rpm
<syntaxhighlight lang="bash">
dnf module reset php
dnf install epel-release
dnf module install php:remi-8.2
dnf install http://rpms.remirepo.net/enterprise/remi-release-9.rpm
dnf module reset php
dnf module install php:remi-8.2
</syntaxhighlight>


'''2. Install required packages:'''
'''2. Install required packages:'''
dnf install wget httpd wireshark php php-gd php-mysqlnd php-mbstring php-zip mtr php-process librsvg2 librsvg2-tools urw-fonts
 
<syntaxhighlight lang="bash">
dnf install wget httpd wireshark php php-gd php-mysqlnd php-mbstring php-zip mtr php-process librsvg2 librsvg2-tools urw-fonts
</syntaxhighlight>


'''3. Install IonCube loader:'''
'''3. Install IonCube loader:'''
wget http://voipmonitor.org/ioncube/x86_64/ioncube_loader_lin_8.2.so -O /usr/lib64/php/modules/ioncube_loader_lin_8.2.so
 
echo "zend_extension = /usr/lib64/php/modules/ioncube_loader_lin_8.2.so" > /etc/php.d/01_ioncube.ini
<syntaxhighlight lang="bash">
wget http://voipmonitor.org/ioncube/x86_64/ioncube_loader_lin_8.2.so -O /usr/lib64/php/modules/ioncube_loader_lin_8.2.so
echo "zend_extension = /usr/lib64/php/modules/ioncube_loader_lin_8.2.so" > /etc/php.d/01_ioncube.ini
</syntaxhighlight>


'''4. Disable SELinux:'''
'''4. Disable SELinux:'''


SELinux must be disabled for VoIPmonitor to function properly:
SELinux must be disabled for VoIPmonitor to function properly:
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
 
setenforce 0
<syntaxhighlight lang="bash">
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
</syntaxhighlight>


'''5. Download and install GUI:'''
'''5. Download and install GUI:'''
cd /var/www/html
 
wget "http://www.voipmonitor.org/download-gui?version=latest&major=5&allowed&phpver=82" -O w.tar.gz
<syntaxhighlight lang="bash">
tar xzf w.tar.gz
cd /var/www/html
mv voipmonitor-gui*/* ./
wget "http://www.voipmonitor.org/download-gui?version=latest&major=5&allowed&phpver=82" -O w.tar.gz
tar xzf w.tar.gz
mv voipmonitor-gui*/* ./
</syntaxhighlight>


'''6. Configure permissions and start Apache:'''
'''6. Configure permissions and start Apache:'''
chown -R apache /var/www/html
 
mkdir -p /var/spool/voipmonitor
<syntaxhighlight lang="bash">
chown apache /var/spool/voipmonitor
chown -R apache /var/www/html
systemctl start httpd
mkdir -p /var/spool/voipmonitor
systemctl enable httpd
chown apache /var/spool/voipmonitor
systemctl start httpd
systemctl enable httpd
</syntaxhighlight>


'''7. Configure cron for alerts and reports:'''
'''7. Configure cron for alerts and reports:'''
echo "* * * * * root php /var/www/html/php/run.php cron" >> /etc/crontab
 
kill -HUP $(pgrep crond)
<syntaxhighlight lang="bash">
echo "* * * * * root php /var/www/html/php/run.php cron" >> /etc/crontab
kill -HUP $(pgrep crond)
</syntaxhighlight>


{{Note|Install Postfix for email alert functionality (see "Post-Installation Tasks" below).}}
{{Note|Install Postfix for email alert functionality (see "Post-Installation Tasks" below).}}
Line 150: Line 189:
'''1. Create systemd service file:'''
'''1. Create systemd service file:'''


Create <code>/etc/systemd/system/voipmonitor.service</code> - see [[systemd for voipmonitor service management]] for the template.
Create <code>/etc/systemd/system/voipmonitor.service</code> - see [[Systemd_for_voipmonitor_service_management|systemd for voipmonitor service management]] for the template.


'''2. Download and install sensor:'''
'''2. Download and install sensor:'''
cd /usr/local/src
 
wget --content-disposition http://www.voipmonitor.org/current-stable-sniffer-static-64bit.tar.gz -O current-stable-sniffer-static-64bit.tar.gz
<syntaxhighlight lang="bash">
tar xzf current-stable-sniffer-static-64bit.tar.gz
cd /usr/local/src
cd voipmonitor-*
wget --content-disposition http://www.voipmonitor.org/current-stable-sniffer-static-64bit.tar.gz -O current-stable-sniffer-static-64bit.tar.gz
mkdir -p /etc/init.d
tar xzf current-stable-sniffer-static-64bit.tar.gz
./install-script.sh --no-user-input
cd voipmonitor-*
mkdir -p /etc/init.d
./install-script.sh --no-user-input
</syntaxhighlight>


'''3. Configure sensor:'''
'''3. Configure sensor:'''


Edit <code>/etc/voipmonitor.conf</code> and set at minimum:
Edit <code>/etc/voipmonitor.conf</code> and set at minimum:
interface = eth0
 
spooldir = /var/spool/voipmonitor
<syntaxhighlight lang="ini">
cleandatabase = 31
interface = eth0
sipport = 5060
spooldir = /var/spool/voipmonitor
maxpoolsize = 102400
cleandatabase = 31
sipport = 5060
maxpoolsize = 102400
</syntaxhighlight>


{{Note|Replace <code>eth0</code> with your actual network interface name.}}
{{Note|Replace <code>eth0</code> with your actual network interface name.}}


'''4. Start and enable sensor:'''
'''4. Start and enable sensor:'''
systemctl daemon-reload
 
systemctl start voipmonitor
<syntaxhighlight lang="bash">
systemctl enable voipmonitor
systemctl daemon-reload
systemctl start voipmonitor
systemctl enable voipmonitor
</syntaxhighlight>


== Firewall Configuration ==
== Firewall Configuration ==


'''Option 1: Allow specific IP access:'''
'''Option 1: Allow specific IP access:'''
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="YOUR_IP" accept'
 
firewall-cmd --reload
<syntaxhighlight lang="bash">
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="YOUR_IP" accept'
firewall-cmd --reload
</syntaxhighlight>


'''Option 2: Open HTTP port:'''
'''Option 2: Open HTTP port:'''
firewall-cmd --permanent --add-service=http
 
firewall-cmd --reload
<syntaxhighlight lang="bash">
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
</syntaxhighlight>


'''Option 3: Disable firewall (not recommended for production):'''
'''Option 3: Disable firewall (not recommended for production):'''
systemctl stop firewalld
 
systemctl disable firewalld
<syntaxhighlight lang="bash">
systemctl stop firewalld
systemctl disable firewalld
</syntaxhighlight>


== Finish Installation ==
== Finish Installation ==
Line 196: Line 253:
== See Also ==
== See Also ==
* [[Scaling]] - Performance tuning
* [[Scaling]] - Performance tuning
* [[Configuration_file]] - Full configuration reference
* [[Sniffer_configuration|Configuration file]] - Full configuration reference
* [[systemd for voipmonitor service management]] - Systemd service file
* [[Systemd_for_voipmonitor_service_management|systemd for voipmonitor service management]] - Systemd service file
 
== AI Summary for RAG ==
 
'''Summary:''' Step-by-step installation guide for VoIPmonitor on Rocky Linux 9 with PHP 8.2 and MySQL 8.0. Covers MySQL installation and configuration (including innodb_buffer_pool_size sizing and authentication notes about caching_sha2_password vs mysql_native_password), Web GUI installation with PHP 8.2 from Remi repository, IonCube loader setup, SELinux disabling, Apache httpd configuration, cron setup for alerts, timezone configuration, Postfix MTA installation for email alerts, optional MySQL data directory relocation, and sensor (sniffer) installation with systemd service management. Includes firewall configuration options using firewall-cmd.
 
'''Keywords:''' Rocky Linux 9, installation, MySQL 8.0, PHP 8.2, Remi repository, IonCube, SELinux, Apache httpd, systemd, firewall-cmd, caching_sha2_password, mysql_native_password, innodb_buffer_pool_size, Postfix, MTA, timezone, sensor installation, voipmonitor.conf
 
'''Key Questions:'''
* How do I install VoIPmonitor on Rocky Linux 9?
* What PHP version is required for VoIPmonitor on Rocky 9?
* How do I install PHP 8.2 on Rocky Linux 9?
* Do I need to configure mysql_native_password on Rocky 9?
* How do I configure the firewall for VoIPmonitor on Rocky Linux?
* How do I install IonCube loader on Rocky Linux 9?
* How do I disable SELinux for VoIPmonitor?
* How do I move MySQL data directory to a different partition?
* What is the systemd service configuration for VoIPmonitor?
* How do I configure email alerts on Rocky Linux 9?
s:
 
===== 1. Immediate Blocking via Custom Scripts =====
 
Configure a custom script in the SIP REGISTER flood alert rule to automatically block the attacker IP. The <code>alert_info</code> object contains the attacker's IP address.
 
<syntaxhighlight lang="bash">
# Block using iptables
iptables -A INPUT -s <ATTACKER_IP> -j DROP
 
# Block using ipset (more efficient for multiple IPs)
ipset add blacklist <ATTACKER_IP>
</syntaxhighlight>
 
===== 2. Network Edge Blocking (Recommended for Prevention) =====
 
For long-term protection, block at your network edge before traffic reaches VoIPmonitor:
* '''Session Border Controller (SBC)''': Configure rate limiting and IP blocking
* '''Firewall''': Block malicious IPs at the perimeter
* '''Fail2ban''': Automatically block IPs after repeated REGISTER failures
 
===== 3. Reducing REGISTER Noise =====
 
* Disable REGISTER processing if not needed: <code>sip-register = no</code> in <code>voipmonitor.conf</code>
* Filter REGISTER packets using firewall rules (block specific countries or networks)
* Use [[Capture_rules|capture rules]] to exclude known good REGISTER sources from processing
 
=== Realtime Concurrent Calls ===
 
Tracks source IPs in realtime (not CDR-based) for concurrent calls. Useful against high-channel attacks.
 
;Parameters:
:* '''Concurrent calls limit''': Trigger on international, local, or both exceeding limits
:* '''Time period rules''': Vary alerts by work/after hours (defined in '''Groups > TimePeriods''')
 
==== IP Filtering Capabilities and Limitations ====
 
The "'''BY'''" dropdown in the Realtime Concurrent Calls alert configuration only supports Source IP aggregation. This is a hard-coded limitation of the realtime detection logic, which monitors concurrent INVITEs per source address to detect attacks.
 
To monitor concurrent calls based on '''Destination IP''' (such as checking if a specific carrier or trunk exceeds a channel limit), use the standard '''Concurrent calls''' alert located in '''GUI > Alerts''' instead. The regular concurrent calls alert supports multiple aggregation options including Source IP, Destination IP (Called), Domain, and custom headers.
 
{| class="wikitable"
|-
! Monitoring Need !! Recommended Alert Type !! GUI Location
|-
| Detect attacks from specific source IPs || '''Realtime concurrent calls''' || Alerts > Anti Fraud
|-
| Monitor trunk/capacity limits (by destination IP) || '''Concurrent calls''' || Alerts (main section)
|-
| Detect domain-specific concurrent call patterns || '''Concurrent calls''' || Alerts (main section)
|}
 
See [[Alerts#Fraud_Concurrent_Calls_vs_Regular_Concurrent_Calls_Alerts|Alerts - Fraud Concurrent Calls vs Regular Concurrent Calls Alerts]] for a detailed comparison.
 
=== Change CDR Country ===
 
Triggers when CDR IP source changes country/continent since last call.
 
;Parameters:
:* '''Exclude countries from alert''': Whitelist countries to skip
 
==== Number-Based Filtering ====
 
You can use the '''Numbers include/exclude''' parameter to limit this alert based on caller number patterns. This is useful when you want to trigger the alert only for specific call signatures, such as detecting fraud calls with malformed caller IDs containing letters.
 
===== Using Regex Patterns Directly =====
 
Enter regex patterns in the '''Numbers include/exclude''' field:
 
:* Detect numbers containing letters:
:<code>R([a-zA-Z])</code>
 
:* Detect numbers that are NOT purely numeric (malformed caller IDs):
:<code>!R(^[+]?[0-9]+$)</code>
 
The <code>R()</code> syntax enables regular expression mode. See [[Call_Detail_Record_-_CDR#Regular_Expressions_for_Advanced_Number_Filtering|CDR filtering documentation]] for more regex examples.
 
===== Using Telephone Number Groups (Recommended for Complex Patterns) =====
 
For complex patterns or when you want to reuse the filter across multiple alerts:
 
1. Create a [[Groups|telephone number group]] at '''GUI > Groups > Tel. numbers'''
2. Add regex patterns or specific numbers to the group (e.g., <code>[a-zA-Z]</code> for numbers containing letters)
3. Test the group by applying it as a filter in the CDR view
4. In the anti-fraud alert settings, click the '''Numbers include/exclude''' field selector
5. Select your telephone number group from the dropdown list
 
Using groups is recommended because you can test the pattern against actual CDR data before applying it to alerts.
 
=== Change REGISTER Country ===
 
Triggers when SIP REGISTER username changes country/continent since last successful registration.
 
;Parameters:
:* '''Exclude countries from alert''': Whitelist countries to skip
 
=== Detecting User-Agent Changes ===
 
There is '''no built-in alert''' for detecting changes to a SIP registration's User-Agent (UA) string. However, you can enable database-level tracking of UA changes by configuring the sniffer to create new register state records when the UA changes.
 
To enable UA change tracking, set <code>sip-register-state-compare-digest_ua = yes</code> (or its alias <code>sip-register-state-compare-ua = yes</code>) in <code>voipmonitor.conf</code>. This forces the sniffer to create a new record in the register state table whenever the UA changes, even if other registration details remain the same. See [[Sniffer_configuration#SIP_REGISTER,_OPTIONS,_SUBSCRIBE,_NOTIFY|Sniffer Configuration]] for details.
 
;Alternative fraud alerts for registration anomalies:
:* '''Change REGISTER country''': Detects when registration source country changes
:* '''Change CDR country''': Detects when call source country changes
 
;Custom detection:
:* Query the <code>register_state</code> database table to detect UA changes programmatically
:* Use custom scripts with anti-fraud rules to trigger actions based on database queries
 
=== Country/Continent Destination ===
 
Triggers on calls to specific country/continent, based on first SIP INVITE (realtime processing).
 
=== SIP PACKETS Flood/Attack ===
 
Triggers when >= N packets from an IP occur within the set interval.
 
=== Fraud: Sequential ===
 
Detects when a high volume of calls are made to any single destination number within a short time period. Use this alert to monitor for patterns like excessive sequential dialing to premium rate numbers or destination abuse.
 
;Parameters:
:* '''Interval''': Time window in seconds to monitor call volume (e.g., 3600 for 1 hour)
:* '''Limit''': Maximum number of calls allowed within the interval (e.g., 100)
:* '''Called number filters''': Destination numbers/prefixes to monitor (leave empty to monitor all destinations)
 
;Configuration for "Any Single Destination":
:* To alert on call volume to '''any''' destination number (not specific numbers), leave the called number field empty. The alert will then detect excessive calling to any single number within the configured time window.
 
;Example Use Cases:
:* Alert when more than 50 calls are made to the same destination within 1 hour
:* Detect sequential dialing to premium rate numbers
:* Identify destination number abuse or toll fraud
:* Detect [[Sniffer_troubleshooting#Routing_Loops|routing loops]] by monitoring excessive calls to a single destination number (routing loops typically cause rapid repeated attempts to the same called number)
 
;Important Limitation:
:* '''Aggregation method:''' This alert aggregates and monitors call volume '''by source IP address''', not by the calling (source) telephone number.
:* If you need to detect excessive use of a '''specific calling number''', use the '''CDR summary report''' instead (configure it with Summary type set to ''source number'').
 
=== Custom Script Examples ===
 
Custom scripts receive alert data as command-line arguments. The fourth argument (<code>$argv[4]</code> in PHP) contains JSON-encoded alert data.
 
==== Logging Passed Arguments ====
 
Simple script to log all arguments for debugging:
 
<syntaxhighlight lang="bash">
#!/bin/bash
echo "$(date): $@" >> /tmp/alert_debug.txt
</syntaxhighlight>
 
==== RTP Alert: Store Audio Files ====
 
Script to automatically download audio for calls that triggered an RTP alert:
 
<syntaxhighlight lang="php">
#!/usr/bin/php
<?php
// Configuration
$directory = '/home/alerts/audio';
$date = trim(`date '+%Y-%m-%d'`);
$guiDir = '/var/www/voipmonitor';
$destdir = $directory . '/' . $date;
 
// Create destination directory
`mkdir -p $destdir`;
 
// Parse alert data (4th argument contains JSON)
$alert = json_decode($argv[4]);
 
// Download audio for each CDR in the alert
foreach ($alert->cdr as $cdr) {
    $params = json_encode([
        'task' => 'getVoiceRecording',
        'user' => 'admin',
        'password' => 'admin',
        'params' => ['cdrId' => $cdr]
    ]);
    $command = "php $guiDir/php/api.php > $destdir/file_id_$cdr.pcap";
    exec("echo '$params' | $command", $arr, $val);
}
?>
</syntaxhighlight>
 
==== RTP Alert: Block IP After Threshold ====
 
Script to block IPs that exceed a threshold number of incidents:
 
<syntaxhighlight lang="php">
#!/usr/bin/php
<?php
// Configuration
$Limit = 19;                                              // Block after this many incidents
$blockCommand = "ssh root@pbx -p2112 ipset add blacklist"; // Remote blocking command
$verbose = 1;                                            // 1 = dry-run, 0 = execute
 
// Parse alert data
$alertsData = json_decode($argv[4]);
 
// Build comma-separated list of CDR IDs
$cdrIds = implode(',', $alertsData->cdr);
 
// Query database for caller IPs and incident counts
$query = "SELECT INET_NTOA(sipcallerip) as ip, COUNT(*) as incidents
          FROM voipmonitor.cdr
          WHERE id IN ($cdrIds)
          GROUP BY sipcallerip
          ORDER BY incidents DESC";
$command = "mysql -h MYSQLHOST -u MYSQLUSER -pMYSQLPASS -N -e \"$query\"";
exec($command, $results);
 
// Process results and block IPs exceeding limit
foreach ($results as $line) {
    list($ip, $count) = preg_split('/\s+/', trim($line));
    if ($count > $Limit) {
        if ($verbose) {
            echo "$ip: $count incidents - would block\n";
        } else {
            exec("$blockCommand $ip", $output, $rc);
            if ($rc != 0) {
                error_log("Failed to block $ip");
            }
        }
    }
}
?>
</syntaxhighlight>
 
==== Concurrent Calls: Block Attacker IP ====
 
Script for blocking IPs based on concurrent calls alert. Enable "By caller IP" in alert settings.
 
<syntaxhighlight lang="php">
#!/usr/bin/php
<?php
// Parse triggered rules (4th argument)
$triggeredRules = json_decode($argv[4]);
 
// Count triggers per IP address
$IPtriggers = [];
foreach ($triggeredRules as $rule) {
    $ip = $rule->alert_info->ip;
    $IPtriggers[$ip] = ($IPtriggers[$ip] ?? 0) + 1;
}
 
// Block all IPs that triggered the rule
foreach ($IPtriggers as $ip => $count) {
    echo "Blocking $ip (triggered $count times)\n";
    passthru("iptables -A INPUT -s $ip -j DROP", $ret);
    if ($ret != 0) {
        echo "ERROR: Failed to block $ip\n";
        exit(1);
    }
}
echo "Blocked " . count($IPtriggers) . " IP(s)\n";
?>
</syntaxhighlight>
 
=== See Also ===
 
* [[Alerts|Alerts & Reports]] - General alert configuration
* [[Capture_rules|Capture Rules]] - Filter traffic before processing
* [[Sniffer_configuration|Sniffer Configuration]] - <code>sip-register</code> and other options
* [[Groups|Groups]] - IP groups and time periods for alerts
 
== AI Summary for RAG ==
 
'''Summary:''' VoIPmonitor anti-fraud rules for detecting SIP attacks (REGISTER floods, packet floods), concurrent calls abuse, geographic anomalies, and high-volume sequential calling patterns. Covers realtime vs CDR-based alert processing differences, custom script examples for automated IP blocking via iptables/ipset, and mitigation strategies for SIP REGISTER spam.
 
'''Keywords:''' anti-fraud, REGISTER flood, SIP attack, concurrent calls, country change, custom scripts, iptables, ipset, fail2ban, realtime alerts, CDR-based alerts, source port limitation, sequential calls, sequential dialing, destination abuse, high call volume, large volume of calls, destination number, short period, alert configuration, number filtering, regex patterns, telephone number groups, R() syntax, Change CDR Country, Change REGISTER Country, Numbers include/exclude, malformed caller IDs, letters in phone numbers
 
'''Key Questions:'''
* What anti-fraud alerts are available in VoIPmonitor?
* How to block SIP REGISTER flood attacks?
* What is the difference between realtime and CDR-based alerts?
* How to create custom scripts for automated IP blocking?
* Why is source port not available in realtime alerts?
* How to configure an alert for a large volume of calls to any single destination number?
* What is the Fraud: sequential alert and how does it work?
* How to filter anti-fraud alerts by caller number patterns?
* How to trigger "Change CDR Country" alert only for numbers containing letters?
* How to use regex patterns (R() syntax) in anti-fraud number filtering?
* How to use telephone number groups in anti-fraud alerts?

Revision as of 11:24, 6 January 2026

Rocky Linux 9 Installation Guide

This guide describes the installation of VoIPmonitor on Rocky Linux 9 with PHP 8.2 and MySQL 8.0. The installation consists of three main components: MySQL database, Web GUI, and the Sensor (sniffer).

Prerequisites

  • Fresh Rocky Linux 9 installation
  • Root access
  • Internet connectivity

MySQL Installation

1. Install MySQL server:

dnf install mysql-server

2. Configure MySQL:

Edit /etc/my.cnf.d/mysql-server.cnf and add:

innodb_flush_log_at_trx_commit = 2
innodb_buffer_pool_size = 8GB
skip-log-bin

Note on MySQL Authentication Methods:

Rocky 9 uses MySQL 8.0 which defaults to caching_sha2_password. Since this guide installs PHP 8.2 (which is newer than PHP 7.4.4), the mysql_native_password line is NOT required. PHP 8.2 with the mysqlnd driver automatically supports caching_sha2_password.

If you see MySQL deprecation warnings about mysql_native_password, you can safely use the standard MySQL 8 authentication without any additional configuration. See the FAQ - MySQL Authentication section for more details.

If you must configure mysql_native_password for compatibility reasons (not recommended):

echo 'default-authentication-plugin=mysql_native_password' >> /etc/my.cnf.d/mysql-server.cnf

ℹ️ Note: Set innodb_buffer_pool_size to approximately half of your available RAM. See the Scaling guide for more details.

3. Start MySQL and configure authentication:

systemctl start mysqld
systemctl enable mysqld

Set root password for MySQL (can be empty):

mysql> ALTER USER root@localhost IDENTIFIED BY '' OR REPLACE;
mysql> FLUSH PRIVILEGES;

4. Run security configuration:

mysql_secure_installation

Web GUI Installation

1. Enable PHP 8.2 from Remi repository:

Rocky 9 ships with PHP 8.0, but IonCube requires PHP 8.2:

dnf install epel-release
dnf install http://rpms.remirepo.net/enterprise/remi-release-9.rpm
dnf module reset php
dnf module install php:remi-8.2

2. Install required packages:

dnf install wget httpd wireshark php php-gd php-mysqlnd php-mbstring php-zip mtr php-process librsvg2 librsvg2-tools urw-fonts

3. Install IonCube loader:

wget http://voipmonitor.org/ioncube/x86_64/ioncube_loader_lin_8.2.so -O /usr/lib64/php/modules/ioncube_loader_lin_8.2.so
echo "zend_extension = /usr/lib64/php/modules/ioncube_loader_lin_8.2.so" > /etc/php.d/01_ioncube.ini

4. Disable SELinux:

SELinux must be disabled for VoIPmonitor to function properly:

sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

5. Download and install GUI:

cd /var/www/html
wget "http://www.voipmonitor.org/download-gui?version=latest&major=5&allowed&phpver=82" -O w.tar.gz
tar xzf w.tar.gz
mv voipmonitor-gui*/* ./

6. Configure permissions and start Apache:

chown -R apache /var/www/html
mkdir -p /var/spool/voipmonitor
chown apache /var/spool/voipmonitor
systemctl start httpd
systemctl enable httpd

7. Configure cron for alerts and reports:

echo "* * * * * root php /var/www/html/php/run.php cron" >> /etc/crontab
kill -HUP $(pgrep crond)

ℹ️ Note: Install Postfix for email alert functionality (see "Post-Installation Tasks" below).

System Timezone Configuration

VoIPmonitor uses the system timezone for MySQL timestamps. Configure the correct timezone before starting the sensor:

# Set system timezone (replace with your timezone)
timedatectl set-timezone Europe/Prague

# Verify the change
timedatectl

ℹ️ Note: This sets the OS timezone used by MySQL. The GUI timezone is configured separately in GUI > Settings > System Configuration > National > Timezone.

Install Mail Transfer Agent (MTA)

Email alerts and reports require a functioning MTA. Postfix is recommended for Rocky Linux 9:

# Install Postfix
dnf install postfix

# Enable and start Postfix
systemctl enable --now postfix

# Verify Postfix is running
systemctl status postfix

For detailed Postfix/SMTP configuration (relay hosts, authentication), see the Alerts & Reports guide.

Post-Installation Task: Moving MySQL Data Directory

If your root partition is too small, move MySQL data to a larger partition (e.g., /home/mysql):

# 1. Stop MySQL
systemctl stop mysqld

# 2. Create new directory on larger partition
mkdir -p /home/mysql

# 3. Copy existing data (preserving permissions)
cp -rp /var/lib/mysql/* /home/mysql/

# 4. Update MySQL configuration
# Edit /etc/my.cnf.d/mysql-server.cnf and change:
# datadir = /home/mysql

# 5. Update SELinux context (if SELinux was not disabled)
semanage fcontext -a -t mysqld_db_t "/home/mysql(/.*)?"
restorecon -Rv /home/mysql

# 6. Start MySQL
systemctl start mysqld

# 7. Verify MySQL is using new directory
mysql -e "SELECT @@datadir;"

⚠️ Warning: Ensure sufficient disk space for the new location before moving MySQL data.

Sensor Installation

1. Create systemd service file:

Create /etc/systemd/system/voipmonitor.service - see systemd for voipmonitor service management for the template.

2. Download and install sensor:

cd /usr/local/src
wget --content-disposition http://www.voipmonitor.org/current-stable-sniffer-static-64bit.tar.gz -O current-stable-sniffer-static-64bit.tar.gz
tar xzf current-stable-sniffer-static-64bit.tar.gz
cd voipmonitor-*
mkdir -p /etc/init.d
./install-script.sh --no-user-input

3. Configure sensor:

Edit /etc/voipmonitor.conf and set at minimum:

interface = eth0
spooldir = /var/spool/voipmonitor
cleandatabase = 31
sipport = 5060
maxpoolsize = 102400

ℹ️ Note: Replace eth0 with your actual network interface name.

4. Start and enable sensor:

systemctl daemon-reload
systemctl start voipmonitor
systemctl enable voipmonitor

Firewall Configuration

Option 1: Allow specific IP access:

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="YOUR_IP" accept'
firewall-cmd --reload

Option 2: Open HTTP port:

firewall-cmd --permanent --add-service=http
firewall-cmd --reload

Option 3: Disable firewall (not recommended for production):

systemctl stop firewalld
systemctl disable firewalld

Finish Installation

Open your browser and navigate to http://your-server-ip/ to complete the web-based setup wizard.

See Also

AI Summary for RAG

Summary: Step-by-step installation guide for VoIPmonitor on Rocky Linux 9 with PHP 8.2 and MySQL 8.0. Covers MySQL installation and configuration (including innodb_buffer_pool_size sizing and authentication notes about caching_sha2_password vs mysql_native_password), Web GUI installation with PHP 8.2 from Remi repository, IonCube loader setup, SELinux disabling, Apache httpd configuration, cron setup for alerts, timezone configuration, Postfix MTA installation for email alerts, optional MySQL data directory relocation, and sensor (sniffer) installation with systemd service management. Includes firewall configuration options using firewall-cmd.

Keywords: Rocky Linux 9, installation, MySQL 8.0, PHP 8.2, Remi repository, IonCube, SELinux, Apache httpd, systemd, firewall-cmd, caching_sha2_password, mysql_native_password, innodb_buffer_pool_size, Postfix, MTA, timezone, sensor installation, voipmonitor.conf

Key Questions:

  • How do I install VoIPmonitor on Rocky Linux 9?
  • What PHP version is required for VoIPmonitor on Rocky 9?
  • How do I install PHP 8.2 on Rocky Linux 9?
  • Do I need to configure mysql_native_password on Rocky 9?
  • How do I configure the firewall for VoIPmonitor on Rocky Linux?
  • How do I install IonCube loader on Rocky Linux 9?
  • How do I disable SELinux for VoIPmonitor?
  • How do I move MySQL data directory to a different partition?
  • What is the systemd service configuration for VoIPmonitor?
  • How do I configure email alerts on Rocky Linux 9?

s:

1. Immediate Blocking via Custom Scripts

Configure a custom script in the SIP REGISTER flood alert rule to automatically block the attacker IP. The alert_info object contains the attacker's IP address.

# Block using iptables
iptables -A INPUT -s <ATTACKER_IP> -j DROP

# Block using ipset (more efficient for multiple IPs)
ipset add blacklist <ATTACKER_IP>
2. Network Edge Blocking (Recommended for Prevention)

For long-term protection, block at your network edge before traffic reaches VoIPmonitor:

  • Session Border Controller (SBC): Configure rate limiting and IP blocking
  • Firewall: Block malicious IPs at the perimeter
  • Fail2ban: Automatically block IPs after repeated REGISTER failures
3. Reducing REGISTER Noise
  • Disable REGISTER processing if not needed: sip-register = no in voipmonitor.conf
  • Filter REGISTER packets using firewall rules (block specific countries or networks)
  • Use capture rules to exclude known good REGISTER sources from processing

Realtime Concurrent Calls

Tracks source IPs in realtime (not CDR-based) for concurrent calls. Useful against high-channel attacks.

Parameters
  • Concurrent calls limit: Trigger on international, local, or both exceeding limits
  • Time period rules: Vary alerts by work/after hours (defined in Groups > TimePeriods)

IP Filtering Capabilities and Limitations

The "BY" dropdown in the Realtime Concurrent Calls alert configuration only supports Source IP aggregation. This is a hard-coded limitation of the realtime detection logic, which monitors concurrent INVITEs per source address to detect attacks.

To monitor concurrent calls based on Destination IP (such as checking if a specific carrier or trunk exceeds a channel limit), use the standard Concurrent calls alert located in GUI > Alerts instead. The regular concurrent calls alert supports multiple aggregation options including Source IP, Destination IP (Called), Domain, and custom headers.

Monitoring Need Recommended Alert Type GUI Location
Detect attacks from specific source IPs Realtime concurrent calls Alerts > Anti Fraud
Monitor trunk/capacity limits (by destination IP) Concurrent calls Alerts (main section)
Detect domain-specific concurrent call patterns Concurrent calls Alerts (main section)

See Alerts - Fraud Concurrent Calls vs Regular Concurrent Calls Alerts for a detailed comparison.

Change CDR Country

Triggers when CDR IP source changes country/continent since last call.

Parameters
  • Exclude countries from alert: Whitelist countries to skip

Number-Based Filtering

You can use the Numbers include/exclude parameter to limit this alert based on caller number patterns. This is useful when you want to trigger the alert only for specific call signatures, such as detecting fraud calls with malformed caller IDs containing letters.

Using Regex Patterns Directly

Enter regex patterns in the Numbers include/exclude field:

  • Detect numbers containing letters:
R([a-zA-Z])
  • Detect numbers that are NOT purely numeric (malformed caller IDs):
!R(^[+]?[0-9]+$)

The R() syntax enables regular expression mode. See CDR filtering documentation for more regex examples.

Using Telephone Number Groups (Recommended for Complex Patterns)

For complex patterns or when you want to reuse the filter across multiple alerts:

1. Create a telephone number group at GUI > Groups > Tel. numbers 2. Add regex patterns or specific numbers to the group (e.g., [a-zA-Z] for numbers containing letters) 3. Test the group by applying it as a filter in the CDR view 4. In the anti-fraud alert settings, click the Numbers include/exclude field selector 5. Select your telephone number group from the dropdown list

Using groups is recommended because you can test the pattern against actual CDR data before applying it to alerts.

Change REGISTER Country

Triggers when SIP REGISTER username changes country/continent since last successful registration.

Parameters
  • Exclude countries from alert: Whitelist countries to skip

Detecting User-Agent Changes

There is no built-in alert for detecting changes to a SIP registration's User-Agent (UA) string. However, you can enable database-level tracking of UA changes by configuring the sniffer to create new register state records when the UA changes.

To enable UA change tracking, set sip-register-state-compare-digest_ua = yes (or its alias sip-register-state-compare-ua = yes) in voipmonitor.conf. This forces the sniffer to create a new record in the register state table whenever the UA changes, even if other registration details remain the same. See Sniffer Configuration for details.

Alternative fraud alerts for registration anomalies
  • Change REGISTER country: Detects when registration source country changes
  • Change CDR country: Detects when call source country changes
Custom detection
  • Query the register_state database table to detect UA changes programmatically
  • Use custom scripts with anti-fraud rules to trigger actions based on database queries

Country/Continent Destination

Triggers on calls to specific country/continent, based on first SIP INVITE (realtime processing).

SIP PACKETS Flood/Attack

Triggers when >= N packets from an IP occur within the set interval.

Fraud: Sequential

Detects when a high volume of calls are made to any single destination number within a short time period. Use this alert to monitor for patterns like excessive sequential dialing to premium rate numbers or destination abuse.

Parameters
  • Interval: Time window in seconds to monitor call volume (e.g., 3600 for 1 hour)
  • Limit: Maximum number of calls allowed within the interval (e.g., 100)
  • Called number filters: Destination numbers/prefixes to monitor (leave empty to monitor all destinations)
Configuration for "Any Single Destination"
  • To alert on call volume to any destination number (not specific numbers), leave the called number field empty. The alert will then detect excessive calling to any single number within the configured time window.
Example Use Cases
  • Alert when more than 50 calls are made to the same destination within 1 hour
  • Detect sequential dialing to premium rate numbers
  • Identify destination number abuse or toll fraud
  • Detect routing loops by monitoring excessive calls to a single destination number (routing loops typically cause rapid repeated attempts to the same called number)
Important Limitation
  • Aggregation method: This alert aggregates and monitors call volume by source IP address, not by the calling (source) telephone number.
  • If you need to detect excessive use of a specific calling number, use the CDR summary report instead (configure it with Summary type set to source number).

Custom Script Examples

Custom scripts receive alert data as command-line arguments. The fourth argument ($argv[4] in PHP) contains JSON-encoded alert data.

Logging Passed Arguments

Simple script to log all arguments for debugging:

#!/bin/bash
echo "$(date): $@" >> /tmp/alert_debug.txt

RTP Alert: Store Audio Files

Script to automatically download audio for calls that triggered an RTP alert:

#!/usr/bin/php
<?php
// Configuration
$directory = '/home/alerts/audio';
$date = trim(`date '+%Y-%m-%d'`);
$guiDir = '/var/www/voipmonitor';
$destdir = $directory . '/' . $date;

// Create destination directory
`mkdir -p $destdir`;

// Parse alert data (4th argument contains JSON)
$alert = json_decode($argv[4]);

// Download audio for each CDR in the alert
foreach ($alert->cdr as $cdr) {
    $params = json_encode([
        'task' => 'getVoiceRecording',
        'user' => 'admin',
        'password' => 'admin',
        'params' => ['cdrId' => $cdr]
    ]);
    $command = "php $guiDir/php/api.php > $destdir/file_id_$cdr.pcap";
    exec("echo '$params' | $command", $arr, $val);
}
?>

RTP Alert: Block IP After Threshold

Script to block IPs that exceed a threshold number of incidents:

#!/usr/bin/php
<?php
// Configuration
$Limit = 19;                                              // Block after this many incidents
$blockCommand = "ssh root@pbx -p2112 ipset add blacklist"; // Remote blocking command
$verbose = 1;                                             // 1 = dry-run, 0 = execute

// Parse alert data
$alertsData = json_decode($argv[4]);

// Build comma-separated list of CDR IDs
$cdrIds = implode(',', $alertsData->cdr);

// Query database for caller IPs and incident counts
$query = "SELECT INET_NTOA(sipcallerip) as ip, COUNT(*) as incidents
          FROM voipmonitor.cdr
          WHERE id IN ($cdrIds)
          GROUP BY sipcallerip
          ORDER BY incidents DESC";
$command = "mysql -h MYSQLHOST -u MYSQLUSER -pMYSQLPASS -N -e \"$query\"";
exec($command, $results);

// Process results and block IPs exceeding limit
foreach ($results as $line) {
    list($ip, $count) = preg_split('/\s+/', trim($line));
    if ($count > $Limit) {
        if ($verbose) {
            echo "$ip: $count incidents - would block\n";
        } else {
            exec("$blockCommand $ip", $output, $rc);
            if ($rc != 0) {
                error_log("Failed to block $ip");
            }
        }
    }
}
?>

Concurrent Calls: Block Attacker IP

Script for blocking IPs based on concurrent calls alert. Enable "By caller IP" in alert settings.

#!/usr/bin/php
<?php
// Parse triggered rules (4th argument)
$triggeredRules = json_decode($argv[4]);

// Count triggers per IP address
$IPtriggers = [];
foreach ($triggeredRules as $rule) {
    $ip = $rule->alert_info->ip;
    $IPtriggers[$ip] = ($IPtriggers[$ip] ?? 0) + 1;
}

// Block all IPs that triggered the rule
foreach ($IPtriggers as $ip => $count) {
    echo "Blocking $ip (triggered $count times)\n";
    passthru("iptables -A INPUT -s $ip -j DROP", $ret);
    if ($ret != 0) {
        echo "ERROR: Failed to block $ip\n";
        exit(1);
    }
}
echo "Blocked " . count($IPtriggers) . " IP(s)\n";
?>

See Also

AI Summary for RAG

Summary: VoIPmonitor anti-fraud rules for detecting SIP attacks (REGISTER floods, packet floods), concurrent calls abuse, geographic anomalies, and high-volume sequential calling patterns. Covers realtime vs CDR-based alert processing differences, custom script examples for automated IP blocking via iptables/ipset, and mitigation strategies for SIP REGISTER spam.

Keywords: anti-fraud, REGISTER flood, SIP attack, concurrent calls, country change, custom scripts, iptables, ipset, fail2ban, realtime alerts, CDR-based alerts, source port limitation, sequential calls, sequential dialing, destination abuse, high call volume, large volume of calls, destination number, short period, alert configuration, number filtering, regex patterns, telephone number groups, R() syntax, Change CDR Country, Change REGISTER Country, Numbers include/exclude, malformed caller IDs, letters in phone numbers

Key Questions:

  • What anti-fraud alerts are available in VoIPmonitor?
  • How to block SIP REGISTER flood attacks?
  • What is the difference between realtime and CDR-based alerts?
  • How to create custom scripts for automated IP blocking?
  • Why is source port not available in realtime alerts?
  • How to configure an alert for a large volume of calls to any single destination number?
  • What is the Fraud: sequential alert and how does it work?
  • How to filter anti-fraud alerts by caller number patterns?
  • How to trigger "Change CDR Country" alert only for numbers containing letters?
  • How to use regex patterns (R() syntax) in anti-fraud number filtering?
  • How to use telephone number groups in anti-fraud alerts?