Not so friendly after all
In my October 2010 articles about Asterisk IP-PBX security (linked here), I described how port scanning probes from the so-called “friendly-scanner” could be seen several times a day on a typical SIP server exposed to the Internet. Since then, I – or at least one of my clients – had the displeasure of experiencing the full fury of this remarkably unfriendly scanner which, when provoked, seems to change from a gentle prod every few hours to a full scale Denial of Service attack at a rate of more than 80 SIP REGISTER requests per second, utterly relentless and lasting for days or even weeks.The port scanning probes used SIP OPTIONS while the really unpleasant, full-on, bandwidth-eating manifestation uses SIP REGISTER requests. The fact that in both cases the User Agent is declared to be “friendly-scanner” does not mean that this is a single application operating in two different modes. It probably indicates that some of the source code for these loathsome applications was derived from a common ancestor or that one is a re-worked version of the other. I believe sipvicious and a python program called svwar.py may have the dubious honour of being in some way the original seed for what has now turned into an irritating and potentially costly problem for VoIP users around the world. But should we blame gun manufacturers when there is an armed robbery or illegal shooting? Perhaps not. Anyway, I digress.
Symptoms of an attack
My client called me to say that their remote users were experiencing serious problems with their connection to the Asterisk phone system at the office. My own phone refused to register using exactly the same credentials as had worked a few days earlier. I tried to use remote access to check the server, but the connection was dreadfully slow to the point where it was unusable.Making sense of what was happening was difficult because there did not seem to be any unauthorised calls and the internal office extensions were all working fine as were the analogue trunks that they use for inbound calls and as a backup in case of Internet problems. I knew the phone account passwords were all sufficiently strong and complex to not be hacked and other security settings such as “alwaysauthreject=yes” were configured for maximum resistance to attack, yet the firewall logs showed that there was a continuous heavy use of bandwidth from the Asterisk PBX to some address on the Internet. The fact that the outbound traffic was using approximately four times the bandwidth of the inbound made me think it must be some malware running on the server. This misconception caused me a considerable delay before I finally thought to run tcpdump and see exactly what was going on. By the way, the Asterisk CLI command “sip set debug on” will also show what is happening, but you may then find it difficult to turn off the sip debug because of the rate at which information is being written to the screen. Running “tcpdump udp -nn” at the Linux command prompt is safer because it just writes one line to the screen per request and Control-C is all that is required to stop it.
The outbound UDP packets outnumbered the inbound because Asterisk was sending a rejection for each registration attempt and then re-sending it when it didn’t get an ACK response – it would send as many as 5 responses to every one inbound REGISTER request. With inbound requests running at nearly 100 per second this was causing it a bit of a headache.
Blocking the attack
As soon as I realised what was happening, it was relatively simple to add a firewall rule to block all inbound data from the single IP address that was sending the requests. Yes, it was all from one IP address and No, contacting the owners of that address was as much use as a chocolate teapot.As soon as I blocked the inbound requests, the remote users were suddenly able to make calls again and everything went quiet. Job done I thought. Well, not quite.
It just carried on and on
I assumed the attack would stop pretty quickly once the inbound packets were blocked at the firewall and no responses were coming back from Asterisk. Not so. I checked the traffic monitor on their firewall the next day and the day after. The inbound stream of requests was still there. After a week, the firewall began to creak and get sick because it was running out of memory. Well it is only a modest little Draytek router, but it is designed for a small business environment and should have been able to cope with the simple task of blocking a continuous stream of unwanted SIP requests coming from one IP address on the Internet. In my opinion, someone at Draytek should be shot for designing a router/firewall that adds an entry to the NAT sessions table before it inspects the firewall rules to see if the source address is blocked!So a quick solution at this point was to add a rule to iptables on the Asterisk box and let the requests come through the Draytek. That took the pressure off the Draytek, but no matter what ICMP response I sent back (including no response), the requests just kept flooding in. If anything, they were getting faster and using more bandwidth (see graph below).
I am now convinced that the unending nature of the attack is not deliberate, but is as a result of a bug in the code which puts it into an infinite loop. Clearly the people who produced these friendly-scanner hacking tools aren’t as clever as they would no doubt like to believe.
How to stop it completely
The answer was in a blog by Joshua Stein, to whom I am indebted. His solution involved redirecting the requests to a new port so it would not be necessary to shut down the Asterisk PBX application. However, my client didn’t need 24×7 operation of their phone system so instead I just modified Joshua’s Ruby script to use port 5060, stopped Asterisk, ran the Ruby script and that was it. The requests just stopped. Then I restarted Asterisk. This graph from the firewall shows the bandwidth being used over a week and the abrupt end of the problem when I finally ran Joshua’s script.Using Joshua’s Ruby script on a CentOS server
Install Ruby using yum: yum install rubyCopy the script from the box below and paste it into a file. I called my file spoof_sip_ok. (If you use a text editor like vi or nano while connected through SSH with Putty, then a right-click of the mouse will paste text previously copied into the clipboard). The original script is no longer available at Joshua’s own blog site, so I have reproduced the whole thing here with a couple of minor adjustments:
#!/usr/bin/env ruby require "socket" s = UDPSocket.new s.bind("0.0.0.0", 5060) while true packet = s.recvfrom(1024) via = packet[0].match(/Via: (.+);rport/)[1] from = packet[0].match(/From: (.+)/)[1] to = packet[0].match(/To: (.+)/)[1] call_id = packet[0].match(/Call-ID: (.+)/)[1] cseq = packet[0].match(/CSeq: (\d+) REGISTER/)[1] remote_ip = packet[1][3] remote_port = packet[1][1].to_i puts packet.inspect if packet[0].match(/^REGISTER /) ret = "SIP/2.0 200 OK\r\n" + "Via: #{via};received=#{remote_ip}\r\n" + "From: #{from}\r\n" + "To: #{to}\r\n" + "Call-ID: #{call_id}\r\n" + "CSeq: #{cseq.to_i + 1} REGISTER\r\n" + "\r\n" puts "sending to #{remote_ip}:#{remote_port}:\n#{ret}" s.send(ret, 0, remote_ip, remote_port) end end
You can insert your own server’s IP address in the s.bind parameters if you want, but 0.0.0.0 should just bind to all interfaces. Also remember to make the file executable, for example using the Linux command chmod 755 spoof_sip_ok
The original article was at “http://jcs.org/notaweblog/2010/04/11/properly_stopping_a_sip_flood”, but the whole domain seems to no longer be active (as of March 2013).
Before you run the above version of the script, make sure Asterisk is stopped. I found it would immediately restart when I used ”amportal stop” and instead used the CLI command “stop now”. You can check that it has stopped by typing this command at the Linux command prompt: netstat -lunp
If Asterisk is running, it will be using port 5060 and the output of the netstat command would look like this:
user@asterisk:~ $ netstat -lunp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 0.0.0.0:5060 0.0.0.0:* 16301/asterisk
To run the Ruby script, just type ./spoof_sip_ok at the Linux prompt.
No comments:
Post a Comment