Your SlideShare is downloading. ×
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Apache Cookbook - TekX Chicago 2010
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Apache Cookbook - TekX Chicago 2010

4,426

Published on

Presentation for TekX in Chicago, 2010. Apache Cookbook by Rich Bowen

Presentation for TekX in Chicago, 2010. Apache Cookbook by Rich Bowen

Published in: Technology
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,426
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
236
Comments
0
Likes
8
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide


  • Old Hat




























































































































































  • Transcript

    • 1. Apache Cookbook Recipes for managing your Apache HTTP Server / Rich Bowen - rbowen@apache.org
    • 2. Shameless Plug Buy! Buy! Buy!
    • 3. Old Hat ----> • 1.3 is end of life • 2.0 will be by the end of the year • 2.2 is now • 2.4 is tomorrow Photo CC by “Lost Albatross” - Flickr
    • 4. URLs you need • http://people.apache.org/~rbowen • http://wiki.apache.org/httpd • http://httpd.apache.org/docs/trunk/
    • 5. Recipes Photo CC by Chemical Heritage Foundation - Flickr
    • 6. Directory listings are boring
    • 7. Say it with style IndexStyleSheet /styles/dir.css ... .odd { background-color: #eef; } .even { background-color: #fff; }
    • 8. Caveat: Some features 2.4 only • In 2.2 and earlier, you can specify a style sheet, but no classes are added to the HTML • Useful, but not quite as useful
    • 9. Now, with extra class <table id="indexlist"> <tr class="indexhead"> <th class="indexcolicon">... <th class="indexcolname">... <th class="indexcollastmod">... <th class="indexcolsize">... <th class="indexcoldesc">... <tr class="indexbreakrow">... <tr class="even"><td class="indexcolicon">...
    • 10. An exercise for the reader: • Nifty mouse-over effects (JS in HeaderName file?) Photo CC by Ugglan - Flickr • AJAXy file interaction of some kind? • Photo gallery, entirely based on mod_autoindex and Javascript?
    • 11. mod_substitite • New module in 2.2 • Rewrite content using regular expressions • Syntax is identical to sed
    • 12. s/foo/bar/ • Simple example - switch fonts LoadModule substitute_module libexec/apache2/mod_substitute.so AddOutputFilterByType SUBSTITUTE text/html Substitute s/ariel/courier/i
    • 13. Proxying • More useful example • Proxying to back-end server that returns fully-qualified URLs LoadModule substitute_module libexec/apache2/mod_substitute.so AddOutputFilterByType SUBSTITUTE text/html Substitute s/backend.local/www.example.com/ni
    • 14. mod_security • Are you running mod_security?
    • 15. mod_security • You should be
    • 16. http firewall • The earlier you catch it ...
    • 17. Holes Photo CC by Darwin Bell
    • 18. SQL Injection # Prevent SQL injection attacks SecFilter "delete[[:space:]]+from" SecFilter "insert[[:space:]]+into" SecFilter "select.+from" 18
    • 19. Make sure you ... # Inspect POST payloads SecFilterScanPOST On # Default action set SecFilterDefaultAction "deny,log,status:406" 19
    • 20. While you’re at it # Inspect POST payloads SecFilterScanPOST On SecFilter “vidocin” 20
    • 21. Acceptable arguments # Only for the FormMail script <Location /cgi-bin/FormMail> # Reject request where the value of parameter "recipient" # does not end with "@apache.org" SecFilterSelective ARG_recipient "![a-zA-Z0-9]+@apache.org$"> </Location> 21
    • 22. Which PHP script is slagging my server? • Which process, and what is it doing? • Look at /server-status for a process list
    • 23. Step 1: Look at top: • Run ‘top’ • Order by CPU usage • Pick off the httpd processes that are causing the problem and make note of their PIDs
    • 24. Step 2: /server-status • Look at /server-status output • Look for the PIDs you noted • Move fast - the process may be gone already
    • 25. /server-status
    • 26. ExtendedStatus On • You’ll need “ExtendedStatus On” to get these details: <Location /server-status> SetHandler server-status </Location> ExtendedStatus On
    • 27. SNI • General knowledge: SSL requires one certificate per IP address • That is, only one SSL site can be on each IP address • Limitation of SSL itself
    • 28. SSL handshake
    • 29. SSL handshake Certificate Hostname
    • 30. Clearly this sucks
    • 31. SNI
    • 32. SNI • Server Name Indication • Passes server name in initial handshake • Simple solutions are always best
    • 33. Caveats • You knew there would be a catch Mozilla Firefox 2.0 or later Opera 8.0 or later (the TLS 1.1 protocol must be enabled) Internet Explorer 7 (Vista or higher, not XP) or later Google Chrome (Vista or higher, not XP. OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer) Safari Safari 3.2.1 and newer on Mac OS X 10.5.6 and Windows Vista or higher, not XP
    • 34. Apache • 2.2.12 or later Listen 443 # Listen for virtual host requests on all IP addresses NameVirtualHost *:443 # Go ahead and accept connections for these vhosts # from non-SNI clients SSLStrictSNIVHostCheck off <VirtualHost *:443> DocumentRoot /www/example1 ServerName www.example.com </VirtualHost> <VirtualHost *:443> DocumentRoot /www/example2 ServerName www.example2.org </VirtualHost>
    • 35. More Info http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI
    • 36. Secure mod_dav deployment • Security rule #1: Content is not writable • Corollary: Anyone telling you to ‘chmod 777’ is a monkey • Anyone telling you ‘chown apache something.php’ *might* be a monkey. Or they might be working around Apache’s annoying permissions model
    • 37. However ... •Setting up WebDAV requires that content be writable ... •And owned by Apache •This is annoying
    • 38. WebDAV <Directory /var/www/content> Dav On </Directory>
    • 39. Why this is a problem • People write bad code • It’s easy to get PHP (or whatever else) to overwrite your content • Now your site is a radical terrorist site • This is a very unpleasant thing to wake up to on a Saturday morning
    • 40. Secure DAV • It’s possible to set up Dav without having the files written by the Apache user • Sort of 40
    • 41. Two Apache Processes Primary Secondary server, server, running as running as user www user dav File System, owned by dav 41
    • 42. Two Apache Processes Read-only Running ordinary set of modules Running web apps, etc Primary server, running as user www File System, owned by dav 42
    • 43. Two Apache Processes Read/Write Remove all extra modules SSL Secondary server, Authenticated running as user dav File System, owned by dav 43
    • 44. Multi-server config. drwxr-xr-x 2 dav dav 68 Oct 3 12:41 /var/www 1 Listen *:80 User www Group www DocumentRoot /var/www/ Listen *:8080 2 DavLockDb /var/lock/dav User dav Group dav DocumentRoot /var/www/ 44
    • 45. drwxr-xr-x 2 dav dav 68 Oct 3 12:41 /var/www 1 Listen *:80 Can write User www Group www DocumentRoot /var/www/ Listen *:8080 2 DavLockDb /var/lock/dav User dav Group dav DocumentRoot /var/www/ 45
    • 46. drwxr-xr-x 2 dav dav 68 Oct 3 12:41 /var/www 1 Can’t Listen *:80 User www Group www DocumentRoot /var/www/ Listen *:8080 2 DavLockDb /var/lock/dav User dav Group dav DocumentRoot /var/www/ 46
    • 47. <If> Picture by BrewBooks (Flickr) My favorite new feature in 2.4
    • 48. <If> <If ‘$req{Host} = “www.example.com”’> RedirectMatch (.*) http://example.com/$1 </If>
    • 49. <If> <If ‘$req{Host} = “www.example.com”’> RedirectMatch (.*) http://example.com/$1 </If> This was hard prior to 2.4, and probably required mod_rewrite, or a separate virtual host.
    • 50. <If> <If ‘$req{Host} = “www.example.com”’> RedirectMatch (.*) http://example.com/$1 </If> $req $resp $env
    • 51. Logging - Conditional Logging • Don’t log certain things • Per-directory logging 51
    • 52. Conditional LogFormat • The LogFormat directive supports some conditionals in the variables • "%!200,304,302{Referer}i" logs Referer on all requests that do not return one of the three specified codes 52
    • 53. Conditional LogFormat • "%400,501{User-agent}i" logs User-agent on 400 errors and 501 errors only • For other status codes, the literal string "-" will be logged 53
    • 54. Conditional CustomLog • Stick Env=xyz on the end • or Env=!xyz • Yes, that’s =! not != 54
    • 55. For example ... SetEnvIf Request_URI .gif$ gif-image CustomLog gif-requests.log common env=gif-image CustomLog nongif-requests.log common env=!gif-image 55
    • 56. For example ... SetEnvIf Request_URI .gif$ gif-image CustomLog gif-requests.log common env=gif-image CustomLog nongif-requests.log common env=!gif-image 56
    • 57. For example ... SetEnvIf Request_URI .gif$ gif-image CustomLog gif-requests.log common env=gif-image CustomLog nongif-requests.log common env=!gif-image 57
    • 58. So the images get logged here SetEnvIf Request_URI .gif$ gif-image CustomLog gif-requests.log common env=gif-image CustomLog nongif-requests.log common env=!gif-image 58
    • 59. And everything else goes here SetEnvIf Request_URI .gif$ gif-image CustomLog gif-requests.log common env=gif-image CustomLog nongif-requests.log common env=!gif-image 59
    • 60. Per directory SetEnvIf Request_URI ^/marketing mkt CustomLog marketing.log common env=mkt 60
    • 61. PCRE Zero-width assertions • Match everything except one thing • While you can do this with RewriteRule, it would be nice if you could do it with other directives DirectoryMatch FilesMatch RedirectMatch
    • 62. Negative Lookahead • PCRE provides a regex syntax to say “not preceded by” or “not followed by” • Negative lookbehind and negative lookahead, respectively
    • 63. Andrei Rocks • While we’re on the topic: • Pretty much the best presentation on regular expressions anywhere: • http://www.slideshare.net/ andreizm/andreis-regex-clinic
    • 64. Everything except ... • “I want to redirect everything except / images” • This is where you’d use a negative lookahead • Necessary because RedirectMatch doesn’t support negation RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    • 65. Everything except ... • Match anything ... • RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    • 66. Everything except ... • Match anything ... • That doesn’t start with images/ RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    • 67. Everything except ... This is called a “zero width” assertion, because it doesn’t fill $1, and doesn’t consume any characters in the match. RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    • 68. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9
    • 69. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9 • Alas, not in .htaccess • Logs are always opened at startup
    • 70. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9 • Most entries between 1-4
    • 71. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9 • If there’s nothing in there, your rules are being ignored.
    • 72. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 73
    • 73. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 74
    • 74. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 75
    • 75. 76
    • 76. Kind of intimidating, isn’t it? 77
    • 77. Learn to ignore the irrelevant bits 78
    • 78. Which bits are those? 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 79
    • 79. Client address 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 80
    • 80. Dunno what those are 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 81
    • 81. Time 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 82
    • 82. Unique id 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 83
    • 83. Request ID 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 84
    • 84. The useful bit 121.14.76.185 - - [24/Sep/2008:21:35:51 --0400] [wooga.drbacchus.com/sid#b83444a8][rid#b85b8d00/ initial] (4) [perdir /var/www/vhosts/drbacchus/] RewriteCond: input='/var/www/vhosts/drbacchus/ podcasts/poetry/maninmoon.mp3' pattern='!-f' => not- matched 85
    • 85. Wouldn’t it be nice if you could just see the useful part? 86
    • 86. You could change the way mod_rewrite logs:
    • 87. Piped logs • I actually use a piped lot handler to remove this superfluous stuff • Like so ... RewriteLog |/usr/local/bin/rewrite_log_pipe RewriteLogLevel 9 88
    • 88. RewriteLog |/usr/local/bin/rewrite_log_pipe RewriteLogLevel 9 with ... #!/usr/bin/perl $|++; open (F, ">>/tmp/rewrite"); select F; while (<>) { s/^.*((d).*)/$1/; print; } 89
    • 89. RewriteLog |/usr/local/bin/rewrite_log_pipe RewriteLogLevel 9 This bit says “instead of logging to a text file, invoke this script and send the log entries there.” 90
    • 90. #!/usr/bin/perl $|++; open (F, ">>/tmp/rewrite"); select F; while (<>) { s/^.*((d).*)/$1/; print; } • Look for the (1) or (2) bit • drop everything before that 91
    • 91. Results in: (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched (3) applying pattern 'wp-rss2.php' to uri '/index.php' (3) applying pattern '(journal/)?index.rdf' to uri '/index.php' (3) applying pattern '^/wordpress/wp-comments' to uri '/index.php' (3) applying pattern '^/perm/(.*)' to uri '/index.php' (3) applying pattern '^/articles?/(.*)' to uri '/index.php' (3) applying pattern '^/blog/(.*)' to uri '/index.php' (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/index.php' (3) applying pattern '^/book/cookbook' to uri '/index.php' (3) applying pattern '^/book/2.2' to uri '/index.php' (3) applying pattern '^/booklink/(.*)' to uri '/index.php' (3) applying pattern '^/books?/(.+)' to uri '/index.php' (1) pass through /index.php 92
    • 92. Results in: (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched (3) applying pattern 'wp-rss2.php' to uri '/index.php' (3) applying pattern '(journal/)?index.rdf' to uri '/index.php' (3) applying pattern '^/wordpress/wp-comments' to uri '/index.php' (3) applying pattern '^/perm/(.*)' to uri '/index.php' (3) applying pattern '^/articles?/(.*)' to uri '/index.php' (3) applying pattern '^/blog/(.*)' to uri '/index.php' better? See? Isn’t that (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/index.php' (3) applying pattern '^/book/cookbook' to uri '/index.php' (3) applying pattern '^/book/2.2' to uri '/index.php' (3) applying pattern '^/booklink/(.*)' to uri '/index.php' (3) applying pattern '^/books?/(.+)' to uri '/index.php' (1) pass through /index.php 93
    • 93. Requested URI (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched (3) applying pattern 'wp-rss2.php' to uri '/index.php' (3) applying pattern '(journal/)?index.rdf' to uri '/index.php' (3) applying pattern '^/wordpress/wp-comments' to uri '/index.php' (3) applying pattern '^/perm/(.*)' to uri '/index.php' (3) applying pattern '^/articles?/(.*)' to uri '/index.php' (3) applying pattern '^/blog/(.*)' to uri '/index.php' (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/index.php' (3) applying pattern '^/book/cookbook' to uri '/index.php' (3) applying pattern '^/book/2.2' to uri '/index.php' (3) applying pattern '^/booklink/(.*)' to uri '/index.php' (3) applying pattern '^/books?/(.+)' to uri '/index.php' (1) pass through /index.php 94
    • 94. Patterns applied (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched (3) applying pattern 'wp-rss2.php' to uri '/index.php' (3) applying pattern '(journal/)?index.rdf' to uri '/index.php' (3) applying pattern '^/wordpress/wp-comments' to uri '/index.php' (3) applying pattern '^/perm/(.*)' to uri '/index.php' (3) applying pattern '^/articles?/(.*)' to uri '/index.php' (3) applying pattern '^/blog/(.*)' to uri '/index.php' (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/index.php' (3) applying pattern '^/book/cookbook' to uri '/index.php' (3) applying pattern '^/book/2.2' to uri '/index.php' (3) applying pattern '^/booklink/(.*)' to uri '/index.php' (3) applying pattern '^/books?/(.+)' to uri '/index.php' (1) pass through /index.php 95
    • 95. None of them matched (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched (3) applying pattern 'wp-rss2.php' to uri '/index.php' (3) applying pattern '(journal/)?index.rdf' to uri '/index.php' (3) applying pattern '^/wordpress/wp-comments' to uri '/index.php' (3) applying pattern '^/perm/(.*)' to uri '/index.php' (3) applying pattern '^/articles?/(.*)' to uri '/index.php' (3) applying pattern '^/blog/(.*)' to uri '/index.php' (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/index.php' (3) applying pattern '^/book/cookbook' to uri '/index.php' (3) applying pattern '^/book/2.2' to uri '/index.php' (3) applying pattern '^/booklink/(.*)' to uri '/index.php' (3) applying pattern '^/books?/(.+)' to uri '/index.php' (1) pass through /index.php 96
    • 96. And now • We can actually make some sense of what’s happening • Less inscrutable noise • Yes, it means something, but not to normal people 97
    • 97. Examples (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched • This was the result of RewriteCond %{HTTP_HOST} !^wooga.drbacchus.com [NC] 98
    • 98. Examples (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched • It shows what the input variable looked like RewriteCond %{HTTP_HOST} !^wooga.drbacchus.com [NC] 99
    • 99. Examples (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched • And what pattern was applied RewriteCond %{HTTP_HOST} !^wooga.drbacchus.com [NC] 100
    • 100. Examples (4) RewriteCond: input='wooga.drbacchus.com' pattern='!^wooga.drbacchus .com' [NC] => not-matched • As well as what happened RewriteCond %{HTTP_HOST} !^wooga.drbacchus.com [NC] 101
    • 101. Another example (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/ index.php' • Was a result of RewriteRule ^/book/(mod)?_?rewrite http://www.amazon.com/exec/obidos/asin/ 1590595610/drbacchus/ [R,L] 102
    • 102. Again ... (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/ index.php' • What was requested RewriteRule ^/book/(mod)?_?rewrite http://www.amazon.com/exec/obidos/asin/ 1590595610/drbacchus/ [R,L] 103
    • 103. And ... (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/ index.php' • What it was compared against RewriteRule ^/book/(mod)?_?rewrite http://www.amazon.com/exec/obidos/asin/ 1590595610/drbacchus/ [R,L] 104
    • 104. Matched? (3) applying pattern '^/book/(mod)?_?rewrite' to uri '/ index.php' • If it matched, the next line will be the action log RewriteRule ^/book/(mod)?_?rewrite http://www.amazon.com/exec/obidos/asin/ 1590595610/drbacchus/ [R,L] 105
    • 105. The whole thing (3) applying pattern '^/books?/(mod)?_?rewrite' to uri '/books/rewrite' (2) rewrite '/books/rewrite' -> 'http://www.amazon.com/exec/obidos/ asin/1590595610/drbacchus/' (2) explicitly forcing redirect with http://www.amazon.com/exec/ obidos/asin/1590595610/drbacchus/ (1) escaping http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ for redirect (1) redirect to http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ [REDIRECT/302] 106
    • 106. The match: (3) applying pattern '^/books?/(mod)?_?rewrite' to uri '/books/rewrite' (2) rewrite '/books/rewrite' -> 'http://www.amazon.com/exec/obidos/ asin/1590595610/drbacchus/' (2) explicitly forcing redirect with http://www.amazon.com/exec/ obidos/asin/1590595610/drbacchus/ (1) escaping http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ for redirect (1) redirect to http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ [REDIRECT/302] 107
    • 107. Followed by (3) applying pattern '^/books?/(mod)?_?rewrite' to uri '/books/rewrite' (2) rewrite '/books/rewrite' -> 'http://www.amazon.com/exec/obidos/ asin/1590595610/drbacchus/' (2) explicitly forcing redirect with http://www.amazon.com/exec/ obidos/asin/1590595610/drbacchus/ (1) escaping http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ for redirect (1) redirect to http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ [REDIRECT/302] 108
    • 108. [R] (3) applying pattern '^/books?/(mod)?_?rewrite' to uri '/books/rewrite' (2) rewrite '/books/rewrite' -> 'http://www.amazon.com/exec/obidos/ asin/1590595610/drbacchus/' (2) explicitly forcing redirect with http://www.amazon.com/exec/ obidos/asin/1590595610/drbacchus/ (1) escaping http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ for redirect (1) redirect to http://www.amazon.com/exec/obidos/asin/1590595610/ drbacchus/ [REDIRECT/302] 109
    • 109. But it all runs together! • Look for: • (2) init rewrite engine with requested uri /atom/1 • ‘init rewrite engine’ shows where a new request started being rewritten 110
    • 110. Load balancing
    • 111. Fortunately ... Photo CC by Camo53 (flickr) • mod_proxy_balancer • Added in 2.1
    • 112. Fairly simple to configure <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass /test balancer://mycluster
    • 113. Fairly simple to configure <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass /test balancer://mycluster
    • 114. Fairly simple to configure <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass /test balancer://mycluster
    • 115. Sticky Sessions Ensures that connections go to the same server they started with. ProxyPass / balancer://mycluster/ stickysession=PHPSESSIONID 118
    • 116. Balancing measures ProxyPass / balancer://hotcluster/ <Proxy balancer://hotcluster> BalancerMember http://1.2.3.4:8009 loadfactor=1 BalancerMember http://1.2.3.5:8009 loadfactor=2 # The below is the hot standby BalancerMember http://1.2.3.6:8009 status=+H ProxySet lbmethod=bytraffic </Proxy> 119
    • 117. 1.2.3.5 gets twice the traffic ProxyPass / balancer://hotcluster/ <Proxy balancer://hotcluster> BalancerMember http://1.2.3.4:8009 loadfactor=1 BalancerMember http://1.2.3.5:8009 loadfactor=2 # The below is the hot standby BalancerMember http://1.2.3.6:8009 status=+H ProxySet lbmethod=bytraffic </Proxy> 120
    • 118. Hot spare ProxyPass / balancer://hotcluster/ <Proxy balancer://hotcluster> BalancerMember http://1.2.3.4:8009 loadfactor=1 BalancerMember http://1.2.3.5:8009 loadfactor=2 # The below is the hot standby BalancerMember http://1.2.3.6:8009 status=+H ProxySet lbmethod=bytraffic </Proxy> 121
    • 119. bytraffic or byrequests ProxyPass / balancer://hotcluster/ <Proxy balancer://hotcluster> BalancerMember http://1.2.3.4:8009 loadfactor=1 BalancerMember http://1.2.3.5:8009 loadfactor=2 # The below is the hot standby BalancerMember http://1.2.3.6:8009 status=+H ProxySet lbmethod=bytraffic </Proxy> 122
    • 120. BalancerManager <Location /balancer-manager> SetHandler balancer-manager Order Deny,Allow Deny from all Allow from .example.com </Location> 123
    • 121. 124
    • 122. Disable a particular host 125
    • 123. Notes • The things on the other end don’t have to be Apache • This is a popular way to set up Ruby on Rails, with Mongrel 126
    • 124. Bandwidth limiting Picture by Joachim S. Müller (Flickr) People always want their websites to run slower. Seems odd to me ...
    • 125. In 2.4 ... • 2.4 adds two new modules for this purpose • mod_dialup • mod_ratelimit
    • 126. mod_dialup Party like it’s 1999
    • 127. v.92? Really? <Location /mysite> ModemStandard V.92 </Location> Also available: V.21 V.26bis V.32 V.92
    • 128. mod_ratelimit <Location /downloads> SetHandler RATE_LIMIT SetEnv rate-limit 400 </Location> Speed is in kb/s
    • 129. Prior to 2.4 A variety of other modules do bandwidth kind of things: mod_cband mod_bwshare mod_bw mod_evasive mod_limitipconn
    • 130. Logging • mod_logio • mod_log_forensic
    • 131. Obligatory ridiculous log photo Photo by Zevotron (Flickr)
    • 132. Not enough • Your log files don’t tell you enough • Want more
    • 133. Logging - mod_logio Complete INPUT and OUTPUT size 136
    • 134. Logging - mod_logio Complete INPUT and OUTPUT size 137
    • 135. Combined Log Format - Bytes transferred 138
    • 136. Less than half the story • Only bytes transferred to the client • Doesn’t include headers • Doesn’t include data sent from the client to the server 139
    • 137. mod_logio •Adds two additional variables •%I - Input bytes •%O - Output bytes •Includes headers, both directions 140
    • 138. LogFormat 141
    • 139. mod_log_forensic • Did it ever finish?
    • 140. ForensicLog ForensicLog /var/log/httpd/forensic.log
    • 141. ForensicLog ForensicLog /var/log/httpd/forensic.log • Post-process with the check-forensic script to tell you which URLs never exited
    • 142. mod_speling CheckSpelling On CheckCaseOnly On
    • 143. Image Theft SetEnvIf Referer ".example.com/" local_referal # Allow browsers that do not send Referer info SetEnvIf Referer "^$" local_referal <Directory /web/images> Order Deny,Allow Deny from all Allow from env=local_referal </Directory>
    • 144. Or ... RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example.com [NC] RewriteRule .(jpe?g|gif|png)$ - [F,NC]
    • 145. Or ... RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example.com [NC] # depending upon in which context # you use the RewriteRule, # you might need a condition to # exclude the go_away.png to prevent # an internal redirect looping. We don't use a RegEx here: RewriteCond %{REQUEST_URI} !=/images/go_away.png RewriteRule .(jpe?g|gif|png)$ /images/go_away.png [NC,L]
    • 146. Or ... RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example.com [NC] # depending upon in which context # you use the RewriteRule, # you might need a condition to # exclude the go_away.png to prevent # an internal redirect looping. We don't use a RegEx here: RewriteCond %{REQUEST_URI} !=/images/go_away.png RewriteRule .(jpe?g|gif|png)$ http://other.example.com/images/go_away.png [R,NC,L]
    • 147. Query Strings and Path Info
    • 148. Query Strings monkeys.php?q=lemur&color=green&level=99.7&doc=info.txt • Query Strings are: • Ugly • Hard to type • Hard to remember • Potentially insecure
    • 149. Query Strings monkeys.php?q=lemur&color=green&level=99.7&doc=info.txt • Query Strings are: • Ugly • Hard to type • Hard to remember • Potentially insecure
    • 150. Path Info monkeys.php?q=lemur&color=green&level=99.7&doc=info.txt /monkeys/lemur/green/99.7/info
    • 151. mod_rewrite monkeys.php?q=lemur&color=green&level=99.7&doc=info.txt /monkeys/lemur/green/99.7/info RewriteRule ^/monkeys/(.+)/(.+)/(.+)/(.+) /monkeys.php?q=$1&color=$2&level=$3&doc=$4.txt [PT,L,NE]
    • 152. Engineering for failure • Why not do it right to begin with, and avoid the mess? • PHP makes this fairly easy
    • 153. Step One: SetHandler /monkeys/lemur/green/99.7/info • We want monkeys to be a PHP script • We rename monkeys.php to monkeys, and then ... <Files monkeys> SetHandler application/x-httpd-php </Files> This goes in your server config, or in .htaccess
    • 154. Step Two: explode() /monkeys/lemur/green/99.7/info • The rest of the solution is in your PHP: $args = explode( $_SERVER[‘PATH_INFO’] ); $type = $args[0]; $color = $args[1]; ...
    • 155. While we’re at it • File extensions are *so* 1980s • All your files are php files, right? • Why give them a .php extension? RewriteCond %{REQUEST_URI} !. RewriteRule ^ - [H=application/x-httpd-php,PT]
    • 156. Write a better FM • I’ll never get this far in the presentation, right?

    ×