SIP has loop detection and prevention built-in. However, when you are interfacing with legacy technology through a gateway there is a very real risk that a loop can be setup between the two systems. The scenario is a large migration from TDM to SIP. As As you add users to the SIPX install, SIPX first looks at current registrations, then will route calls through the dial-plan. If through an accounting error, your TDM systems sends calls to SIPX and there is no matching extension in SIPX then the call is routed back out to the TDM system, which routes it back into SIPX...you get the idea. This can result in calls that go above 40,000/hour! It will bring your proxies to their knees. Below is a simple script you can run from cron to block calls.
You will also need a file in the root directory of the user running this (likely root for iptables) file: .pgpass
localhost:*:SIPXCDR:sipxcdruser:secret
#!/bin/bash maxcall=75 email='khaefner@colostate.edu' subject='Potential Call Loop' date="$(date +%s)" #create a white list declare -a white_list=(15500 0 2) #parse iptables looking to see if there is a block already iptable_output=$(iptables -L INPUT -n --line-numbers | grep BLOCKED) #get what is blocked into arrays from comments ID1='\n' read -a blocked_numbers <<<$(sed -e 's/^.*BLOCKED:\([0-9]*\).*$/\1/' <<<"$iptable_output") ID2='\n' read -a blocked_dates <<<$(sed -e 's/^.*WHEN:\([a-zA-Z0-9]*\|[\s]*\).*$/\1/' <<<"$iptable_output") ID3='\n' read -a blocked_lines <<<$(sed -e 's/^\([0-9]*\)\s.*$/\1/' <<<"$iptable_output") #Look through CDR to see if there are any calls output=$(echo "select callee_aor, count(*) from view_cdrs where start_time > CURRENT_TIMESTAMP AT TIME ZONE 'UTC' - interval '1' minute GROUP BY callee_aor order by count DESC LIMIT 1" | psql -t -q --user provision SIPXCDR) caller=$(sed -e 's/^.*<sip:\([0-9]*\).*$/\1/' <<<"$output") callsperminute=$(sed -e 's/^.*|\s*\([[0-9]*\)/\1/' <<<"$output") message="The number $caller has been blocked because it has made $callsperminute calls in the last minute. Calls for this number will be blocked for the next 10 minutes." #Check if we have blocked the number previsously if we have check timestamp if greater than 600 seconds remove rule for i in ${!blocked_numbers[*]}; do timediff=$((date-${blocked_dates[$i]})) if [ "$timediff" -gt "600" ] then iptables -D INPUT -i eth0 -p udp -m udp --dport 5060 -m string --string "INVITE sip:${blocked_numbers[$i]}" --algo bm --to 65 -j DROP -m comment --comment "BLOCKED:${blocked_numbers[$i]} WHEN:${blocked_dates[$i]}" fi done #check if we have already block the number so we don't block again for i in ${!blocked_numbers[*]}; do if [ "$caller" = "${blocked_numbers[$i]}" ] then exit fi for w in ${white_list[@]}; do if [ "$w" = "${blocked_numbers[$i]}" ] then echo $w exit fi done done if [ -n "$callsperminute" ] then if [ -n "$caller" ] then if [ "$callsperminute" -gt "$maxcall" ] then echo $message #echo $message | /bin/mail -s "$subject" "$email" iptables -I INPUT -i eth0 -p udp -m udp --dport 5060 -m string --string "INVITE sip:$caller" --algo bm --to 65 -j DROP -m comment --comment "BLOCKED:$caller WHEN:$date" fi fi fi