{"id":231,"date":"2007-10-23T01:34:27","date_gmt":"2007-10-23T05:34:27","guid":{"rendered":"http:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/23\/bans-for-fun-profit\/"},"modified":"2007-10-23T01:34:27","modified_gmt":"2007-10-23T05:34:27","slug":"bans-for-fun-profit","status":"publish","type":"post","link":"https:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/23\/bans-for-fun-profit\/","title":{"rendered":"Bans for Fun &amp; Profit"},"content":{"rendered":"<p>The way I use this server gives me a luxury that bigger sites don&#8217;t: my visitors come from a select range, and I don&#8217;t have to worry much about blocking people erroneously. Therefore I can be quite aggressive in blocking IPs. \/etc\/hosts.deny is my new favorite file.<\/p>\n<p>When I moderate comments here, I have a few choices&#8230; I can approve it, delete it, or mark it as spam. I never got what marking it as spam did&#8230; Apparently it doesn&#8217;t do much but set a &#8216;spam&#8217; bit. (I&#8217;d hoped it trained Bayesian filters or something, but no such luck.) But what it <em>does<\/em> do is make it super-simple to construct an SQL query to pull out all the IPs that have posted spam. Add a little more and you get just the IPs <em>this month<\/em> that had posts flagged as spam. And you drop them in \/etc\/hosts.deny.<\/p>\n<p>But then I was watching the system log file, and noticed lots of spam coming in. I&#8217;m not running much of a mailserver, so most addresses are bouncing. (Especially since they&#8217;re spamming addresses that have <em>never<\/em> existed?)<\/p>\n<p>This is good news, though, for the IP-banhappy out there.  Here&#8217;s my latest concoction:<\/p>\n<blockquote>\n<pre>grep NOQUEUE \/var\/log\/messages | awk '{print $10}' | \\\nsed \"s\/[\/ \/g\" | sed \"s\/]\/ \/g\" | awk '{print \"ALL\", $2}' | \\\nsort | uniq -c | sort | tail<\/pre>\n<\/blockquote>\n<p>In a nutshell, we look for &#8220;NOQUEUE&#8221; in the log files, pull out the 10th column (IP), split out the junk so it&#8217;s just a numeric IP, sort it, weed out the dupes with <tt>uniq<\/tt> and pass it the <tt>-c<\/tt> flag, which has it count the number of times each line occurs, and then we sort that, so that the list is now sorted by the number of bounces. It defaults to ascending order, so that the top of the file is all people who&#8217;ve only e-mailed one invalid address. So the &#8216;juicy&#8217; part is the end of the file. So we pipe it to tail, which, by default, shows the last ten lines. So the output looks like:<\/p>\n<blockquote>\n<pre>      5 ALL 219.140.194.117\n      5 ALL 85.130.84.9\n      6 ALL 86.152.15.119\n      7 ALL 83.182.186.224\n      8 ALL 125.181.70.135\n      8 ALL 207.144.11.87\n     10 ALL 125.212.188.156\n     15 ALL 88.238.145.22\n     17 ALL 217.26.169.66\n     17 ALL 62.149.197.247<\/pre>\n<\/blockquote>\n<p>You could use a little more magic to automatically add the second and third columns to \/etc\/hosts.deny, but I prefer to do it this way&#8230; The reason is that sometimes (not in this example) you&#8217;ll see posts from a range of similar IPs. It&#8217;s more of a judgment call where you draw the line, so I like to give it the once-over.<\/p>","protected":false},"excerpt":{"rendered":"<p>The way I use this server gives me a luxury that bigger sites don&#8217;t: my visitors come from a select range, and I don&#8217;t have to worry much about blocking people erroneously. Therefore I can be quite aggressive in blocking &hellip; <a href=\"https:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/23\/bans-for-fun-profit\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,15,18,22,24],"tags":[],"class_list":["post-231","post","type-post","status-publish","format-standard","hentry","category-computers","category-living","category-ocd","category-programming","category-rants-raves"],"_links":{"self":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/posts\/231","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/comments?post=231"}],"version-history":[{"count":0,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/posts\/231\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/media?parent=231"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/categories?post=231"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/tags?post=231"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}