diff --git a/checkdnsbl.sh b/dronebl/checkdnsbl.sh similarity index 100% rename from checkdnsbl.sh rename to dronebl/checkdnsbl.sh diff --git a/dronebl/dronebl-tools_0.3.tar.gz b/dronebl/dronebl-tools_0.3.tar.gz new file mode 100644 index 0000000..4f16c05 Binary files /dev/null and b/dronebl/dronebl-tools_0.3.tar.gz differ diff --git a/dronebl/dronebl.py b/dronebl/dronebl.py new file mode 100644 index 0000000..89096cb --- /dev/null +++ b/dronebl/dronebl.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# Copyright (c) 2008 DroneBL contributors +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the author nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +class DroneBLClient: + """Class for accessing DroneBL.""" + def __init__(self, rpckey=None, server="https://dronebl.org/RPC2"): + self.server = server + self.rpckey = rpckey + self.submitList = "" + + def addIP(self, ip, type): + """Adds IP to DroneBL.""" + self.submitList += "\t\n"; + + def lookupIP(self, ip): + """Adds a lookup request to the message.""" + self.submitList += "\t\n" + + def makeRequest(self): + """Generates the request.""" + self.request = "\n\n" + self.submitList + "" + + def showRequest(self): + """Shows the request.""" + self.makeRequest() + print self.request + + def makeConnection(self): + """Connects to the RPC server.""" + import urllib + type, uri = urllib.splittype(self.server) + self.__host, self.__handler = urllib.splithost(uri) + + import httplib + self.connection = httplib.HTTPConnection(self.__host) + + def postRequest(self): + """Executes the request.""" + self.makeRequest() + self.makeConnection() + self.connection.putrequest("POST", self.__handler) + self.connection.putheader("Content-Type", "text/xml") + self.connection.putheader("Content-Length", str(int(len(self.request)))) + self.connection.endheaders() + self.connection.send(self.request) + self.__response = self.connection.getresponse() + + def printResponse(self): + """Display the XML response.""" + print self.__response.read() + diff --git a/dronebl/libdronebl-tcl_1.3.tar.gz b/dronebl/libdronebl-tcl_1.3.tar.gz new file mode 100644 index 0000000..32fa24d Binary files /dev/null and b/dronebl/libdronebl-tcl_1.3.tar.gz differ diff --git a/dronebl/remove.sh b/dronebl/remove.sh new file mode 100644 index 0000000..bb6d7e1 --- /dev/null +++ b/dronebl/remove.sh @@ -0,0 +1,29 @@ +#!/bin/bash +cd "$(dirname "$0")" +KEY="$(" + while [ -n "$1" ] ; do + echo "" + shift + done + echo "" +) \ +| curl -s --data @- https://dronebl.org/RPC2 \ +| (xmllint --xpath '/response/result/@id' - 2>/dev/null | sed -n -e 's, id="\([^"]*\)",\1\n,gp') \ +|( + echo "" + while read ID ; do + echo "Remove ID $ID" >&2 + echo "" + done + echo "" +) \ +| tee -a dronebl-remove.log \ +| curl -s --data @- https://dronebl.org/RPC2 | tee -a dronebl-remove.log | grep -q "\"success\"" +if [ $? -eq 0 ] ; then + echo "DRONEBL: successfully removed $@" +else + echo "DRONEBL: error removing $@" +fi diff --git a/dronebl/submit.sh b/dronebl/submit.sh new file mode 100644 index 0000000..aa62c4f --- /dev/null +++ b/dronebl/submit.sh @@ -0,0 +1,175 @@ +#!/bin/bash +# syntax: dronebl-submit.sh [bantype [host|IP|datafile [host|IP|datafile [etc.]]] +# where datafile contains one host or IP per line. +# This script will sort | uniq datafiles and query for existing active listings, so +# duplicate entries are no problem. +# +# dependencies: bash, wget, standard GNU utils (host / sed / grep / sort / etc) +# +# Version history: +# 2.1 -- fixed a logic error; removed the removal of /tmp/dronebl-*.xml files on error +# 2.0 -- completely rewritten for RPC2 (although argument syntax is backward- +# compatible) + +RPCKEY="/etc/fail2ban/dronebl.rpckey" # key, or path to file containing rpckey +REPORT_TO="https://dronebl.org/RPC2" + +### end of user variables ### + +if [ ! -w "/tmp" ]; then + echo "Unable to write to /tmp. Please ensure the disk is not full, and that this account has appropriate permissions." + exit 1 +fi + +if [ -f "$RPCKEY" ]; then + if [ -r "$RPCKEY" ]; then + RPCKEY=`cat $RPCKEY` + else + echo "RPC key in $RPCKEY is unreadable. Exiting." + exit 1 + fi +fi + +function wash { # wash -- sets $IP by reference + ADDR=$1 + TEST=`echo "${ADDR}." | grep -E "^([0-9]{1,3}\.){4}$"` + if [ "$TEST" ]; then + VALID=0 + else + VALID=1 + fi + + if [ "$VALID" = "1" ]; then + echo -n "Looking up $ADDR... " + ADDR=`host $ADDR | grep -E -o -e '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'` + TEST=`echo "${ADDR}." | grep -E "^([0-9]{1,3}\.){4}$"` + if [ "$TEST" ]; then + echo "$ADDR" + else + echo "Unable to resolve. Skipping." + return 1 + fi + fi + eval "IP=$ADDR" + return 0 +} + +function rinse { # rinse -- if bantype is contained in the deprecated list, exit + DEPRECATED=( 4 11 12 ) + for dep in ${DEPRECATED[@]}; do + if [ "$BANTYPE" == "$dep" ]; then + echo "Bantype $BANTYPE has been deprecated. The DroneBL is probably not the appropriate listing service for this sort of activity. Please visit us on irc.atheme.org in #dronebl if you believe otherwise. Exiting." + exit 1 + fi + done +} + +function checkerror { #checkerror -- prints error messages from xml and exits + ERROR=`grep -i error $1` + if [ "$ERROR" ]; then + ERROR=`grep '' $1 | sed -r -e 's/<[^>]*>//g' -e 's/^\s*//g'` + ERROR="$ERROR: `grep '' $1 | sed -r -e 's/<[^>]*>//g' -e 's/^\s*//g'`" + echo "The server returned an error ($ERROR) -- see /tmp/dronebl-query.xml and /tmp/dronebl-response.xml for full details." + exit 1 + fi +} + +if [ "$2" = "" ]; then + echo -n 'Syntax: +'$0' [bantype [host|IP|datafile [host|IP|datafile [etc.]]]] + +Types are as follows: +2 = Sample +3 = IRC Drone +4 = Tor exit node (deprecated) +5 = Bottler +6 = Unknown spambot or drone +7 = DDOS Drone +8 = SOCKS Proxy +9 = HTTP Proxy +10 = ProxyChain +11 = Machines and netblocks compromised or owned by MediaDefender (deprecated) +12 = Trolls (deprecated) +13 = Brute force attackers +14 = Open Wingate +15 = Open Router +255 = Unknown + +Which type? ' + read BANTYPE + rinse $BANTYPE + echo -n "What's the hostname / IP address? " + read ADDR + wash $ADDR + if [ $? ]; then + IPLIST[0]=$IP + else + echo "Unable to resolve $ADDR. Exiting." + exit 1 + fi +else + rinse $1 + args=($@) + echo "A little housekeeping..." + for (( x=1; x<${#args[@]}; x++ )); do + if [ "${args[$x]}" != "" ]; then + filename="${args[$x]}" + if [ ! -r "$filename" ]; then filename="$PWD/${args[$x]}"; fi + if [ -r "$filename" ]; then + for i in `sort -u $PWD/${args[$x]}`; do + wash $i + if [ $? ]; then IPLIST[${#IPLIST[@]}]=$IP; fi + done + else + wash ${args[$x]} + if [ $? ]; then IPLIST[${#IPLIST[@]}]=$IP; fi + fi + fi + done + IPLIST=( `for (( x=0; x<${#IPLIST[@]}; x++ )) ; do echo ${IPLIST[$x]}; done | sort -u` ) + BANTYPE=$1 +fi + +POSTFILE="/tmp/dronebl-query.xml" +RESPONSEFILE="/tmp/dronebl-response.xml" + +echo "Housekeeping finished. Working with ${#IPLIST[@]} unique, valid addresses." +if [ ${#IPLIST[@]} -eq 0 ]; then + echo "No hosts to report. Exiting." + exit 0 +fi + +echo "Checking for exiting entries... " +echo " +" >$POSTFILE +for i in ${IPLIST[@]}; do + echo " " >>$POSTFILE +done +echo "" >>$POSTFILE +wget -q --post-file="$POSTFILE" -O "$RESPONSEFILE" --header="Content-Type: text/xml" $REPORT_TO +checkerror $RESPONSEFILE +grepfor='type="'$BANTYPE'"' +for i in `grep 'listed="1"' $RESPONSEFILE | grep $grepfor | grep -E -o -e '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u`; do + IPLIST=( ${IPLIST[@]%%$i} ) + echo "$i is already active in the DroneBL database as ban type $BANTYPE. Removing." +done + +if [ ${#IPLIST[@]} -eq 0 ]; then + echo "No hosts to report. Exiting." + exit 0 +elif [ ${#IPLIST[@]} -eq 1 ]; then + echo -n "Reporting ${IPLIST[@]} as ban type $BANTYPE... " +else + echo -n "Reporting ${#IPLIST[@]} hosts as ban type $BANTYPE... " +fi +echo " +" >$POSTFILE +for i in ${IPLIST[@]}; do + if [ "`echo ${i}. | grep -E '^([0-9]{1,3}\.){4}$'`" != "" ]; then echo " " >>$POSTFILE; fi +done +echo "" >>$POSTFILE +wget -q --post-file="$POSTFILE" -O "$RESPONSEFILE" --header="Content-Type: text/xml" $REPORT_TO +checkerror $RESPONSEFILE +echo "done." +rm -f /tmp/dronebl*.xml +exit 0