PBX Security

Hello,

I’m hoping for a bit of help with regards to the Security of my PBX.

Question 1:
I found the following post by @dicko Am I being hacked? - #15 by dicko

There is another function of Asterisk which also greatly improves security (but little used) if you use UDP/5060 (the target of 99.99% of the bad guys) .For chan_sip , just add:
domain=your.dns.name
domain= 127.0.0.1 ;If you have t38modems or the like

I have this done for chan_SIP however we also use chan_pjsip for our extensions:

For chan_pjsip, I’m sure there is an equivalency in your AOR setup to reject any IP based URI’s

Does anyone know equlivant setting on how to achieve this for chan_PJSIP also?

Question 2:
We have remote chan_pjsip extensions which connect to our PBX from unknown random IP Addresses. Response firewall/fail2ban seem to do a great job at securing the PBX and keeping potential attackers away however recently we have seen PJSIP/Anonymous attempted calls which do not get blocked.

[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-sip-external:1] NoOp(“PJSIP/anonymous-00000001”, “Received incoming SIP connection from unknown peer to 48893076002”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-sip-external:2] Set(“PJSIP/anonymous-00000001”, “DID=48893076002”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-sip-external:3] Goto(“PJSIP/anonymous-00000001”, “s,1”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (from-sip-external,s,1)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@from-sip-external:1] GotoIf(“PJSIP/anonymous-00000001”, “1?setlanguage:checkanon”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (from-sip-external,s,2)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@from-sip-external:2] Set(“PJSIP/anonymous-00000001”, “CHANNEL(language)=en”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@from-sip-external:3] GotoIf(“PJSIP/anonymous-00000001”, “0?noanonymous”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@from-sip-external:4] Goto(“PJSIP/anonymous-00000001”, “from-trunk,48893076002,1”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (from-trunk,48893076002,1)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-trunk:1] Set(“PJSIP/anonymous-00000001”, “CHANNEL(accountcode)=48893076002”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-trunk:2] ExecIf(“PJSIP/anonymous-00000001”, “0 = 1?Set(CALLERID(num)=0)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-trunk:3] Set(“PJSIP/anonymous-00000001”, “__FROM_DID=48893076002”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [48893076002@from-trunk:4] Goto(“PJSIP/anonymous-00000001”, “ext-did,s,1”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (ext-did,s,1)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@ext-did:1] Set(“PJSIP/anonymous-00000001”, “__DIRECTION=INBOUND”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@ext-did:2] Gosub(“PJSIP/anonymous-00000001”, “sub-record-check,s,1(in,s,Array)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:1] GotoIf(“PJSIP/anonymous-00000001”, “0?initialized”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:2] Set(“PJSIP/anonymous-00000001”, “__REC_STATUS=INITIALIZED”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:3] Set(“PJSIP/anonymous-00000001”, “NOW=1552676469”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:4] Set(“PJSIP/anonymous-00000001”, “__DAY=15”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:5] Set(“PJSIP/anonymous-00000001”, “__MONTH=03”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:6] Set(“PJSIP/anonymous-00000001”, “__YEAR=2019”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:7] Set(“PJSIP/anonymous-00000001”, “__TIMESTR=20190315-190109”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:8] Set(“PJSIP/anonymous-00000001”, “__FROMEXTEN=unknown”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:9] Set(“PJSIP/anonymous-00000001”, “__MON_FMT=wav”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:10] NoOp(“PJSIP/anonymous-00000001”, “Recordings initialized”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:11] ExecIf(“PJSIP/anonymous-00000001”, “0?Set(ARG3=dontcare)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:12] Set(“PJSIP/anonymous-00000001”, “REC_POLICY_MODE_SAVE=”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:13] ExecIf(“PJSIP/anonymous-00000001”, “0?Set(REC_STATUS=NO)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:14] GotoIf(“PJSIP/anonymous-00000001”, “2?checkaction”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (sub-record-check,s,17)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [s@sub-record-check:17] GotoIf(“PJSIP/anonymous-00000001”, “1?sub-record-check,in,1”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx_builtins.c: Goto (sub-record-check,in,1)
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [in@sub-record-check:1] NoOp(“PJSIP/anonymous-00000001”, “Inbound Recording Check to s”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [in@sub-record-check:2] Set(“PJSIP/anonymous-00000001”, “FROMEXTEN=unknown”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [in@sub-record-check:3] ExecIf(“PJSIP/anonymous-00000001”, “8?Set(FROMEXTEN=Itribune)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [in@sub-record-check:4] Gosub(“PJSIP/anonymous-00000001”, “recordcheck,1(Array,in,s)”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [recordcheck@sub-record-check:1] NoOp(“PJSIP/anonymous-00000001”, “Starting recording check against Array”) in new stack
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Executing [recordcheck@sub-record-check:2] Goto(“PJSIP/anonymous-00000001”, “Array”) in new stack
[2019-03-15 19:01:09] NOTICE[3843][C-00000003] pbx.c: No such label ‘Array’ in extension ‘recordcheck’ in context ‘sub-record-check’
[2019-03-15 19:01:09] WARNING[3843][C-00000003] pbx.c: Priority ‘Array’ must be a number > 0, or valid label
[2019-03-15 19:01:09] VERBOSE[3843][C-00000003] pbx.c: Spawn extension (sub-record-check, recordcheck, 2) exited non-zero on ‘PJSIP/anonymous-00000001’

Normally, the solution would be to disable Allow Anonymous Inbound SIP Calls in Asterisk SIP Settings however enabling this option is a requirement by our telephone provider and enabling prevent inbound calls. I have spoken with the provider and registering with them is not an option. Their advice is to block all IP address except their subnet however this would block our remote extensions. Ideally, I do not want to use a VPN as many of our endpoints do not support this.

Does anyone know of a way on how I can block these PJSIP/Anonymous calls without disabling the above setting?

I found this: Re: Who tries to hack YOUR Asterisk system? - VOIP Tech Chat | DSLReports Forums and created the following rules using the FreePBX Responsive Firewall Custom rules however they do not seem to apply (I think because the rule 1 is being applied first before my custom rules)

[root@PBX root]# iptables -L --line-numbers --numeric
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 fpbxfirewall all – 0.0.0.0/0 0.0.0.0/0
2 ACCEPT udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 state RELATED,ESTABLISHED
3 ACCEPT udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “REGISTER sip:my.pbx.com” ALGO name bm TO 65535
4 DROP udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “REGISTER sip:” ALGO name bm TO 65535
5 ACCEPT udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “OPTIONS sip:my.pbx.com” ALGO name bm TO 65535
6 DROP udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “OPTIONS sip:” ALGO name bm TO 65535
7 ACCEPT udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “INVITE sip:my.pbx.com” ALGO name bm TO 65535
8 DROP udp – 0.0.0.0/0 0.0.0.0/0 udp dpt:5060 STRING match “INVITE sip:” ALGO name bm TO 65535

All our endpoints and DIDs point to my.pbx.com. Anything received directly to the IP address would be a potential attacker.

Thanks,
Fraser

There is NO time when a provider should tell you that anonymous access is required for them to access your system. If they are telling you they need that, you need to find a professional provider.

The easiest solution for providers with large numbers of POPs is for you to set up a single Chan-SIP trunk and use anonymous access. With the advent of PJ-SIP, this requirement for a provider is not longer accurate or appropriate. With PJ-SIP, you specify a list of servers (or a range or subnet or …) and all of the providers servers are then allowed access.

To be clear YOU NEED TO TURN OFF ANONYMOUS ACCESS ASAP.

Just in case there’s still a doubt in your mind: ASAP.

Your client situation is the definition of why the Adaptive Firewall was added to the system. This technology allows you to manage these connections without requiring Anonymous calling from random connections.

Between PJ-SIP access lists for your providers and the Adaptive Firewall, you should be well placed to solve these problems.

Yes - We have closed SIP to the outside world for the time being and are manually allowing remote workers to the PBX by whitelisting their IP address. Its a pain to update/maintain IPTABLES when a remote users IP Address changes but hopefully I can get a permanent solution soon.

We receive anonymous calls from our provider on SIP only (our extensions all use PJSIP) so if there was a way I could enable Allow Anonymous SIP calls for SIP only and not PJSIP then this would be a suitable solution (as SIP is only accessible from trusted sources).

Thanks,
Fraser.

If you were to use a pjsip trunk for your provider, you could use the Match (Permit) field to enumerate all the IPs/subnets from which the provider sends invites, and eliminate the need to enable anonymous calls.

These two statements are contradictory. An anonymous call is an INVITE that originates from an IP you don’t recognize. If you are able to filter IPs to trusted, you are not receiving anonymous calls.

2 Likes

Yes - but what I mean is only trusted IP Address are able to communicate with PBX on SIP.
However, everyone is able to communicate with with PBX on PJSIP.

Fraser.

I believe if I’m able to get these Custom Firewall Rules working then I should be able to solve my problem - Does anyone have any experience as to why they aren’t working and how I can fix them?

[root@PBX root]# fwconsole ma list firewall | grep firewall
| firewall | 13.0.57.1 | Enabled | AGPLv3+ |

I have a system running with a very simple firewall. Everything not explicitly permitted is dropped. FreePBX firewall is not used.

Chain INPUT (policy DROP)
num target prot opt in out source    destination
1   ACCEPT all  --  *  *   0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2   ACCEPT icmp --  *  *   0.0.0.0/0 0.0.0.0/0
3   ACCEPT all  --  lo *   0.0.0.0/0 0.0.0.0/0
4   ACCEPT udp  --  *  *   0.0.0.0/0 0.0.0.0/0 udp dpts:10000:20000
5   ACCEPT udp  --  *  *   0.0.0.0/0 0.0.0.0/0 udp dpts:5000:5999 STRING match "my.pbx.com" ALGO name bm TO 65535
6   ACCEPT tcp  --  *  *   0.0.0.0/0 0.0.0.0/0 multiport dports 22,80,443
  1. Accept replies and everything already recognized by conntrack.
  2. Allow ping, etc.
  3. Allow loopback traffic.
  4. Allow RTP.
  5. Allow SIP packets containing my ‘secret’ domain name.
  6. Allow SSH, HTTP, HTTPS.

In addition, there is some simple Apache configuration that permits only requests with the domain name. Requests by IP address or an incorrect name receive a dummy site and a dummy (self-signed) certificate.

SSH is configured to require RSA authentication (a password will not work).

Notes on trunking:
Although register trunks will work automatically (incoming INVITEs appear as ESTABLISHED to conntrack), I put the domain name in the Contact user (using from-pstn-toheader as the context), so if a network interruption causes the conntrack association to be lost, an incoming call will still pass the firewall.

On IP authentication trunks, the incoming SIP URI will normally have the domain name. If the provider requires a numeric IP address for the destination, I put the domain name in the user part of the URI. If you have a provider that also doesn’t allow you to configure that, you will need to add iptables rules to accept packets from their IP addresses.

1 Like

Ohhhh, simple yet effective! Maybe I could use something similar to this with FreePBX custom rules although I can seem to get them to work!

On a side note, are you not concerned having 22 open to the outside world?

Fraser

I have managed to get this working. In my Custom Firewall Rules files /etc/firewall-4.rules, I was using -A for APPEND, rather than -I for INSERT.

Changing to INSERT then added my firewall rules BEFORE the FreePBX Firewall.

I also changed my rules so rather than to ACCEPT the packets on successful match they are now sent on to the FreePBX fpbxfirewall chain for processing,

>[root@PBX2 root]# cat /etc/firewall-4.rules

-I INPUT -p udp --dport 5060 -m string --string "INVITE sip:" --algo bm -j DROP
-I INPUT -p udp --dport 5060 -m string --string "INVITE sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p udp --dport 5060 -m string --string "OPTIONS sip:" --algo bm -j DROP
-I INPUT -p udp --dport 5060 -m string --string "OPTIONS sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p udp --dport 5060 -m string --string "REGISTER sip:" --algo bm -j DROP
-I INPUT -p udp --dport 5060 -m string --string "REGISTER sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p udp --dport 5060 -m state --state ESTABLISHED,RELATED -j fpbxfirewall
-I INPUT -p tcp --dport 5060 -m string --string "INVITE sip:" --algo bm -j DROP
-I INPUT -p tcp --dport 5060 -m string --string "INVITE sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p tcp --dport 5060 -m string --string "OPTIONS sip:" --algo bm -j DROP
-I INPUT -p tcp --dport 5060 -m string --string "OPTIONS sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p tcp --dport 5060 -m string --string "REGISTER sip:" --algo bm -j DROP
-I INPUT -p tcp --dport 5060 -m string --string "REGISTER sip:my.pbx.com" --algo bm -j fpbxfirewall
-I INPUT -p tcp --dport 5060 -m state --state ESTABLISHED,RELATED -j fpbxfirewall

Still testing this and will look at it again next week to tidy it up before putting live on our production server.

Big thanks to @xrobau :slight_smile:

Thanks
Fraser.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.