As soon as our Asterisk PBX server goes online—whether via a direct public IP address or behind a firewall using NAT—automated botnets begin, within minutes, to aggressively scan port 5060, attempt to guess passwords, and search for vulnerabilities. In 2026, VoIP threats are fully automated, which means our defenses must be automated as well.
The optimal tool for this purpose on Linux is Fail2Ban, which uses filter rules to scan relevant log files for suspicious patterns, allowing it to block problematic IP addresses. For instance, if an attacker attempts to gain access to a server via the SSH port, you can configure the system so that, after 5 or more attempts, the attacking IP address is blocked—either for a set duration or even permanently—via the firewall.
That covers the basic function and concept behind Fail2Ban.
In our case, since the Asterisk server is not exposed directly to the internet but is instead situated behind an OpenWRT firewall, using Fail2Ban on the Raspberry Pi running Asterisk is completely ineffective. This is because any requests arriving on port 5060 will always appear to the Asterisk server as originating from the router's IP address—the same address used by the OpenWRT firewall (in this instance, 192.168.0.1). Consequently, a Fail2Ban rule designed to block SIP attacks would end up blocking the IP 192.168.0.1, which would immediately cause the telephony service to fail—clearly not the desired outcome. An Asterisk server positioned behind a firewall can never see the actual IP addresses of the attackers; that information is only accessible at the level of the OpenWRT firewall itself.
The objective is to secure an Asterisk server located behind an OpenWrt router running version 23.05 with Firewall4 (fw4/nftables). The provider's IP address must be exempted from any blocks. The desired outcome is the automatic blocking of external SIP sources that are not part of the provider exception. Fail2Ban handles the dynamic blocking of identified source IP addresses. A comprehensive whitelist—which blocks all other sources before the first packet is even processed—is a separate mechanism, implemented here via an additional static firewall rule.
The challenge here lies in identifying which of the many IP addresses appearing in the kernel log are responsible for the unauthorized SIP requests. As a reminder, Fail2Ban scans log files—in this case, logically, /var/log/asterisk.log. However, since this file resides on the Asterisk server (in this instance, a Raspberry Pi), it is not directly accessible to the firewall.
Given that OpenWRT typically maintains logs within the kernel log—and any files in /var/log exist only in RAM—we must create a searchable log file that Fail2Ban can utilize.
The nftables configuration located at /etc/nftables.d/sip-wan-log.nft was used to detect incoming SIP packets.
chain sip_wan_log {
type filter hook prerouting priority filter; policy accept;
iifname "pppoe-wan" meta l4proto { tcp, udp } th dport 5060 limit rate 20/second counter log prefix "SIP-WAN-IN " flags all
}
The prefix SIP-WAN-IN identifies the relevant packets in the kernel log.
For kernel warning messages to be written to /var/log/firewall.log, rsyslog must be configured accordingly.
~# uci add rsyslog selector
~# uci set rsyslog.@selector[-1].source='kern.warn'
~# uci set rsyslog.@selector[-1].destination='/var/log/firewall.log'
~# uci commit rsyslog
~# /etc/init.d/rsyslog restart
There is also a Fail2Ban package available for OpenWRT, which can be easily installed within OpenWRT’s BusyBox environment.
~# opkg update
~# opkg install fail2ban
Next, the IP addresses of the VoIP provider (in this case, Telekom GmbH) are required for exclusion purposes. To obtain these, we will perform a DIG query regarding the service and the protocol:
~# dig SRV _sip._udp.tel.t-online.de
; <<>> DiG 9.20.23-1~deb13u1-Debian <<>> SRV _sip._udp.tel.t-online.de
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22742
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_sip._udp.tel.t-online.de. IN SRV
;; ANSWER SECTION:
_sip._udp.tel.t-online.de. 1975 IN SRV 30 0 5060 hno002-f01-mav-pc-ra-001.edns.t-ipnet.de.
_sip._udp.tel.t-online.de. 1975 IN SRV 10 0 5060 stg010-l01-mav-pc-rb-001.edns.t-ipnet.de.
_sip._udp.tel.t-online.de. 1975 IN SRV 20 0 5060 nes008-f01-mav-pc-ra-001.edns.t-ipnet.de.
;; Query time: 0 msec
From this, the IP addresses can now be resolved:
~# dig +short A stg010-l01-mav-pc-rb-001.edns.t-ipnet.de
~# dig +short A nes008-f01-mav-pc-ra-001.edns.t-ipnet.de
~# dig +short A hno002-f01-mav-pc-ra-001.edns.t-ipnet.de
217.0.146.198
217.0.147.5
217.0.147.197
With this, we have everything we need to build the Fail2Ban rule.
This filter file, /etc/fail2ban/filter.d/sip-wan.conf, identifies logged SIP packets based on the source IP and destination port 5060:
[Definition]
failregex = ^.*SIP-WAN-IN .*SRC=<HOST> .*DPT=5060(?:\s|$)
ignoreregex =
In this process, the filter uses <HOST> as a placeholder for the IP address that Fail2Ban can block upon a match.
This configuration is created at /etc/fail2ban/jail.d/sip-wan.local:
[sip-wan]
enabled = true
filter = sip-wan
logpath = /var/log/firewall.log
backend = polling
port = 5060
protocol = udp
ignoreip = 127.0.0.1/8 ::1 217.0.146.198
maxretry = 604800
findtime = 600
bantime =
action = nftables-multiport[name=sip-wan, port=5060, protocol=udp, chain_hook=forward, chain_priority=-1]
We have set the duration of the ban to one week (604800); a permanent ban would be represented by "-1". However, in that case, you would have to manually unblock IP addresses on a regular basis, as the storage could otherwise eventually fill up.
~# fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sip-wan
list table inet f2b-table
To test the action in a targeted manner, a reserved documentation address is temporarily blocked:
~# fail2ban-client set sip-wan banip 192.0.2.123
~# nft list tables
table inet fw4
table inet f2b-table
The test IP is subsequently released again:
~# fail2ban-client set sip-wan unbanip 192.0.2.123
~# nft list table inet f2b-table
Actual blocking rule
table inet f2b-table {
set addr-set-sip-wan {
type ipv4_addr
elements = { 172.110.223.179 }
}
chain f2b-chain {
type filter hook forward priority filter - 1; policy accept;
udp dport 5060 ip saddr @addr-set-sip-wan reject with icmp port-unreachable
}
}
The following query confirms the active jail:
~# fail2ban-client status sip-wan
Status for the jail: sip-wan
|- Filter
| |- Currently failed: 0
| |- Total failed: 1
| `- File list: /var/log/firewall.log
`- Actions
|- Currently banned: 1
|- Total banned: 2
`- Banned IP list: 172.110.223.179
The provider exception is also checked:
~# fail2ban-client get sip-wan ignoreip
These IP addresses/networks are ignored:
|- 127.0.0.0/8
|- 217.0.146.198
~# fail2ban-client status sip-wan
Status for the jail: sip-wan
|- Filter
| |- Currently failed: 0
| |- Total failed: 1
| `- File list: /var/log/firewall.log
`- Actions
|- Currently banned: 1
|- Total banned: 2
`- Banned IP list: 172.110.223.179
or just the list of blocked IPs
~# fail2ban-client status sip-wan | grep 'Banned IP list'
`- Banned IP list: 172.110.223.179
This provides an effective defense mechanism directly on an OpenWRT firewall, protecting the Asterisk PBX system behind it from SIP-based attacks. In cases where the Asterisk server has a public IP address, a similar protective measure can be implemented using a Fail2Ban rule—independent of firewall rules. Furthermore, this prevents the Asterisk "full" log file from filling up rapidly, which would otherwise happen if dozens of SIP registration attempts were logged every minute.