This is'nt quite a topic regarding speciffic code, but rather a conceptual discussion on how to "solve" an issue.
The issue at hand is a very persistent spammer in one of the channels I'm managing. I have sofar tracked down 4 C-class non-dns networks, aswell as atleast one additional ISP network. Most likely more will emerge as time passes by.
The method of spamming makes it hard to use dynamic banning, as (s)he generally joins, at some times sends a single spam-message, quits with the spam-message in his/her quit-message. The only option sofar is sticky bans, which unfortunately fills up the banlist, aswell as makes it hard to keep track of which networks are still in use.
The only thing that remains constant is the actual spam, although (s)he tends to use the same nickname over some time before switching. Using nickname banning has sofar only resulted in quicker changes of nickname, making it an unsatisfying solution.
To date, the best resolution has been to manually (using tools such as grep) to dig through logfiles in search of new traces and new hosts.
One recent idea though, was to use periodic WHOIS/WHOWAS queries of known nicks to scan for new hosts of his/hers. Could also be used as an indicator of inactive hosts.
Anyone got some reflections on this idea, or other ideas of keeping this annoyance out?
I know have a script that might help you out, however, I'm reluctant to give it over a public forum I know is visited by spammers.
Let me know if you would like me to send you a link by private message.
Thnx for the input sofar, unfortunately, most of those ideas are based on detecting random offenders once they've joined.
In this case, I'm trying to keep him/her out in the first place, so the key event here is to identify the networks he uses.
Apparently, most random-flooders have either abandoned this channel, or never found it in the first place, as random floods are very rare, and when they occur are easily managed using built-in flood protection.
However, this one spammer simply wont quit. One of the (now assumed stale) bans dates some 3 years back...
Using temporary bans usually means (s)he'll be back in a few hours doing the same thing. On some more persistent bans, (s)he'll just be back with a new host/network. Using a TLD-ban isn't quite an option, as we do have behaving visitors from within that TLD aswell.
As for nicks and idents, sofar they've not been random in the fashion of floodbots, but seem to be manually changed whenever banned. Hence, there's been no point using anything other than sitebans whenever a new network has been identified.
Any thoughts on the idea of using periodic WHOIS/WHOWAS-queries to known nicks of his/hers?
Might add, that the networks mentioned in my first post are considdered still active, there are other believed not in use anymore.
Unfortunately ircnet doesn't support who requests based on ident (although it does sometimes register on ident, odd).
Ircnet does support wildcarding in the who request, which will work on nick and host, so you could use possibly use that.
Edit:
Then there is the issue of preventing the script from "tagging" friendlies, which could be done by adding channel regulars to the bot's userlist and exempting valid users from being banned.
Who-requests would be a better option for whois-requests, as (s)he sometimes uses suffixes to his/her nickname. Did'nt think of wildcards, thnx
ISON does not return any information regarding ident or host, making it not ideal for identifying new networks in use. I guess it could be used to check if (s)he is online, and then do a who/whois to get the extended info; in order to not p*ss off ircops.
Main idea of using whowas requests, is that this information is cached over several hours, meaning I don't have to time the request to the short window when (s)he's online.
I am not familiar with /watch, something similar to the NoteServ service on Ircnet? (noteserv is unfortunately useful until (s)he actually joins the channel due to the fact that noteserv honors the +i usermode)
I've read over this again and i thought it might help if i tell ya what am using on one of my eggdrops to stop spam & drones. Also on the network i use, they use unrealircd so they have a spam filter. Which to a serton extent helps alot in keeping spam of the network. I kinda looked into a system that was simlar to this and found this script. It supports regex as well as normal wild card matching, can handle public and both private messages. Dose make life alot easyer for banning people that spam, but it comes down to getting them to spam the bot or else it wont do much good. As for the drones, I also found an other script (by the same person) which is a ban mask type of script, same fuctions of the bad word script. Can be seen here. I dont know if you are aware of the unrealircd spam filter, but i think if thats the kinda thing that would be usefull in this case. And for me it makes these scripts a good subsitution for it.
UnrealIRCd's spam filter: http://www.vulnscan.org/UnrealIRCd/unre ... spamfilter.
I've liked this post for a while and i came back to it a few days ago. Since i had a little time on my hands i came up with a new system i thought might help in the fight against spam. Its not that complicated and pretty simple.
Firstly, this was based around MC_8's spamcheck tcl. And this is the code i've got
# The Channel to report warnings to
set spamcheck(report2) "#mychannel"
# The spam string to search for in message's/notice's
set spamcheck(strings) {
"*DCC*"
"*http://*"
"*.*"
"*#*"
"*j*n*"
"*/*/*"
"*visit*"
"*irc*"
}
# exempt nicknames (Prevents spam warnings on services' notices/messages i.e op requests with channel names)
set spamcheck(exempts) {
"NickServ!ident@hostmask"
"ChanServ!ident@hostmask"
}
# check for drones
set spamcheck(drone-on) 1
# number of upper case letters in nickname + ident
set spamcheck(drone-upper) 4
# numer of numbers in nickname + ident
set spamcheck(drone-number) 2
# number of chars in nickname + ident
set spamcheck(drone-chars) 0
# number of lower case letters in nickname + ident
set spamcheck(drone-lower) 0
# number of score match by a nickname + ident to issue a warning on
set spamcheck(drone-score) 3
proc msgm:spamcheck {nick host handle text} {
global spamcheck
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
set string [filter -tcl [join [stripcodes bcruag [mirc_strip "$text"]]]]
foreach strings $spamcheck(strings) {
foreach exempt $spamcheck(exempts) {
if {([string match -nocase "$strings" "$string"]) && (![string match -nocase "$exempt" "$nick!$host"])} {
puthelp "PRIVMSG $spamcheck(report2) :\0039\002SPAM\002 \"\[MESSAGE\] $string\" from \002$nick\002 (\037$host\037)\0039"
}
}
}; return
}
}
proc notc:spamcheck {nick host handle text {dest ""}} {
global botnick spamcheck
if {$dest == ""} {set dest "${botnick}"}
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
set string [filter -tcl [join [stripcodes bcruag [mirc_strip "$text"]]]]
foreach strings $spamcheck(strings) {
foreach exempt $spamcheck(exempts) {
if {([string match -nocase "$strings" "$string"]) && (![string match -nocase "$exempt" "$nick!$host"])} {
puthelp "PRIVMSG $spamcheck(report2) :\0039\002SPAM\002 \"\[NOTICE\] $string\" from \002$nick\002 (\037$host\037)\0039"
}
}
}; return
}
}
proc ctcp:spamcheck {nick host handle dest keyword text} {
global spamcheck
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
puthelp "PRIVMSG $spamcheck(report2) :\0037\002CTCP\002 [join \"\[$keyword\] $text\"] from \002$nick\002 (\037$host\037)\0037"
return
}
}
proc ctcr:spamcheck {nick host handle dest keyword text} {
global spamcheck
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
puthelp "PRIVMSG $spamcheck(report2) :\0037\002CTCR\002 [join \"\[$keyword\] $text\"] from \002$nick\002 (\037$host\037)\0037"
return
}
}
proc flud:spamcheck {nick host handle type channel} {
global spamcheck
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
if {"${type}" == "pub"} {puthelp "PRIVMSG $spamcheck(report2) :\0032\002TEXT FLOOD\002 from \002$nick\002 (\037$host\037) on $channel\0032"}
if {"${type}" == "msg"} {puthelp "PRIVMSG $spamcheck(report2) :\0036\002MESSAGE FLOOD\002 from \002$nick\002 (\037$host\037)\0036"}
if {"${type}" == "join"} {puthelp "PRIVMSG $spamcheck(report2) :\0034\002JOIN FLOOD\002 from \002$nick\002 (\037$host\037) at $channel\0034"}
if {"${type}" == "ctcp"} {puthelp "PRIVMSG $spamcheck(report2) :\00313\002CTCP FLOOD\002 from \002$nick\002 (\037$host\037)\00313"}
return
}
}
proc raw:spamcheck {from key text} {
global spamcheck
if {[validchan $spamcheck(report2)] && [botonchan $spamcheck(report2)]} {
puthelp "PRIVMSG $spamcheck(report2) :\00312\002INVITE\002 to [lindex [split $text] 3] from \002[lindex [split [lindex [split $text] 0] "!"] 0]\002 (\037[lindex [split [lindex [split $text] 0] "!"] 1]\037)\00312"
return
}
}
proc join:spamcheck {nick host handle channel} {
global spamcheck
if {([validchan $spamcheck(report2)]) && ([botonchan $spamcheck(report2)]) && ([chanflag $channel spamcheck-drones]) && ($spamcheck(drone-on) == 1)} {
set spamcheck(drone:*!*@[lindex [split $host "@"] 1]) "0"
if {[regexp -all {[A-Z]} "$nick[lindex [split $host "@"] 0]"] >= $spamcheck(drone-upper)} {
set spamcheck(drone:*!*@[lindex [split $host "@"] 1]) "[expr $spamcheck(drone:*!*@[lindex [split $host "@"] 1]) + 1]"
}
if {[regexp -all {[0-9]} "$nick[lindex [split $host "@"] 0]"] >= $spamcheck(drone-number)} {
set spamcheck(drone:*!*@[lindex [split $host "@"] 1]) "[expr $spamcheck(drone:*!*@[lindex [split $host "@"] 1]) + 1]"
}
if {[regexp -all {[:punct:]} "$nick[lindex [split $host "@"] 0]"] >= $spamcheck(drone-chars)} {
set spamcheck(drone:*!*@[lindex [split $host "@"] 1]) "[expr $spamcheck(drone:*!*@[lindex [split $host "@"] 1]) + 1]"
}
if {[regexp -all {[a-z]} "$nick[lindex [split $host "@"] 0]"] >= $spamcheck(drone-lower)} {
set spamcheck(drone:*!*@[lindex [split $host "@"] 1]) "[expr $spamcheck(drone:*!*@[lindex [split $host "@"] 1]) + 1]"
}
if {$spamcheck(drone:*!*@[lindex [split $host "@"] 1]) >= $spamcheck(drone-score)} {
puthelp "PRIVMSG $spamcheck(report2) :\0033\002DRONE\002 detected \002$nick\002 (\037$host\037) at $channel\0033"
return
}
}
}
setudef flag spamcheck-drones
bind msgm - "*" msgm:spamcheck
bind notc - "*" notc:spamcheck
bind ctcp - "*" ctcp:spamcheck
bind ctcr - "*" ctcr:spamcheck
bind flud - "*" flud:spamcheck
bind raw - "INVITE" raw:spamcheck
bind join - "* *" join:spamcheck
putlog "loaded spamcheck_ext.tcl version 1.5b by TCL_no_TK"
return
uses MC more tools. I've used this on two differant bots using the spamcheck and this on differant channels at differant times. It can probably be a bit better and the code might have a few problems. But i thought it was worth making a reply post with i hope things like this will help someone out there. I've made it display a warning on CTCP n CTCR since, this way am able to see /ctcp chat's n other stuff. like i said, its pretty simple
Last edited by TCL_no_TK on Wed Feb 13, 2008 4:40 pm, edited 3 times in total.
This is abit of a brainstorming-thread, so I guess most ideas are welcome, although the primary objective is/was to keep track of a known spammer.
Might give a little status update while at it;
Scanning through old channel-logs reveals no traces of this spammer since november 2007, so either (s)he's given up, taken a break, or ran out of hosts for the time being.
Not available anymore due to my scripts being leaked by some noobs scanning my files and releasing my biggest script service.tcl publicly which might kill my botservice #pwnd.bots @ qnet.