<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Looking for the paradigm &#187; apache</title>
	<atom:link href="http://www.evanhoffman.com/evan/tag/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.evanhoffman.com/evan</link>
	<description>So I can pass it off</description>
	<lastBuildDate>Thu, 26 Jan 2012 22:17:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Making sure SSLv2 is disabled in Apache (and Nginx)</title>
		<link>http://www.evanhoffman.com/evan/2011/09/20/making-sure-sslv2-is-disabled-in-apache/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=making-sure-sslv2-is-disabled-in-apache</link>
		<comments>http://www.evanhoffman.com/evan/2011/09/20/making-sure-sslv2-is-disabled-in-apache/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 18:06:38 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[beast]]></category>
		<category><![CDATA[cipher]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[httpd]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mitm]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[sslciphersuite]]></category>
		<category><![CDATA[sslv2]]></category>
		<category><![CDATA[tls]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=1606</guid>
		<description><![CDATA[Tweet Edit Jan 24, 2012: Deleted all the crap from this story and just left the recommended Apache and Nginx SSL cipher suites for maximum security without SSLv2 and without BEAST vulnerability (at least according to Qualys). Apache httpd SSLProtocol -ALL +SSLv3 +TLSv1 SSLCipherSuite ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM; SSLHonorCipherOrder on nginx ssl_protocols SSLv3 TLSv1; ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM; ssl_prefer_server_ciphers on; [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2011/09/20/making-sure-sslv2-is-disabled-in-apache/&via=EvanHoffman&text=Making sure SSLv2 is disabled in Apache (and Nginx)&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2011/09/20/making-sure-sslv2-is-disabled-in-apache/"></g:plusone></div><p><ins datetime="2012-01-24T03:50:52+00:00"><br />
<strong>Edit Jan 24, 2012: </strong> Deleted all the crap from this story and just left the recommended Apache and Nginx SSL cipher suites for maximum security without SSLv2 and without BEAST vulnerability (at least according to Qualys).<br />
</ins><br />
<strong>Apache httpd</strong></p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">SSLProtocol -ALL +SSLv3 +TLSv1
SSLCipherSuite ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM;
SSLHonorCipherOrder on</pre></div></div>

<p><strong>nginx</strong></p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">        ssl_protocols  SSLv3 TLSv1;
        ssl_ciphers     ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM;
        ssl_prefer_server_ciphers   on;</pre></div></div>

<p>Source: </p>
<ul>
<li>
<a href="https://community.qualys.com/blogs/securitylabs/2011/10/17/mitigating-the-beast-attack-on-tls">Qualys</a></li>
<li><a href="https://www.ssllabs.com/ssldb/">SSL checker</a></li>
</ul>
<p><a target="_blank" href="http://affiliate.godaddy.com/redirect/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC"><img src="http://affiliate.godaddy.com/ads/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC" border="0" width="468"  height="60" alt="Go Daddy $12.99 SSL Sale!"/></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2011/09/20/making-sure-sslv2-is-disabled-in-apache/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Logging RT username in Apache access_log</title>
		<link>http://www.evanhoffman.com/evan/2011/08/08/logging-rt-username-in-apache-access_log/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=logging-rt-username-in-apache-access_log</link>
		<comments>http://www.evanhoffman.com/evan/2011/08/08/logging-rt-username-in-apache-access_log/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 21:34:18 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[access_log]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[httpd]]></category>
		<category><![CDATA[httpd.conf]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[mod_perl]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[rt]]></category>
		<category><![CDATA[rtuser]]></category>
		<category><![CDATA[username]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=1513</guid>
		<description><![CDATA[TweetRT has its own internal accounting &#038; tracking system for logging activity, but I was interested in even more granular stuff, like seeing who looked at which tickets. I figured it wouldn&#8217;t be that hard to log this in Apache. Well, I was kind of right, in that it wasn&#8217;t &#8220;hard,&#8221; but it took me [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2011/08/08/logging-rt-username-in-apache-access_log/&via=EvanHoffman&text=Logging RT username in Apache access_log&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2011/08/08/logging-rt-username-in-apache-access_log/"></g:plusone></div><p><a href="http://bestpractical.com/rt/">RT</a> has its own internal accounting &#038; tracking system for logging activity, but I was interested in even more granular stuff, like seeing who looked at which tickets.  I figured it wouldn&#8217;t be that hard to log this in Apache.  Well, I was kind of right, in that it wasn&#8217;t &#8220;hard,&#8221; but it took me a long time to find the right place to do it.  I did finally get it though.<br />
<span id="more-1513"></span></p>
<h3>httpd.conf</h3>
<p>In <code>httpd.conf</code> I created a new LogFormat:</p>

<div class="wp_syntax"><div class="code"><pre class="conf" style="font-family:monospace;">LogFormat &quot;%h %l %{RTUSER}e %t \&quot;%r\&quot; %&gt;s %b \&quot;%{Referer}i\&quot; \&quot;%{User-Agent}i\&quot;&quot; combined-rt</pre></div></div>

<p>So instead of the HTTP-auth user, it puts the RT user in this field.  Make sure to update your VirtualHost config to use the combined-rt LogFormat.</p>
<h3>/usr/share/rt3/html/autohandler</h3>
<p>In <code>/usr/share/rt3/html/autohandler</code>, right under this section:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># If we've got credentials, let's serve the file up.</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>    <span style="color: #009900;">&#40;</span> <span style="color: #000066;">defined</span> <span style="color: #0000ff;">$session</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'CurrentUser'</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #b1b100;">and</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">$session</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'CurrentUser'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">Id</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span></pre></div></div>

<p>Add this:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;">        <span style="color: #0000ff;">$ENV</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'RTUSER'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$session</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'CurrentUser'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">UserObj</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">EmailAddress</span><span style="color: #339933;">;</span></pre></div></div>

<p>This populates the RTUSER environment variable with the currently-logged-in user&#8217;s email address.</p>
<p>Restart httpd and the RT user&#8217;s email address should now appear in <code>access_log</code>.  Note that it will only appear for Perl pages (not gifs/jpgs or other static content, since Perl doesn&#8217;t process those):</p>

<div class="wp_syntax"><div class="code"><pre class="log" style="font-family:monospace;">10.0.0.10 - evan@example.com [08/Aug/2011:17:30:34 -0400] &quot;GET /rt3/index.html HTTP/1.1&quot; 200 46809 &quot;-&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0.1) Gecko/20100101 Firefox/5.0.1&quot;
10.0.0.10 - - [08/Aug/2011:17:30:34 -0400] &quot;GET /rt3/NoAuth/images//css/rolldown-arrow.gif HTTP/1.1&quot; 200 83 &quot;https://help.example.com/rt3/NoAuth/css/3.5-default/main-squished.css&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0.1) Gecko/20100101 Firefox/5.0.1&quot;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2011/08/08/logging-rt-username-in-apache-access_log/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Putting up a &quot;down for maintenance&quot; message using mod_rewrite</title>
		<link>http://www.evanhoffman.com/evan/2010/10/08/putting-up-a-down-for-maintenance-message-using-mod_rewrite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=putting-up-a-down-for-maintenance-message-using-mod_rewrite</link>
		<comments>http://www.evanhoffman.com/evan/2010/10/08/putting-up-a-down-for-maintenance-message-using-mod_rewrite/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 22:11:42 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[redirect]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=808</guid>
		<description><![CDATA[TweetPutting this here for safekeeping so my future self can find it. Mod_rewrite is one of my favorite tools, but it&#8217;s easy to spend 30 minutes crafting a 2-line directive that actually does what you want. I put this in a .htaccess file in the DocumentRoot of the server, put a &#8220;We&#8217;re down&#8221; message in [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2010/10/08/putting-up-a-down-for-maintenance-message-using-mod_rewrite/&via=EvanHoffman&text=Putting up a &quot;down for maintenance&quot; message using mod_rewrite&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2010/10/08/putting-up-a-down-for-maintenance-message-using-mod_rewrite/"></g:plusone></div><p>Putting this here for safekeeping so my future self can find it.  Mod_rewrite is one of my favorite tools, but it&#8217;s easy to spend 30 minutes crafting a 2-line directive that actually does what you want.  I put this in a .htaccess file in the DocumentRoot of the server, put a &#8220;We&#8217;re down&#8221; message in maintenance.html (or whatever), and all requests will get a 302 redirect to /maintenance.html, except requests for /maintenance.html (for obvious reasons).  It appends the original request in case you want to do something with it but that&#8217;s not really important.  It also doesn&#8217;t do the redirect for images/js/css so those can actually be used in the maintenance message.</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteRule</span> ^maintenance.html	-	[PT,L]
&nbsp;
<span style="color: #00007f;">RewriteCond</span> %{REQUEST_URI}	!(gif|jpg|css|js)$
<span style="color: #00007f;">RewriteRule</span> (.*) /maintenance.html?redir=true&amp;originalRequest=%{REQUEST_URI} [R=<span style="color: #ff0000;">302</span>]</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/10/08/putting-up-a-down-for-maintenance-message-using-mod_rewrite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forcing WordPress administration over SSL</title>
		<link>http://www.evanhoffman.com/evan/2010/09/20/forcing-wordpress-administration-over-ssl/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=forcing-wordpress-administration-over-ssl</link>
		<comments>http://www.evanhoffman.com/evan/2010/09/20/forcing-wordpress-administration-over-ssl/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 19:46:05 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=635</guid>
		<description><![CDATA[TweetI never like typing a password into a non-SSL site, no matter how trivial it is. In order to give my own site this ability I simply used mod_rewrite to force requests to WordPress&#8217;s admin pages to go over SSL. The .htaccess file for the site looks like this: # BEGIN WordPress &#60;ifModule mod_rewrite.c&#62; RewriteEngine [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2010/09/20/forcing-wordpress-administration-over-ssl/&via=EvanHoffman&text=Forcing WordPress administration over SSL&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2010/09/20/forcing-wordpress-administration-over-ssl/"></g:plusone></div><p>I never like typing a password into a non-SSL site, no matter how trivial it is.  In order to give my own site this ability I simply used mod_rewrite to force requests to WordPress&#8217;s admin pages to go over SSL.</p>
<p>The .htaccess file for the site looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># BEGIN WordPress</span>
&lt;<span style="color: #000000; font-weight:bold;">ifModule</span> mod_rewrite.c&gt;
<span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
<span style="color: #00007f;">RewriteBase</span> /evan/
<span style="color: #00007f;">RewriteRule</span> ^index\.php$ - [L]
<span style="color: #00007f;">RewriteCond</span> %{REQUEST_FILENAME} !-f
<span style="color: #00007f;">RewriteCond</span> %{REQUEST_FILENAME} !-d
<span style="color: #00007f;">RewriteRule</span> . /evan/index.php [L]
&lt;/<span style="color: #000000; font-weight:bold;">ifModule</span>&gt;
&nbsp;
<span style="color: #adadad; font-style: italic;"># END WordPress</span></pre></div></div>

<p>To force the admin pages to SSL, just add these lines under <strong>RewriteEngine On</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">RewriteCond</span> %{HTTPS} !=<span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteRule</span> ^wp-(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}      [R,L]</pre></div></div>

<p><strong>Edit</strong> &#8211; The above code screws up uploads (which go into the /wp-content directory).  I replaced that with the following and it Worked As Intended.</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">RewriteCond</span> %{HTTPS} !=<span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteRule</span> ^wp-login(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}      [R,L]
<span style="color: #00007f;">RewriteCond</span> %{HTTPS} !=<span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteRule</span> ^wp-admin(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}      [R,L]</pre></div></div>

<p>That&#8217;s pretty much it.  If your request starts with &#8220;wp-&#8221; it&#8217;ll redirect you to the same URL, but starting with https://.  Problem solved.  You do need to make sure you have an SSL VirtualHost pointing to your WordPress DocumentRoot so that https://yoursite.com goes to the same place as http://yoursite.com.</p>
<p><a target="_blank" href="http://affiliate.godaddy.com/redirect/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC"><img src="http://affiliate.godaddy.com/ads/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC" border="0" width="468"  height="60" alt="Go Daddy $12.99 SSL Sale!"/></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/09/20/forcing-wordpress-administration-over-ssl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Blocking comment spammers by IP</title>
		<link>http://www.evanhoffman.com/evan/2010/08/13/blocking-comment-spammers-by-ip/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=blocking-comment-spammers-by-ip</link>
		<comments>http://www.evanhoffman.com/evan/2010/08/13/blocking-comment-spammers-by-ip/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 15:59:27 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[allow]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[block]]></category>
		<category><![CDATA[deny]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=538</guid>
		<description><![CDATA[TweetI use Akismet to block comment spam, but it still annoys me that it even exists. Last night I put a simple IP ban into my httpd config. But who to block? I used a grep &#38; Perl to get a rough guess of which IPs were submitting the most comments (working on the assumption [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2010/08/13/blocking-comment-spammers-by-ip/&via=EvanHoffman&text=Blocking comment spammers by IP&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2010/08/13/blocking-comment-spammers-by-ip/"></g:plusone></div><p>I use <a href="http://akismet.com/">Akismet</a> to block comment spam, but it still annoys me that it even exists.  Last night I put a simple IP ban into my httpd config.  But who to block?</p>
<p>I used a grep &amp; Perl to get a rough guess of which IPs were submitting the most comments (working on the assumption that one IP address submits many spam comments) It took me about 20 minutes to write this mess but it does what I wanted to do:<br />
<code><br />
[root@lunix ~]# zgrep  POST /var/log/httpd/evanhoffman-access_log-201008??.gz  | grep comment | perl -ne 'chomp; $_ =~ m/(?:\d{1,3}\.){3}\d{1,3}/; print "$&amp;\n";' | perl -e '%a = (); while (&lt;&gt;) { chomp;  $a{$_} += 1; } while (my ($key, $value) = each (%a)) { if ($value &gt; 1) { print "$value\t=&gt;\t$key\n";}}'<br />
2       =&gt;      218.6.9.140<br />
180     =&gt;      91.201.66.34<br />
2       =&gt;      213.5.67.41<br />
2       =&gt;      188.187.102.74<br />
[root@lunix ~]#<br />
</code></p>
<p>That&#8217;s pretty hard to read.  Here&#8217;s a quick explanation of each piece:</p>
<blockquote><p>zgrep  POST /var/log/httpd/evanhoffman-access_log-201008??.gz</p></blockquote>
<p>Use zgrep to search for the string &#8220;POST&#8221; in all of the gzipped Apache logs for August.  Pipe the results (the matching lines) to the next part:</p>
<blockquote><p>grep comment</p></blockquote>
<p>grep for the string &#8220;comment&#8221;.  This isn&#8217;t really scientific, but I feel safe in assuming that if &#8220;POST&#8221; and &#8220;comment&#8221; both appear in the HTTP request, it&#8217;s probably someone posting a comment.  Pipe the matches to&#8230;</p>
<blockquote><p>perl -ne &#8216;chomp; $_ =~ m/(?:\d{1,3}\.){3}\d{1,3}/; print &#8220;$&amp;\n&#8221;;&#8217;</p></blockquote>
<p>This is a perl one-liner that uses a regular expression to match an IP address in a given line and print it out.  The original regex I used was <code>\d+\.\d+\.\d+\.\d+</code>, this one was slightly fancier but did the same work in this case.  It&#8217;s worth noting that this will only print out the first match in the given line, but since the requester&#8217;s IP (REMOTE_ADDR) is the first field in <a href="http://httpd.apache.org/docs/2.0/logs.html#accesslog">Combined Log Format</a>, that&#8217;s fine this case.</p>
<p>The output (the IPs from which comment posts have been made) is piped to&#8230;</p>
<blockquote><p>perl -e &#8216;%a = (); while (&lt;&gt;) { chomp;  $a{$_} += 1; } while (my ($key, $value) = each (%a)) { if ($value &gt; 1) { print &#8220;$value\t=&gt;\t$key\n&#8221;;}}&#8217;</p></blockquote>
<p>This is another perl one-liner.  Basically, it maintains a hash of String=&gt;count pairs, so each time it sees a string it increments a &#8220;counter&#8221; for that line.  Then when it&#8217;s done receiving input (i.e. all the data has been processed) it prints out the contents of the hash for keys that have a value &gt; 1 (i.e. IPs that have POSTed more than 1 comment).</p>
<p>The output shows pretty clearly where the spam is coming from:</p>
<blockquote><p>2 =&gt; 218.6.9.140<br />
180 =&gt; 91.201.66.34<br />
2 =&gt; 213.5.67.41<br />
2 =&gt; 188.187.102.74</p></blockquote>
<p>180 submits from 91.201.66.34.  Out of curiosity I looked up that IP in whois:</p>
<pre>[root@lunix ~]# whois 91.201.66.34
[Querying whois.ripe.net]
[whois.ripe.net]
% This is the RIPE Database query service.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See http://www.ripe.net/db/support/db-terms-conditions.pdf

% Note: This output has been filtered.
%       To receive output for a database update, use the "-B" flag.

% Information related to '91.201.64.0 - 91.201.67.255'

inetnum:        91.201.64.0 - 91.201.67.255
netname:        Donekoserv
descr:          DonEkoService Ltd
country:        RU
org:            ORG-DS41-RIPE
admin-c:        MNV32-RIPE
tech-c:         MNV32-RIPE
status:         ASSIGNED PI
mnt-by:         RIPE-NCC-END-MNT
mnt-by:         MNT-DONECO
mnt-by:         MNT-DONECO
mnt-lower:      RIPE-NCC-END-MNT
mnt-routes:     MHOST-MNT
mnt-routes:     MNT-PIN
mnt-domains:    MHOST-MNT
source:         RIPE # Filtered

organisation:   ORG-DS41-RIPE
org-name:       DonEko Service
org-type:       OTHER
address:        novocherkassk, ul stremyannaya d.6
e-mail:         admin@pinspb.ru
mnt-ref:        MNT-PIN
mnt-by:         MNT-PIN
source:         RIPE # Filtered

person:         Metluk Nikolay Valeryevich
address:        korp. 1a 40 Slavy ave.,
address:        St.-Petersburg, Russia
e-mail:         nm@internet-spb.ru
phone:          +7 812 4483863
fax-no:         +7 901 3149449
nic-hdl:        MNV32-RIPE
mnt-by:         MNT-PIN
source:         RIPE # Filtered

% Information related to '91.201.66.0/23AS21098'

route:          91.201.66.0/23
descr:          Route MHOST IDC
origin:         AS21098
mnt-by:         MHOST-MNT
source:         RIPE # Filtered

[root@lunix ~]#
</pre>
<p>Not much info other than the IP is based in Russia.  Well, anyway, I IP blocked 91.0.0.0/8 (sorry, Russia), so if you&#8217;re in that subnet you&#8217;re probably seeing a 403 now.</p>
<p><strong>Edit</strong>: It occurred to me that I can accomplish the same thing while being less draconian if I wrap the Deny in a &lt;Limit&gt;&lt;/Limit&gt; clause.  This way everyone can still see the site but certain IP ranges won&#8217;t be able to POST anything:</p>
<pre>
&lt;Limit POST PUT DELETE&gt;
Order Allow,Deny
Allow from all
Deny from 218.6.9.
Deny from 173.203.101.
Deny from 122.162.28.
Deny from 91.
Deny from 213.5
&lt;/Limit&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/08/13/blocking-comment-spammers-by-ip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LDAP-Active Directory authentication, Part 3</title>
		<link>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ldap-active-directory-authentication-part-3</link>
		<comments>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 23:12:34 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[DSID-03190F00]]></category>
		<category><![CDATA[DSID-031A0F44]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[unicodePwd]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=309</guid>
		<description><![CDATA[TweetSo I got everything working with .htaccess and AD/LDAP authentication. Just add LDAPVerifyServerCert Off to the httpd config to let Apache authenticate against an AD server with a self-signed certificate (without dealing with the annoyance of putting the cert on each Apache server). With that piece of the puzzle largely solved, I moved on to [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/&via=EvanHoffman&text=LDAP-Active Directory authentication, Part 3&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/"></g:plusone></div><p>So I got everything working with .htaccess and AD/LDAP authentication.  Just add <tt>LDAPVerifyServerCert Off</tt> to the httpd config to let Apache authenticate against an AD server with a self-signed certificate (without dealing with the annoyance of putting the cert on each Apache server).</p>
<p>With that piece of the puzzle largely solved, I moved on to another: how will users change their passwords (which are all stored in Active Directory)?  For users running Windows this is pretty trivial &#8212; they can do it right in Windows when they&#8217;re logged into the domain.  But what about Linux users?  I figured the easiest thing to do would be to make a web form to do this.  The user would login (with the http/LDAP auth I previously setup) and the form would ask for their password (twice) and update it in Active Directory.  Sounds pretty simple to me.  I think if this were OpenLDAP it probably would be, but being AD, it&#8217;s not.</p>
<p><span id="more-309"></span></p>
<p>I&#8217;d already spent an hour or two writing the script (in PHP) when I was able to test its basic functionality.  What I got was this:</p>
<pre>Warning: ldap_mod_replace() [function.ldap-mod-replace]: Modify: Insufficient access in /home/evan/public_html/authtest/index.php</pre>
<p>After some hair pulling I realized that I was binding with my &#8220;dummy&#8221; user when attempting to change the password.  I figured the solution would be to re-bind as the user whose password I was attempting to change, which is what I did.  I verified that the new bind worked, but I still couldn&#8217;t change the password.  I decided to fall back to command line and started issuing some ldapmodify commands to see what I could and couldn&#8217;t do as the user.  For whatever reason, it appears that even though the user CAN change his password in AD (the &#8220;user cannot change password&#8221; setting is NOT selected &#8212; I checked), the user cannot change his password through LDAP.</p>
<pre>
$ ldapmodify -vv -x -d8 -D "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com" -w secret -H ldaps://activedirectory.example.com -f bfett.ldif
ldap_initialize( ldaps://activedirectory.example.com )
TLS certificate verification: Error, unable to get local issuer certificate
request done: ld 0x9dd86e8 msgid 1
replace unicodePwd:
        "
modifying entry "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com"
modify complete
request done: ld 0x9dd86e8 msgid 2
ldapmodify: Insufficient access (50)
        additional info: 00000005: SecErr: DSID-031A0F44, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
</pre>
<p>I Googled for the error code &#8211; <a href="http://www.google.com/search?q=DSID-031A0F44">DSID-031A0F44</a> &#8211; and found a couple of threads about people with the same problem, but no solutions.</p>
<p>The LDIF file I fed in looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ldif" style="font-family:monospace;">dn: CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com
changetype: modify
replace: unicodePwd
unicodePwd::IgBhAGIAYwBkAGUAZgBnAGgAIgA=
-</pre></div></div>

<p>When I run the same command with my own DN/password for binding it works fine (though I did discover that you can assign multiple values to unicodePwd, meaning that, until I fixed it, the test user had <b>two valid passwords</b>, which seems like a bug on Microsoft&#8217;s part), I assume because I&#8217;m a domain admin.  An &#8220;easy&#8221; out would be simply to have the script bind as a domain admin, but that means I&#8217;d be hardcoding a Domain Admin password in the script, which I&#8217;m against.  I&#8217;ll have to put some more thought into this.  Maybe Linux users will just have to log in to a Windows workstation to change their passwords.  That&#8217;s not ideal, but it does already work.</p>
<p>Grr&#8230;</p>
<p><b>Update</b> &#8211; Click the &#8220;ldap&#8221; tag below to see all the LDAP-related posts, including the solution to changing AD passwords via a browser.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2010/01/08/ldap-active-directory-authentication-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Monitoring SSL certificate expiration with ssl-cert-check</title>
		<link>http://www.evanhoffman.com/evan/2009/08/31/monitoring-ssl-certificate-expiration-with-ssl-cert-check/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=monitoring-ssl-certificate-expiration-with-ssl-cert-check</link>
		<comments>http://www.evanhoffman.com/evan/2009/08/31/monitoring-ssl-certificate-expiration-with-ssl-cert-check/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 19:29:11 +0000</pubDate>
		<dc:creator>Evan Hoffman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[certificates]]></category>
		<category><![CDATA[ssl]]></category>

		<guid isPermaLink="false">http://www.evanhoffman.com/evan/?p=159</guid>
		<description><![CDATA[TweetI was about to write a script using OpenSSL to monitor the SSL certificate expiration dates for a few servers when it dawned on me that someone had probably done this already. The ssl-cert-check shell script takes a list of hosts/ports and prints out the expiration date (and how many days away that date is). [...]]]></description>
			<content:encoded><![CDATA[<div style="vertical-align: top; float: right; margin-left: 10px;"><a href="http://twitter.com/share?url=http://www.evanhoffman.com/evan/2009/08/31/monitoring-ssl-certificate-expiration-with-ssl-cert-check/&via=EvanHoffman&text=Monitoring SSL certificate expiration with ssl-cert-check&related=EvanHoffman:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="plus-one-wrap"><g:plusone size="small" href="http://www.evanhoffman.com/evan/2009/08/31/monitoring-ssl-certificate-expiration-with-ssl-cert-check/"></g:plusone></div><p>I was about to write a script using OpenSSL to monitor the SSL certificate expiration dates for a few servers when it dawned on me that someone had probably done this already.</p>
<p>The <a href="http://prefetch.net/articles/checkcertificate.html">ssl-cert-check</a> shell script takes a list of hosts/ports and prints out the expiration date (and how many days away that date is).  It can also be configured to email a message for any certificates expiring in less than N days for easy cronibility (?).  Seems lovely!</p>
<p><a target="_blank" href="http://affiliate.godaddy.com/redirect/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC"><img src="http://affiliate.godaddy.com/ads/5F43C3ECBA841ACFC3859F4F4E6CA7DA64C271385B2D61A3AD6F3CCE83EB1DD8235E60DCD7D63BCD92E2429E79A75FAC" border="0" width="468"  height="60" alt="Go Daddy $12.99 SSL Sale!"/></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.evanhoffman.com/evan/2009/08/31/monitoring-ssl-certificate-expiration-with-ssl-cert-check/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

