{"id":202,"date":"2007-10-12T17:30:31","date_gmt":"2007-10-12T21:30:31","guid":{"rendered":"http:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/12\/fun-with-shell-commands\/"},"modified":"2007-10-12T17:30:31","modified_gmt":"2007-10-12T21:30:31","slug":"fun-with-shell-commands","status":"publish","type":"post","link":"https:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/12\/fun-with-shell-commands\/","title":{"rendered":"Fun with Shell Commands"},"content":{"rendered":"<p>I&#8217;m now running a mailserver, and I was trying to set up Mailman to handle a mailing list. I was having some odd behavior causing Mailman to barf up a fatal error, so I used a trailing monitor on the log file with <tt>tail -f<\/tt>.<\/p>\n<p>In the course of doing that, I noticed <em>several<\/em> hosts connect attempting to deliver mail (presumably spam) to &#8220;bumttwagnerfor@domain&#8230;&#8221;, a bizarre address that definitely doesn&#8217;t exist.<\/p>\n<p>It&#8217;s not a big deal, because the mail&#8217;s just bouncing. But it got irritating watching them all in the log file.<\/p>\n<p>I wanted to ban them. It turns out that Linux makes this easy: there&#8217;s a hosts.deny file, and anyone in it is banned from connecting. I already have a script that watches for repeat failed login attempts on ssh and bans them. (And I have something like 200 IPs banned, although I suspect that it&#8217;s not purging them appropriately.)<\/p>\n<p>All the log entries are in a common format, and look like this:<\/p>\n<blockquote><tt>\nOct  8 05:41:31 oxygen postfix\/smtpd[23212]: NOQUEUE: reject: RCPT from unknown[62.233.163.250]: 550 5.1.1 <bumttwagnerfor@ttwagner.com>: Recipient address rejected: User unknown in local recipient table; from=<kqcwglupoqb@bonairenews.com> to=<bumttwagnerfor@ttwagner.com> proto=ESMTP helo=<250.248\/30.163.233.62.in-addr.arpa>\n<\/tt><\/blockquote>\n<p>We can see (actually, guess, in my case) that the IP is the 10th &#8216;column&#8217; (using a &#8216;space&#8217; as a delimiter). So we can begin a rudimentary script to print out just that:<\/p>\n<pre>\n<b># grep bumttwagnerfor \/var\/log\/messages  | awk '{ print $10}' | head<\/b>\nunknown[211.49.17.175]:\n81.202.185.36.dyn.user.ono.com[81.202.185.36]:\nhost-89-228-234-224.kalisz.mm.pl[89.228.234.224]:\nLSt-Amand-152-32-14-78.w82-127.abo.wanadoo.fr[82.127.29.78]:\n<\/pre>\n<p>But there&#8217;s an obvious problem: the hostname is rammed up against the IP. I want to just ban the IP, and strip out the hostname. The correct way is to write a lengthy regular expression to match just whatever&#8217;s between the [ and ]. (Note that you can&#8217;t just write a regular expression to match IPs: the very first one has an IP in its hostname, for example, which would throw you off.)<\/p>\n<p>The quick and easy solution is to replace the [ with a space and the ] with a space, which gives you &#8220;hostname IP &#8220;. And then you use awk again to print it:<\/p>\n<p><tt>grep bumttwagnerfor \/var\/log\/messages  | awk '{ print $10}' | sed \"s\/[\/ \/g\" | sed \"s\/]\/ \/g\" | awk '{print $2}'<\/tt><\/p>\n<p>This is a pretty ugly command. Just the way I like it. \ud83d\ude09<\/p>\n<p>But we&#8217;re not quite done! The format for hosts.deny is &#8220;Service: Address.&#8221; We&#8217;re just getting addresses here. I want the output to be something like <tt>ALL: 1.2.3.4<\/tt> for each entry. (If they&#8217;re spamming me, I don&#8217;t want to allow them access to any other services.)<\/p>\n<p>When it&#8217;s all said and done, here&#8217;s the command:<\/p>\n<p><tt>grep bumttwagnerfor \/var\/log\/messages  | awk '{ print $10}' | sed \"s\/[\/ \/g\" | sed \"s\/]\/ \/g\" | awk '{print \"ALL\", $2}'<\/tt><\/p>\n<p>You can just append a <tt>>> hosts.deny<\/tt> to deny them right away, or parse it through <tt>head<\/tt> or <tt>less<\/tt> to review first.<\/p>\n<p>And viola. 440 IPs banned.<\/p>\n<p>Seriously, though. wtf is going on? 440 different people have tried spamming this address that has definitely never existed.<\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m now running a mailserver, and I was trying to set up Mailman to handle a mailing list. I was having some odd behavior causing Mailman to barf up a fatal error, so I used a trailing monitor on the &hellip; <a href=\"https:\/\/blogs.n1zyy.com\/n1zyy\/2007\/10\/12\/fun-with-shell-commands\/\">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,11,18,22,27],"tags":[],"class_list":["post-202","post","type-post","status-publish","format-standard","hentry","category-computers","category-insanity","category-ocd","category-programming","category-security"],"_links":{"self":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/posts\/202","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=202"}],"version-history":[{"count":0,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/posts\/202\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/media?parent=202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/categories?post=202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.n1zyy.com\/n1zyy\/wp-json\/wp\/v2\/tags?post=202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}