<?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>AskApache &#187; Apache</title>
	<atom:link href="http://www.askapache.com/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.askapache.com</link>
	<description>Advanced Web Development</description>
	<lastBuildDate>Thu, 19 Nov 2009 12:21:49 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Optimizing Servers and Processes for Speed with ionice, nice, ulimit</title>
		<link>http://www.askapache.com/linux-unix/optimize-nice-ionice.html</link>
		<comments>http://www.askapache.com/linux-unix/optimize-nice-ionice.html#comments</comments>
		<pubDate>Sat, 10 Oct 2009 05:41:28 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[Review]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Shell Scripting]]></category>
		<category><![CDATA[Web Hosting]]></category>
		<category><![CDATA[Webmaster]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[chrt]]></category>
		<category><![CDATA[CPU Scheduling]]></category>
		<category><![CDATA[Disk IO]]></category>
		<category><![CDATA[ionice]]></category>
		<category><![CDATA[iostat]]></category>
		<category><![CDATA[Nice]]></category>
		<category><![CDATA[optimize processes]]></category>
		<category><![CDATA[Renice]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[taskset]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3167</guid>
		<description><![CDATA[<p><a href="http://www.askapache.com/linux-unix/optimize-nice-ionice.html" class="IFL"><img src="/wp-content/uploads/2009/10/nice-chart-115x74.png" alt="NICE Levels Chart" title="NICE Levels Chart" width="115" height="74" /></a>To prepare for several upcoming articles on AskApache that are focused on optimizing Servers and Sites from a server admin level, here is an article to introduce the main tools that we will be using.  These tools are used to optimize CPU time for each process using <strong>nice</strong> and <strong>renice</strong>, and other tools like <strong>ionice</strong> are used to optimize the Disk IO, or Disk speed / Disk traffic for each process.  Then you can make sure your mysqld and httpd processes are always fast and prioritized.<br class="C" /></p> ]]></description>
			<content:encoded><![CDATA[<p>Ok, sup.  I really felt I had to get this out of the way, because I have a whole stack of drafts waiting to be published, but I realized that not many people will benefit from all the advanced optimizations and tricks I&#8217;m writing unless they get a basic understanding of some of the tools I&#8217;m using.  I decided to write a series of articles explaining how I optimize servers for speed because lately I&#8217;ve been getting a lot more people wanting to hire me to do that.  I take on projects when I can but there is clearly a need out here on the net for some self-help.   The momentum is swinging more and more towards VPS type of web hosting, and I would say that 99% of those customers are getting supremely ripped off, which goes against the foundation of the web.</p>
<p>Keep in mind that this blog and my research is only a hobby of mine, my job is primarily marketing and sales, so I&#8217;m not some licensed expert or anything, or even an unlicensed expert! haha.  But it does bother me that those who are tech-savvy enough to run web-hosting companies are happily ripping people off.  So this article details the main tools that are used to speed up and optimize your machine by delegating levels of priority to specific processes.  Future articles will use these tools alot, so this is meant as an intro.</p>
<p><a id="cpu-disk-io" name="cpu-disk-io"></a></p>
<h2>CPU and Disk I/O</h2>
<p>As most of you are aware, there are 2 variables that determine any computer or programs speed.  CPU and Disk I/O.  CPU determines how fast you can process data, crunch numbers, etc. while disk I/O determines how fast your disks can read and write data to the hard-drive.  Wouldn&#8217;t it be great if you could easily configure your server to give your httpd, php, and other processes both greater CPU processing and disk IO than your non-important processes like backup scripts, ftp daemons, etc.?  We are talking about Linux in this article, so of course YES not only can you do that, you should!</p>
<p><a name="optimize-ram" id="optimize-ram"></a></p>
<h3>RAM</h3>
<p>RAM is like a hard-drive in that data is stored on it, and read/written to it.  The difference is that RAM is somewhere around 30x faster than disk I/O, but the cost of that incredible speed is that the data stored on it is only temporary in the sense that it won&#8217;t be stored permanently, it is completely erased when your machine is rebooted.  RAM is also expensive, and there is a limit to how much a server or machine can have due to hardware limits.</p>
<p><a name="optimize-swap" id="optimize-swap"></a></p>
<h3>SWAP</h3>
<p>SWAP takes off when you run out of RAM but you still want certain data to be read/write quickly.  Basically when you start running out of RAM your machine starts supplementing RAM with SWAP storage.  SWAP is usually a partition on a second hard-drive disk.  There is an upper limit on how much I/O can occur on a disk at one time, and the more I/O takes place, the slower all I/O becomes, so SWAP works well on a separate hard-drive as it will have much faster I/O.  On Windows they opted to copy the SWAP mechanism but instead use a file named pagefile.sys, and that is just one reason people in the know do not care for Windows.</p>
<p><a name="optimize-cpu" id="optimize-cpu"></a></p>
<h3>CPU</h3>
<p>So lets do this, think of your CPU (your processor) as having an amount of 100% processing available when not being used, 0% when its maxed out.  CPU&#8217;s handle multiple processing tasks simultaneously, so what we will discuss in this article is how to specify HOW MUCH of that processing amount each of your programs (heretofore &#8220;processes&#8221;) are able to use.  Yes, very very cool.</p>
<p>That is correct, you can easily configure your server to provide more of the available processing time to certain programs over others, like you can configure apache and php to utilize 50% of your CPU processing time by themselves, so that all other processes (proftpd, sshd, rsync, etc.) combined can only utilize 50%.  The terminology is we can give certain specific processes (like php.cgi, httpd, fast-cgi.cgi) a specific <strong>priority</strong>, where -19 is the most priority, and +19 is the least amount of priority, or CPU processing time.  I know it seems backwards.. </p>
<p><a id="tools" name="tools"></a></p>
<h2>The Tools</h2>
<p>If you run Windows, you are in the right place&#8230; because the following advice will save your life:  GET LINUX! Ok, now that that is out of the way, the following are the tools dicussed on this page.  All of them are free, open-source, and wonderful.  The basic idea of these tools is to control how much CPU is devoted to each process, and also how much Disk IO/Disk traffic is given to each process.</p>
<dl>
<dt><a href="#nice-tool">nice</a></dt>
<dd>run a program with modified scheduling priority</dd>
<dt><a href="#renice-tool">renice</a></dt>
<dd>alter priority of running processes</dd>
<dt><a href="#ionice-tool">ionice</a></dt>
<dd>set or retrieve the I/O priority for a given pid or execute a new task with a given I/O priority.</dd>
<dt><a href="#iostat-tool">iostat</a></dt>
<dd>Report Central Processing Unit (CPU) statistics and input/output statistics for devices and partitions.</dd>
<dt><a href="#ulimit-tool">ulimit</a></dt>
<dd>Ulimit provides control over the resources available to processes started by the shell, on systems that allow such control.</dd>
<dt><a href="#chrt-tool">chrt</a></dt>
<dd>set or retrieve real-time scheduling parameters for a given pid or execute a new task under given scheduling parameters.</dd>
<dt><a href="#taskset-tool">taskset</a></dt>
<dd>set or retrieve task CPU affinity for a given pid or execute a new task under a given affinity mask.</dd>
<dt></dt>
<dd></dd>
</dl>
<p><a id="part1-processes" name="part1-processes"></a></p>
<h2>Part 1: Process Processes Faster</h2>
<p>Ok so lets tackle figuring out how to give your response-intensive processes (like apache, php, ruby, perl, java) meaning a request to your server/machine requires a <em>response</em>.  For instance, when you requested this page that you are reading at this very second, several things on my server had to happen for you to be able to read this.</p>
<p>First your computer sends out a request to see what server the www.askapache.com domain name is.  DNS servers respond with my server IP, so for servers dedicated as nameservers, optimizing the DNS processes like bind would speed that up.  Now that your computer knows how to reach my server it sends an HTTP GET request for this url.  This request is received by the httpd process that is apache, and apache determines this url should be handled by my custom compiled php5.3.0 binary, because this page is WordPress generated.  So the php binary loads up the WordPress /index.php file, which chain-loads several other php files, including <code>wp-config.php</code> containing my MySql database settings.  Now php connects to my MySql Server to fetch this articles content, comments, title, tags, etc. and then generates the HTML and hands that back to Apache.</p>
<p>Finally, Apache generates a HTTP RESPONSE and sends the RESPONSE and CONTENT back to your Browser, which then in turn renders the page for your eyes with the necessary javascript, images, css, and other files included in the HTML response.</p>
<h3>Too much Processing</h3>
<p>Now you see why I&#8217;ve opted to write my own caching plugin that takes the php and mysql processes OUT of that equation.  Both the php binary and the mysql instance consume CPU processing, and disk IO, to load all their library files, make various network requests and sockets, check permissions, and on and on.  And that&#8217;s completely ok, the thing is, unless you configure these processes (Apache, PHP, MySQL) they will use the same amount of CPU processing that other processes use, other processes that have very little to do with you reading this sentence.  Processes to run my mail server, my FTP server, my SSH server, my cronjobs, cleanup scripts, atd daemon, etc.. and they will get the same amount of CPU!</p>
<p>Another even simpler example is what got me to look into this myself.  I wrote a shell script that created hourly, daily, weekly, and monthly backups for all of my websites and sql databases, and set it up to run by cronjob at those set intervals.  Eventually I noticed my sites were slower, my php even slower, and sometimes I even saw 503 errors that my host throws up when my server is overloaded.  The research that I pursued to prevent that from happening has been hugely eye-opening.  What does a backup script do?  Mine just created tar archives of all the files in my web root, then gzipped the tar archive saving to a backup server using scp (a file transfer using ssh).  This resulted in the following huge problems that seem to have nothing to do with a faster server and speedier website, but they have everything to with it.</p>
<ol>
<li><strong>CPU Bottleneck #1</strong> &#8211; tar and gzip use compression algorithms at a low level to create a compressed version, and all that compressing uses a whole lot of crunching &#8211; CPU processing</li>
<li><strong>DISK IO Bottleneck</strong> &#8211; Tarring the whole web root directory was creating a ton of disk io, and remember the more disk io that is going on, the less is available for everything else.</li>
<li><strong>CPU Bottleneck #2</strong> &#8211; Using scp to send my backups was security-smart, but these huge archive files had to be encrypted and sent over the net.</li>
</ol>
<p><a id="breaking-bottlenecks" name="breaking-bottlenecks"></a></p>
<h2>Breaking Bottles</h2>
<p>I apologize for being a little long-winded there, but I think it&#8217;s important to make sure everyone understands those basic concepts, which are foreign to most people.  Once you understand what is causing the bottlenecks, then you can understand the solutions, which actually are incredibly simple and even a novice linux user can easily do.  Besides, the net gets a little bit faster every time someone implements this.</p>
<p><a id="nice-tool" name="nice-tool"></a></p>
<h3>nice</h3>
<p><img src="/wp-content/uploads/2009/10/nice-chart.png" alt="NICE Levels Chart" title="NICE Levels Chart" width="351" height="225" class="IFL" />Nice allows you to run a program with modified scheduling priority which specifies how much CPU is devoted to a particular process.  Run COMMAND with an adjusted niceness, which affects process scheduling.  With no COMMAND, print the current niceness.  </p>
<p>Nicenesses range from -20 (most favorable scheduling) to 19 (least favorable).   <code>-n, &#45;-adjustment=N</code> &#8211;  add integer N to the niceness (default 10).   <code>nice +19</code> tasks get a HZ-independent 1.5%.  Running a <code>nice +10</code> and a <code>nice +11</code> task means the first will get 55% of the CPU, the other 45%.<br class="C" /></p>
<p><a id="nice-usage" name="nice-usage"></a></p>
<h4>nice usage</h4>
<pre>nice [OPTION] [COMMAND [ARG]&#46;..]
&nbsp;
-n, &#45;-adjustment=ADJUST   increment priority by ADJUST first</pre>
<p><a id="nice-examples" name="nice-examples"></a></p>
<h4>Examples of nice</h4>
<p>Using nice to download a file</p>
<pre>nice -n 17 curl -q -v -A &#039;Mozilla/5.0&#039; -L -O http://wordpress.org/latest.zip</pre>
<p>Unzipping a file with nice</p>
<pre>nice -n 17 unzip latest.zip</pre>
<p>Nice way to build from source</p>
<pre>nice -n 2 ./configure
nice -n 2 make
nice -n 2 make install</pre>
<p>It is sometimes useful to run non-interactive programs with reduced priority.</p>
<pre>$ nice factor `echo &#039;2^9 - 1&#039;|bc`
511: 7 73</pre>
<p>Since nice prints the current priority, we can invoke it through itself to demonstrate how it works: The default behavior is to reduce priority by 10.</p>
<pre> $ nice nice
10
$ nice -n 10 nice
10</pre>
<p> The ADJUSTMENT is relative to the current priority.  The first <code>nice</code> invocation runs the second one at priority 10, and it in turn runs the final one at a priority lowered by 3 more.</p>
<pre>$ nice nice -n 3 nice
13</pre>
<p>Specifying a priority larger than 19 is the same as specifying 19.</p>
<pre>$ nice -n 30 nice
19</pre>
<p>Only a privileged user may run a process with higher priority.</p>
<pre>$ nice -n -1 nice
nice: cannot set priority: Permission denied
$ sudo nice -n -1 nice
-1</pre>
<blockquote cite="/wp-content/uploads/2009/08/sched-nice-design.txt">
<p>The new scheduler in v2.6.23 addresses all three types of complaints:</p>
<p>To address the first complaint (of nice levels being not &#8220;punchy&#8221; enough), the scheduler was decoupled from &#8216;time slice&#8217; and HZ concepts (and granularity was made a separate concept from nice levels) and thus it was possible to implement better and more consistent nice +19 support: with the new scheduler nice +19 tasks get a HZ-independent 1.5%, instead of the variable 3%-5%-9% range they got in the old scheduler.</p>
<p>To address the second complaint (of nice levels not being consistent), the new scheduler makes nice(1) have the same CPU utilization effect on tasks, regardless of their absolute nice levels. So on the new scheduler, running a nice +10 and a nice 11 task has the same CPU utilization &#8220;split&#8221; between them as running a nice -5 and a nice -4 task. (one will get 55% of the CPU, the other 45%.) That is why nice levels were changed to be &#8220;multiplicative&#8221; (or exponential) &#8211; that way it does not matter which nice level you start out from, the &#8216;relative result&#8217; will always be the same.</p>
<p>The third complaint (of negative nice levels not being &#8220;punchy&#8221; enough and forcing audio apps to run under the more dangerous SCHED_FIFO scheduling policy) is addressed by the new scheduler almost automatically: stronger negative nice levels are an automatic side-effect of the recalibrated dynamic range of nice levels.</p>
</blockquote>
<p><a id="renice-tool" name="renice-tool"></a></p>
<h3>renice</h3>
<p>Renice is similar to the nice command, but it lets you modify the nice of a currently running process.  This is nice for shell scripts where you can add this to the top of the script to nicify the whole script to 19.</p>
<p><a id="renice-usage" name="renice-usage"></a></p>
<h4>renice usage</h4>
<pre>renice priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ]
&nbsp;
-g      Force who parameters to be interpreted as process group ID&#039;s.
-u      Force the who parameters to be interpreted as user names.
-p      Resets the who interpretation to be (the default) process ID&#039;s.</pre>
<p><a id="renice-examples" name="renice-examples"></a></p>
<h4>Examples of renice</h4>
<p>From the shell, changes the priority of the shell and all children to 19.  From a shell script, does the same but only for the script and its children.</p>
<pre>renice 19 -p $$</pre>
<p>This runs renice without any output</p>
<pre>renice 19 -p $$ &&gt;/dev/null</pre>
<p>10 gets more CPU than 19</p>
<pre>renice 10 -p $$</pre>
<p>change the priority of process ID&#8217;s 987 and 32, and all processes owned by users daemon and root.</p>
<pre>renice +1 987 -u daemon root -p 32</pre>
<p><a id="part2-disk-io" name="part2-disk-io"></a></p>
<h2>Part 2: Optimizing Disk I/O</h2>
<p><a id="scheduling-policies" name="scheduling-policies"></a></p>
<h3>Linux Scheduling Policies</h3>
<p>The scheduler is the kernel component that decides which runnable process will be executed by the CPU next.  Each process has an associated scheduling policy and a static scheduling priority, sched_priority</p>
<p>Processes scheduled under one of the real-time policies (SCHED_FIFO, SCHED_RR) have a sched_priority value in the <strong>range 1 (low) to 99 (high)</strong>.  (As the numbers imply, real-time processes always have higher priority than normal processes.)   The following &#8220;real-time&#8221; policies are also supported, for special time-critical applications that need precise control over the way in which runnable processes are selected for execution:</p>
<p>Currently, Linux supports the following &#8220;normal&#8221; (i.e., non-real-time) scheduling policies:</p>
<dl>
<dt><strong>SCHED_OTHER</strong>: Default Linux time-sharing scheduling</dt>
<dd>The standard round-robin time-sharing policy</dd>
<dt><strong>SCHED_BATCH</strong>: Scheduling batch processes</dt>
<dd>This policy is useful for workloads that are non-interactive, but do not want to lower their nice value, and for workloads that want a deterministic scheduling policy without interactivity causing extra preemptions (between the workload&#8217;s tasks).</dd>
<dt><strong>SCHED_IDLE</strong>: Scheduling very low priority jobs</dt>
<dd>This policy is intended for running jobs at extremely low priority (lower even than a +19 nice value with the SCHED_OTHER or SCHED_BATCH policies)</dd>
<dt><strong>SCHED_FIFO</strong>: First In-First Out scheduling</dt>
<dd>A first-in, first-out policy</dd>
<dt><strong>SCHED_RR</strong>: Round Robin scheduling</dt>
<dd>A round-robin policy.</dd>
</dl>
<p><a id="scheduling-classes" name="scheduling-classes"></a></p>
<h3>Scheduling Classes</h3>
<dl>
<dt><code>IOPRIO_CLASS_RT</code></dt>
<dd>This is the realtime io class. The RT scheduling class is given first access to the disk, regardless of what else is going on in the system. Thus the RT class needs to be used with some care, as it can starve other processes. As with the best effort class, 8 priority levels are defined denoting how big a time slice a given process will receive on each scheduling window.  This scheduling class is given higher priority than any other in the system, processes from this class are given first access to the disk every time. Thus it needs to be used with some care, one io RT process can starve the entire system. Within the RT class, there are 8 levels of class data that determine exactly how much time this process needs the disk for on each service. In the future this might change to be more directly mappable to performance, by passing in a wanted data rate instead.</dd>
<dt><code>IOPRIO_CLASS_BE</code></dt>
<dd>This is the best-effort scheduling class, which is the default for any process that hasn&#8217;t set a specific io priority. This is the default scheduling class for any process that hasn&#8217;t asked for a specific io priority. Programs inherit the CPU nice setting for io priorities. This class takes a priority argument from 0-7, with lower number being higher priority. Programs running at the same best effort priority are served in a round-robin fashion.  The class data determines how much io bandwidth the process will get, it&#8217;s directly mappable to the cpu nice levels just more coarsely implemented. 0 is the highest BE prio level, 7 is the lowest. The mapping between cpu nice level and io nice level is determined as: io_nice = (cpu_nice + 20) / 5.</dd>
<dt><code>IOPRIO_CLASS_IDLE</code></dt>
<dd>This is the idle scheduling class, processes running at this level only get io time when no one else needs the disk. A program running with idle io priority will only get disk time when no other program has asked for disk io for a defined grace period. The impact of idle io processes on normal system activity should be zero. This scheduling class does not take a priority argument.    The idle class has no class data, since it doesn&#8217;t really apply here.</dd>
</dl>
<p><a id="ionice-tool" name="ionice-tool"></a></p>
<h3>ionice</h3>
<p>ionice &#8211; get/set program io scheduling class and priority.  This program sets the io scheduling class and priority for a program.  Since v3 (aka CFQ Time Sliced) CFQ implements I/O nice levels similar to those of CPU scheduling. These nice levels are grouped in three scheduling classes each one containing one or more priority levels:</p>
<p><a id="ionice-usage" name="ionice-usage"></a></p>
<h4>ionice usage</h4>
<p>If no arguments or just -p is given, ionice will query the current io scheduling class and priority for that process.</p>
<pre>ionice [-c] [-n] [-p] [COMMAND [ARG&#46;..]]</pre>
<ul>
<li><strong>-c</strong> &#8211; The scheduling class. 1 for real time, 2 for best-effort, 3 for idle.</li>
<li><strong>-n</strong> &#8211; The scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data.</li>
<li><strong>-p</strong> &#8211; Pass in a process pid to change an already running process. If this argument is not given, ionice will run the listed program with the given parameters.</li>
</ul>
<p><a id="ionice-examples" name="ionice-examples"></a></p>
<h4>ionice Examples</h4>
<p>Sets process with PID 89 as an idle io process.</p>
<pre>ionice -c3 -p89</pre>
<p>Runs &#8216;bash&#8217; as a best-effort program with highest priority.</p>
<pre>ionice -c2 -n0 bash</pre>
<p>Returns the class and priority of the process with PID 89</p>
<pre>ionice -p89</pre>
<blockquote cite="http://gaarai.com/2009/03/06/multitasking-from-the-linux-command-line-plus-process-prioritization/">
<p>
<p>With the ionice command, you can set the IO priority for a process to one of three classes: Idle (3), Best Effort (2), and Real Time (1). The Idle class means that the process will only be able to read and write to the disk when all other processes are not using the disk. The Best Effort class is the default and has eight different priority levels from 0 (top priority) to 7 (lowest priority). The Real Time class results in the process having first access to the disk irregardless of other process and should never be used unless you know what you are doing.</p>
<p>If we wish to run the updatedb process in the background with an Idle IO class priority, we can run the following:</p>
<pre>
$ sudo date
$ sudo updatedb &#038;
[1] 16324
$ sudo ionice -c3 -p16324
</pre>
<p>If we’d rather just lower the Best Effort class priority (defaults to 4) for the command so the process isn’t limited to idle IO periods, we can run the following:</p>
<pre>
$ sudo date
$ sudo updatedb &#038;
[1] 16324
$ sudo ionice -c2 -n7 -p16324
</pre>
<p>Again, the Real Time class should not be used as it can prevent you from being able to interact with your system.</p>
<p>You may wonder where you can get the process ID if you don’t know it, can’t remember it, or didn’t start the process (an automatted script may have launched it). You can find process IDs with the ps command.</p>
<p>For example, if I had an updatedb program running in the background, and I wanted to find its process ID, I can run the following:</p>
<pre>
$ ps -C updatedb
PID TTY TIME CMD
4234 ? 00:00:42 updatedb
</pre>
<p>This tells me that the process’ process ID (PID) is 4234.</p>
</p>
</blockquote>
<p><a id="iostat-tool" name="iostat-tool"></a></p>
<h3>iostat</h3>
<p><a id="iostat-usage" name="iostat-usage"></a></p>
<h4>iostat Usage</h4>
<pre>iostat [ -c ] [ -d ] [ -N ] [ -n ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ] [ &lt;device&gt; [&#46;..] | ALL ] [ -p [ &lt;device&gt; [,&#46;..] | ALL ] ] [ &lt;interval&gt; [ &lt;count&gt; ] ]

-c     The -c option is exclusive of the -d option and displays only the CPU usage report.
-d     The -d option is exclusive of the -c option and displays only the device utilization report.
-k     Display statistics in kilobytes per second instead of blocks per second.  Data displayed are valid only with kernels 2.4 and newer.
-m     Display statistics in megabytes per second instead of blocks or kilobytes per second.  Data displayed are valid only with kernels 2.4 and newer.
-n     Displays the NFS-directory statistic.  Data displayed are valid only with kernels 2.6.17 and newer.  This option is exclusive ot the -x option.
-h     Display the NFS report more human readable.
-p [ { device | ALL } ]   The  -p  option  is  exclusive  of  the -x option and displays statistics for block devices and all their partitions that are used by the system.
-t     Print the time for each report displayed.
-x     Display extended statistics.
</pre>
<p><a id="iostat-examples" name="iostat-examples"></a></p>
<h4>iostat Examples</h4>
<pre>iostat -p ALL 2 1000
avg-cpu:  %user   %nice    %sys %iowait   %idle
            8.34    0.08    1.26    2.27   88.05
</pre>
<p>Display a single history since boot report for all CPU and Devices.</p>
<pre>$ iostat</pre>
<p>Display a continuous device report at two second intervals.</p>
<pre>$ iostat -d 2</pre>
<p>Display six reports at two second intervals for all devices.</p>
<pre>$ iostat -d 2 6</pre>
<p>Display six reports of extended statistics at two second intervals for devices hda and hdb.</p>
<pre>$ iostat -x hda hdb 2 6</pre>
<p>Display six reports at two second intervals for device sda and all its partitions (sda1, etc.)</p>
<pre>$ iostat -p sda 2 6</pre>
<p><a id="schedule-utils" name="schedule-utils"></a></p>
<h2>Schedule Utils</h2>
<p>These are the Linux scheduler utilities &#8211; schedutils for short.  These programs take advantage of the scheduler family of syscalls that Linux implements across various kernels.  These system calls implement interfaces for scheduler-related parameters such as CPU affinity and real-time attributes.  The standard UNIX utilities do not provide support for these interfaces &#8212; thus this package.</p>
<p>The programs that are included in this package are chrt and taskset.  Together with nice and renice (not included), they allow full control of process scheduling parameters.  Suggestions for related utilities are welcome, although it is believed (barring new interfaces) that all scheduling interfaces are covered.</p>
<p>I&#8217;ve found that quite a few servers do not have this package installed, indicating to you that they might not know what they are doing.  Here is how you can install this incredible package, for non-root users.  Root users know how to do this, or they shouldn&#8217;t be root.  Download and install in 1 line provided you have curl.  Or just use the following commands.</p>
<pre>mkdir -pv $HOME/{dist,source,bin,share/man/man1} &#038;&#038; cd ~/dist &#038;&#038; curl -O http://ftp.de.debian.org/debian/pool/main/s/schedutils/schedutils_1.5.0.orig.tar.gz &#038;&#038; cd ~/source &#038;&#038; tar -xvzf ~/dist/sch*z &#038;&#038; cd sch* &#038;&#038; sed -i -e &#039;s,= /usr/local,=${HOME},g&#039; Makefile &#038;&#038; make &#038;&#038; make install &#038;&#038; make installdoc</pre>
<pre>
mkdir -pv $HOME/{dist,source,bin,share/man/man1}
cd ~/dist &#038;&#038; curl -O http://ftp.de.debian.org/debian/pool/main/s/schedutils/schedutils_1.5.0.orig.tar.gz
cd ~/source &#038;&#038; tar -xvzf ~/dist/schedutils_1.5.0.orig.tar.gz
cd ~/source/schedutils-1.5.0 &#038;&#038; sed -i -e &#039;s,= /usr/local,=${HOME},g&#039; Makefile
make || make -d &#038;&#038; make install || make install -d &#038;&#038; make installdoc || make installdoc -d
</pre>
<p><a id="taskset-tool" name="taskset-tool"></a></p>
<h3>taskset</h3>
<p>Taskset  is  used to set or retrieve the CPU affinity of a running process given its PID or to launch a new COMMAND with a given CPU affinity.  CPU affinity is a scheduler property that &#8220;bonds&#8221; a process to a given set of CPUs on the system.  The Linux scheduler will honor the given CPU affinity and the process will not run on any other CPUs.  Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practical for performance reasons.  Therefore, forcing a specific CPU affinity is useful only in certain applications.</p>
<p>The  CPU  affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corresponding to the last logical CPU.  Not all CPUs may exist on a given system but a mask may specify more CPUs than are present.  A retrieved mask will reflect only the bits that correspond to CPUs physically on the system.  If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned.  A user must possess CAP_SYS_NICE to change the CPU affinity of a process.  Any user can retrieve the affinity mask.</p>
<p><a id="taskset-usage" name="taskset-usage"></a></p>
<h4>taskset Usage</h4>
<pre>taskset [options] [mask | cpu-list] [pid | cmd [args&#46;..]]
&nbsp;
-p, &#45;-pid            operate on existing given pid
-c, &#45;-cpu-list     display and specify cpus in list format</pre>
<p><a id="taskset-examples" name="taskset-examples"></a></p>
<h4>taskset-examples</h4>
<p>The default behavior is to run a new command:</p>
<pre>$ taskset 03 sshd -b 1024</pre>
<p>You can retrieve the mask of an existing task or set it:</p>
<pre>$ taskset -p 700
$ taskset -p 03 700</pre>
<p>List format uses a comma-separated list instead of a mask:</p>
<pre>$ taskset -pc 0,3,7-11 700</pre>
<p><a id="chrt-tool" name="chrt-tool"></a></p>
<h3>chrt</h3>
<p><code>chrt</code> sets or retrieves the real-time scheduling attributes of an existing PID or runs COMMAND with the given attributes.  Both policy (one of <code>SCHED_FIFO</code>, <code>SCHED_RR</code>, or <code>SCHED_OTHER</code>) and priority can be set and retrieved.  A user must possess CAP_SYS_NICE to change the scheduling attributes of a process.  Any user can retrieve the scheduling information.</p>
<p><a id="chrt-usage" name="chrt-usage"></a></p>
<h4>chrt Usage</h4>
<pre>chrt [options] [prio] [pid | cmd [args&#46;..]]
&nbsp;
-p, &#45;-pid operate on an existing PID and do not launch a new task
-f, &#45;-fifo set scheduling policy to SCHED_FIFO
-m, &#45;-max show minimum and maximum valid priorities, then exit
-o, &#45;-other set policy scheduling policy to SCHED_OTHER
-r, &#45;-rr set scheduling policy to SCHED_RR (the default)
</pre>
<p><a id="chrt-examples" name="chrt-examples"></a></p>
<h4>chrt Examples</h4>
<p>The default behavior is to run a new command:   <code>chrt [prio] &#45;- [command] [arguments]</code></p>
<p>You can also retrieve the real-time attributes of an existing task:</p>
<pre>chrt -p [pid]</pre>
<p>Or set them:</p>
<pre>chrt -p [prio] [pid]</pre>
<p><a id="ulimit-tool" name="ulimit-tool"></a></p>
<h2>ulimit &#8211; get and set user limits</h2>
<p>Ulimit provides control over the resources available to processes started by the shell, on systems that allow such control. One can set the resource limits of the shell using the built-in ulimit command.  The shell&#8217;s resource limits are inherited by the processes that it creates to execute commands.</p>
<p><a id="ulimit-usage" name="ulimit-usage"></a></p>
<h4>ulimit Usage</h4>
<pre>ulimit [-SHacdfilmnpqstuvx] [limit]</pre>
<dl>
<dt>-S</dt>
<dd>use the `soft&#8217; resource limit</dd>
<dt>-H</dt>
<dd>use the `hard&#8217; resource limit</dd>
<dt>-a</dt>
<dd>all current limits are reported</dd>
<dt>-c</dt>
<dd>the maximum size of core files created</dd>
<dt>-d</dt>
<dd>the maximum size of a process&#8217;s data segment</dd>
<dt>-f</dt>
<dd>the maximum size of files created by the shell</dd>
<dt>-l</dt>
<dd>the maximum size a process may lock into memory</dd>
<dt>-m</dt>
<dd>the maximum resident set size</dd>
<dt>-n</dt>
<dd>the maximum number of open file descriptors</dd>
<dt>-p</dt>
<dd>the pipe buffer size</dd>
<dt>-s</dt>
<dd>the maximum stack size</dd>
<dt>-t</dt>
<dd>the maximum amount of cpu time in seconds</dd>
<dt>-u</dt>
<dd>the maximum number of user processes</dd>
<dt>-v</dt>
<dd>the size of virtual memory</dd>
</dl>
<p>If LIMIT is given, it is the new value of the specified resource; the special LIMIT values `soft&#8217;, `hard&#8217;, and `unlimited&#8217; stand for the current soft limit, the current hard limit, and no limit, respectively.  Otherwise, the current value of the specified resource is printed.  If no option is given, then -f is assumed.  Values are in 1024-byte increments, except for -t, which is in seconds, -p, which is in increments of 512 bytes, and -u, which is an unscaled number of processes.</p>
<dl>
<dt>RLIMIT_AS</dt>
<dd>The maximum size of the process&#8217;s virtual memory (address space) in bytes.  This limit affects calls to brk(2), mmap(2) and mremap(2), which fail with the error ENOMEM upon exceeding this limit.  Also automatic stack expansion will fail (and generate a SIGSEGV that kills the process if no alternate stack has been made available via sigaltstack(2)).  Since the value is a long, on machines with a 32-bit long either this limit is at most 2 GiB, or this resource is unlimited.</dd>
<dt>RLIMIT_CORE</dt>
<dd>Maximum size of core file.  When 0 no core dump files are created. When non-zero, larger dumps are truncated to this size.</dd>
<dt>RLIMIT_CPU CPU</dt>
<dd>time limit in seconds.  When the process reaches the soft limit, it is sent a SIGXCPU signal.  The default action for this signal is to terminate the process.  However, the signal can be caught, and the handler can return control to the main program.  If the process continues to consume CPU time, it will be sent SIGXCPU once per second until the hard limit is reached, at which time it is sent SIGKILL. (This latter point describes Linux 2.2 through 2.6 behavior. Implementations vary in how they treat processes which continue to consume CPU time after reaching the soft limit.  Portable applications that need to catch this signal should perform an orderly termination upon first receipt of SIGXCPU.)</dd>
<dt>RLIMIT_DATA</dt>
<dd>The maximum size of the process&#8217;s data segment (initialized data, uninitialized data, and heap).  This limit affects calls to brk(2) and sbrk(2), which fail with the error ENOMEM upon encountering the soft limit of this resource.</dd>
<dt>RLIMIT_FSIZE</dt>
<dd>The maximum size of files that the process may create.  Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. By default, this signal terminates a process, but a process can catch this signal instead, in which case the relevant system call (e.g., write(2), truncate(2)) fails with the error EFBIG.</dd>
<dt>RLIMIT_LOCKS</dt>
<dd>(Early Linux 2.4 only) A limit on the combined number of flock(2) locks and fcntl(2) leases that this process may establish.</dd>
<dt>RLIMIT_MEMLOCK</dt>
<dd>The maximum number of bytes of memory that may be locked into RAM.  In effect this limit is rounded down to the nearest multiple of the system page size.  This limit affects mlock(2) and mlockall(2) and the mmap(2) MAP_LOCKED operation.  Since Linux 2.6.9 it also affects the shmctl(2) SHM_LOCK operation, where it sets a maximum on the total bytes in shared memory segments (see shmget(2)) that may be locked by the real user ID of the calling process.  The shmctl(2) SHM_LOCK locks are accounted for separately from the per-process memory locks established by mlock(2), mlockall(2), and mmap(2) MAP_LOCKED; a process can lock bytes up to this limit in each of these two categories.  In Linux kernels before 2.6.9, this limit controlled the amount of memory that could be locked by a privileged process.  Since Linux 2.6.9, no limits are placed on the amount of memory that a privileged process may lock, and this limit instead governs the amount of memory that an unprivileged process may lock.</dd>
<dt>RLIMIT_MSGQUEUE</dt>
<dd>(Since Linux 2.6.8) Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process.  This limit is enforced for mq_open(3).  Each message queue that the user creates counts (until it is removed) against this limit according to the formula:  <code>bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +             attr.mq_maxmsg * attr.mq_msgsize</code> where attr is the mq_attr structure specified as the fourth argument to mq_open(3).  The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead).</dd>
<dt>RLIMIT_NICE</dt>
<dd>(since Linux 2.6.12, but see BUGS below) Specifies a ceiling to which the process&#8217;s nice value can be raised using setpriority(2) or nice(2).  The actual ceiling for the nice value is calculated as 20 &#8211; rlim_cur.  (This strangeness occurs because negative numbers cannot be specified as resource limit values, since they typically have special meanings.  For example, RLIM_INFINITY typically is the same as -1.)</dd>
<dt>RLIMIT_NOFILE</dt>
<dd>Specifies a value one greater than the maximum file descriptor number that can be opened by this process.  Attempts (open(2), pipe(2), dup(2), etc.)  to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.)</dd>
<dt>RLIMIT_NPROC</dt>
<dd>The maximum number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of the calling process.  Upon encountering this limit, fork(2) fails with the error EAGAIN.</dd>
<dt>RLIMIT_RSS</dt>
<dd>Specifies the limit (in pages) of the process&#8217;s resident set (the number of virtual pages resident in RAM).  This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.</dd>
<dt>RLIMIT_RTPRIO</dt>
<dd>(Since Linux 2.6.12, but see BUGS) Specifies a ceiling on the real-time priority that may be set for this process using sched_setscheduler(2) and sched_setparam(2).</dd>
<dt>RLIMIT_RTTIME</dt>
<dd>(Since Linux 2.6.25) Specifies a limit on the amount of CPU time that a process scheduled under a real-time scheduling policy may consume without making a blocking system call.  For the purpose of this limit, each time a process makes a blocking system call, the count of its consumed CPU time is reset to zero.  The CPU time count is not reset if the process continues trying to use the CPU but is preempted, its time slice expires, or it calls sched_yield(2). Upon reaching the soft limit, the process is sent a SIGXCPU signal.  If the process catches or ignores this signal and continues consuming CPU time, then SIGXCPU will be generated once each second until the hard limit is reached, at which point the process is sent a SIGKILL signal.  The intended use of this limit is to stop a runaway real-time process from locking up the system.</dd>
<dt>RLIMIT_SIGPENDING</dt>
<dd>(Since Linux 2.6.8) Specifies the limit on the number of signals that may be queued for the real user ID of the calling process.  Both standard and real-time signals are counted for the purpose of checking this limit.  However, the limit is only enforced for sigqueue(2); it is always possible to use kill(2) to queue one instance of any of the signals that are not already queued to the process.</dd>
<dt>RLIMIT_STACK</dt>
<dd>The maximum size of the process stack, in bytes.  Upon reaching this limit, a SIGSEGV signal is generated.  To handle this signal, a process must employ an alternate signal stack (sigaltstack(2)).</dd>
</dl>
<p><a id="ulimit-examples" name="ulimit-examples"></a></p>
<h4>ulimit Examples</h4>
<p>Turn off core dumps</p>
<pre>ulimit -S -c 0</pre>
<h2>More Reading</h2>
<ul>
<li>Please see the <a href="http://pagesperso-orange.fr/sebastien.godard/">SYSSTAT Utilities Home for more performance monitoring tools</a> like sar, sadf, mpstat, iostat, pidstat and sa tools.</li>
<li><a href="http://gaarai.com/2009/03/06/multitasking-from-the-linux-command-line-plus-process-prioritization/">Multitasking from the Linux Command Line + Process Prioritization</a></li>
</ul>
<h2>Man Pages</h2>
<ol>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/sched_setscheduler.2.html">sched_setscheduler</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man7/cpuset.7.html">cpuset</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html">signal</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html">getrlimit</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man3/ulimit.3.html">ulimit</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/ioprio_get.2.html">ioprio_get</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/ioprio_set.2.html">ioprio_set</a></li>
</ol>
<h2>Kernel Documentation</h2>
<ul>
<li><a href='/wp-content/uploads/2009/08/sched-stats.txt'>information on schedstats (Linux Scheduler Statistics)</a></li>
<li><a href='/wp-content/uploads/2009/08/sched-rt-group.txt'>real-time group scheduling</a></li>
<li><a href='/wp-content/uploads/2009/08/sched-nice-design.txt'>How and why the scheduler&#8217;s nice levels are implemented</a></li>
<li><a href='/wp-content/uploads/2009/08/sched-domains.txt'>information on scheduling domains</a></li>
<li><a href='/wp-content/uploads/2009/08/sched-design-CFS.txt'>goals, design and implementation of the Complete Fair Scheduler</a></li>
</ul>
<h2>Future Discussions:</h2>
<p><a href="http://www.cuddletech.com/blog/pivot/entry.php?id=820">IO Benchmarking: How, Why and With What</a></p>
<p><a href="http://www.askapache.com/linux-unix/optimize-nice-ionice.html">Optimizing Servers and Processes for Speed with ionice, nice, ulimit</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/linux-unix/optimize-nice-ionice.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Protecting Files with Advanced Mod_Rewrite Anti-Hotlinking</title>
		<link>http://www.askapache.com/htaccess/anti-hotlinking-mod_rewrite.html</link>
		<comments>http://www.askapache.com/htaccess/anti-hotlinking-mod_rewrite.html#comments</comments>
		<pubDate>Wed, 16 Sep 2009 05:09:11 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Modules]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Webmaster]]></category>
		<category><![CDATA[htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3287</guid>
		<description><![CDATA[<p><a class="IFL" href="http://www.askapache.com/htaccess/anti-hotlinking-mod_rewrite.html "><img src="/wp-content/uploads/2009/09/866310_predestrian_lights-71x116.jpg" alt="Stop hotlinking with .htaccess mod_rewrite" title="Stop hotlinking with .htaccess mod_rewrite" width="71" height="116" /></a>If you have files on your site that you don't want indexed by malicious search engines, grabbed and leeched by malicious spammers, or stolen and made available elsewhere, you can use mod_rewrite to drastically reduce or totally reduce that activity.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a class="IFL" href="/wp-content/uploads/2009/09/866310_predestrian_lights.jpg"><img src="/wp-content/uploads/2009/09/866310_predestrian_lights.jpg" alt="Stop hotlinking with .htaccess mod_rewrite" title="Stop hotlinking with .htaccess mod_rewrite" width="184" height="300" class="size-full wp-image-3288" /></a><br style="padding-top:2em;" /><br />If you have files on your site that you don&#8217;t want indexed by malicious search engines, grabbed and leeched by malicious spammers, or stolen and made available elsewhere, you can use mod_rewrite to drastically reduce or totally reduce that activity.</p>
<h2>The Worst Kind of People</h2>
<p><strong>Spammers, and Leechers</strong>.  They operate like this:  Let&#8217;s say you have some mp3 files on a server, and SOMEWHERE on the web there is a link to that mp3 file&#8217;s location.  This includes in javascript files, css files, robots.txt files, the spammers and leechers robots check all those files looking for the type of link they are looking for.   Then they try to request that file usually utilizing a number of different types of requests to get access to the file.  Then they use it for personal gain, at your peril.</p>
<p>Some robots perform valuable services for the world wide web community, and other leeching programming is pretty cool, so not all these activities are perpetrated by nefarious spammers.</p>
<p><br class="C" /></p>
<h2>Blocking by IP COOKIE</h2>
<p>Ok so if a link exists to your file, it is going to be requested by a robot eventually, so the way to defeat them is by doing something on your site that modifies the way a user would request it.  Robots for the most part are not javascript-capable, so the most-common advanced method is to set a cookie using javascript, and then we can check for that cookie in the request for the file using mod_rewrite.</p>
<p>So if your site sets a cookie named fspammers, and furthermore gives that cookie a value of 445, then this is what the request sent by an HTTP Client like Firefox looks like.</p>
<pre>
GET /hotlink/lovefreedom.mp3 HTTP/1.1
Host: z.askapache.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://www.askapache.com/wordpress/seo-in-wordpress.html
Cookie: fspammers=455
</pre>
<h2>Mod_Rewrite HTTP Headers</h2>
<p>The mod_rewrite module has access to ALL the HTTP Headers sent in a request, so for each of the HTTP Headers in the request example above, we can use mod_rewrite to validate.</p>
<h2>Mod_Rewrite .htaccess Example</h2>
<p>Finally, now that everyone is on the same page about what is really going on, here is the <a href="http://www.askapache.com/htaccess/htaccess.html" title=".htaccess tutorial">.htaccess</a> code that blocks any requests for anything in the /hotlink/ folder.</p>
<p>Here are the triggers this code blocks access based on.</p>
<ol>
<li><strong>Cookie</strong>: Checks if fspammers cookie is present, and that it has the value of 445. </li>
<li><strong>HTTP Protocol</strong>: Checks if HTTP 1.1 is being used (many robots use 1.0)</li>
<li><strong>Host</strong>: Checks that the HOST Requested was z.askapache.com</li>
<li><strong>Referer</strong>:  Checks for Referring site is z.askapache.com or www.askapache.com</li>
</ol>
<pre>
RewriteEngine On
RewriteBase /
&nbsp;
RewriteCond %{HTTP_COOKIE} !^.*fspammers=445.*$ [NC,OR]
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ /(.*)\ HTTP/1\.1 [NC,OR]
RewriteCond %{HTTP_HOST} !^z\.askapache\.com$ [NC,OR]
RewriteCond %{HTTP_REFERER} !^http://(www|z)\.askapache\.com.*$ [NC]
RewriteRule ^hotlink/.*$ - [F]&lt;/p&gt;
</pre>
<p><a href="http://www.askapache.com/htaccess/anti-hotlinking-mod_rewrite.html">Protecting Files with Advanced Mod_Rewrite Anti-Hotlinking</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/anti-hotlinking-mod_rewrite.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Crazy Advanced Mod_Rewrite Tutorial</title>
		<link>http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html</link>
		<comments>http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html#comments</comments>
		<pubDate>Fri, 11 Sep 2009 16:55:32 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Modules]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[advanced]]></category>
		<category><![CDATA[askapache]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[htaccess rewrite]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=1209</guid>
		<description><![CDATA[<p><strong>Note:  Extremely ILL Content</strong><br />Find the key to unlocking mod_rewrite and you WILL be sick..  sick with a diamond disease on your wrist!<br /><a class="hs hs13" href="/wp-content/uploads/2008/08/mod_rewrite_ascii.png"></a></p>]]></description>
			<content:encoded><![CDATA[<p><a class="hs hs13" href="/wp-content/uploads/2008/08/mod_rewrite_ascii.png"></a><strong>Are you an advanced mod_rewrite expert or guru?</strong>  This article is for YOU too!  Just make sure to read all the way to the bottom..<br class="C" /></p>
<p class="anote">The following undocumented techniques and methods will allow you to utilize mod_rewrite at an  &#8220;expert level&#8221; by showing you how to <a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html#decoded">unlock its secrets</a>.  <br class="C" /></p>
<p>Most if not all web developers and server administrators struggle with Apache mod_rewrite.  It&#8217;s very tough and only gets a little easier with practice.  Until Now!  Get ready to explode your learning curve, I figured something out.</p>
<h2>Why mod_rewrite is so tough</h2>
<p>I have come to the conclusion, after many hours of zenful thought, that the reason mod_rewrite is so tough is pretty obvious, people are trying to apply regular-expressions to URLs and Variables that they don&#8217;t really understand.  They understand what they want, but they don&#8217;t understand what the URLS and Variables are that they are trying to rewrite.</p>
<h2>Hit-Or-Miss with mod_rewrite</h2>
<p>A lot of the mod_rewrite &#8220;experts&#8221; and &#8220;gurus&#8221; floating around the net absolutely know their mod_rewrite, but what separates them from a beginner or novice is for the most part an understanding of what the URLS and Variables look like that are targeted by the regular expressions.  Take this simple rewriterule that rewrites requests made without the www to www.</p>
<pre class='brushhtaccess'>
RewriteEngine On
RewriteBase /
&nbsp;
RewriteCond %{HTTP_HOST} !^www\.askapache\.com$ [NC]
RewriteRule .+ http://www.askapache.com%{REQUEST_URI}
</pre>
<p>Pretty simple right?  WRONG.  Most people could not figure that out..</p>
<h3>Why?</h3>
<p>The reason intelligent people can&#8217;t figure that out is because they have no idea what HTTP_HOST or REQUEST_URI actually looks like.  How can you write a rule for something if you don&#8217;t know what it looks like?  You can&#8217;t.</p>
<h2>When Not To Use Mod_Rewrite</h2>
<p>Ok so heres an important concept that alot of people haven&#8217;t heard.  You should only use <a href="http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html">mod_rewrite&#8217;s rewriterule </a>when you use a rewritecond or if you are rewriting internally like my <a href="http://www.askapache.com/htaccess/pimp-out-your-feedburner-count.html">feedcount hack</a>.</p>
<p>If you are simply redirecting one url to another, you should definately be using the much easier <a href="http://www.askapache.com/htaccess/seo-search-engine-friendly-redirects-without-mod_rewrite.html">mod_alias&#8217;s redirect and redirectmatch</a>, which is enabled on most Apache servers.</p>
<h2>When To Use Mod_Rewrite</h2>
<p>So then, you should only use mod_rewrite&#8217;s rewriterule when you are checking against one of the Apache Environment Variables to determine whether to rewrite or not.  This is where the Apache Documentation is grossly lacking.  They don&#8217;t tell you what those variables look like, leaving us completely incapable of creating rewrites based on them.  <strong>Not anymore.</strong></p>
<h3>Mod_Rewrite Environment Variables (The Secret)</h3>
<p>Here&#8217;s the variables I have found accessible by <a href="http://httpd.apache.org/docs/trunk/mod/mod_rewrite.html#rewritecond">mod_rewrite</a> (both documented and undocumented).   A thing to note is that you can set these variables early in an .htaccess file using SetEnv, RewriteRule, Header, etc.. and they will be accessible at the end of the .htaccess file.<br class="C" /></p>
<ul class="UL1">
<li><code>API_VERSION</code></li>
<li><code>AUTH_TYPE</code></li>
<li><code>CONTENT_LENGTH</code></li>
<li><code>CONTENT_TYPE</code></li>
<li><code>DOCUMENT_ROOT</code></li>
<li><code>GATEWAY_INTERFACE</code></li>
<li><code>HTTPS</code></li>
<li><code>HTTP_ACCEPT</code></li>
<li><code>HTTP_ACCEPT_CHARSET</code></li>
<li><code>HTTP_ACCEPT_ENCODING</code></li>
<li><code>HTTP_ACCEPT_LANGUAGE</code></li>
<li><code>HTTP_CACHE_CONTROL</code></li>
</ul>
<ul class="UL1">
<li><code>HTTP_CONNECTION</code></li>
<li><code>HTTP_COOKIE</code></li>
<li><code>HTTP_FORWARDED</code></li>
<li><code>HTTP_HOST</code></li>
<li><code>HTTP_KEEP_ALIVE</code></li>
<li><code>HTTP_PROXY_CONNECTION</code></li>
<li><code>HTTP_REFERER</code></li>
<li><code>HTTP_USER_AGENT</code></li>
<li><code>IS_SUBREQ</code></li>
<li><code>ORIG_PATH_INFO</code></li>
<li><code>ORIG_PATH_TRANSLATED</code></li>
<li><code>ORIG_SCRIPT_FILENAME</code></li>
</ul>
<ul class="UL1">
<li><code>ORIG_SCRIPT_NAME</code></li>
<li><code>PATH</code></li>
<li><code>PATH_INFO</code></li>
<li><code>PHP_SELF</code></li>
<li><code>QUERY_STRING</code></li>
<li><code>REDIRECT_QUERY_STRING</code></li>
<li><code>REDIRECT_REMOTE_USER</code></li>
<li><code>REDIRECT_STATUS</code></li>
<li><code>REDIRECT_URL</code></li>
<li><code>REMOTE_ADDR</code></li>
<li><code>REMOTE_HOST</code></li>
<li><code>REMOTE_IDENT</code></li>
</ul>
<ul class="UL1">
<li><code>REMOTE_PORT</code></li>
<li><code>REMOTE_USER</code></li>
<li><code>REQUEST_FILENAME</code></li>
<li><code>REQUEST_METHOD</code></li>
<li><code>REQUEST_TIME</code></li>
<li><code>REQUEST_URI</code></li>
<li><code>SCRIPT_FILENAME</code></li>
<li><code>SCRIPT_GROUP</code></li>
<li><code>SCRIPT_NAME</code></li>
<li><code>SCRIPT_URI</code></li>
<li><code>SCRIPT_URL</code></li>
<li><code>SCRIPT_USER</code></li>
</ul>
<ul class="UL1">
<li><code>SERVER_ADDR</code></li>
<li><code>SERVER_ADMIN</code></li>
<li><code>SERVER_NAME</code></li>
<li><code>SERVER_PORT</code></li>
<li><code>SERVER_PROTOCOL</code></li>
<li><code>SERVER_SIGNATURE</code></li>
<li><code>SERVER_SOFTWARE</code></li>
<li><code>THE_REQUEST</code></li>
<li><code>TIME</code></li>
<li><code>TIME_DAY</code></li>
<li><code>TIME_HOUR</code></li>
<li><code>TIME_MIN</code></li>
</ul>
<ul class="UL1">
<li><code>TIME_MON</code></li>
<li><code>TIME_SEC</code></li>
<li><code>TIME_WDAY</code></li>
<li><code>TIME_YEAR</code></li>
<li><code>TZ</code></li>
<li><code>UNIQUE_ID</code></li>
</ul>
<hr class="C" />
<h2>Decoding Mod_Rewrite Variables</h2>
<p>So when I realized my problem was that I didn&#8217;t know the value of the variable being tested by the RewriteCond, I set out to try and discover how to view those variables..  Keep in mind you can also use RewriteLogging, but its only allowed for root users who can edit the httpd.conf, this is .htaccess.</p>
<h3>Setting Environment Variables with RewriteRule</h3>
<p>I discovered a multitude of methods to set and view apache environment variables, using various modules and some core tricks, but the method that allows me to view the most environment variables is RewriteRule.. I wanted to use <a href="http://www.askapache.com/htaccess/setenvif.html">SetEnvIf</a> more, but its just not as powerful as mod_rewrite, due to programming.</p>
<p>This code sets the variable <code>INFO_REQUEST_URI</code> to have the value of <code>REQUEST_URI</code>.</p>
<pre class='brushhtaccess'>
RewriteEngine On
RewriteBase /
RewriteRule .* - [E=INFO_REQUEST_URI:%{REQUEST_URI},NE]
</pre>
<h3>Saving the Apache Variable Values</h3>
<p>Now the trick is how to view that environment variable&#8230;  The method I came up with is nice&#8230; We will send the environment variable value in an HTTP Header, as there isn&#8217;t much data manipulation/validation so you get an accurate look at the actual value..  At first I tried adding the variable value to a redirection using the query_string.. but a HTTP_USER_AGENT value doesn&#8217;t play well as a query_string.</p>
<h4>Using RequestHeader in .htaccess</h4>
<p>This code takes advantage of the incredible mod_headers apache module to actually ADD a whole new header to YOUR request.  Seriously one of the coolest tricks I&#8217;ve found yet.. Its almost the same as being able to spoof POST requests!  Since Headers can be protected data&#8230; <em>especially the HTTP_COOKIE header</em>..</p>
<pre class='brushhtaccess'>
RequestHeader set INFO_REQUEST_URI "%{INFO_REQUEST_URI}e"
</pre>
<h3>Viewing the Variable Values</h3>
<p>Now you can use any kind of server-run interpreter like perl, php, ruby, etc., to view all the variable values.  All cgi-script handlers like those are able to view request headers.. </p>
<h3>PHP Code to access Apache Variables</h3>
<p>Works even in safe-mode&#8230; any interpreter can view HTTP Headers!  Note that each of these variables are added as HTTP headers to the request for the script.. kinda confusing.. So each variable sent as a header is prefixed with HTTP_ to denote it was a header.</p>
<pre>
&lt;?php
header("Content-Type: text/plain");
$INFO=$MISS=array();
foreach($_SERVER as $v=&gt;$r)
{
  if(substr($v,0,9)==&#039;HTTP_INFO&#039;)
  {
    if(!empty($r))$INFO[substr($v,10)]=$r;
    else $MISS[substr($v,10)]=$r;
  }
}
&nbsp;
/* thanks Mike! */
ksort($INFO);
ksort($MISS);
ksort($_SERVER);
&nbsp;
echo "Received These Variables:\n";
print_r($INFO);
&nbsp;
echo "Missed These Variables:\n";
print_r($MISS);
&nbsp;
echo "ALL Variables:\n";
print_r($_SERVER);
?&gt;
</pre>
<h2>Time to Get Crazy</h2>
<p>Just create the above php file on your site as <code>/test/index.php</code> or whatever, then create /test/.htaccess which should contain the below <code>.htaccess file</code> snippet.  Now just request <code>/test/index.php</code> and be amazed!   If you&#8217;re looking for more general help check out this excellent <a href="http://www.addedbytes.com/apache/mod_rewrite-cheat-sheet/">mod_rewrite cheat sheet</a>.</p>
<p>Ok, so I&#8217;ve prepared the .htaccess code you can use to view the values of all these variables.  Just add it to a .htaccess file and make a request.  For this test I created an index.php file that printed out all the <code>$_SERVER</code> variables, and made requests to it.</p>
<pre class='brushhtaccess'>
RewriteEngine On
RewriteBase /
RewriteRule .* - [E=INFO_API_VERSION:%{API_VERSION},NE]
RewriteRule .* - [E=INFO_AUTH_TYPE:%{AUTH_TYPE},NE]
RewriteRule .* - [E=INFO_CONTENT_LENGTH:%{CONTENT_LENGTH},NE]
RewriteRule .* - [E=INFO_CONTENT_TYPE:%{CONTENT_TYPE},NE]
RewriteRule .* - [E=INFO_DOCUMENT_ROOT:%{DOCUMENT_ROOT},NE]
RewriteRule .* - [E=INFO_GATEWAY_INTERFACE:%{GATEWAY_INTERFACE},NE]
RewriteRule .* - [E=INFO_HTTPS:%{HTTPS},NE]
RewriteRule .* - [E=INFO_HTTP_ACCEPT:%{HTTP_ACCEPT},NE]
RewriteRule .* - [E=INFO_HTTP_ACCEPT_CHARSET:%{HTTP_ACCEPT_CHARSET},NE]
RewriteRule .* - [E=INFO_HTTP_ACCEPT_ENCODING:%{HTTP_ACCEPT_ENCODING},NE]
RewriteRule .* - [E=INFO_HTTP_ACCEPT_LANGUAGE:%{HTTP_ACCEPT_LANGUAGE},NE]
RewriteRule .* - [E=INFO_HTTP_CACHE_CONTROL:%{HTTP_CACHE_CONTROL},NE]
RewriteRule .* - [E=INFO_HTTP_CONNECTION:%{HTTP_CONNECTION},NE]
RewriteRule .* - [E=INFO_HTTP_COOKIE:%{HTTP_COOKIE},NE]
RewriteRule .* - [E=INFO_HTTP_FORWARDED:%{HTTP_FORWARDED},NE]
RewriteRule .* - [E=INFO_HTTP_HOST:%{HTTP_HOST},NE]
RewriteRule .* - [E=INFO_HTTP_KEEP_ALIVE:%{HTTP_KEEP_ALIVE},NE]
RewriteRule .* - [E=INFO_HTTP_MOD_SECURITY_MESSAGE:%{HTTP_MOD_SECURITY_MESSAGE},NE]
RewriteRule .* - [E=INFO_HTTP_PROXY_CONNECTION:%{HTTP_PROXY_CONNECTION},NE]
RewriteRule .* - [E=INFO_HTTP_REFERER:%{HTTP_REFERER},NE]
RewriteRule .* - [E=INFO_HTTP_USER_AGENT:%{HTTP_USER_AGENT},NE]
RewriteRule .* - [E=INFO_IS_SUBREQ:%{IS_SUBREQ},NE]
RewriteRule .* - [E=INFO_ORIG_PATH_INFO:%{ORIG_PATH_INFO},NE]
RewriteRule .* - [E=INFO_ORIG_PATH_TRANSLATED:%{ORIG_PATH_TRANSLATED},NE]
RewriteRule .* - [E=INFO_ORIG_SCRIPT_FILENAME:%{ORIG_SCRIPT_FILENAME},NE]
RewriteRule .* - [E=INFO_ORIG_SCRIPT_NAME:%{ORIG_SCRIPT_NAME},NE]
RewriteRule .* - [E=INFO_PATH:%{PATH},NE]
RewriteRule .* - [E=INFO_PATH_INFO:%{PATH_INFO},NE]
RewriteRule .* - [E=INFO_PHP_SELF:%{PHP_SELF},NE]
RewriteRule .* - [E=INFO_QUERY_STRING:%{QUERY_STRING},NE]
RewriteRule .* - [E=INFO_REDIRECT_QUERY_STRING:%{REDIRECT_QUERY_STRING},NE]
RewriteRule .* - [E=INFO_REDIRECT_REMOTE_USER:%{REDIRECT_REMOTE_USER},NE]
RewriteRule .* - [E=INFO_REDIRECT_STATUS:%{REDIRECT_STATUS},NE]
RewriteRule .* - [E=INFO_REDIRECT_URL:%{REDIRECT_URL},NE]
RewriteRule .* - [E=INFO_REMOTE_ADDR:%{REMOTE_ADDR},NE]
RewriteRule .* - [E=INFO_REMOTE_HOST:%{REMOTE_HOST},NE]
RewriteRule .* - [E=INFO_REMOTE_IDENT:%{REMOTE_IDENT},NE]
RewriteRule .* - [E=INFO_REMOTE_PORT:%{REMOTE_PORT},NE]
RewriteRule .* - [E=INFO_REMOTE_USER:%{REMOTE_USER},NE]
RewriteRule .* - [E=INFO_REQUEST_FILENAME:%{REQUEST_FILENAME},NE]
RewriteRule .* - [E=INFO_REQUEST_METHOD:%{REQUEST_METHOD},NE]
RewriteRule .* - [E=INFO_REQUEST_TIME:%{REQUEST_TIME},NE]
RewriteRule .* - [E=INFO_REQUEST_URI:%{REQUEST_URI},NE]
RewriteRule .* - [E=INFO_SCRIPT_FILENAME:%{SCRIPT_FILENAME},NE]
RewriteRule .* - [E=INFO_SCRIPT_GROUP:%{SCRIPT_GROUP},NE]
RewriteRule .* - [E=INFO_SCRIPT_NAME:%{SCRIPT_NAME},NE]
RewriteRule .* - [E=INFO_SCRIPT_URI:%{SCRIPT_URI},NE]
RewriteRule .* - [E=INFO_SCRIPT_URL:%{SCRIPT_URL},NE]
RewriteRule .* - [E=INFO_SCRIPT_USER:%{SCRIPT_USER},NE]
RewriteRule .* - [E=INFO_SERVER_ADDR:%{SERVER_ADDR},NE]
RewriteRule .* - [E=INFO_SERVER_ADMIN:%{SERVER_ADMIN},NE]
RewriteRule .* - [E=INFO_SERVER_NAME:%{SERVER_NAME},NE]
RewriteRule .* - [E=INFO_SERVER_PORT:%{SERVER_PORT},NE]
RewriteRule .* - [E=INFO_SERVER_PROTOCOL:%{SERVER_PROTOCOL},NE]
RewriteRule .* - [E=INFO_SERVER_SIGNATURE:%{SERVER_SIGNATURE},NE]
RewriteRule .* - [E=INFO_SERVER_SOFTWARE:%{SERVER_SOFTWARE},NE]
RewriteRule .* - [E=INFO_THE_REQUEST:%{THE_REQUEST},NE]
RewriteRule .* - [E=INFO_TIME:%{TIME},NE]
RewriteRule .* - [E=INFO_TIME_DAY:%{TIME_DAY},NE]
RewriteRule .* - [E=INFO_TIME_HOUR:%{TIME_HOUR},NE]
RewriteRule .* - [E=INFO_TIME_MIN:%{TIME_MIN},NE]
RewriteRule .* - [E=INFO_TIME_MON:%{TIME_MON},NE]
RewriteRule .* - [E=INFO_TIME_SEC:%{TIME_SEC},NE]
RewriteRule .* - [E=INFO_TIME_WDAY:%{TIME_WDAY},NE]
RewriteRule .* - [E=INFO_TIME_YEAR:%{TIME_YEAR},NE]
RewriteRule .* - [E=INFO_TZ:%{TZ},NE]
RewriteRule .* - [E=INFO_UNIQUE_ID:%{UNIQUE_ID},NE]
&nbsp;
RequestHeader set INFO_API_VERSION "%{INFO_API_VERSION}e"
RequestHeader set INFO_AUTH_TYPE "%{INFO_AUTH_TYPE}e"
RequestHeader set INFO_CONTENT_LENGTH "%{INFO_CONTENT_LENGTH}e"
RequestHeader set INFO_CONTENT_TYPE "%{INFO_CONTENT_TYPE}e"
RequestHeader set INFO_DOCUMENT_ROOT "%{INFO_DOCUMENT_ROOT}e"
RequestHeader set INFO_GATEWAY_INTERFACE "%{INFO_GATEWAY_INTERFACE}e"
RequestHeader set INFO_HTTPS "%{INFO_HTTPS}e"
RequestHeader set INFO_HTTP_ACCEPT "%{INFO_HTTP_ACCEPT}e"
RequestHeader set INFO_HTTP_ACCEPT_CHARSET "%{INFO_HTTP_ACCEPT_CHARSET}e"
RequestHeader set INFO_HTTP_ACCEPT_ENCODING "%{INFO_HTTP_ACCEPT_ENCODING}e"
RequestHeader set INFO_HTTP_ACCEPT_LANGUAGE "%{INFO_HTTP_ACCEPT_LANGUAGE}e"
RequestHeader set INFO_HTTP_CACHE_CONTROL "%{INFO_HTTP_CACHE_CONTROL}e"
RequestHeader set INFO_HTTP_CONNECTION "%{INFO_HTTP_CONNECTION}e"
RequestHeader set INFO_HTTP_COOKIE "%{INFO_HTTP_COOKIE}e"
RequestHeader set INFO_HTTP_FORWARDED "%{INFO_HTTP_FORWARDED}e"
RequestHeader set INFO_HTTP_HOST "%{INFO_HTTP_HOST}e"
RequestHeader set INFO_HTTP_KEEP_ALIVE "%{INFO_HTTP_KEEP_ALIVE}e"
RequestHeader set INFO_HTTP_MOD_SECURITY_MESSAGE "%{INFO_HTTP_MOD_SECURITY_MESSAGE}e"
RequestHeader set INFO_HTTP_PROXY_CONNECTION "%{INFO_HTTP_PROXY_CONNECTION}e"
RequestHeader set INFO_HTTP_REFERER "%{INFO_HTTP_REFERER}e"
RequestHeader set INFO_HTTP_USER_AGENT "%{INFO_HTTP_USER_AGENT}e"
RequestHeader set INFO_IS_SUBREQ "%{INFO_IS_SUBREQ}e"
RequestHeader set INFO_ORIG_PATH_INFO "%{INFO_ORIG_PATH_INFO}e"
RequestHeader set INFO_ORIG_PATH_TRANSLATED "%{INFO_ORIG_PATH_TRANSLATED}e"
RequestHeader set INFO_ORIG_SCRIPT_FILENAME "%{INFO_ORIG_SCRIPT_FILENAME}e"
RequestHeader set INFO_ORIG_SCRIPT_NAME "%{INFO_ORIG_SCRIPT_NAME}e"
RequestHeader set INFO_PATH "%{INFO_PATH}e"
RequestHeader set INFO_PATH_INFO "%{INFO_PATH_INFO}e"
RequestHeader set INFO_PHP_SELF "%{INFO_PHP_SELF}e"
RequestHeader set INFO_QUERY_STRING "%{INFO_QUERY_STRING}e"
RequestHeader set INFO_REDIRECT_QUERY_STRING "%{INFO_REDIRECT_QUERY_STRING}e"
RequestHeader set INFO_REDIRECT_REMOTE_USER "%{INFO_REDIRECT_REMOTE_USER}e"
RequestHeader set INFO_REDIRECT_STATUS "%{INFO_REDIRECT_STATUS}e"
RequestHeader set INFO_REDIRECT_URL "%{INFO_REDIRECT_URL}e"
RequestHeader set INFO_REMOTE_ADDR "%{INFO_REMOTE_ADDR}e"
RequestHeader set INFO_REMOTE_HOST "%{INFO_REMOTE_HOST}e"
RequestHeader set INFO_REMOTE_IDENT "%{INFO_REMOTE_IDENT}e"
RequestHeader set INFO_REMOTE_PORT "%{INFO_REMOTE_PORT}e"
RequestHeader set INFO_REMOTE_USER "%{INFO_REMOTE_USER}e"
RequestHeader set INFO_REQUEST_FILENAME "%{INFO_REQUEST_FILENAME}e"
RequestHeader set INFO_REQUEST_METHOD "%{INFO_REQUEST_METHOD}e"
RequestHeader set INFO_REQUEST_TIME "%{INFO_REQUEST_TIME}e"
RequestHeader set INFO_REQUEST_URI "%{INFO_REQUEST_URI}e"
RequestHeader set INFO_SCRIPT_FILENAME "%{INFO_SCRIPT_FILENAME}e"
RequestHeader set INFO_SCRIPT_GROUP "%{INFO_SCRIPT_GROUP}e"
RequestHeader set INFO_SCRIPT_NAME "%{INFO_SCRIPT_NAME}e"
RequestHeader set INFO_SCRIPT_URI "%{INFO_SCRIPT_URI}e"
RequestHeader set INFO_SCRIPT_URL "%{INFO_SCRIPT_URL}e"
RequestHeader set INFO_SCRIPT_USER "%{INFO_SCRIPT_USER}e"
RequestHeader set INFO_SERVER_ADDR "%{INFO_SERVER_ADDR}e"
RequestHeader set INFO_SERVER_ADMIN "%{INFO_SERVER_ADMIN}e"
RequestHeader set INFO_SERVER_NAME "%{INFO_SERVER_NAME}e"
RequestHeader set INFO_SERVER_PORT "%{INFO_SERVER_PORT}e"
RequestHeader set INFO_SERVER_PROTOCOL "%{INFO_SERVER_PROTOCOL}e"
RequestHeader set INFO_SERVER_SIGNATURE "%{INFO_SERVER_SIGNATURE}e"
RequestHeader set INFO_SERVER_SOFTWARE "%{INFO_SERVER_SOFTWARE}e"
RequestHeader set INFO_THE_REQUEST "%{INFO_THE_REQUEST}e"
RequestHeader set INFO_TIME "%{INFO_TIME}e"
RequestHeader set INFO_TIME_DAY "%{INFO_TIME_DAY}e"
RequestHeader set INFO_TIME_HOUR "%{INFO_TIME_HOUR}e"
RequestHeader set INFO_TIME_MIN "%{INFO_TIME_MIN}e"
RequestHeader set INFO_TIME_MON "%{INFO_TIME_MON}e"
RequestHeader set INFO_TIME_SEC "%{INFO_TIME_SEC}e"
RequestHeader set INFO_TIME_WDAY "%{INFO_TIME_WDAY}e"
RequestHeader set INFO_TIME_YEAR "%{INFO_TIME_YEAR}e"
RequestHeader set INFO_TZ "%{INFO_TZ}e"
RequestHeader set INFO_UNIQUE_ID "%{INFO_UNIQUE_ID}e"
</pre>
<h2><a id="decoded"></a>Mod_Rewrite Variables Decoded!</h2>
<pre class='brushhtaccess'>
[API_VERSION] =&gt; 20020903:12
[AUTH_TYPE] =&gt; Digest
[DOCUMENT_ROOT] =&gt; /home/user/www_root/askapache.com
[HTTPS] =&gt; off
[HTTP_ACCEPT] =&gt; text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_COOKIE] =&gt; PHPSESSID=752ee6d56e15f305233e30045987e5ce568c034; __qca=1176541225-59967328-5223185;
[HTTP_HOST] =&gt; www.askapache.com
[HTTP_REFERER] =&gt; http://www.askapache.com/protest/index.php?askapache=awesomeness&#038;you=rock
[HTTP_USER_AGENT] =&gt; Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16
[IS_SUBREQ] =&gt; false
[QUERY_STRING] =&gt; e=404
[REMOTE_ADDR] =&gt; 22.162.144.211
[REMOTE_HOST] =&gt; 22.162.144.211
[REMOTE_PORT] =&gt; 4511
[REMOTE_USER] =&gt; administrator
[REQUEST_FILENAME] =&gt; /home/user/www_root/askapache.com/protest/index.php
[REQUEST_METHOD] =&gt; GET
[REQUEST_URI] =&gt; /protest/index.php
[SCRIPT_FILENAME] =&gt; /home/user/www_root/askapache.com/protest/index.php
[SCRIPT_GROUP] =&gt; daemonu
[SCRIPT_USER] =&gt; askapache
[SERVER_ADDR] =&gt; 208.113.134.190
[SERVER_ADMIN] =&gt; webmaster@askapache.com
[SERVER_NAME] =&gt; www.askapache.com
[SERVER_PORT] =&gt; 80
[SERVER_PROTOCOL] =&gt; HTTP/1.1
[SERVER_SOFTWARE] =&gt; Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2
[THE_REQUEST] =&gt; GET /protest/adf HTTP/1.1
[TIME] =&gt; 20080820014309
[TIME_DAY] =&gt; 20
[TIME_HOUR] =&gt; 01
[TIME_MIN] =&gt; 43
[TIME_MON] =&gt; 08
[TIME_SEC] =&gt; 09
[TIME_WDAY] =&gt; 3
[TIME_YEAR] =&gt; 2008
</pre>
<h3>Request using HTTPS</h3>
<pre class='brushhtaccess'>
[API_VERSION] =&gt; 20020903:12
[AUTH_TYPE] =&gt; Digest
[DOCUMENT_ROOT] =&gt; /home/user/www_root/askapache.com
[HTTPS] =&gt; on
[HTTP_ACCEPT] =&gt; text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_COOKIE] =&gt; PHPSESSID=752ee6d56e15f305233e30045987e5ce568c034; __qca=1176541225-59967328-5223185;
[HTTP_HOST] =&gt; www.askapache.com
[HTTP_REFERER] =&gt; http://www.askapache.com/protest/index.php?askapache=awesomeness&#038;you=rock
[HTTP_USER_AGENT] =&gt; Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16
[IS_SUBREQ] =&gt; false
[QUERY_STRING] =&gt; hi=you&#038;whats=&amp;you
[REMOTE_ADDR] =&gt; 22.162.144.211
[REMOTE_HOST] =&gt; 22.162.144.211
[REMOTE_PORT] =&gt; 4605
[REMOTE_USER] =&gt; administrator
[REQUEST_FILENAME] =&gt; /home/user/www_root/askapache.com/protest/index.php
[REQUEST_METHOD] =&gt; GET
[REQUEST_URI] =&gt; /protest/index.php
[SCRIPT_FILENAME] =&gt; /home/user/www_root/askapache.com/protest/index.php
[SCRIPT_GROUP] =&gt; daemonu
[SCRIPT_USER] =&gt; askapache
[SERVER_ADDR] =&gt; 208.113.134.190
[SERVER_ADMIN] =&gt; webmaster@askapache.com
[SERVER_NAME] =&gt; www.askapache.com
[SERVER_PORT] =&gt; 443
[SERVER_PROTOCOL] =&gt; HTTP/1.1
[SERVER_SOFTWARE] =&gt; Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2
[THE_REQUEST] =&gt; GET /protest/index.php?hi=you&#038;whats=&amp;you HTTP/1.1
[TIME] =&gt; 20080820015016
[TIME_DAY] =&gt; 20
[TIME_HOUR] =&gt; 01
[TIME_MIN] =&gt; 50
[TIME_MON] =&gt; 08
[TIME_SEC] =&gt; 16
[TIME_WDAY] =&gt; 3
[TIME_YEAR] =&gt; 2008
</pre>
<h2>Emulating ErrorDocuments with Mod_Rewrite</h2>
<p>The ErrorDocument directive is helpful because an errordocument is called differently then a normal file, and it contains special variables to help an admin debug.</p>
<p>I&#8217;ve wanted to use a RewriteCond + a RewriteRule to cause an Apache ErrorDocument to be displayed for a long time&#8230; I finally figured it out.  Simply use the <a href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html">HTTP STATUS CODE trick</a> in combination with a simple RewriteRule to trigger an Apache ErrorDocument.</p>
<p>This code emulates the internal 404 process Apache goes through.. If the file is not found it requests the /test/trigger-error/404 internally which triggers the 404 ErrorDocument.</p>
<pre class='brushhtaccess'>
ErrorDocument 404 /test/errordocument/404.html
Redirect 404 /test/trigger-error/404
&nbsp;
RewriteEngine On
RewriteBase /
RewriteCond %{ENV:REDIRECT_STATUS} !=404
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /test/trigger-error/404 [L]
</pre>
<p><strong>Big Deal..</strong> you might say&#8230; well consider that this works with any status code, and using this method you now have the power to trigger any errordocument page based on any kind of rewritecond.  I&#8217;ll be writing about some practical uses for this powerful method in the coming weeks, but heres a good example now so you can see how it can be used.</p>
<p>This bit of code Triggers the <a href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html#status-505">505 HTTP Version Not Supported</a> When a request is made to the server with a protocol other than 1.1.</p>
<pre class='brushhtaccess'>
ErrorDocument 505 /test/errordocument/505.html
Redirect 505 /test/trigger-error/505
&nbsp;
RewriteEngine On
RewriteBase /
&nbsp;
RewriteCond %{ENV:REDIRECT_STATUS} !=505
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ /.*\ HTTP/(0\.9|1\.0|1\.1) [NC]
RewriteRule .* /test/trigger-error/505 [L]
</pre>
<p class="anote"><strong>YES!</strong> I realize I didn&#8217;t explain that very well, I didn&#8217;t realize it was that complicated..  I wanted to go into how to use these advanced tricks and methods to achieve some really cool stuff, but explaining just this little bit took me awhile and I&#8217;m out of page space!</p>
<p>So play around with this and I&#8217;ll post back some of the <em>untapped sicknesses</em> you can give a website with such powerful methods at your disposal.</p>
<blockquote cite="http://httpd.apache.org/"><p>
<cite><strong>Ralf S. Engelschall</strong></cite></p>
<pre>
/*
 *  URL Rewriting Module
 *
 *  This module uses a rule-based rewriting engine (based on a
 *  regular-expression parser) to rewrite requested URLs on the fly.
 *
 *  It supports an unlimited number of additional rule conditions (which can
 *  operate on a lot of variables, even on HTTP headers) for granular
 *  matching and even external database lookups (either via plain text
 *  tables, DBM hash files or even external processes) for advanced URL
 *  substitution.
 *
 *  It operates on the full URLs (including the PATH_INFO part) both in
 *  per-server context (httpd.conf) and per-dir context (.htaccess) and even
 *  can generate QUERY_STRING parts on result.   The rewriting result finally
 *  can lead to internal subprocessing, external request redirection or even
 *  to internal proxy throughput.
 *
 *  This module was originally written in April 1996 and
 *  gifted exclusively to the The Apache Software Foundation in July 1997 by
 *
 *      Ralf S. Engelschall
 *      rse engelschall.com
 *      www.engelschall.com
 */
</pre>
</blockquote>
<p><a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html">Crazy Advanced Mod_Rewrite Tutorial</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>mod_rewrite Fix for Caching Updated Files</title>
		<link>http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html</link>
		<comments>http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html#comments</comments>
		<pubDate>Sun, 30 Aug 2009 13:20:59 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[DreamHost]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[Web Hosting]]></category>
		<category><![CDATA[Webmaster]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[Cache-Control]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[If-Modified-Since]]></category>

		<guid isPermaLink="false">http://www.askapache.com/htaccess/mod_rewrite-code-to-fix-caching-updated-files.html</guid>
		<description><![CDATA[<p>Web Developers sometimes use <code>file.ext?v=004</code> as a version control system to force visitors to use updated files.  <strong>This is terrible.</strong>  Instead link to <code>apache-003.css</code> and set it to be cached forever. When you change the file you just change the links to <code>apache-004.css</code>. That eliminates millions of bandwidth and resource robbing If-Modified-Since requests. You only need Apache with mod_rewrite, and 1-10 minutes!</p>]]></description>
			<content:encoded><![CDATA[<p><strong>Web Developers sometimes use</strong> <code>file.ext?v=137</code> as a <strong>version control system</strong> so they can force visitors to use an updated file.  <strong>This is so terrible</strong>.  Instead link to <code>apache-003.css</code> and set it to be cached forever. When you change the file you just change the links to <code>apache-004.css</code>.</p>
<h2>Raw Speed Benefit</h2>
<p>This eliminates millions of bandwidth and resource robbing <code>304 If-Modified-Since</code> requests.</p>
<hr />
<h2>Renaming links vs. Renaming files</h2>
<p>On the server my files are named <strong>apache.css</strong> and <strong>apache.js</strong>, but in the xhtml I point to them using the names <code>apache-113.css</code> and <code>apache-113.js</code>, after I change the file I just add 1 to the number, and the new file is cached. They are internally redirected to apache.css and apache.js (invisible to the user) The concept is similar to a &#8220;shortcut&#8221; in windows or a symlink in BSD.  The trick is that I never actually rename the files on the server.  I just rename them in the html.  That means <code>apache-135.css</code> is served from the file apache.css but the browser/cache only see and know about <code>apache-135.css</code>.</p>
<h2>XHTML</h2>
<p><strong>NOTE</strong>: You can do your own investigating of this sites source code and <a href="http://www.askapache.com/online-tools/http-headers-tool/">HTTP headers</a> to see this whole system in action</p>
<pre>
&lt;link href="http://z.askapache.com/z/c/apache-0031.css" rel="stylesheet" type="text/css" /&gt;
&lt;script src="http://z.askapache.com/z/j/apache-0031.js" type="text/javascript"&gt;&lt;/script&gt;
</pre>
<h2>mod_rewrite code for htaccess or httpd.conf</h2>
<p><strong>Updated:</strong> 10/20/2008</p>
<pre>
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /z/([a-z]+)/(.+)-([0-9]+)\.(js|css).*\ HTTP/ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .+ /z/%2/%3.%5 [NC,L]
</pre>
<h3>Alternate mod_rewrite code</h3>
<pre>
RewriteEngine On
RewriteBase /
RewriteRule ^([cij]+)(/?[a-z]*)/([a-z]+)-([0-9]+)\.([a-z]+)$ /$1$2/$3.$5 [L]
</pre>
<h2>Ideal Caching Scheme</h2>
<p>Ok so you want the xhtml to be the only file that isn&#8217;t cached without being validated, its simple to <a href="http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html" title="Speed Up Sites with htaccess Caching">setup your own caching scheme</a>.</p>
<h3>Bad Cache information for a file with the <code>?v=foo</code> hack</h3>
<blockquote><p>This object will be fresh for 1 week. It can be validated with Last-Modified. This object requests that a Cookie be set; this makes it and other pages affected automatically stale; clients must check them upon every request. Because it contains a query (&#8216;?&#8217;) in the URL, many caches will not keep this object.</p>
</blockquote>
<p><a href="http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html">mod_rewrite Fix for Caching Updated Files</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An AskApache Plugin Upgrade to Rule them All</title>
		<link>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html</link>
		<comments>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html#comments</comments>
		<pubDate>Wed, 29 Jul 2009 17:59:07 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Modules]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web Hosting]]></category>
		<category><![CDATA[Web Tools]]></category>
		<category><![CDATA[Webmaster]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress Plugins]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[AskApache Google 404]]></category>
		<category><![CDATA[AskApache Password Protection]]></category>
		<category><![CDATA[Fsockopen]]></category>
		<category><![CDATA[wordpress security]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3062</guid>
		<description><![CDATA[<p><a class="IFL" href="/wp-content/uploads/2009/07/apache-server-status.png"><img src="/wp-content/uploads/2009/07/apache-server-status-350x164.png" alt="apache-server-status" title="apache-server-status" width="350" height="164" class="alignnone size-medium wp-image-3070" /></a>So my blog as been rather quiet for almost a year now, and very few updates if any have been released for my Password Protection PLugin, my Google 404 Plugin, and definately not for my AskApache CrazyCache plugin, which I will be releasing last...  So for all of you who've helped me out by sending me suggestions and notifying me of errors and sticking with it...  Just wanted to <strong>say sorry about that, and thanks for all the great ideas.. </strong> Well, I've been sticking with it as well believe it our not.  I manage to get free days once in a while, and then its <strong>time to jam</strong>.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a class="IFL" href="/wp-content/uploads/2009/07/apache-server-status.png"><img src="/wp-content/uploads/2009/07/apache-server-status-350x164.png" alt="apache-server-status" title="apache-server-status" width="350" height="164" class="alignnone size-medium wp-image-3070" /></a>So my blog as been rather quiet for almost a year now, and very few updates if any have been released for my Password Protection PLugin, my Google 404 Plugin, and definately not for my AskApache CrazyCache plugin, which I will be releasing last&#8230;  So for all of you who&#8217;ve helped me out by sending me suggestions and notifying me of errors and sticking with it&#8230;  Just wanted to <strong>say sorry about that, and thanks for all the great ideas.. </strong> Well, I&#8217;ve been sticking with it as well believe it our not.  I manage to get free days once in a while, and then its <strong>time to jam</strong>.</p>
<p>I&#8217;ve used just about every CMS/Blog/Forum/Trac/Gallery/etc) and really didn&#8217;t like a lot of the way they coded&#8230;  I could use php but I didn&#8217;t KNOW php.. so I&#8217;ve had to learn php also, and it was tough to learn the advanced class usage and all the other language specific (but similar) constructs for php.  It was especially difficult (but fun and challenging) to program so as to be compatible with php4 and php5 (Such is WordPress).    But I kept at it, and soon you can decide for yourself what to make of it.</p>
<p>I can code in plenty of languages (bash, lua, windows .bat and vbs,  ocaml, big fan of all things shell) and can work my way through C and even sorta somewhat with assembly.  Assembly is the hardest, by far,  I&#8217;m into easy and powerful languages like Python, Javascript, perl, php, ruby, and CGI. I&#8217;ve used PHP for a long time to do various things,  but never to build software projects like this.  Once I noticed WordPress&#8217;s core .php files and the excellent programming I wanted to try and learn hot to do it.   The WordPress code is some of the best I&#8217;ve seen.  It appears the way they built it was planned, and not just dreamt up while typing that I can&#8217;t help but do.    Every time I read through the core code I learn a new trick or very nice way to do something.  Those guys are really good, and I think WordPress is going to dominate for a long long time.</p>
<h2>The Strategy</h2>
<p>The Password Protection (passpro) plugin has a lot of complex stuff going on, especially for a newbie to PHP and WordPress like me, so after refactoring the whole thing at least 5 times I decided to modify my approach, and wrote the AskApache Google 404 Plugin as a way to practice on a simpler piece of code, while at the same time providing a plugin of value.   Eventually I stopped thinking I could just code the whole thing in one sit-down with a stream-of-consciousness, and had to instead modularize the code and focus in on each part before moving to the next (I go without a plan because its fun, just not the most productive, but again, I&#8217;m not a programmer in the scientific sense.).</p>
<p>So I decided I had to really learn how WordPress Plugins work, filters, hooks, actions, and basically comfortability at reverse-engineering code, (Im a beginner for the last time), and so with the upcoming release of the AskApache Google 404 Plugin I have succeeded in making an incredibly stable plugin.  That way I only have to worry about what the aapasspro plugin is doing, instead of trying to fit it into a framework.  </p>
<h2>AskApache Google 404 Upgrade</h2>
<p>I think its rather unusual to develop a nice plugin like this 404 handler merely for the purpose of improving upon another plugin, but hey it worked.  As of <em>08/03/2009 14:06PM EST</em> I have about 1 hour left of finishing touches to release this upgrade.  But as you cantell by my badly edited posts, I don&#8217;t have a lot of time to myself.  An hour here and there is about it.  So it could be up to 2 weeks before I actually have the time to commit the release to the repo.  On a sidenote, have you checked out <a href="http://windows7news.com/" title="Windows 7 News">Windows 7 News</a>?  I&#8217;ve been contracted to do some technical work for them and thought they had an excellent site.</p>
<p><a href="/wp-content/uploads/2009/07/askapache-google-upgrade-ss1.png"><img src="/wp-content/uploads/2009/07/askapache-google-upgrade-ss1-344x350.png" alt="askapache-google-upgrade-ss1" title="askapache-google-upgrade-ss1" width="344" height="350" class="alignnone size-medium wp-image-3139" /></a></p>
<p><a href="/wp-content/uploads/2009/07/askapache-google-upgrade-ss2.png"><img src="/wp-content/uploads/2009/07/askapache-google-upgrade-ss2-293x350.png" alt="askapache-google-upgrade-ss2" title="askapache-google-upgrade-ss2" width="293" height="350" class="alignnone size-medium wp-image-3138" /></a></p>
<p>But keep in mind, the 404 PLugin is just where I practice for the passpro plugin, which truly does have features that no other software like it has ever had.  I understand the technology behind this plugin, and know it would really have a great impact on improving the Web (esp. WordPress) for all of us, I&#8217;ve just had to learn how to make it.</p>
<h2>AskApache Password Protection</h2>
<p>Probably still a couple weeks away, this plugin is the ultimate culmination of apache hackers dreams, at least those on shared servers (who may be interested in learning how to bypass security of said servers)..  So this is something I have much too fun with doing what I like to do.. network/protocol-level security.  I&#8217;ve examined the source code for many software packages that I use or have used to audit a server&#8217;s security, and this simple php plugin in most instances can enumerate with accuraccy most of the server&#8217;s setup in about a minute.  The catch (and the file permission problems I had to find a workaround too) is that this software is launched on the server, not remotely against the server.</p>
<p>Some of the software I examined was whiskers, nessus, nmap, hping, mozilla source, wireshark, ncftp, netcat, etc..  The closest comparison to the socket-level class I&#8217;ve hacked together to those is wireshark.  Except that wireshark only interprets (captures) the data passing over the wire, while this class does that and in fact sends and receives the data like netcat or nmap.  Its really more similar to metasploit, and can easily be used to send hex, binary, ascii, or any type of payload to the remote or local host.</p>
<h2>The Upgrades Begin</h2>
<p>Well I started working on them a long time ago.  Both the Password Protection plugin and the Google 404 plugin needed serious work.   And I finally have it all figured out.  Essentially I would work on one and finish an upgrade, but I just wasn&#8217;t happy with it and I wold start all over again, refactoring the code.   So as I put the finishing touches on those 2 plugins keep an eye out.  They are major upgrades.   I was able to meet all the goals I had for them, and came up with a lot of more improvements during the process.One of the main things I needed was a socket-level class to perform all kinds of checks and tests on.  I need this also for my crazy cache plugin, which my blog is currently using ,  and I have a 2 more really nice pplugins I use that also needed  access to a network class.  I wrote about what I was doing with fsockopen, and I&#8217;ve been improving on that example ever since.  I use this class to do some really powerful and exciting stuff, but you&#8217;ll see it soon enough.  As an indication of &#8216;getting it right&#8217; for the Password Protection plugin, the plugin will now work on Windows, Apache, IIS, Lighthttpd, and will even work running on a blackberry web server.  So now everyone using wordpress can at least get some security()</p>
<p class="enote">Many of the the other improvements focus on using the fsockopen class and .htaccess tricks to basically enumerate and discover all the different capabilities of your particular server;  That way you can learn about all the features and security that are possible for your specific server, and the securty modules wi8ll be geared for that as well.  FINALLY this plugin is going to be stable, and I just cant wait to see how people react when they learn all great capability their Apache-based Server has that they didn&#8217;t have a clue about.   Its amazing in that sense, and hackers will love theh way it works.. but your server admins will love it even more because its entirely 100% focused on helping you to set your site up (if you have Apache) to keep spammers out, to keep virii-serving robots and their log-hogging exploit requests and CPU/Mem robiing 404 errors off of your servers for real.  This will have a noticeable affect to whoever is running the server.   As you can tell.. I am pumped!</br></p>
<hr class="C" />
Apache is easy to configure and use, but only when you have root access.  Most people on shared and private hosting aren&#8217;t even able to view the main config file, let alone execute the Apache binaries to see what features are available and what configuration is being used.<br class="C" /></p>
<p>Apache can only be influenced by the main server configs and by .htaccess files.  Not by php, not by perl, and the main configs are almost never accessible to the masses.  But .htaccess files are.  And many hosting providers allow and enable .htaccess files, a configuration file for your web server.  The advanced features and capabilities of Apache were out of reach for most of us, it just wasn&#8217;t possible to enumerate or access, and most hosting providers are infamous for their lack of .htaccess (customer) support.  This plugin goes around those problems to give the power back to the people.<br class="C" /></p>
<p>y creating custom .htaccess files containing unpublished .htaccess tricks and techniques and combining that with the use of socket-level networking from WordPress (PHP) using <a href="http://www.askapache.com/php/fsockopen-socket.html">fsockopen</a>, we can effectively enumerate and discover an incredible amount of features and settings you will be able to control and use with this plugin.</p>
<p>Here are a few examples of the capabilities of this plugin, some of which I believe no other software can do..  <em>(Open source free to copy!)</em>.</p>
<ol>
<li>Current Version of Apache (<strong>Down to the API Version</strong>)</li>
<li>List of <strong>ALL Modules currently enabled</strong> by Apache (Such as Mod_Rewrite)</li>
<li>List of <strong>ALL Directives enabled by EACH enabled Module.</strong></li>
<li>Enumerate .htaccess Overrides, Context Permissions</li>
<li>Test for any builtin Handlers (like the <a href="/wp-content/uploads/2009/07/apache-server-status.png">status handler screenshot</a>)</li>
<li>Configure SSI (<a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security">http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security</a>)</li>
</ol>
<blockquote cite="http://www.askapache.com/htaccess/password-protection-plugin-status.html"><div class="inote"><cite><a href="http://www.askapache.com/htaccess/password-protection-plugin-status.html"></a></cite>
<p><strong>March 1, 2009</strong><br /><strong>I would focus on the method that WordPress uses</strong>.  The code they have now (2.8 bleeding-edge) still isn&#8217;t where it needs to be, but this is some difficult stuff and <strong>they have a brilliant start, it&#8217;ll work.. just a question of when</strong>.</p>
<p><a class="IFL" href="/wp-content/uploads/2009/03/apache-security-model-tall1.png"><img src="/wp-content/uploads/2009/03/apache-security-model-tall1-250x123.png" alt="Apache Security Model - In Color" title="apache-security-model-wide" width="250" height="123" /></a><strong>The main issue</strong> with the password protection plugin working for some people and not others is due to <a title="detailed file permission article" href="http://www.askapache.com/security/chmod-stat.html">file permission configurations</a>.  The plugin attempts to write/modify files in your blog&#8217;s root directory.<br class="C" /></p>
</div>
</blockquote>
<hr class="C" />
<blockquote cite="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html"><div class="inote"><cite><a href="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html"></a></cite>
<p><strong>November 05, 2008</strong><br />To make a long story short, I downloaded each major release of the apache httpd source code starting at version 1.3.0 and finishing with version 2.2.11, I then compiled each version and built a HTTPD from source for all these apache versions.</p>
<div>
<div style="width:100px;overflow:hidden;float:left;">
<ul>
<li>1.3.0</li>
<li>1.3.1</li>
<li>1.3.11</li>
<li>1.3.12</li>
<li>1.3.14</li>
<li>1.3.17</li>
<li>1.3.19</li>
<li>1.3.2</li>
<li>1.3.20</li>
<li>1.3.22</li>
<li>1.3.23</li>
<li>1.3.24</li>
<li>1.3.27</li>
<li>1.3.28</li>
</ul>
</div>
<div style="width:100px;overflow:hidden;float:left;">
<ul>
<li>1.3.29</li>
<li>1.3.3</li>
<li>1.3.31</li>
<li>1.3.32</li>
<li>1.3.33</li>
<li>1.3.34</li>
<li>1.3.35</li>
<li>1.3.36</li>
<li>1.3.37</li>
<li>1.3.39</li>
<li>1.3.4</li>
<li>1.3.41</li>
<li>1.3.6</li>
<li>1.3.9</li>
</ul>
</div>
<div style="width:100px;overflow:hidden;float:left;">
<ul>
<li>2.0.35</li>
<li>2.0.36</li>
<li>2.0.39</li>
<li>2.0.40</li>
<li>2.0.42</li>
<li>2.0.43</li>
<li>2.0.44</li>
<li>2.0.45</li>
<li>2.0.46</li>
<li>2.0.47</li>
<li>2.0.48</li>
<li>2.0.49</li>
<li>2.0.50</li>
<li>2.0.51</li>
</ul>
</div>
<div style="width:150px;overflow:hidden;float:left;">
<ul>
<li>2.0.52</li>
<li>2.0.53</li>
<li>2.0.54</li>
<li>2.0.55</li>
<li>2.0.58</li>
<li>2.0.59</li>
<li>2.0.61</li>
<li>2.0.63</li>
<li>2.1.3-beta</li>
<li>2.1.6-alpha</li>
<li>2.1.7-beta</li>
<li>2.1.8-beta</li>
<li>2.1.9-beta</li>
</ul>
</div>
<div style="width:100px;overflow:hidden;float:left;">
<ul>
<li>2.2.0</li>
<li>2.2.10</li>
<li>2.2.2</li>
<li>2.2.3</li>
<li>2.2.4</li>
<li>2.2.6</li>
<li>2.2.8</li>
<li>2.2.9</li>
<li><strong>2.2.10</strong></li>
<li><strong>2.2.11</strong></li>
</ul>
</div>
<p><br class="C" /></div>
<p>Then I went through each version and determined the compatible modules for that version, and I&#8217;m pretty confident that I was also able to find each and every directive allowed by the compatible modules for that version (including core directives).  See <a href="http://www.askapache.com/htaccess/htaccess.html#htaccess-directives">.htaccess directive list</a>.  Basically I can now test a server using a variety of methods and determine almost 100% accurately what version of Apache (down to the API) is running, what modules (and versions) are enabled, and each and every directive that is allowed or disallowed for that version.  So this is so awesome because now we can enable all sorts of additional security features.</p>
</div>
</blockquote>
<hr class="C" />
<blockquote cite="http://www.askapache.com/htaccess/htaccess.html#htaccess-modules"><p><cite><a href="http://www.askapache.com/htaccess/htaccess.html#htaccess-modules">Htaccess enabled Modules</a></cite>
<p>Here are most of the modules that come with Apache.  Each one can have new commands that can be used in .htaccess file scopes.</p>
<p><a href="http://www.askapache.com/servers/mod_actions.c.html">mod_actions</a>, <a href="http://www.askapache.com/servers/mod_alias.c.html">mod_alias</a>, <a href="http://www.askapache.com/servers/mod_asis.c.html">mod_asis</a>, <a href="http://www.askapache.com/servers/mod_auth_basic.c.html">mod_auth_basic</a>, <a href="http://www.askapache.com/servers/mod_auth_digest.c.html">mod_auth_digest</a>, <a href="http://www.askapache.com/servers/mod_authn_anon.c.html">mod_authn_anon</a>, <a href="http://www.askapache.com/servers/mod_authn_dbd.c.html">mod_authn_dbd</a>, <a href="http://www.askapache.com/servers/mod_authn_dbm.c.html">mod_authn_dbm</a>, <a href="http://www.askapache.com/servers/mod_authn_default.c.html">mod_authn_default</a>, <a href="http://www.askapache.com/servers/mod_authn_file.c.html">mod_authn_file</a>, <a href="http://www.askapache.com/servers/mod_authz_dbm.c.html">mod_authz_dbm</a>, <a href="http://www.askapache.com/servers/mod_authz_default.c.html">mod_authz_default</a>, <a href="http://www.askapache.com/servers/mod_authz_groupfile.c.html">mod_authz_groupfile</a>, <a href="http://www.askapache.com/servers/mod_authz_host.c.html">mod_authz_host</a>, <a href="http://www.askapache.com/servers/mod_authz_owner.c.html">mod_authz_owner</a>, <a href="http://www.askapache.com/servers/mod_authz_user.c.html">mod_authz_user</a>, <a href="http://www.askapache.com/servers/mod_autoindex.c.html">mod_autoindex</a>, <a href="http://www.askapache.com/servers/mod_cache.c.html">mod_cache</a>, <a href="http://www.askapache.com/servers/mod_cern_meta.c.html">mod_cern_meta</a>, <a href="http://www.askapache.com/servers/mod_cgi.c.html">mod_cgi</a>, <a href="http://www.askapache.com/servers/mod_dav.c.html">mod_dav</a>, <a href="http://www.askapache.com/servers/mod_dav_fs.c.html">mod_dav_fs</a>, <a href="http://www.askapache.com/servers/mod_dbd.c.html">mod_dbd</a>, <a href="http://www.askapache.com/servers/mod_deflate.c.html">mod_deflate</a>, <a href="http://www.askapache.com/servers/mod_dir.c.html">mod_dir</a>, <a href="http://www.askapache.com/servers/mod_disk_cache.c.html">mod_disk_cache</a>, <a href="http://www.askapache.com/servers/mod_dumpio.c.html">mod_dumpio</a>, <a href="http://www.askapache.com/servers/mod_env.c.html">mod_env</a>, <a href="http://www.askapache.com/servers/mod_expires.c.html">mod_expires</a>, <a href="http://www.askapache.com/servers/mod_ext_filter.c.html">mod_ext_filter</a>, <a href="http://www.askapache.com/servers/mod_file_cache.c.html">mod_file_cache</a>, <a href="http://www.askapache.com/servers/mod_filter.c.html">mod_filter</a>, <a href="http://www.askapache.com/servers/mod_headers.c.html">mod_headers</a>, <a href="http://www.askapache.com/servers/mod_ident.c.html">mod_ident</a>, <a href="http://www.askapache.com/servers/mod_imagemap.c.html">mod_imagemap</a>, <a href="http://www.askapache.com/servers/mod_include.c.html">mod_include</a>, <a href="http://www.askapache.com/servers/mod_info.c.html">mod_info</a>, <a href="http://www.askapache.com/servers/mod_log_config.c.html">mod_log_config</a>, <a href="http://www.askapache.com/servers/mod_log_forensic.c.html">mod_log_forensic</a>, <a href="http://www.askapache.com/servers/mod_logio.c.html">mod_logio</a>, <a href="http://www.askapache.com/servers/mod_mem_cache.c.html">mod_mem_cache</a>, <a href="http://www.askapache.com/servers/mod_mime.c.html">mod_mime</a>, <a href="http://www.askapache.com/servers/mod_mime_magic.c.html">mod_mime_magic</a>, <a href="http://www.askapache.com/servers/mod_negotiation.c.html">mod_negotiation</a>, <a href="http://www.askapache.com/servers/mod_proxy.c.html">mod_proxy</a>, <a href="http://www.askapache.com/servers/mod_proxy_ajp.c.html">mod_proxy_ajp</a>, <a href="http://www.askapache.com/servers/mod_proxy_balancer.c.html">mod_proxy_balancer</a>, <a href="http://www.askapache.com/servers/mod_proxy_connect.c.html">mod_proxy_connect</a>, <a href="http://www.askapache.com/servers/mod_proxy_ftp.c.html">mod_proxy_ftp</a>, <a href="http://www.askapache.com/servers/mod_proxy_http.c.html">mod_proxy_http</a>, <a href="http://www.askapache.com/servers/mod_rewrite.c.html">mod_rewrite</a>, <a href="http://www.askapache.com/servers/mod_setenvif.c.html">mod_setenvif</a>, <a href="http://www.askapache.com/servers/mod_speling.c.html">mod_speling</a>, <a href="http://www.askapache.com/servers/mod_ssl.c.html">mod_ssl</a>, <a href="http://www.askapache.com/servers/mod_status.c.html">mod_status</a>, <a href="http://www.askapache.com/servers/mod_substitute.c.html">mod_substitute</a>, <a href="http://www.askapache.com/servers/mod_unique_id.c.html">mod_unique_id</a>, <a href="http://www.askapache.com/servers/mod_userdir.c.html">mod_userdir</a>, <a href="http://www.askapache.com/servers/mod_usertrack.c.html">mod_usertrack</a>, <a href="http://www.askapache.com/servers/mod_version.c.html">mod_version</a>, <a href="http://www.askapache.com/servers/mod_vhost_alias.c.html">mod_vhost_alias</a></p>
</blockquote>
<hr class="C" />
<hr class="C" />
<h2>Debugging HTTP protocol</h2>
<p>Check this out!  I&#8217;m particularly happy about this feature, which outputs an exact trace of any requests made by the plugin (such as during the testing phase) by saving the actual raw data sent out on the wire using fsockopen, RX and TX.  This is useful for a number of reasons, viewing your headers, finding Redirect Loops, testing RewriteRules, and following the request hop-by-hop for debugging.  The below example shows 2 requests for 2 URIs.  The first URI is protected using Digest Authentication, the 2nd shows Basic.</p>
<pre>
 ______________
|  RAW TRACE   |
==================================================================================================================================
GET /htaccess/index.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
&nbsp;
HTTP/1.1 401 Authorization Required
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
WWW-Authenticate: Digest realm="do or die", nonce="03328f3ec7c7b", algorithm=MD5, domain="/", qop="auth"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 882
Connection: close
Content-Type: text/html; charset=UTF-8
&nbsp;
GET /htaccess/index.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
Authorization: Digest username="test",realm="do or die",nonce="03328f3ec7c7b",uri="/htaccess/index.txt?testing=query",
cnonce="82d057852a9dc497",nc=00000001,algorithm=MD5,response="9d476e9ea3",qop="auth"
&nbsp;
HTTP/1.1 200 OK
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
Authentication-Info: rspauth="9051b01ee26dd62b3e2b40dada694f45", cnonce="82d057852a9dc497", nc=00000001, qop=auth
Last-Modified: Tue, 21 Jul 2009 23:56:00 GMT
Accept-Ranges: bytes
Cache-Control: max-age=3600
Expires: Wed, 22 Jul 2009 07:29:58 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 27
Connection: close
Content-Type: text/plain; charset=UTF-8
&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;``
&nbsp;
 ______________
|  RAW TRACE   |
==================================================================================================================================
GET /htaccess/po.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
&nbsp;
HTTP/1.1 401 Authorization Required
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
WWW-Authenticate: Basic realm="Po Pimping"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 878
Connection: close
Content-Type: text/html; charset=UTF-8
&nbsp;
GET /htaccess/po.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
Authorization: Basic adfAGAltcA==
&nbsp;
HTTP/1.1 200 OK
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 05:54:39 GMT
Accept-Ranges: bytes
Cache-Control: max-age=3600
Expires: Wed, 22 Jul 2009 07:29:58 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 27
Connection: close
Content-Type: text/plain; charset=UTF-8
&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;`&#96;``
</pre>
<h2>.htaccess Directives</h2>
<p>AcceptFilter, AcceptMutex, AcceptPathInfo, AccessFileName, Action, AddAlt, AddAltByEncoding, AddAltByType, AddCharset, AddDefaultCharset, AddDescription, AddEncoding, AddHandler, AddIcon, AddIconByEncoding, AddIconByType, AddInputFilter, AddLanguage, AddModuleInfo, AddOutputFilter, AddOutputFilterByType, AddType, Alias, AliasMatch, AllowCONNECT, AllowEncodedSlashes, AllowOverride, Anonymous, Anonymous_Authoritative, Anonymous_LogEmail, Anonymous_MustGiveEmail, Anonymous_NoUserID, Anonymous_NoUserId, Anonymous_VerifyEmail, AssignUserId, AuthAuthoritative, AuthBasicAuthoritative, AuthBasicProvider, AuthDBDUserPWQuery, AuthDBDUserRealmQuery, AuthDBM, AuthDBMAuthoritative, AuthDBMGroupFile, AuthDBMType, AuthDBMUserFile, AuthDefaultAuthoritative, AuthDigestAlgorithm, AuthDigestDomain, AuthDigestFile, AuthDigestGroupFile, AuthDigestNcCheck, AuthDigestNonceFormat, AuthDigestNonceLifetime, AuthDigestProvider, AuthDigestQop, AuthDigestShmemSize, AuthGroupFile, AuthLDAPAuthzEnabled, AuthLDAPBindDN, AuthLDAPBindON, AuthLDAPBindPassword, AuthLDAPCharsetConfig, AuthLDAPCompareDNOnServer, AuthLDAPDereferenceAliases, AuthLDAPEnabled, AuthLDAPFrontPageHack, AuthLDAPGroupAttribute, AuthLDAPGroupAttributeIsDN, AuthLDAPRemoteUserAttribute, AuthLDAPRemoteUserIsDN, AuthLDAPStartTLS, AuthLDAPURL, AuthLDAPUrl, AuthName, AuthType, AuthUserFile, AuthzDBMAuthoritative, AuthzDBMType, AuthzDefaultAuthoritative, AuthzGroupFileAuthoritative, AuthzLDAPAuthoritative, AuthzOwnerAuthoritative, AuthzUserAuthoritative, BS2000Account, BalancerMember, BrowserMatch, BrowserMatchNoCase, BufferedLogs, CGIMapExtension, CacheDefaultExpire, CacheDirLength, CacheDirLevels, CacheDisable, CacheEnable, CacheExpiryCheck, CacheFile, CacheForceCompletion, CacheGcClean, CacheGcDaily, CacheGcInterval, CacheGcMemUsage, CacheGcUnused, CacheIgnoreCacheControl, CacheIgnoreHeaders, CacheIgnoreNoLastMod, CacheLastModifiedFactor, CacheMaxExpire, CacheMaxFileSize, CacheMaxStreamingBuffer, CacheMinFileSize, CacheNegotiatedDocs, CacheRoot, CacheSize, CacheStoreNoStore, CacheStorePrivate, CacheTimeMargin, CharsetDefault, CharsetOptions, CharsetSourceEnc, CheckCaseOnly, CheckSpelling, ChildPerUserId, ContentDigest, CookieDomain, CookieExpires, CookieLog, CookieName, CookieStyle, CookieTracking, CoreDumpDirectory, CustomLog, DAV, DAVDepthInfinity, DAVGenericLockDB, DAVMinTimeout, DBDExptime, DBDKeep, DBDMax, DBDMin, DBDParams, DBDPersist, DBDPrepareSQL, DBDriver, Dav, DavDepthInfinity, DavGenericLockDB, DavLockDB, DavMinTimeout, DefaultIcon, DefaultLanguage, DefaultType, DeflateBufferSize, DeflateCompressionLevel, DeflateFilterNote, DeflateMemLevel, DeflateWindowSize, Directory, DirectoryIndex, DirectoryMatch, DirectorySlash, DocumentRoot, DumpIOInput, DumpIOOutput, EnableExceptionHook, EnableMMAP, EnableSendfile, ErrorDocument, ErrorLog, Example, ExpiresActive, ExpiresByType, ExpiresDefault, ExtFilterDefine, ExtFilterOptions, ExtendedStatus, FancyIndexing, FileETag, Files, FilesMatch, FilterChain, FilterDeclare, FilterProtocol, FilterProvider, FilterTrace, ForceLanguagePriority, ForceType, ForensicLog, GprofDir, GracefulShutdownTimeout, Group, Header, HeaderName, HostNameLookups, HostnameLookups, ISAIPFakeAsync, ISAPIAppendLogToErrors, ISAPIAppendLogToQuery, ISAPICacheFile, ISAPIFakeAsync, ISAPILogNotSupported, ISAPIReadAheadBuffer, IdentityCheck, IdentityCheckTimeout, IfDefine, IfModule, IfVersion, ImapBase, ImapDefault, ImapMenu, Include, IndexIgnore, IndexOptions, IndexOrderDefault, IndexStyleSheet, KeepAlive, KeepAliveTimeout, LDAPCacheEntries, LDAPCacheTTL, LDAPCertDBPath, LDAPConnectionTimeout, LDAPOpCacheEntries, LDAPOpCacheTTL, LDAPSharedCacheFile, LDAPSharedCacheSize, LDAPTrustedClientCert, LDAPTrustedGlobalCert, LDAPTrustedMode, LDAPVerifyServerCert, LanguagePriority, Limit, LimitExcept, LimitInternalRecursion, LimitRequestBody, LimitRequestFields, LimitRequestFieldsize, LimitRequestLine, LimitXMLRequestBody, Listen, ListenBacklog, LoadFile, LoadModule, Location, LocationMatch, LockFile, LogFormat, LogLevel, MCacheMaxObjectCount, MCacheMaxObjectSize, MCacheMaxStreamingBuffer, MCacheMinObjectSize, MCacheRemovalAlgorithm, MCacheSize, MMapFile, MaxClients, MaxKeepAliveRequests, MaxMemFree, MaxRequestsPerChild, MaxSpareServers, MaxSpareThreads, MaxSpareThreadsPerChild, MaxThreads, MetaDir, MetaFiles, MetaSuffix, MimeMagicFile, MinSpareServers, MinSpareThreads, ModMimeUsePathInfo, MultiviewsMatch, NWSSLTrustedCerts, NWSSLUpgradeable, NameVirtualHost, NoProxy, NumServers, Options, PassEnv, PerlAccessHandler, PerlAuthenHandler, PerlAuthzHandler, PerlChildExitHandler, PerlChildInitHandler, PerlCleanupHandler, PerlDispatchHandler, PerlFixupHandler, PerlFreshRestart, PerlHandler, PerlHeaderParserHandler, PerlInitHandler, PerlLogHandler, PerlModule, PerlPassEnv, PerlPostReadRequestHandler, PerlRequire, PerlRestartHandler, PerlSendHeader, PerlSetEnv, PerlSetVar, PerlSetupEnv, PerlTaintCheck, PerlTransHandler, PerlTypeHandler, PerlWarn, PidFile, Port, Protocol, ProtocolEcho, Proxy, ProxyBadHeader, ProxyBlock, ProxyDomain, ProxyErrorOverride, ProxyFtpDirCharset, ProxyIOBufferSize, ProxyMatch, ProxyMaxForwards, ProxyPass, ProxyPassInterpolateEnv, ProxyPassMatch, ProxyPassReverse, ProxyPassReverseCookieDomain, ProxyPassReverseCookiePath, ProxyPreserveHost, ProxyReceiveBufferSize, ProxyRemote, ProxyRemoteMatch, ProxyRequests, ProxySet, ProxyStatus, ProxyTimeout, ProxyVia, RLimitCPU, RLimitMEM, RLimitNPROC, ReadmeName, Redirect, RedirectMatch, RedirectPermanent, RedirectTemp, RemoveCharset, RemoveEncoding, RemoveHandler, RemoveInputFilter, RemoveLanguage, RemoveOutputFilter, RemoveType, RequestHeader, Require, RewriteBase, RewriteCond, RewriteEngine, RewriteLock, RewriteLog, RewriteLogLevel, RewriteMap, RewriteOptions, RewriteRule, SSIAccessEnable, SSIEndTag, SSIErrorMsg, SSIStartTag, SSITimeFormat, SSIUndefinedEcho, SSLCACertificateFile, SSLCACertificatePath, SSLCADNRequestFile, SSLCADNRequestPath, SSLCARevocationFile, SSLCARevocationPath, SSLCertificateChainFile, SSLCertificateFile, SSLCertificateKeyFile, SSLCipherSuite, SSLCryptoDevice, SSLEngine, SSLHonorCipherOrder, SSLLog, SSLLogLevel, SSLMutex, SSLOptions, SSLPassPhraseDialog, SSLProtocol, SSLProxyCACertificateFile, SSLProxyCACertificatePath, SSLProxyCARevocationFile, SSLProxyCARevocationPath, SSLProxyCipherSuite, SSLProxyEngine, SSLProxyMachineCertificateFile, SSLProxyMachineCertificatePath, SSLProxyProtocol, SSLProxyVerify, SSLProxyVerifyDepth, SSLRandomSeed, SSLRequire, SSLRequireSSL, SSLSessionCache, SSLSessionCacheTimeout, SSLUserName, SSLVerifyClient, SSLVerifyDepth, Satisfy, ScoreBoardFile, Script, ScriptAlias, ScriptAliasMatch, ScriptInterpreterSource, ScriptLog, ScriptLogBuffer, ScriptLogLength, ScriptStock, SecureListen, SendBufferSize, ServerAdmin, ServerAlias, ServerLimit, ServerName, ServerPath, ServerRoot, ServerSignature, ServerTokens, SetEnv, SetEnvIf, SetEnvIfNoCase, SetHandler, SetInputFilter, SetOutputFilter, StartServers, StartThreads, Substitute, SuexecUserGroup, ThreadLimit, ThreadStackSize, ThreadsPerChild, TimeOut, Timeout, TraceEnable, TransferLog, TypeAuthDBMUserFile, TypesConfig, UnsetEnv, UseCanonicalName, UseCanonicalPhysicalPort, User, UserDir, VirtualDocumentRoot, VirtualDocumentRootIP, VirtualHost, VirtualScriptAlias, VirtualScriptAliasIP, Win32DisableAcceptEx, XBitHack, allow, deny, order, php_admin_flag, php_admin_value, php_flag, php_value</p>
<p class="anote">You can view the <a href="http://www.askapache.com/htaccess/htaccess-security-block-spam-hackers.html">plugins home page</a>, <a href="http://www.askapache.com/wordpress/htaccess-password-protect.html#aadl">old</a>, or <a href="http://wordpress.org/extend/plugins/askapache-password-protect/">view it on the wordpress.org site</a>.</p>
<p><a href="http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html">An AskApache Plugin Upgrade to Rule them All</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DNS Round Robin Configuration using Rsync over SSH</title>
		<link>http://www.askapache.com/linux-unix/dns-round-robin-rsync-over-ssh.html</link>
		<comments>http://www.askapache.com/linux-unix/dns-round-robin-rsync-over-ssh.html#comments</comments>
		<pubDate>Tue, 14 Apr 2009 05:46:20 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Modules]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[Web Hosting]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[DreamHost]]></category>
		<category><![CDATA[HostGator]]></category>
		<category><![CDATA[Powweb]]></category>
		<category><![CDATA[Round Robin]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2540</guid>
		<description><![CDATA[<p><a class="IFL" href="http://www.askapache.com/dreamhost/dns-round-robin-rsync-over-ssh.html"><img src="/wp-content/uploads/2009/04/round-robin-dns-116x98.png" /></a><strong>The goal is to add the HostGator server</strong> to be an exact mirror of the z.askapache.com domain, then to add that server as a 2nd A record to my DNS zone.  That way half the visitors to the size will be taking up resources and bandwidth on the <a href="http://secure.hostgator.com/cgi-bin/affiliates/clickthru.cgi?id=AskApache-rrdns">HostGator</a> server instead of mine.<br /><br /><strong>Round Robin A records</strong> in DNS are intended to evenly distribute queries between each host of the same name.  Using some tricks straight out of a hackers toolbox we can verify if the distribution is taking place.  (<a href="http://www.askapache.com/dreamhost/dns-round-robin-rsync-over-ssh.html#dns-robin-works">It is.</a>)  <br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p>My traffic is growing, alot, and I need to plan how I&#8217;m going to maintain scalability, high availability, and redundancy.   Scalability is an application&#8217;s ability to support a growing number of users. High availability can be defined as redundancy or speed.  I decided to setup <a href="#dns-robin-round">Round Robin DNS</a> for <a href="http://z.askapache.com/">z.askapache.com</a>, which is the &#8220;static&#8221; <a href="http://www.askapache.com/htaccess/apache-speed-subdomains.html">subdomain</a> of <a href="http://www.askapache.com/">AskApache</a> that serves all the static assets like images, javascript, css, etc.. (<em>BTW, the z stands for ZAP</em>)..  All I needed to attempt setting this up was another hosting account on a separate server.  I have hosting accounts with around 10 different companies from working with various clients over the years, like <a href="http://www.powweb.com/join/index.bml?AffID=582654">Powweb</a> and I don&#8217;t use them because they suck in terms of the unix environment.  Many of these web hosts are actually very fast bandwidth-wise..</p>
<h2><a id="#round-robin-concept" name="#round-robin-concept"></a>Round Robin Concept</h2>
<p><a class="IFL" href="#"><img src="/wp-content/uploads/2009/04/round-robin-dns.png" alt="Round Robin DNS" title="Round Robin DNS" width="396" height="335" class="size-full wp-image-2622" /></a><strong>A few months ago</strong> I was given a free hosting account on <a href="http://secure.hostgator.com/cgi-bin/affiliates/clickthru.cgi?id=AskApache-rrdns">HostGator</a> to evaluate and tempt me away from DreamHost to become a Gator.  I get a lot of these types of offers from time to time from the smaller Web companies who read AskApache.. but when I noticed the SSH access was jailed and saw how restrictive the shell was I felt like I was on a windows box..  I want a shell, cpanel sucks.  I compile and run everything from the shell so thats was a deal-breaker and I sorta forgot all about it.</p>
<p><strong>The goal is to add the HostGator server</strong> to be an <a href="http://www.askapache.com/security/mirror-using-rsync-ssh.html">exact mirror</a> of the z.askapache.com domain, then to add that server as a 2nd A record to my DNS zone.  That way half the visitors to the size will be taking up resources and bandwidth on the <a href="http://secure.hostgator.com/cgi-bin/affiliates/clickthru.cgi?id=AskApache-rrdns">HostGator</a> server instead of mine.</p>
<p><strong>Round Robin A records</strong> in DNS are intended to evenly distribute queries between each host of the same name.  Using some tricks straight out of a <a href="http://www.askapache.com/security/computer-security-toolbox-2.html">hackers toolbox</a> we can <a href="#dns-robin-works">verify if the distribution</a> is taking place.  (<a href="#dns-robin-works">It is.</a>)  <br class="C" /></p>
<h2><a id="#dns-robin-dns" name="#dns-robin-dns"></a>DNS &#8211; Domain Name System</h2>
<p>The Domain Name System is often analogized as a &#8220;phone book&#8221; for the Internet because it translates human-friendly computer hostnames into IP addresses. For example, <code>www.askapache.com</code> translates to <code>208.113.134.190</code>.  Every request for a human-friendly hostname first needs to be translated to the IP before the server can be queried.  Normally each hostname corresponds to exactly 1 IP address.  But in a Round Robin setup, the idea is to have the hostname correspond to multiple IP addresses, which are different servers that house the exact same content, resulting in some hosts requesting files from one server, and another host requesting files from the other server, resulting in less CPU resources and bandwidth.</p>
<p>Here is an the zone for <code>z.askapache.com</code> Round Robin records:</p>
<table summary="Round Robin DNS Records" id="ver-zebra">
<colgroup>
<col class="e" />
<col class="o" />
<col class="e" />
<col class="o" />
<col class="e" /></colgroup>
<thead>
<tr>
<th scope="col" class="e">QUERY</th>
<th scope="col" class="o">TTL</th>
<th scope="col" class="e">CLASS</th>
<th scope="col" class="o">TYPE</th>
<th scope="col" class="e">ANSWER</th>
</tr>
</thead>
<tbody>
<tr>
<td>z.askapache.com</td>
<td>13084</td>
<td>IN</td>
<td>A</td>
<td>64.111.114.111</td>
</tr>
<tr>
<td>z.askapache.com</td>
<td>13084</td>
<td>IN</td>
<td>A</td>
<td>69.56.174.114</td>
</tr>
</tbody>
</table>
<h2><a id="#dns-robin-round" name="#dns-robin-round"></a>Round Robin DNS</h2>
<p>Round robin DNS is a technique of load distribution, load balancing, or fault-tolerance provisioning multiple, redundant Internet Protocol service hosts, e.g., Web servers, FTP servers, by managing the Domain Name System&#8217;s (DNS) responses to address requests from client computers according to an appropriate statistical model.</p>
<p>In its simplest implementation Round-robin DNS works by responding to DNS requests not only with a single IP address, but a list of IP addresses of several servers that host identical services. The order in which IP addresses from the list are returned is the basis for the term round robin. With each DNS response, the IP address sequence in the list is permuted. Usually, basic IP clients attempt connections with the first address returned from a DNS query so that on different connection attempts clients would receive service from different providers, thus distributing the overall load among servers.</p>
<p>Round robin DNS is often used for balancing the load of geographically-distributed Web servers. For example, a company has one domain name and three identical web sites residing on three servers with three different IP addresses. When one user accesses the home page it will be sent to the first IP address. The second user who accesses the home page will be sent to the next IP address, and the third user will be sent to the third IP address. In each case, once the IP address is given out, it goes to the end of the list. The fourth user, therefore, will be sent to the first IP address, and so forth.</p>
<p>Although easy to implement, round robin DNS has problematic drawbacks, such as those arising from record caching in the DNS hierarchy itself, as well as client-side address caching and reuse, the combination of which can be difficult to manage. Round robin DNS should not solely be relied upon for service availability. If a service at one of the addresses in the list fails, the DNS will continue to hand out that address and clients will still attempt to reach the inoperable service.</p>
<h2><a id="#dns-robin-works" name="#dns-robin-works" title="Efficacy of DNS Load Balancing"></a>Does Round Robin Work</h2>
<p>Definately.  I can look at the access logs for both servers and see that they are splitting the requests nicely.   It is definately not an exact split however, look at these statistics and you&#8217;ll see what I mean.</p>
<pre class='brushbash'>
$ dig @ns1.dreamhost.com +authority +all z.askapache.com
&nbsp;
;; ANSWER SECTION:
z.askapache.com.        14400   IN      A       69.56.174.114
z.askapache.com.        14400   IN      A       64.111.114.111
&nbsp;
$ dig @ns1.dreamhost.com +authority +all z.askapache.com
&nbsp;
;; ANSWER SECTION:
z.askapache.com.        14400   IN      A       64.111.114.111
z.askapache.com.        14400   IN      A       69.56.174.114
</pre>
<p>The effects of caching will distort the effectiveness of any IP address allocation algorithm unless a 0 TTL is used which has the effect of significantly increasing the load on the DNS (and is not always implemented consistently). In this case the cure may be worse than the disease Good news we have good load balancing on our web servers. Bad news we need 17 more DNS servers!. Intuitively, and without running any experiments to verify, we would suggest that given a normal TTL (12 hours or more) and ANY IP allocation algorithm other than a single static list, loads should be reasonably balanced .</p>
<p><strong>Full root server query</strong></p>
<pre class='brushbash'>
Tracing to z.askapache.com[a] via A.ROOT-SERVERS.NET, maximum of 3 retries
A.ROOT-SERVERS.NET [.] (198.41.0.4)
 |\___ L.GTLD-SERVERS.NET [com] (192.41.162.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ D.GTLD-SERVERS.NET [com] (192.31.80.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ J.GTLD-SERVERS.NET [com] (192.48.79.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ H.GTLD-SERVERS.NET [com] (192.54.112.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ E.GTLD-SERVERS.NET [com] (192.12.94.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ F.GTLD-SERVERS.NET [com] (192.35.51.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ I.GTLD-SERVERS.NET [com] (192.43.172.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ G.GTLD-SERVERS.NET [com] (192.42.93.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ B.GTLD-SERVERS.NET [com] (2001:0503:231d:0000:0000:0000:0002:0030) Not queried
 |\___ B.GTLD-SERVERS.NET [com] (192.33.14.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ A.GTLD-SERVERS.NET [com] (2001:0503:a83e:0000:0000:0000:0002:0030) Not queried
 |\___ A.GTLD-SERVERS.NET [com] (192.5.6.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ C.GTLD-SERVERS.NET [com] (192.26.92.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
 |\___ M.GTLD-SERVERS.NET [com] (192.55.83.30)
 |     |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
 |     |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
 |      \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
  \___ K.GTLD-SERVERS.NET [com] (192.52.178.30)
       |\___ ns3.dreamhost.com [askapache.com] (66.33.216.216) Got authoritative answer
       |\___ ns2.dreamhost.com [askapache.com] (208.96.10.221)
        \___ ns1.dreamhost.com [askapache.com] (66.33.206.206) Got authoritative answer
&nbsp;
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 64.111.114.111
  ns1.dreamhost.com (66.33.206.206)       z.askapache.com -&gt; 69.56.174.114
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 64.111.114.111
  ns3.dreamhost.com (66.33.216.216)       z.askapache.com -&gt; 69.56.174.114
</pre>
<h2><a id="#dns-online-tools" name="#dns-online-tools"></a>Live Online DNS Tools</h2>
<ul>
<li><a href="http://member.dnsstuff.com/amember/go.php?r=323972&#038;i=l0">DNSstuff.com &#8211; Your Destination for DNS and Networking Tools</a></li>
<li><a href="http://www.zonecheck.fr/cgi-bin/zc.cgi?zone=askapache.com&#038;ns0=ns1.dreamhost.com&#038;ips0=&#038;ns1=ns2.dreamhost.com&#038;ips1=&#038;ns2=ns3.dreamhost.com&#038;ips2=&#038;ns3=&#038;ips3=&#038;ns4=&#038;ips4=&#038;ns5=&#038;ips5=&#038;ns6=&#038;ips6=&#038;ns7=&#038;ips7=&#038;intro=t&#038;explain=t&#038;details=t&#038;progress=counter&#038;report=byseverity&#038;format=html&#038;lang=en&#038;errorlvl=allwarning&#038;profile=automatic&#038;chkmail=t&#038;chkzone=t&#038;chkrir=t&#038;transp3=ipv4&#038;transp3=ipv6&#038;transp4=std">ZoneCheck</a></li>
<li><a href="http://pingability.com/zoneinfo.jsp?domain=askapache.com">Quick Check &#8211; Pingability.com</a></li>
<li><a href="http://www.squish.net/dnscheck/dnscheck.cgi?host=askapache.com&#038;type=ANY&#038;show_rootservers=on&#038;removebroken=on&#038;cnameprocessing=on&#038;show_mainworkings=on&#038;show_resolving=on&#038;show_allservers=on&#038;getbindversions=on&#038;retries=5&#038;querylevel=15">Squishywishywoo: complete dns traversal checking</a></li>
<li><a href="http://www.zonecut.net/dns/?domain=askapache.com&#038;find_subs=on">ZoneCut DNS</a></li>
<li><a href="http://atrey.karlin.mff.cuni.cz/~mj/sleuth/?domain=askapache.com&#038;verbose=ON&#038;server=ns1.dreamhost.com&#038;serverip=&#038;action=Submit&#038;.cgifields=verbose">DNS Sleuth</a></li>
<li><a href="http://www.pweb.cz/en/dns-test/dom.php">DNS test &#8211; Domain name DNS test &#8211; pweb.cz</a></li>
<li><a href="http://www.opendns.com/support/cache/?d=z.askapache.com">OpenDNS &#8211; Support &#8211; CacheCheck</a></li>
<li><a href="http://www.dnscolos.com/dnsreport.php">DNSReport</a></li>
<li><a href="http://freedns.afraid.org/domain/dnstrace.php?domain=askapache.com&#038;submit=Trace">DNSTrace</a></li>
<li><a href="http://www.intodns.com/askapache.com">intoDNS</a></li>
<li><a href="http://www.dnsthru.com/">DNSthru.com</a></li>
<li><a href="http://demo.dnsdoctor.org/cgi-bin/diagnose.cgi?zone=askapache.com&#038;ns0=ns1.dreamhost.com&#038;ips0=&#038;ns1=ns2.dreamhost.com&#038;ips1=&#038;ns2=ns3.dreamhost.com&#038;ips2=&#038;ns3=&#038;ips3=&#038;ns4=&#038;ips4=67.19.1.10&#038;ns5=&#038;ips5=67.19.0.10&#038;ns6=&#038;ips6=67.18.150.114&#038;ns7=&#038;ips7=&#038;intro=t&#038;format=html&#038;lang=en&#038;testname=t&#038;explain=t&#038;details=t&#038;progress=testdesc&#038;errorlvl=allwarning&#038;dontstop=nostop&#038;profile=automatic&#038;report=byseverity&#038;chkmail=t&#038;transp3=ipv4&#038;transp3=ipv6&#038;transp4=std">DNS Doctor</a></li>
<li><a href="http://www.checkdns.net/powercheck.aspx">Power Check</a></li>
</ul>
<h2><a id="#dns-links" name="#dns-links"></a>More Reading</h2>
<ul>
<li><a href="http://www.zytrax.com/books/dns/ch9/rr.html">HOWTO &#8211; Configure Load Balancing</a></li>
<li><a href="http://ntrg.cs.tcd.ie/undergrad/4ba2.01/group8/DNS.html">Load Sharing with DNS</a></li>
</ul>
<h3><a id="#dns-rfc-list" name="#dns-rfc-list"></a>RFC&#8217;s related to DNS</h3>
<ul>
<li><a href="http://rfc.askapache.com/rfc920/rfc920.html" title="protocol,signature,resource,dnssec,records,response,record,dnskey,algorithm,standards,domain,server,resolver,security">RFC 920</a>:  Specified original TLDs: .arpa, .com, .edu, .org, .gov, .mil and two-character country codes</li>
<li><a href="http://rfc.askapache.com/rfc1032/rfc1032.html">RFC 1032</a>:  Domain administrators guide</li>
<li><a href="http://rfc.askapache.com/rfc1033/rfc1033.html">RFC 1033</a>:  Domain administrators operations guide</li>
<li><a href="http://rfc.askapache.com/rfc1034/rfc1034.html">RFC 1034</a>:  Domain Names &#8211; Concepts and Facilities.</li>
<li><a href="http://rfc.askapache.com/rfc1035/rfc1035.html">RFC 1035</a>:  Domain Names &#8211; Implementation and Specification</li>
<li><a href="http://rfc.askapache.com/rfc1101/rfc1101.html">RFC 1101</a>:  DNS Encodings of Network Names and Other Types</li>
<li><a href="http://rfc.askapache.com/rfc1123/rfc1123.html">RFC 1123</a>:  Requirements for Internet Hosts &#8212; Application and Support</li>
<li><a href="http://rfc.askapache.com/rfc1912/rfc1912.html">RFC 1912</a>:  Common DNS Operational and Configuration Errors</li>
<li><a href="http://rfc.askapache.com/rfc1995/rfc1995.html">RFC 1995</a>:  Incremental Zone Transfer in DNS</li>
<li><a href="http://rfc.askapache.com/rfc1996/rfc1996.html">RFC 1996</a>:  A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)</li>
<li><a href="http://rfc.askapache.com/rfc2136/rfc2136.html">RFC 2136</a>:  Dynamic Updates in the domain name system (DNS UPDATE)</li>
<li><a href="http://rfc.askapache.com/rfc2181/rfc2181.html">RFC 2181</a>:  Clarifications to the DNS Specification</li>
<li><a href="http://rfc.askapache.com/rfc2182/rfc2182.html">RFC 2182</a>:  Selection and Operation of Secondary DNS Servers</li>
<li><a href="http://rfc.askapache.com/rfc2308/rfc2308.html">RFC 2308</a>:  Negative Caching of DNS Queries (DNS NCACHE)</li>
<li><a href="http://rfc.askapache.com/rfc2317/rfc2317.html">RFC 2317</a>:  Classless IN-ADDR.ARPA delegation</li>
<li><a href="http://rfc.askapache.com/rfc2671/rfc2671.html">RFC 2671</a>:  Extension Mechanisms for DNS (EDNS0)</li>
<li><a href="http://rfc.askapache.com/rfc3597/rfc3597.html">RFC 3597</a>:  Handling of Unknown DNS Resource Record (RR) Types</li>
<li><a href="http://rfc.askapache.com/rfc3696/rfc3696.html">RFC 3696</a>:  Application Techniques for Checking and Transformation of Names</li>
<li><a href="http://rfc.askapache.com/rfc4343/rfc4343.html">RFC 4343</a>:  Domain Name System (DNS) Case Insensitivity Clarification</li>
<li><a href="http://rfc.askapache.com/rfc4592/rfc4592.html">RFC 4592</a>:  The Role of Wildcards in the Domain Name System</li>
<li><a href="http://rfc.askapache.com/rfc4892/rfc4892.html">RFC 4892</a>:  Requirements for a Mechanism Identifying a Name Server Instance</li>
<li><a href="http://rfc.askapache.com/rfc5001/rfc5001.html">RFC 5001</a>:  DNS Name Server Identifier Option (NSID)</li>
<li>RFC 5395:  Domain Name System (DNS) IANA Considerations</li>
</ul>
<p class="wikicop">This page contains content by <a rel="nofollow" href="http://en.wikipedia.org/w/index.php?title=Round_robin_DNS&#038;action=history">Author</a> of <a href="http://en.wikipedia.org/wiki/Round_robin_DNS" rel="nofollow">Article</a> from <a href="http://en.wikipedia.org/wiki/Main_Page" rel="nofollow">Wikipedia</a> and is licensed under the <a href="http://www.askapache.com/gnu-fdl.txt" rel="nofollow">GNU FDL</a>.</p>
<p><strong>Table of Contents</strong></p>
<ul>
<li><a href="#round-robin-concept">Round Robin Concept</a></li>
<li><a href="#dns-robin-dns">DNS &#8211; Domain Name System</a></li>
<li><a href="#dns-robin-round">Round Robin DNS</a></li>
<li><a href="#dns-robin-works">Efficacy of DNS Load Balancing</a></li>
<li><a href="#dns-online-tools">Live Online DNS Tools</a></li>
<li><a href="#dns-links">More Reading</a></li>
<li><a href="#dns-rfc-list">RFC&#8217;s related to DNS</a></li>
</ul>
<p><a href="http://www.askapache.com/linux-unix/dns-round-robin-rsync-over-ssh.html">DNS Round Robin Configuration using Rsync over SSH</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/linux-unix/dns-round-robin-rsync-over-ssh.html/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mirroring an Entire Site using Rsync over SSH</title>
		<link>http://www.askapache.com/security/mirror-using-rsync-ssh.html</link>
		<comments>http://www.askapache.com/security/mirror-using-rsync-ssh.html#comments</comments>
		<pubDate>Fri, 10 Apr 2009 11:40:44 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Linux Unix BSD]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Shell Scripting]]></category>
		<category><![CDATA[Web Hosting]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[mirror]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2581</guid>
		<description><![CDATA[<p><a href="http://www.askapache.com/security/mirror-using-rsync-ssh.html" class="IFL"><img src="/wp-content/uploads/2009/04/mirror_buildings.jpg" alt="Website Mirrors with Rsync" title="Website Mirrors with Rsync" width="300" height="201" /></a><strong>Sometimes there is an urgent need</strong> for creating an exact duplicate or "mirror" of a web site on a separate server.  This could be needed for creating Round Robin Setups, Load-Balancing, Failovers, or for just plain vanilla backups.  In the past I have used a lot of different methods to copy data from one server to another, including creating an archive of the whole directory and then using scp to send the file over, creating an archive and then encrypting it and then sending that file over using ftp, <a href="http://curl.askapache.com/">curl</a>, etc., and my <strong>persistence at learning new ways to do things has paid off</strong> because now I use rsync to keep an exact replica of the entire directory on an external server, without having to use all the CPU and resources of other mirroring methods.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/security/mirror-using-rsync-ssh.html" class="IFL"><img src="/wp-content/uploads/2009/04/mirror_buildings.jpg" alt="Website Mirrors with Rsync" title="Website Mirrors with Rsync" width="300" height="201" /></a><strong>Sometimes there is an urgent need</strong> for creating an exact duplicate or &#8220;mirror&#8221; of a web site on a separate server.  This could be needed for creating Round Robin Setups, Load-Balancing, Failovers, or for just plain vanilla backups.  In the past I have used a lot of different methods to copy data from one server to another, including creating an archive of the whole directory and then using scp to send the file over, creating an archive and then encrypting it and then sending that file over using ftp, <a href="http://curl.askapache.com/">curl</a>, etc., and my <strong>persistence at learning new ways to do things has paid off</strong> because now I use rsync to keep an exact replica of the entire directory on an external server, without having to use all the CPU and resources of other mirroring methods.<br class="C" /></p>
<p>For this article I will show how I setup a web mirror of <var>z.askapache.com</var> from my DreamHost server to my HostGator Server.  For the transfer and synchronization of the directories we will be using rsync over SSH.  We will also be automating this task using a cronjob with no user-interaction, so creating public and private keys for the ssh will be neccessary.  Finally, I provide a simple shell script that prevents anyone from logging into your account with the created keys for any purpose other than to rsync.</p>
<p><br class="C" /><strong>Table of Contents</strong></p>
<ol>
<li><a href="#rsync-mirror">Rsync Synchronization Magic</a></li>
<li><a href="#site-mirror-rsync-ssh">Securing Rsync with SSH</a></li>
<li><a href="#site-mirror-ssh-keygen">Generate Keys with No Password</a></li>
<li><a href="#ssh-config-file">Custom SSH Connection Info</a></li>
<li><a href="#ssh-crontab-rsync">Creating Cronjob for Synchronization</a></li>
<li><a href="#secure-ssh-keys">Only Allow rsync</a></li>
<li><a href="#debug-ssh-rsync">Rsync/SSH Debugging and Stats</a></li>
<li><a href="#rsync-algorithm">Rsync Algorithm</a></li>
</ol>
<h2><a id="rsync-mirror" name="rsync-mirror"></a>Rsync Synchronization Magic</h2>
<div><a class="IFL" href="http://rsync.samba.org/"><img src="/wp-content/uploads/2009/04/200px-newrsynclogo.jpg" alt="rsync" title="rsync" width="200" height="125" /></a></p>
<dl>
<dt><strong>rsync</strong></dt>
<dd><a href="http://rsync.samba.org/">rsync</a> is an <a href="http://www.opensource.org/">open source</a> file transfer program for Unix systems that uses the &#8220;rsync algorithm&#8221; which provides a very fast method for synchronizing files and directories from one location to another while minimizing data transfer using delta encoding when appropriate. An important feature of rsync not found in most similar programs/protocols is that the mirroring takes place with only one transmission in each direction.. It does this by sending just the differences in the files across the link, without requiring that both sets of files are present at one of the ends of the link beforehand. </dd>
</dl>
<p><br class="C" /></div>
<h2><a id="site-mirror-rsync-ssh" name="site-mirror-rsync-ssh"></a>Securing Rsync with SSH</h2>
<p>I NEVER transfer any unencrypted data around unless that data is transported encrypted and to a trusted recipient, (<em>I use HTTPS for WordPress administration</em>) and I haven&#8217;t had time to probe the HostGator system for security issues yet, so right away I decided I needed an automated way to securely transfer z.askapache.com files TO hostgator, while not allowing my hostgator account access back on my main server.  So if the hostgator account were to get hacked somehow, the cracker/spammer wouldn&#8217;t have access back to my main server.</p>
<h2><a id="site-mirror-ssh-keygen" name="site-mirror-ssh-keygen"></a>Generate Keys with No Password</h2>
<p>First I created a private key, specifically a passwordless host key, meaning to gain access with ssh you only need to supply the key, not a password+key like normal.</p>
<pre class='brushbash'>
[local@dreamhost] $ mkdir -p ~/.ssh &#038;&#038; chmod 700 ~/.ssh
&nbsp;
# Create the public and private keys
# public key at: z.askapache-hostgator.id_rsa.pub
# private key at: z.askapache-hostgator.id_rsa
[local@dreamhost] $ ssh-keygen -t rsa -b 2048 -f ~/.ssh/z.askapache-hostgator.id_rsa
&nbsp;
# add the public key to remote hosts ~/.ssh/authorized_keys file
[local@dreamhost] $ ssh-copy-id -i ~/.ssh/z.askapache-hostgator.id_rsa.pub remoteuser@remotehost
&nbsp;
# or use scp + ssh to add the public key
[local@dreamhost] $ scp ~/.ssh/z.askapache-hostgator.id_rsa.pub remoteuser@remotehost:/home/remoteuser/
[local@dreamhost] $ ssh remoteuser@remotehost
[gatoraskapache@gator] $ mkdir -p ~/.ssh &#038;&#038; chmod 700 ~/.ssh
[gatoraskapache@gator] $ cat ~/z.askapache-hostgator.id_rsa.pub &gt;&gt; ~/.ssh/authorized_keys
[gatoraskapache@gator] $ chmod 600 ~/.ssh/authorized_keys
</pre>
<h2><a id="ssh-config-file" name="ssh-config-file"></a>Custom SSH Connection Info</h2>
<p>This helps alot, by adding this to the very top of my ~/.ssh/config file I don&#8217;t have to add all this stuff to the rsync command-line.  Basically when I reference connecting to the host &#8216;gator&#8217; it uses all these options.  Very helpful and you can add as many entries as you want.</p>
<pre class='brushbash'>
Host gator
   IdentityFile ~/.ssh/z.askapache-hostgator.id_rsa
   Port 2222
   Protocol 2
   User gatoraskapache
   HostName gator555.hostgator.com
   PasswordAuthentication no
</pre>
<h2><a id="ssh-crontab-rsync" name="ssh-crontab-rsync"></a>Creating Cronjob for Synchronization</h2>
<p>This cronjob runs every 30 minutes, copying all modified files from my local directory <code>~/z.askapache.com/</code> to the remote directory <code>~/public_html/z/</code>.  First I backup the current crontab, then I edit the crontab and add this.</p>
<p><kbd>crontab -l > .crontab-`date +%F.backup`; crontab -e</kbd></p>
<pre class='brushhtaccess'>
*/30 * * * * /usr/bin/rsync -e &#039;ssh&#039; -rt &#45;-delete ~/z.askapache.com/ gator:&#039;~/public_html/z/&#039; 1&gt;/dev/null
@midnight /usr/bin/find ~/z.askapache.com/ -type d ! -perm 755 -exec chmod 755 {} \; 1&gt;/dev/null
@midnight /usr/bin/find ~/z.askapache.com/ -type f ! -perm 644 -exec chmod 644 {} \; 1&gt;/dev/null
</pre>
<p>Those 2 find commands scheduled to run at midnight simply fix and permissions on files and directories in my static folder.  They are all static files so there is no reason they need to have any other permission.</p>
<h2><a id="secure-ssh-keys" name="secure-ssh-keys"></a>Only Allow rsync</h2>
<p>This is SWEET!  If you like candy that is..  It&#8217;s called each time anything logs into your machine using the password less key we created above, and it simple checks what command the login process is attempting to issue.  To set this up you need to edit the ~/.ssh/authorized_keys file on the remote host and prefix your public key that you added with a command directive to execute a script:</p>
<pre class='brushbash'>
command="/home/remoteuser/validate-rsync.sh" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwBhj6UCS7JbJ08C8pWJqCh2iXZMN7tXpYZh47f4gZZBwrNHZQ== localuser@dreamhost
</pre>
<h3>validate-rsync.sh</h3>
<p>For rsync requests it will always be <code>rsync &#45;-server</code> at the start of the command, so if the command is anything else then this script:</p>
<ol>
<li>Sends you an email notifying you somethings up..</li>
<li>Moves the <code>~/.ssh</code> folder to <code>~/.locked-ssh</code></li>
<li>Adds cronjob to move the folder back in about an hour.</li>
</ol>
<pre class='brushbash'>
#!/bin/bash
# Author: http://www.askapache.com
# Version: 1.2
# Date: 04-08-2009
&nbsp;
# If the command used to login to ssh correctly starts with &#039;rsync &#45;-server&#039;
# then exit this script and dont process the rest of the script
case "$SSH_ORIGINAL_COMMAND" in &#039;rsync &#45;-server&#039;*) exit 0; ;; esac;
&nbsp;
# the home directory where the .ssh folder is located
H=/home/remoteuser
&nbsp;
# if there is a locked ssh folder, kill the rsync and die
[[ -d $H/.lssh ]] &#038;&#038; echo "REJECTED" &#038;&#038; exit 1
&nbsp;
EMAIL=webmaster@askapache.com # notified about locked status
OC=$H/old-crontab.txt # the original crontab
NC=$H/new-crontab.txt #the new crontab
&nbsp;
# When to unlock the rsync
UNLOCK_AT=$(( date +%M\ %k &#45;-date=&#039;30 minute 1 hour&#039; ))
&nbsp;
# move the .ssh to .lssh which locks all key-logins
mv $H/.ssh $H/.lssh
&nbsp;
# mail a notice to the boss
echo $SSH_CONNECTION | mail -s &#039;RSYNC LOCKED!!!&#039; "$EMAIL"
&nbsp;
# subshell backs-up crontab then deletes active cron
(

 crontab -l &gt; $OC &&gt;/dev/null || echo -n #backup current crontab
 crontab -r &gt;/dev/null 2&gt;&#038;1 || echo -n # delete current crontab
)
&nbsp;
# subshell creates new crontab combined with old crontab
(
 # create new crontab
 echo -en "MAILTO=&#039;${EMAIL}&#039;\n${UNLOCK_AT} * * * mv $H/.lssh $H/.ssh" &gt;&gt; $NC
 echo -n " &#038;&#038; date|mail -s &#039;UNLOCKED!!!&#039; &#039;${EMAIL}&#039; &#038;&#038; crontab $OC || rm $OC &#038;&#038; rm $OC" &gt;&gt; $NC

 # add old crontab to new crontab minus any MAILTO lines
 cat $OC | sed &#039;/^MAILTO/d&#039; &gt;&gt; $NC

 # load the new crontab and if it doesnt work notify boss
 crontab $NC || echo "manually mv .lssh to .ssh" mail -s &#039;CRONTAB PROBLEM!!!&#039; "$EMAIL"

 # remove new crontab
 rm $NC
)
&nbsp;
exit $?
</pre>
<p><strong>Here is the cronjob entry</strong> it creates&#8230; This will enable the rsync again by moving the folder back, then it mails you to alert you that its back up, and finally the original crontab is restored.</p>
<pre class='brushbash'>
MAILTO="askapache@gmail.com"
03 9 * * * mv ~/.locked-ssh ~/.ssh &#038;&#038; date|mail -s &#039;RUNLOCKED!!!&#039; "webmaster@askapache.com" &#038;&#038; crontab ~/old-crontab.txt
</pre>
<h2><a id="debug-ssh-rsync" name="debug-ssh-rsync"></a>Rsync/SSH Debugging and Stats</h2>
<p>Adding the option -v to the ssh command, ie <kbd>rsync -e 'ssh -vv'</kbd> will give you a lot of debugging info.</p>
<p>By adding &#8211;stats to your rsync command you can get a detailed look at its efficacy.</p>
<pre class='brushhtaccess'>
Number of files: 14900
Number of files transferred: 0
Total file size: 1456832331 bytes
Total transferred file size: 0 bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 320551
File list generation time: 17.393 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 320571
Total bytes received: 20
&nbsp;
sent 320571 bytes  received 20 bytes  17329.24 bytes/sec
total size is 1456832331  speedup is 4544.21
</pre>
<h2><a id="rsync-algorithm" name="rsync-algorithm"></a>Rsync Algorithm</h2>
<p>The rsync utility uses an algorithm (invented by the Australian computer programmer Andrew Tridgell) for efficiently transmitting a structure (such as a file) across a communications link when the receiving computer already has a different version of the same structure.</p>
<p>The recipient splits its copy of the file into fixed-size non-overlapping chunks, of size S, and computes two checksums for each chunk: the MD4 hash, and a weaker &#8216;rolling checksum&#8217;. It sends these checksums to the sender. Version 30 of the protocol (released with rsync version 3.0.0) now uses MD5 hashes rather than MD4.</p>
<p>The sender computes the rolling checksum for every chunk of size S in its own version of the file, even overlapping chunks. This can be calculated efficiently because of a special property of the rolling checksum: if the rolling checksum of bytes n through n + S − 1 is R, the rolling checksum of bytes n + 1 through n + S can be computed from R, byte n, and byte n + S without having to examine the intervening bytes. Thus, if one had already calculated the rolling checksum of bytes 1–25, one could calculate the rolling checksum of bytes 2–26 solely from the previous checksum, and from bytes 1 and 26.</p>
<p>The rolling checksum used in rsync is based on Mark Adler&#8217;s adler-32 checksum, which is used in zlib, and which itself is based on Fletcher&#8217;s checksum.  The sender then compares its rolling checksums with the set sent by the recipient to determine if any matches exist. If they do, it verifies the match by computing the MD4 checksum for the matching block and by comparing it with the MD4 checksum sent by the recipient.</p>
<p>The sender then sends the recipient those parts of its file that did not match any of the recipient&#8217;s blocks, along with assembly instructions on how to merge these blocks into the recipient&#8217;s version. In practice, this creates a file identical to the sender&#8217;s copy. However, it is in principle possible that the recipient&#8217;s copy differs at this point from the sender&#8217;s: this can happen when the two files have different chunks that nonetheless possess the same MD4 hash and rolling checksum; the chances for this to happen are in practice extremely remote.</p>
<p>If the sender&#8217;s and recipient&#8217;s versions of the file have many sections in common, the utility needs to transfer relatively little data to synchronize the files.</p>
<p>While the rsync algorithm forms the heart of the rsync application that essentially optimizes transfers between two computers over TCP/IP, the rsync application supports other key features that aid significantly in data transfers or backup. They include compression and decompression of data block by block using zlib at sending and receiving ends, respectively, and support for protocols such as ssh that enables encrypted transmission of compressed and efficient differential data using rsync algorithm. Instead of ssh, stunnel can also be used to create an encrypted tunnel to secure the data transmitted.</p>
<p>Finally, rsync is capable of limiting the bandwidth consumed during a transfer, a useful feature that few other standard file transfer protocol offer.</p>
<p class="wikicop">This page contains content by <a rel="nofollow" href="http://en.wikipedia.org/w/index.php?title=Rsync&#038;action=history">Author</a> of <a href="http://en.wikipedia.org/wiki/Rsync" rel="nofollow">Article</a> from <a href="http://en.wikipedia.org/wiki/Main_Page" rel="nofollow">Wikipedia</a> and is licensed under the <a href="http://www.askapache.com/gnu-fdl.txt" rel="nofollow">GNU FDL</a>.</p>
<p><a href="http://www.askapache.com/security/mirror-using-rsync-ssh.html">Mirroring an Entire Site using Rsync over SSH</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/security/mirror-using-rsync-ssh.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Advanced Htaccess Demo/Example using Cookies, Headers, Rewrites</title>
		<link>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html</link>
		<comments>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html#comments</comments>
		<pubDate>Wed, 01 Apr 2009 03:07:53 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[htaccess rewrites]]></category>
		<category><![CDATA[http headers]]></category>
		<category><![CDATA[pdf]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2328</guid>
		<description><![CDATA[<p><a class="IFL" href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"><img src="/wp-content/uploads/2009/03/nsa-350x272.jpg" alt="Advanced Htaccess NSA" title="Advanced Htaccess NSA" width="350" height="272" /></a><strong>Whoa pretty sweet huh?</strong>  Bet you've never seen that before!  As I explain the htaccess code that achieves this, keep in mind this is merely one simple application for this code.  It's much more advanced than your basic htaccess trick, notice how this htaccess acts like a php script, very unusual..  I really wanted to share this trick after I created it for one of my clients because this is the tip of the iceberg.  Another use would be to display an alternate style sheet depending on a users theme preference.  The coolest thing about this example <acronym title="In My Humble Opinion">IMHO</acronym> is that it uses multiple advanced .htaccess ideas in order for it to work, most htaccess code on the net is very singular.  This code uses mod_headers to set the Content-Disposition header for forcing a download and uses mod_rewrite to do the rest.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a class="IFL" href="/wp-content/uploads/2009/03/nsa.jpg"><img src="/wp-content/uploads/2009/03/nsa-350x272.jpg" alt="Advanced Htaccess NSA" title="Advanced Htaccess NSA" width="350" height="272" /></a></p>
<p><strong>Welcome to the first generation of the new .htaccess tutorials/articles</strong>.  Basically these are articles detailing my BEST (almost) successful .htaccess experiments, meaning this is the only place on the net you&#8217;ll find this technique.  It&#8217;s home-grown .htaccess, and its some kush, good kush. Instead of just publishing my cryptic results and code in days past, whoah.. a working demo <em>and the NSA building</em>  <strong>;)</strong></p>
<p>Using the <a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">Mod_Rewrite Variables Cheatsheet</a> makes this example, and all advanced .htaccess code easier to understand.  Well, advanced for me at least.  I know alot of AskApache visitors are some of the top gurus in many IT fields, but mostly web developers or website owners like me..   This demo is pretty self-explanatory.. Try it out to see how simple of a task this <a href="http://www.askapache.com/htaccess/htaccess.html">.htaccess trick</a> performs.  And make sure you read the whole article as this htaccess technique can be used to do a heck of a lot more than this simple demo.</p>
<h2>Set PDF Viewing Mode</h2>
<div class="cnote">
<p id="pdfi" class="BTN FL"><span class="y"><span class="t"></span><span class="text">Inline</span></span><span class="b"><span></span></span></p>
<p id="pdfa" class="BTN FL"><span class="y"><span class="t"></span><span class="text">Download</span></span><span class="b"><span></span></span></p>
<p id="pdfs" class="BTN FL"><span class="y"><span class="t"></span><span class="text">Save As</span></span><span class="b"><span></span></span></p>
<p class="FL" style="margin-left:50px;"><kbd id="pdfr" style="border:2px solid #BFBFCC;padding:10px;line-height:1.1em;">Please make a selection, defaults to "Save As" mode.</kbd></p>
<p><br class="C" /><br />
<a style="font-size:1.2em;line-height:1.2em;width:22em;" class="BTN" href="http://www.askapache.com/storage/pdf/AskApache-Test.pdf"><span class="y"><span class="t"></span><span class="text">View PDF using selected mode &raquo;</span></span><span class="b"><span></span></span></a>
</div>
<p>Whoa pretty sweet huh?  Bet you&#8217;ve never seen that before!  As I explain the htaccess code that achieves this, keep in mind this is merely one simple application for this code.  It&#8217;s much more advanced than your basic htaccess trick, notice how this htaccess acts like a php script, very unusual..  I really wanted to share this trick after I created it for one of my clients because this is the tip of the iceberg.  Another use would be to display an alternate style sheet depending on a users theme preference.  The coolest thing about this example <acronym title="In My Humble Opinion">IMHO</acronym> is that it uses multiple advanced .htaccess ideas in order for it to work, most htaccess code on the net is very singular.  This code uses mod_headers to set the Content-Disposition header for forcing a download and uses mod_rewrite to:</p>
<ol>
<li>Send different Content-Type headers</li>
<li>Check the value of a cookie</li>
<li>Set environment variables for use later by mod_headers header directive</li>
</ol>
<h2>What&#8217;s Going On</h2>
<p>There are 3 different ways for a server to send a pdf file in response to a request for one.  This causes 3 different ways to open/view the pdf file in the clients browser.</p>
<ol>
<li>The browser display&#8217;s a <strong>&#8220;Save File As&#8221;</strong> dialog, allowing you to save the file or open.</li>
<li>The browser opens the pdf file <strong>&#8220;Inline&#8221;</strong>, opening the pdf file in the browser like a web page.</li>
<li>The browser &#8220;<strong>Downloads</strong>&#8221; the pdf file automatically as an &#8220;<strong>Attachment</strong>&#8221; and then causes an external pdf reader program like adobe reader to open the file.</li>
</ol>
<p>Some people prefer to have the option of saving the file to view later, some prefer opening it with an external program, and some just like the pdf file to load right in the browser&#8230;  The point is that by using .htaccess, we can let them choose any of the 3 methods and save their preference for all further pdf files requested from our site by that user.</p>
<h2>How It Works</h2>
<p>When you click on one of the 3 demo buttons above, &#8220;Inline&#8221;, &#8220;Save As&#8221;, or &#8220;Download&#8221;, a cookie named <code>askapache_pdf</code> is saved in your browser using the javascript below, with the value being set to which button you clicked.  Then when you request the pdf file the .htaccess code below uses mod_rewrite to read the value of the askapache_pdf cookie, and depending on which was your preference it will send alternate HTTP Headers that control how your browser handles the file.</p>
<h3>Htaccess Demo File</h3>
<p>For the demo I created the folder /storage/pdf/ and this is the .htaccess file at /storage/pdf/.htaccess</p>
<pre class='brushhtaccess'>
#
# The default Content-Type for .pdf files
# This will make .pdf files default Content-Type header have
# the value &#039;application/pdf&#039; - but the default can be overridden by
# using RewriteRule with the [T=&#039;different/type&#039;]
#
AddType application/pdf .pdf
&nbsp;
#
# Turn on the rewrite engine
# if its already on you dont need this
#
RewriteEngine On
&nbsp;
#
# Skip RewriteRules if not .pdf request, like autoindexing
# The next [2] RewriteRule directives are specific for .pdf files
# so if the filename requested does not end in .pdf
# then the [S=2] instructs the next 2 RewriteRule
# directives to be completely skipped
#
RewriteRule !.*\.pdf$ - [S=2]
&nbsp;
#
# The first RewriteCond checks to see if the askapache_pdf cookie
# is NOT set.  The second RewriteCond checks to see if the askapche_pdf
# cookie has the value of s, which is the value corresponding to
# someone clicking the "Save As" button.
#
# The [NC,OR] flag means that if the cookie askapache_pdf does not
# exist, OR (next cond) if the askapache_pdf cookie does exist and is set to &#039;s&#039;
# then process the RewriteRule.  If neither cond is true the rewriterule is skipped.
#
# If one of the RewriteCond is true, then the RewriteRule is processed.
# The RewriteRule applies to any/all requests (.*) but doesn&#039;t rewrite anything (-)
# This RewriteRule sets an Apache environment variable ASKAPACHE_PDFS to have the
# value of 1 if either rewritecond is true.  The variable can be checked by any directives
# following the rewriterule in the whole htaccess file.  The ASKAPACHE_PDFS ends in S
# because if this variable exists then it means the users preference is &#039;Save As&#039;
#
# Notice that if the user requested the pdf file without selecting a preference
# i.e. no cookie exists, then the ASKAPACHE_PDFS variable is still set.
# This just lets us pick the default preference for them, in this example the
# default is &#039;Save As&#039;
#
RewriteCond %{HTTP_COOKIE} !^.*askapache_pdf.*$ [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*askapache_pdf=s.*$ [NC]
RewriteRule .* - [E=ASKAPACHE_PDFS:1]
&nbsp;
#
# The RewriteCond checks the askapache_pdf cookie for the value &#039;a&#039;
# which &#039;a&#039; represents &#039;Download&#039;
#
# If the cookies value is &#039;a&#039; then the RewriteRule overrides the default
# Content-Type from &#039;application/pdf&#039; set with AddType earlier, to
# &#039;application/octet-stream&#039;, which is a special content-type that tells the browser
# that the file cannot be loaded by the browser &#039;Inline&#039;, but must be saved
# which will be opened by an external viewer depending on browser
#
RewriteCond %{HTTP_COOKIE} ^.*askapache_pdf=a.*$
RewriteRule .* - [T=application/octet-stream]
&nbsp;
#
# This is superfly.  If the cookie/users-preference was &#039;Save As&#039; (s)
# then the RewriteRule above the last one set the environment
# variable ASKAPACHE_PDFS to have the value 1.  The Header directive here
# is ONLY processed in that variable ASKAPACHE_PDFS exists.  That is what
# the end &#039;env=ASKAPACHE_PDFS&#039; does, it is the condition that must be met or
# the Header directive is skipped.
#
# If the ASKAPACHE_PDFS environment variable set by RewriteRule does exist
# then the header directive adds the header &#039;Content-Disposition: attachment&#039; to
# the normal Response Headers.  The &#039;Content-Disposition: attachment&#039; header
# instructs your browser to present you with the &#039;Save As&#039; dialog box
# allowing you to choose whether you want to save or open
#
Header set Content-Disposition "attachment" env=ASKAPACHE_PDFS
</pre>
<h3>Unique HTTP Headers Returned</h3>
<p>When it comes down to it, the following information is the 3 modes.  Notice each one is different, because these headers are the only thing controlling how your browser handles the file.</p>
<p>Save As Mode (askapache_pdf=s)</p>
<pre class='brushhtaccess'>
Content-Disposition: attachment
Content-Type: application/pdf
</pre>
<p>Inline Mode (askapache_pdf=i)</p>
<pre class='brushhtaccess'>
Content-Type: application/pdf
</pre>
<p>Download Mode (askapache_pdf=a)</p>
<pre class='brushhtaccess'>
Content-Type: application/octet-stream
</pre>
<h2>Javascript used by Demo</h2>
<p>The best place for javascript is quirksmode, here is a definitive article on setting, reading, parsing, etc.. <a title="I am a javascript cookie monster" href="http://www.quirksmode.org/js/cookies.html">COOKIES</a>.</p>
<pre>
  if(!gi(&#039;pdfr&#039;))return;
  var pdfr=gi(&#039;pdfr&#039;);
  var cval=getCookie(&#039;askapache_pdf&#039;);

  if(cval==&#039;i&#039;){pdfr.innerHTML=&#039;Currently set to "Inline".&#039;;}
  else if(cval==&#039;a&#039;){pdfr.innerHTML=&#039;Currently set to "Download" mode.&#039;;}
  else if(cval==&#039;s&#039;){pdfr.innerHTML=&#039;Currently set to "Save As" mode.&#039;;}
&nbsp;
  addMyEvent(gi(&#039;pdfi&#039;),"mousedown",function(){setCookie("askapache_pdf", "i", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Inline".&#039;; return false; });
  addMyEvent(gi(&#039;pdfa&#039;),"mousedown",function(){setCookie("askapache_pdf", "a", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Download".&#039;; return false; });
  addMyEvent(gi(&#039;pdfs&#039;),"mousedown",function(){setCookie("askapache_pdf", "s", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Save As".&#039;; return false; });
</pre>
<hr class="C" />
<hr class="C" />
<h2>Alternative Method &#8211; No Cookies + PHP</h2>
<p>This is what I came up with first for my client, and then while programming the php I noticed.. Hey!  I think I can do the same thing using .htaccess, which would save me on cpu/memory/potential security/etc.. but this works great too.  Though you will need to hack the code to get it working probably..</p>
<p>Note that the .htaccess rewrite code I used here used FILENAME-i.pdf or FILENAME-s.pdf to pass the preference to the pdf-dl.php script, it also worked for FILENAME.pdf?i=i</p>
<h3>pdf-dl.php</h3>
<p><?php<br />
if (<br />
  !isset($_GET['file'])<br />
  || ($f=$_GET['file'])===false<br />
  || ($fp=@fopen($f,"rb"))===false<br />
  || ($fi=pathinfo($f))===false<br />
  || ($fi['fsize']=filesize($f))===false<br />
  || strtolower($fi["extension"])!='pdf'<br />
) die('Failed');</p>
<p>ob_start();<br />
header('Accept-Ranges: bytes');<br />
header("Content-Length: {$fi['fsize']}");<br />
header('Content-Type: application/pdf');<br />
if(!isset($_GET['i'])) header("Content-Disposition: attachment; filename=\"{$fi['basename']}\"");</p>
<p>$sent = 0;<br />
while ( !feof($fp) &#038;&#038; $sent < $fi['fsize'] &#038;&#038; ($buf = fread($fp, 8192)) != '' ){<br />
  echo $buf;<br />
  $sent += strlen($buf);<br />
  flush();<br />
  ob_flush();<br />
}<br />
fclose($fp);<br />
exit;<br />
?>
</pre>
<h3>Alternate Method .htaccess</h3>
<pre class='brushhtaccess'>
#
# Deny direct request to pdf-dl.php file
#
RewriteCond %{THE_REQUEST} ^.*pdf-dl\.php.*$ [NC]
RewriteRule .* - [F]
&nbsp;
#
# Handle PDF files named anything-i.pdf as inline
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]*)-i\.pdf$  /cgi-bin/pdf-dl.php?i=i&#038;file=%{DOCUMENT_ROOT}/storage/pdf/$1.pdf [L,NC,QSA,S=1]
&nbsp;
#
# Handle PDF files without -i.pdf as attachments
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]*)\.pdf$  /cgi-bin/pdf-dl.php?file=%{DOCUMENT_ROOT}/storage/pdf/$1.pdf [L,NC,QSA]
</pre>
<h2>More Info</h2>
<p>The following is more information about the Content-Dispositon header and related headers, and will make you an expert at this if you read it all.. (no thanks)</p>
<h3>Interesting Reading</h3>
<p>Here is the thread of the original draft proposal for the Content-Disposition header.</p>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03620.html">Content-Disposition Header</a>, <em>Rens Troost - 22 Jun 1993</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03629.html">Re: Content-Disposition Header</a>, <em>Nathaniel Borenstein</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03630.html">Re: Content-Disposition Header</a>, <em>Gabe Beged-Dov</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03631.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03635.html">Re: Content-Disposition Header</a>, <em>Gabe Beged-Dov</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03641.html">Content-Disposition Header and multipart/alternative</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03645.html">Re: Content-Disposition Header and multipart/alternative</a>, <em>Nathaniel Borenstein</em></li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03632.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03633.html">Re: Content-Disposition Header</a>, <em>Nathaniel Borenstein</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03634.html">Re: Content-Disposition Header</a>, <em>Ed Levinson (Contractor)</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03636.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03640.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03650.html">Re: Content-Disposition Header</a>, <em>Harald Tveit Alvestrand</em></li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03621.html">Re: Content-Disposition Header</a>, <em>Steve Dorner</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03622.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03624.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em></li>
</ul>
</li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03652.html">Re: Content-Disposition Header</a>, <em>Carlyn M. Lowery</em></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>Intense Reading</h3>
<ul>
<li><a href="http://www2.roguewave.com/support/docs/leif/sourcepro/html/protocolsug/10-1.html">Using the MIME Headers Effectively</a></li>
<li><a href="http://www.iana.org/assignments/mail-cont-disp">Mail Content Disposition Values and Parameters</a></li>
<li><cite><a href="http://rfc.askapache.com/rfc1766/rfc1766.txt">Tags for the Identification of Languages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1436/rfc1436.txt">The Internet Gopher Protocol (a distributed document search and retrieval protocol)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1630/rfc1630.txt">Universal Resource Identifiers in WWW</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1738/rfc1738.txt">Uniform Resource Locators (URL)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1866/rfc1866.txt">Hypertext Markup Language - 2.0</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1945/rfc1945.txt">Hypertext Transfer Protocol -- HTTP/1.0</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2045/rfc2045.txt">Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1123/rfc1123.txt">Requirements for Internet Hosts -- Communication Layers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc822/rfc822.txt">Standard for The Format of ARPA Internet Text Messages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1808/rfc1808.txt">Relative Uniform Resource Locators</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1036/rfc1036.txt">Standard for Interchange of USENET Messages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc977/rfc977.txt">Network News Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2047/rfc2047.txt">MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1867/rfc1867.txt">Form-based File Upload in HTML</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc821/rfc821.txt">Simple Mail Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1590/rfc1590.txt">Media Type Registration Procedure</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc959/rfc959.txt">File Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1700/rfc1700.txt">Assigned Numbers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1737/rfc1737.txt">Functional Requirements for Uniform Resource Names</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1864/rfc1864.txt">The Content-MD5 Header Field</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1900/rfc1900.txt">Renumbering Needs Work</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1952/rfc1952.txt">GZIP file format specification version 4.3</a></cite></li>
<li><cite>Improving HTTP Latency</cite></li>
<li><cite><a href="http://www.isi.edu/touch/pubs/http-perf96/">Analysis of HTTP Performance</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1305/rfc1305.txt">Network Time Protocol (Version 3) Specification, Implementation and Analysis</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1951/rfc1951.txt">DEFLATE Compressed Data Format Specification version 1.3</a></cite></li>
<li><cite><a href="http://sunsite.unc.edu/mdma-release/http-prob.html">Analysis of HTTP Performance Problems,</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1950/rfc1950.txt">ZLIB Compressed Data Format Specification version 3.3</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2069/rfc2069.txt">An Extension to HTTP: Digest Access Authentication</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2068/rfc2068.txt">Hypertext Transfer Protocol -- HTTP/1.1</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2119/rfc2119.txt">Key words for use in RFCs to Indicate Requirement Levels</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1806/rfc1806.txt">Communicating Presentation Information in Internet Messages: The Content-Disposition Header</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2145/rfc2145.txt">Use and Interpretation of HTTP Version Numbers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2076/rfc2076.txt">Common Internet Message Headers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2279/rfc2279.txt">UTF-8, a transformation format of Unicode and ISO-10646</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2046/rfc2046.txt">Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2277/rfc2277.txt">IETF Policy on Character Sets and Languages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2396/rfc2396.txt">Uniform Resource Identifiers (URI): Generic Syntax and Semantics</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2617/rfc2617.txt">HTTP Authentication: Basic and Digest Access Authentication</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2110/rfc2110.txt">MIME E-mail Encapsulation of Aggregate Documents, such as HTML (MHTML)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2026/rfc2026.txt">The Internet Standards Process -- Revision 3</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2324/rfc2324.txt">Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2049/rfc2049.txt">Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2183/rfc2183.txt">Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field</a></cite></li>
</ul>
<p><a href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html">Advanced Htaccess Demo/Example using Cookies, Headers, Rewrites</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Htaccess SEO Trends by Google</title>
		<link>http://www.askapache.com/htaccess/htaccess-seo-trends.html</link>
		<comments>http://www.askapache.com/htaccess/htaccess-seo-trends.html#comments</comments>
		<pubDate>Sun, 29 Mar 2009 06:10:03 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=1059</guid>
		<description><![CDATA[<p><strong><span class="Gred">htaccess</span> vs. <span class="Gblue">httpd.conf</span></strong></p>
<p><a class="IFL hs hs24" href="http://www.askapache.com/htaccess/htaccess-seo-trends.html" title=".htaccess seo vs. httpd.conf seo"></a><br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<h2>How Relevant Is <span class="Gblue">.htaccess</span>?</h2>
<p><strong>Scale is based on the average worldwide traffic of htaccess in all years.</strong></p>
<p><img src="http://www.google.com/trends/viz?q=.htaccess&#038;graph=weekly_img&#038;sa=N" alt=".htaccess usage and seo" width="580" height="260" /><br class="C" /></p>
<h3><strong>.</strong><span class="Gred">htaccess</span> vs. <span class="Gblue">htaccess</span></h3>
<p><a href="http://google.com/trends/viz?q=.htaccess,+htaccess&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N"><img src="http://www.google.com/trends/viz?q=.htaccess,+htaccess&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="comparing .htaccess and htaccess seo" /></a><br class="C" /></p>
<h3><span class="Gred">htaccess</span> vs. <span class="Gblue">httpd.conf</span></h3>
<p><a href="http://www.google.com/trends?q=httpd.conf%2C+.htaccess&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0" title="htaccess vs. httpd.conf"><img src="http://www.google.com/trends/viz?q=httpd.conf,+.htaccess&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="htaccess vs. httpd.conf" /></a><br class="C" /></p>
<h3><span class="Gblue">mod_rewrite</span> vs. <span class="Gred">mod_security</span></h3>
<p><a href="http://google.com/trends?q=mod_rewrite%2Cmod_security&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0"><img src="http://www.google.com/trends/viz?q=mod_rewrite,mod_security&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="comparing mod_rewrite and mod_security" /></a><br class="C" /></p>
<hr class="C" />
<h2>Web Server Comparisons</h2>
<p>Of course IIS is well-known to someone like me&#8230; but who cares about the big servers when small, light, <a href="http://en.wikipedia.org/wiki/Comparison_of_lightweight_web_servers">super-fast servers</a> are on the rise?  See this <a href="http://en.wikipedia.org/wiki/Comparison_of_web_server_software">Comparison of Web Servers</a>.</p>
<h3><span class="Gblue">Apache HTTP</span> vs. <span class="Gred">Windows IIS</span></h3>
<p><a href="http://www.google.com/trends?q=%22apache+HTTP%22%2C+%22windows+IIS%22&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0" alt="Apache vs. IIS"><img src='http://www.google.com/trends/viz?q=%22apache+HTTP%22,+%22windows+IIS%22&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N' width="580" height="260" alt="Apache or Microsoft IIS" /></a><br class="C" /></p>
<h3><span class="Gred">Fnord</span>, Nginx, <span class="Gblue">LightHttpd</span></h3>
<p>Fnord what is going on?</p>
<p><a href="http://google.com/trends?q=lighttpd%2Cnginx%2Cfnord&#038;ctab=0&#038;geo=all&#038;date=ytd&#038;sort=0"><img src="http://www.google.com/trends/viz?q=lighttpd,nginx,fnord&#038;date=ytd&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="Which light server is popular" /></a><br class="C" /></p>
<hr class="C" />
<h2>Web Programming Comparisons</h2>
<p>An interesting look at the search engine trends of programming languages out there today&#8230;</p>
<h3>Did <span class="Gred">Ruby</span> Pass <span class="Gblue">Perl</span>!</h3>
<p>Keep in mind that Google may be interpreting &#8220;ruby&#8221; to be a precious stone&#8230; and what is a &#8220;perl&#8221; exactly?  ;)</p>
<p><a href="http://google.com/trends?q=perl%2Cruby&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0"><img src="http://www.google.com/trends/viz?q=perl,+ruby&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="Ruby vs Perl Programming Language" /></a><br class="C" /></p>
<h3><span class="Gblue">Perl</span> vs. <span class="Gred">PHP</span>, Old Debate</h3>
<p><a href="http://google.com/trends?q=perl%2Cphp&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0"><img src="http://www.google.com/trends/viz?q=perl,+php&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="Is it Perl or PHP" /></a><br class="C" /></p>
<hr class="C" />
<h2><span class="Gblue">SEO</span></h2>
<p>Wow. Big surpise there ;)</p>
<p><a href="http://google.com/trends?q=seo&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0"><img src="http://www.google.com/trends/viz?q=seo&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="Well at least something is drastically up" /></a><br class="C" /></p>
<hr class="C" />
<h2><span class="Gblue">Treo</span> vs. <span class="Gred">Blackberry</span> vs. <span class="Gorange">Palm</span></h2>
<p>I love my Blackberry Curve!  I used to love my Sony Clie, and I won&#8217;t forget my many Palms!</p>
<p><a href="http://google.com/trends?q=treo%2Cblackberry%2Cpalm&#038;ctab=0&#038;geo=all&#038;date=all&#038;sort=0"><img src="http://www.google.com/trends/viz?q=treo,blackberry,palm&#038;date=all&#038;geo=all&#038;graph=weekly_img&#038;sort=0&#038;sa=N" alt="Treo vs. Blackberry vs. Palm" /></a><br class="C" /></p>
<hr class="C" />
<h2>AskApache WebSite</h2>
<p>Google Trends also lets you compare websites, I can&#8217;t believe its been over a year for askapache.com, thanks for stopping by!</p>
<p><a href="http://trends.google.com/websites?q=askapache.com&#038;geo=all&#038;date=all&#038;sort=0"><img src='http://z.askapache.com/i/google-rank.png' alt='AskApache.com Google Rank' class='alignnone' /></a><br class="C" /></p>
<hr class="C" />
<h2>Google Trends &#8211; Rocks!</h2>
<p><strong>Fun, free, and helpful tool from who else?</strong><br />
<a href='http://google.com/trends'><img src="/wp-content/uploads/2008/07/logo-200x79.gif" alt="Google Trends by Google Labs" title="logo" width="200" height="79" /></a><br class="C" /></p>
<p><a href="http://www.askapache.com/htaccess/htaccess-seo-trends.html">Htaccess SEO Trends by Google</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/htaccess-seo-trends.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Advanced Htaccess &#8211; SSI, ErrorDocuments, DirectoryIndexing SEO</title>
		<link>http://www.askapache.com/htaccess/advanced-htaccess-ssi.html</link>
		<comments>http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#comments</comments>
		<pubDate>Mon, 09 Mar 2009 08:02:02 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Modules]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Webmaster]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[errordocument]]></category>
		<category><![CDATA[htaccess rewrite]]></category>
		<category><![CDATA[mod_include]]></category>
		<category><![CDATA[Server Side Includes]]></category>
		<category><![CDATA[SSI]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2236</guid>
		<description><![CDATA[<p><a class="IFL" href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-directory" title="Improved Directory Listings and SEO"><img src="/wp-content/uploads/2009/03/htaccess-directory-index-116x76.png" alt="htaccess directory indexing" title="Improved Directory Listings and SEO" /></a><a class="IFL" style="border-bottom:15px solid #FFF;" href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-error" title="Enhanced Error Pages"><img src="/wp-content/uploads/2009/03/example-errordocument-116x67.png" alt="ErrorDocument from .htaccess" title="Enhanced Error Pages" /></a>3-Part article covering practical implementation of 3 advanced .htaccess features.   Discover an easy way to <a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-directory">boost your SEO the <dfn title="Design your site for Humans">AskApache way</dfn></a> (<em>focus on visitors</em>), a tip you might keep and use for life. <a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security">Get some cool security tricks</a> to use against spammers, crackers, and other nefarious sorts.  <a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-error">Take your site's error handling to the next level</a>, enhanced ErrorDocuments that go beyond 404's. <br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><acronym title="Server Side Includes">SSI</acronym>, Server Side Includes, can be very useful to webmasters and visitors alike.  They are easily set up in an .htaccess file and require little to no maintaining.. the term &#8220;Set it and Forget it&#8221; applies here.  Before we look at how to implement SSI, and dig into the Apache module that makes them possible, lets look at few uses for SSI so you can quickly determine if you would like to read further.</p>
<ol>
<li><a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-directory">Improved Directory Listings and SEO</a></li>
<li><a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-error">Enhanced Error Pages</a></li>
<li><a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security">Dealing with Spam and Website Attacks</a></li>
</ol>
<hr class="C" />
<h2><a name="htaccess-ssi-directory" id="htaccess-ssi-directory"></a>Improved Directory Listings and SEO</h2>
<p><a class="IFL" href="/wp-content/uploads/2009/03/htaccess-directory-index.png" title="htaccess directory indexing"><img src="/wp-content/uploads/2009/03/htaccess-directory-index-116x76.png" alt="htaccess directory indexing" title="htaccess directory indexing" /></a>One way that I use SSI is for improved Directory Listing.  Anyone here like SEO?  Check out my <a href="/wp-content/uploads/">WordPress uploads directory</a> to get an idea.  Basically I can customize the header and footer of each directory..  Pretty sweet, thanks Apache!<br class="C" /></p>
<p>In your <code>/uploads/.htaccess</code></p>
<pre>
# turn on auto-indexing and turn off SSI&#039;s ability to exec
Options None
Options SymLinksIfOwnerMatch Indexes IncludesNOEXEC
&nbsp;
# we need to make sure files are displayed when requested, not executed or parsed
AddType text/plain .ini .sh .bsh .bash .csh .var .asc .md5 .sha .sha1 .cgi .pl .php .inc .asp .exe .bin
DefaultType text/plain
&nbsp;
# turn on auto-indexing, with askapache-optimized options
IndexOptions FancyIndexing SuppressColumnSorting SuppressHTMLPreamble IconHeight=22 IconWidth=20
IndexOptions IgnoreClient NameWidth=40 DescriptionWidth=* XHTML FoldersFirst
&nbsp;
# don&#039;t show these files and folders
IndexIgnore .htaccess .ht* *_notes *.log feed inc HEADER.html FOOTER.html feed*.gif
&nbsp;
# the SSI files used for the header and footer
HeaderName /ssi/HEADER.html
ReadmeName /ssi/FOOTER.html
&nbsp;
# used to determine the time and for SSI output
SetEnv TZ America/Indianapolis
SetEnv SERVER_ADMIN webmaster@askapache.com
</pre>
<p>In your <code>/ssi/.htaccess</code></p>
<pre>
# makes files ending in .html be filtered through the INCLUDES filter before being sent to client
AddOutputFilter Includes html
</pre>
<p>My <code>HEADER.html</code></p>
<pre>
&lt;!&#45;-#set var="PAGETITLE" value="&#45;- z.askapache.com" &#45;-&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;&lt;!&#45;-#echo encoding="none" var="REQUEST_URI" &#45;-&gt; &lt;!&#45;-#echo encoding="none" var="PAGETITLE" &#45;-&gt;&lt;/title&gt;
  &lt;meta http-equiv="content-type" content="text/html; charset=UTF-8" /&gt;
  &lt;link rel="stylesheet" href="http://z.askapache.com/c/error.css" /&gt;
  &lt;link rev="made" href="mailto:&lt;!&#45;-#echo encoding="url" var="SERVER_ADMIN" &#45;-&gt;" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;&lt;a href="http://www.askapache.com/" title="AskApache Home" accesskey="1"&gt;
&lt;img src="http://www.askapache.com/nlogo.jpg" height="75" alt="AskApache" /&gt;
&lt;/a&gt; &lt;!&#45;-#echo encoding="url" var="REQUEST_URI" &#45;-&gt; &lt;!&#45;-#echo encoding="none" var="PAGETITLE" &#45;-&gt;&lt;/h1&gt;
&lt;hr /&gt;
</pre>
<p>My <code>FOOTER.html</code></p>
<pre>
&lt;p&gt;Find the information you are looking for on the &lt;a href="http://www.askapache.com/"&gt;AskApache Home page&lt;/a&gt;
or the &lt;a href="http://www.askapache.com/search&lt;!&#45;-#echo encoding="url" var="REQUEST_URI" &#45;-&gt;"&gt;
AskApache search page&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;address&gt;
  &lt;small&gt;$Id:&lt;!&#45;-#echo encoding="none" var="UNIQUE_ID" &#45;-&gt; E:&lt;!&#45;-#echo encoding="none" var="REDIRECT_STATUS" &#45;-&gt;,v 1.30
&lt;!&#45;-#config timefmt="%c" &#45;-&gt;&lt;!&#45;-#echo var="DATE_LOCAL" &#45;-&gt;&lt;/small&gt;&lt;br /&gt;
  &lt;small&gt;&lt;!&#45;-#echo var="SERVER_SOFTWARE" &#45;-&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;
  z.askapache.com &#45;- AskApache | &lt;a href="http://www.askapache.com/about/"&gt;Webmaster&lt;/a&gt;
| Copyright &copy; 2009 AskApache&lt;br /&gt;
&lt;/address&gt;
&lt;!&#45;-#if expr="$REMOTE_ADDR = 10.10.10.10" &#45;-&gt;
&lt;pre &gt;&lt;!&#45;-#printenv &#45;-&gt;&lt;/ pre&gt;
&lt;!&#45;-#endif &#45;-&gt;
&lt;script src="http://z.askapache.com/j/apache-0780.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;var pageTracker = _gat._getTracker("UA-7"+"321"+"53-38");
pageTracker._initData();pageTracker._trackPageview();&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h2><a name="htaccess-ssi-error id="htaccess-ssi-error></a>Enhanced Error Pages</h2>
<p><a class="IFL" href="/wp-content/uploads/2009/03/example-errordocument.png" title="htaccess-errordocument"><img src="/wp-content/uploads/2009/03/example-errordocument-116x67.png" alt="ErrorDocument from .htaccess" title="htaccess-errordocument" /></a>If you are using WordPress, I&#8217;m sure you are using my <a href="http://www.askapache.com/seo/404-google-wordpress-plugin.html">AskApache Google 404 Plugin</a>, but whatever your <a href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html">error pages</a> may be, using SSI you can make them better.  My 404 Error Page is handled by WordPress and PHP, but all of my other error pages (codes 4xx to 5xx) are handled using SSI.  You can check out any of them: <a href="http://www.askapache.com/show-error-400">/show-error-400</a>, <a href="http://www.askapache.com/show-error-400">/show-error-403</a>, <a href="http://www.askapache.com/show-error-500">/show-error-503</a>, etc..<br class="C" /></p>
<p>Notice the email note which has the subject prefilled?  Thats one of the main uses for SSI, you can add forms to your errordocuments and get notified of problems which mean you can fix them.</p>
<p>Add this to your <code>/.htaccess</code> for each <code>ErrorDocument</code> you make.</p>
<pre>
ErrorDocument 503 /errordocs/503.html
</pre>
<p>My <code>/errordocs/.htaccess</code></p>
<pre>
# turn on symlinks for rewrites and turn off SSI&#039;s ability to exec
Options None
Options SymLinksIfOwnerMatch IncludesNOEXEC
&nbsp;
# makes files ending in .html be filtered through the INCLUDES filter before being sent to client
AddOutputFilter Includes html
&nbsp;
# this internal apache variable prevents your errordocs from allowing keep-alive connections
SetEnv nokeepalive
&nbsp;
# used to determine the time and for SSI output
SetEnv TZ America/Indianapolis
SetEnv SERVER_ADMIN webmaster@askapache.com
</pre>
<p>My <code>/errordocs/503.html</code></p>
<pre>
&lt;!&#45;-#set var="TITLE" value="Service Temporarily Unavailable" &#45;-&gt;
&lt;!&#45;-#include virtual="/errordocs/TOP.html" &#45;-&gt;
&lt;p&gt;The server is temporarily unable to service your
request due to &lt;strong&gt;maintenance downtime&lt;/strong&gt;
or super-crazy-extreme capacity problems. Please try
again later&#46;.. Or &lt;a href="mailto:&lt;!&#45;-#echo encoding="url" var="SERVER_ADMIN" &#45;-&gt;"&gt;send me an email&lt;/a&gt; and let me know about it..&lt;/p&gt;
&lt;!&#45;-#include virtual="/errordocs/BOTTOM.html" &#45;-&gt;
</pre>
<p>My <code>/errordocs/TOP.html</code></p>
<pre>
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;&lt;!&#45;-#echo encoding="none" var="REQUEST_URI" &#45;-&gt; &lt;!&#45;-#echo encoding="none" var="TITLE" &#45;-&gt;&lt;/title&gt;
  &lt;meta http-equiv="content-type" content="text/html; charset=UTF-8" /&gt;
  &lt;link rel="stylesheet" href="http://z.askapache.com/c/error.css" /&gt;
  &lt;link rev="made" href="mailto:&lt;!&#45;-#echo encoding="url" var="SERVER_ADMIN" &#45;-&gt;" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;&lt;a href="http://www.askapache.com/" title="AskApache Home" accesskey="1"&gt;&lt;img src="http://www.askapache.com/nlogo.jpg" height="75" alt="AskApache" /&gt;
&lt;/a&gt; &lt;!&#45;-#echo encoding="url" var="REQUEST_URI" &#45;-&gt; &lt;!&#45;-#echo encoding="none" var="TITLE" &#45;-&gt;&lt;/h1&gt;
&lt;hr /&gt;
</pre>
<p>My <code>/errordocs/BOTTOM.html</code></p>
<pre>
&lt;p&gt;If this should not be an error please &lt;a href="mailto:webmaster@askapache.com?subject=ID#&lt;!&#45;-#echo encoding="none" var="UNIQUE_ID" &#45;-&gt;"&gt;email&lt;/a&gt; me right away.&lt;/p&gt;
&lt;!&#45;-#if expr="$HTTP_REFERER" &#45;-&gt;
&lt;p&gt;You came from &lt;!&#45;-#echo var="HTTP_REFERER"&#45;-&gt;&lt;/p&gt;
&lt;!&#45;-#endif &#45;-&gt;
&lt;p&gt;If you still have a question, please try to find the information you are looking
for on the &lt;a href="http://www.askapache.com/"&gt;AskApache Home page&lt;/a&gt; or
the &lt;a href="http://www.askapache.com/search/"&gt;AskApache search page&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;address&gt;
  &lt;a href="http://www.askapache.com/about/"&gt;Webmaster&lt;/a&gt;
  $Id:&lt;!&#45;-#echo encoding="none" var="UNIQUE_ID" &#45;-&gt; Error-&lt;!&#45;-#echo encoding="none" var="REDIRECT_STATUS" &#45;-&gt;,v 1.30 &lt;!&#45;-#config timefmt="%c" &#45;-&gt;&lt;!&#45;-#echo var="DATE_LOCAL" &#45;-&gt;&lt;br /&gt;
  &lt;!&#45;-#echo var="SERVER_SOFTWARE" &#45;-&gt;
&lt;/address&gt;
&lt;!&#45;-#if expr="$REMOTE_ADDR = 10.10.10.10" &#45;-&gt;
&lt;pre &gt;&lt;!&#45;-#printenv &#45;-&gt;&lt;/ pre&gt;
&lt;!&#45;-#endif &#45;-&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h2><a name="htaccess-ssi-security" id="htaccess-ssi-security"></a>Dealing with Spam and Website Attacks</h2>
<p><a class="IFL" href="/wp-content/uploads/2009/03/htaccess-f-off.png" title="htaccess f-off"><img src="/wp-content/uploads/2009/03/htaccess-f-off-350x273.png" alt="htaccess SSI to scare spammers and crackers" title="htaccess f-off" /></a>Say you are using some nice <a href="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html">.htaccess rewrite</a> rules to block offending bots, web scrapers, and other nefarious net characters.  Instead of just sending a 403 Denied, you could send them to be handled by an SSI document that could do any number of things.. From adding the offending bot&#8217;s IP address to the .htaccess Deny List (blacklisting), emailing you with an alert, emailing the IP Block Owner, executing a denial-of-service response ala <a href="http://www.xav.com/scripts/guardian/help/1013.html">guardian</a> (<em>script will return an artificially high Content-Length, and will then spoon-feed content bytes back to the client at a rate of one byte per second, for single-threaded or fixed-threadpool clients, this will hang all of their requests and render the attack inoperable</em>), or just output a frightening looking message which usually does the trick if the bot is humanoid.<br class="C" /></p>
<pre>
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC]
RewriteRule .* - [F]
&nbsp;
ErrorDocument 403 /errordocs/f-off.html
</pre>
<p>Example <code>/errordocs/f-off.html</code>  <a href="http://z.askapache.com/f-off">View it Live</a> (<em>Not Responsible for mental or physical harm caused by fright</em>)</p>
<pre>
&lt;html&gt;&lt;head&gt;&lt;title&gt;WARNING &lt;!&#45;-#echo encoding="none" var="REMOTE_ADDR" &#45;-&gt;
- SECURITY TEAM ALERTED&lt;/title&gt;&lt;/head&gt;&lt;body&gt;
&lt;h2&gt;ATTENTION &lt;!&#45;-#echo encoding="none" var="REMOTE_ADDR" &#45;-&gt;&lt;/h2&gt;
&lt;p&gt;You have been flagged by our system as a potential threat.&lt;/p&gt;
&lt;p&gt;This request has been logged and the Security Team has been notified.&lt;br&gt;
Repeated attempts from IP address &lt;strong&gt;&lt;!&#45;-#echo encoding="none" var="REMOTE_ADDR" &#45;-&gt;&lt;/strong&gt; will result &lt;br&gt;
in the IP automatically being &lt;strong&gt;blacklisted&lt;/strong&gt; on this server&lt;br&gt;
and sent to blacklists around the world.  Additionally, the Security Team&lt;br&gt;
WILL alert the IP Address Block Owner and/or contact the authorities.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&nbsp;
&lt;h3&gt;LOGGED INFORMATION FROM THIS REQUEST&lt;/h3&gt;
&lt; pre&gt;
REMOTE_ADDR   :  &lt;!&#45;-#echo encoding="none" var="REMOTE_ADDR" &#45;-&gt;
REMOTE_PORT   :  &lt;!&#45;-#echo encoding="none" var="REMOTE_PORT" &#45;-&gt;
REQUEST_METHOD:  &lt;!&#45;-#echo encoding="none" var="REQUEST_METHOD" &#45;-&gt;&lt;!&#45;-#if expr="$HTTP_REFERER"
&#45;-&gt;
REFERER       :  &lt;!&#45;-#echo encoding="url" var="HTTP_REFERER" &#45;-&gt;&lt;!&#45;-#endif
&#45;-&gt;
REQUEST_URI   :  &lt;!&#45;-#echo encoding="url" var="REQUEST_URI" &#45;-&gt;&lt;!&#45;-#if expr="$HTTP_USER_AGENT"
&#45;-&gt;
USER_AGENT    :&lt;/ pre&gt;
&lt; pre style="white-space:normal;margin-left:150px;max-width:80%;"&gt;  &lt;!&#45;-#echo encoding="none" var="HTTP_USER_AGENT" &#45;-&gt;
&lt;/ pre&gt;
&lt; pre&gt;&lt;!&#45;-#endif
&#45;-&gt;&lt;!&#45;-#if expr="$HTTP_COOKIE"
&#45;-&gt;
COOKIES       :&lt;/ pre&gt;
&lt; pre style="white-space:normal;margin-left:150px;max-width:80%;"&gt;  &lt;!&#45;-#echo encoding="none" var="HTTP_COOKIE" &#45;-&gt;
&lt;/ pre&gt;
&lt; pre&gt;&lt;!&#45;-#endif
&#45;-&gt;&lt;!&#45;-#if expr="$QUERY_STRING"
&#45;-&gt;
QUERY_STRING  :  &lt;!&#45;-#echo encoding="url" var="QUERY_STRING" &#45;-&gt;&lt;!&#45;-#endif
&#45;-&gt;
&lt;/ pre&gt;&lt;/body&gt;&lt;/html&gt;
</pre>
<hr class="C" />
<h2>Server Side Includes Detailed Info</h2>
<p>Ok now that we have the real-world usage out of the way, lets dig in a bit to the actual module <a style="color:#222;" href='http://z.askapache.com/servers/mod_include.c'>mod_include</a>, which if you want you can <a href="http://z.askapache.com/servers/mod_include.c.html">view the source code here</a>.</p>
<h3>Enabling Server-Side Includes</h3>
<p>Server Side Includes are implemented by the INCLUDES filter.  For backwards compatibility, the server-parsed handler also activates the INCLUDES filter. As well, Apache will activate the INCLUDES filter for any document with mime type text/x-server-parsed-html or text/x-server-parsed-html3 (and the resulting output will have the mime type text/html).  If documents containing server-side include directives are given the extension .shtml, the following directives will make Apache parse them and assign the resulting document the mime type of text/html:</p>
<pre>
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
</pre>
<p>The following directive must be given for the directories containing the shtml files (typically in a <directory> section, but this directive is also valid in <a href="http://www.askapache.com/htaccess/htaccess.html">.htaccess files</a> if AllowOverride Options is set):</p>
<pre>
Options +Includes
</pre>
<h3>Server-Side Include Directives</h3>
<p>These are the Directives allowed in .htaccess files that are handled by <a href="http://httpd.apache.org/docs/1.3/mod/mod_include.html">mod_include</a>.  Note that other modules may add additional directives, for instance the <code>exec</code> SSI Directive is supplied by <a href="http://httpd.apache.org/docs/trunk/mod/mod_cgi.html">mod_cgi</a>.  This is how mod_cgi registers with mod_include to provide processing of the <code>exec</code> directive.  This is the code required to handle the &#8220;exec&#8221; SSI directive.</p>
<pre>
cgi_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
cgi_pfn_reg_with_ssi("exec", handle_exec);
static const char * const aszPre[] = { "mod_include.c", NULL };
</pre>
<dl>
<dt><code>config</code></dt>
<dd>Controls various aspects of the parsing.</p>
<pre>&lt;!&#45;-#config [timefmt="&#46;.."] [sizefmt="&#46;.."] [errmsg="&#46;.."] &#45;-&gt;
&lt;!&#45;-#config [echomsg="&#46;.."] &#45;-&gt;
&lt;!&#45;-#config errmsg="[It appears that you don&#039;t know how to use SSI]" &#45;-&gt;</pre>
<dl>
<dt><code>echomsg</code></dt>
<dd>(<em>since 2.1</em>) The value is a message that is sent back to the client if the <code>&lt;a href="#element.echo"&gt;echo&lt;/a&gt;</code> element attempts to echo an undefined variable. This overrides any <code class='directive'>&lt;a href="#ssiundefinedecho"&gt;SSIUndefinedEcho&lt;/a&gt;</code> directives.</dd>
<dt><code>errmsg</code></dt>
<dd>The value is a message that is sent back to the client if an error occurs while parsing the document. This overrides any <code class='directive'>&lt;a href="#ssierrormsg"&gt;SSIErrorMsg&lt;/a&gt;</code> directives.</dd>
<dt><code>sizefmt</code></dt>
<dd>The value sets the format to be used which displaying the size of a file. Valid values are <code>bytes</code> for a count in bytes, or <code>abbrev</code> for a count in Kb or Mb as appropriate, for example a size of 1024 bytes will be printed as &#8220;1K&#8221;.</dd>
<dt><code>timefmt</code></dt>
<dd>The value is a string to be used by the <code>strftime(3)</code> library routine when printing dates.</dd>
</dl>
</dd>
<dt><code>echo</code></dt>
<dd>Prints one of the include variables. If the variable is unset, the result is determined by the SSIUndefinedEcho directive.</p>
<pre class='a'>&lt;!&#45;-#echo [encoding="none|url|entity"] var="&#46;.." [encoding="none|url|entity"] var="&#46;.." &#46;.. &#45;-&gt;</pre>
<dl>
<dt><code>var</code></dt>
<dd>The value is the name of the variable to print.</dd>
<dt><code>encoding</code></dt>
<dd>
<p>Specifies how Apache should encode special characters contained in the variable before outputting them. If set to <code>none</code>, no encoding will be done. If set to <code>url</code>, then URL encoding (also known as %-encoding; this is appropriate for use within URLs in links, etc.) will be performed. The default is set to <code>entity</code>, resulting in entity encoding.</p>
</dd>
</dl>
</dd>
<dt><code>exec</code></dt>
<dd>Execute external programs</p>
<pre>&lt;!&#45;-#exec cgi="/cgi-bin/s.cgi" &#45;-&gt;
&lt;!&#45;-#exec cmd="ls" &#45;-&gt;
&lt;!&#45;-#include virtual="/cgi-bin/s.cgi?argument=value" &#45;-&gt;
&lt;!&#45;-#exec cmd="perl /cgi-bin/s.pl args" &#45;-&gt;</pre>
</dd>
<dt><code>include</code></dt>
<dd>Include a file</p>
<pre class='a'>&lt;!&#45;-#include virtual|file="&#46;.." [virtual|file="&#46;.."] &#46;.. &#45;-&gt;</pre>
</dd>
<dt><code>printenv</code></dt>
<dd>Print all available variables</p>
<pre>&lt;!&#45;-#printenv &#45;-&gt;</pre>
</dd>
<dt><code>set</code></dt>
<dd>Set a value of a variable.</p>
<pre class='a'>&lt;!&#45;-#set var="&#46;.." value="&#46;.." &#46;.. &#45;-&gt;
&lt;!&#45;-#set var="modified" value="$LAST_MODIFIED" &#45;-&gt;
&lt;!&#45;-#set var="name" value="AskApache" &#45;-&gt;
&lt;!&#45;-#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" &#45;-&gt;</pre>
</dd>
<dt><code>flastmod</code></dt>
<dd>Prints the last modification date of the specified file, subject to the timefmt format specification.</p>
<pre>&lt;!&#45;-#flastmod virtual|file="&#46;.." [virtual|file="&#46;.."] &#46;.. &#45;-&gt;</pre>
</dd>
<dt><code>fsize</code></dt>
<dd>Prints the size of the specified file, subject to the sizefmt format specification.</p>
<pre class='a'>&lt;!&#45;-#fsize virtual|file="&#46;.." [virtual|file="&#46;.."] &#46;.. &#45;-&gt;</pre>
</dd>
<dt><code>if</code></dt>
<dd>The if element works like an if statement in a programming language. The test condition is evaluated and if the result is true, then the text until the next elif, else or endif element is included in the output stream.</p>
<pre>&lt;!&#45;-#if expr="&#46;.." &#45;-&gt;
&lt;!&#45;-#if expr="${REMOTE_USER} &#038;&#038; ${HTTP_USER_AGENT}" &#45;-&gt;</pre>
<pre>&lt;!&#45;-#if expr="test_condition" &#45;-&gt;
&lt;!&#45;-#elif expr="test_condition" &#45;-&gt;
&lt;!&#45;-#else &#45;-&gt;
&lt;!&#45;-#endif &#45;-&gt;</pre>
</dd>
<dt><code>elif</code></dt>
<dd>Used to put text into the output stream if the original test_condition was false. </p>
<pre class='a'>&lt;!&#45;-#elif expr="&#46;.." &#45;-&gt;</pre>
</dd>
<dt><code>else</code></dt>
<dd>Used to put text into the output stream if the original test_condition was false.</p>
<pre>&lt;!&#45;-#else &#45;-&gt;</pre>
</dd>
<dt><code>endif</code></dt>
<dd>Ends the if element and is required.</p>
<pre class='a'>&lt;!&#45;-#endif &#45;-&gt;</pre>
</dd>
</dl>
<h3>.htaccess directives</h3>
<ol>
<li>XBitHack</li>
<li>SSIErrorMsg</li>
<li>SSITimeFormat</li>
<li>SSIStartTag</li>
<li>SSIEndTag</li>
<li>SSIUndefinedEcho</li>
<li>SSIAccessEnable</li>
</ol>
<h3>mod_include Default SSI Values</h3>
<dl>
<dt><code>START_SEQUENCE</code></dt>
<dd><code>&lt;!&#45;-#</code> &#8211; The starting tag for mod_include to recognize and parse as SSI.</code></dd>
<dt><code>END_SEQUENCE</code></dt>
<dd><code>&#45;-&gt;</code> - The ending tag for mod_include to recognize and parse as SSI.</dd>
<dt><code>ERROR_MSG</code></dt>
<dd><code>[an error occurred while processing this directive]</code> - On Errors parsing SSI.</dd>
<dt><code>TIME_FORMAT</code></dt>
<dd><code>%A, %d-%b-%Y %H:%M:%S %Z</code> - Default Time format for DATE</dd>
<dt><code>UNDEFINED_ECHO</code></dt>
<dd><code>(none)</code> - When echoing an undefined variable.</dd>
</dl>
<h3>SSI Variables</h3>
<pre>
DATE_GMT=Sun Mar  8 22:58:56 2009
DATE_LOCAL=Sun Mar  8 15:58:56 2009
DOCUMENT_NAME=FOOTER.html
DOCUMENT_ROOT=/root-srv/protected/askapache.com/sec
DOCUMENT_URI=/includes/FOOTER.html
GATEWAY_INTERFACE=CGI/1.1
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_ACCEPT_ENCODING=gzip,deflate
HTTP_ACCEPT_LANGUAGE=en-us,en;q=0.5
HTTP_CACHE_CONTROL=max-age=0
HTTP_CONNECTION=keep-alive
HTTP_COOKIE=__qca=12298910-686528-46510;  __utmb=50625.1.0.11311
HTTP_HOST=www.askapache.com
HTTP_KEEP_ALIVE=300
HTTP_REFERER=http://www.askapache.com/htaccess/htaccess.html
HTTP_USER_AGENT=Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6 (.NET CLR 3.5.30729)
LAST_MODIFIED=Sun Mar  8 14:53:50 2009
PATH=/bin:/usr/bin:/sbin:/usr/sbin
QUERY_STRING=
REMOTE_ADDR=24.123.215.60
REMOTE_PORT=4785
REQUEST_METHOD=GET
REQUEST_URI=/htaccess/
SCRIPT_FILENAME=/root-srv/protected/askapache.com/sec/includes/FOOTER.html
SCRIPT_NAME=/includes/FOOTER.html
SCRIPT_URI=http://www.askapache.com/htaccess/
SCRIPT_URL=/htaccess/
SERVER_ADDR=64.111.114.111
SERVER_ADMIN=webmaster@askapache.com
SERVER_NAME=www.askapache.com
SERVER_PORT=80
SERVER_PROTOCOL=INCLUDED
SERVER_SIGNATURE=
SERVER_SOFTWARE=Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.63 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
UNIQUE_ID=dnbtH0Bvcm8A2ZHqcAAAAM
USER_NAME=
</pre>
<h3>More SSI Information</h3>
<ol>
<li><a href="http://httpd.apache.org/docs/trunk/mod/mod_include.html">mod_include</a></li>
<li><a href="http://httpd.apache.org/docs/trunk/filter.html">Apache Filters</a></li>
<li><a href="http://httpd.apache.org/docs/trunk/howto/ssi.html">Introduction to Server Side Includes</a></li>
<li><a href="http://httpd.apache.org/docs/trunk/handler.html">Apache Handlers</a></li>
</ol>
<p><a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html">Advanced Htaccess &#8211; SSI, ErrorDocuments, DirectoryIndexing SEO</a> originally appeared on AskApache.</p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/advanced-htaccess-ssi.html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
