Useful scripts

Hi All,
This is a little script set I wrote to check the IP of visitors to your service against DNS RBL's. Handy to block known botnets and/or bad IP's. This filter is a little complex but simply put it, will record the IP's of any system connecting to the firewall on port 22 (or any other service port you want to put a JUMP rule in for) and check them against a DNS based Blacklist of known attackers. So you don't have to put up with the hassle of them on your systems.

First are the firewall filters:

/ip firewall filter add action=jump chain=forward comment="Check intruders in \"Dynamic_blacklist\" chain (SSH)" dst-port=22 in-interface-list=WAN jump-target=dynamic_blacklist protocol=tcp
/ip firewall filter add action=add-src-to-address-list address-list=DNSBL_unchecked address-list-timeout=30m chain=dynamic_blacklist comment="DNS Blacklist add ip to list to check." connection-state=!established,related in-interface-list=WAN src-address-list=!DNSBL_unchecked
/ip firewall filter add action=return chain=dynamic_blacklist comment="Return to the chain that jumped into dynamic_blacklist chain"
/ip firewall raw add action=drop chain=prerouting comment="Drop blacklist" in-interface-list=WAN log-prefix="DYNAMIC BLACKLIST IP (Raw)" src-address-list=bl_blacklist

Next is the script to check the DNS blacklist, schedule this to run every 5,10 or 15 mins. I chose bl.blocklist.de but you can use your favourite. the script only checks for a positive response it does not localise the return to a particular listing type, though you could improve the script to check for this.

DNS Blacklist Script

# DNS Blacklist service call
:local blserver "bl.blocklist.de"
:local ToListIPList [:toarray ""]
:local octets
:local revip
:local bllookup
:local blresult
:local i
:global returnOctet;

# for each IP in the unchecked list load it into an array
:set i (0);
:foreach fwlist in=[/ip firewall address-list find where list=DNSBL_unchecked] do={
:foreach ip in=[/ip firewall address-list get $fwlist value-name=address] do={
:set ($ToListIPList->"$i") $ip;
:put "$ip is loaded into array at index $i"
#remove ip from address list to check ether way
/ip firewall address-list { remove [find address=$ip list=DNSBL_unchecked]};
:set i ($i + 1);
};
};

#delete entire list=DNSBL_unchecked
#/ip firewall address-list remove [/ip firewall address-list find list="DNSBL_unchecked"];

#take the IPs and Progress;
:foreach ip in=$ToListIPList do={
:put $ip;
# seperate IP into $octets array;
:set octets [$returnOctet $ip 5];
# Reverse the IP address for reverse DNS lookup;
:set revip ([:tostr [:pick $octets 3]] . "." . [:tostr [:pick $octets 2]] . "." . [:tostr [:pick $octets 1]] . "." . [:tostr [:pick $octets 0]]);
# construct the blacklist lookup
:set bllookup ($revip . "." . $blserver);
:put $bllookup;
# perform the lookup and correct an empty response;
:do {
:set blresult [:resolve $bllookup];
} on-error={
#"No blacklist record found, correct the error";
:set $blresult "fail";
}
# check the result
:if ( $blresult != "fail" ) do={
# if the address is listed add it to the blacklist
:put "listing ip";
/ip firewall address-list add address=$ip list=DNSBL_listed timeout=168h;
};
};

The second script is a global function stolen fair and square from Rextended on Return IP Octet Function though i did do a little error correcting on it. Just put this in your scripts so it is accessible by the DNS blacklist script.

:global returnOctet do={
:if ([:typeof [:toip $1]] != "ip") do={ :error message="You did not specify any VALID IP Address."; };
:if ( (($2 + 0) < 1) || (($2 + 0) > 5) ) do={ :error message="You did not specify any VALID argument to return."; };
:local workString value=[:tostr [:toip $1]];
:local endString value="";
:local thisChar value="";
:for i from=0 to=[:len $workString] step=1 do={
:set $thisChar value=[:pick $workString $i ($i+1)];
:if ($thisChar = ".") do={ :set $thisChar value=",";};
:set $endString value=($endString.$thisChar);
};
:local resultArray value=[:toarray $endString];
:if (($2 + 0) = 5) do={ :return value=$resultArray; } else={ :return value=($resultArray->($2 - 1)); };
}