Apache Cookbook - TekX Chicago 2010

4,960 views
4,863 views

Published on

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,960
On SlideShare
0
From Embeds
0
Number of Embeds
141
Actions
Shares
0
Downloads
244
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide


  • Old Hat




























































































































































  • Apache Cookbook - TekX Chicago 2010

    1. 1. Apache Cookbook Recipes for managing your Apache HTTP Server / Rich Bowen - rbowen@apache.org
    2. 2. Shameless Plug Buy! Buy! Buy!
    3. 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. 4. URLs you need • http://people.apache.org/~rbowen • http://wiki.apache.org/httpd • http://httpd.apache.org/docs/trunk/
    5. 5. Recipes Photo CC by Chemical Heritage Foundation - Flickr
    6. 6. Directory listings are boring
    7. 7. Say it with style IndexStyleSheet /styles/dir.css ... .odd { background-color: #eef; } .even { background-color: #fff; }
    8. 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. 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. 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. 11. mod_substitite • New module in 2.2 • Rewrite content using regular expressions • Syntax is identical to sed
    12. 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. 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. 14. mod_security • Are you running mod_security?
    15. 15. mod_security • You should be
    16. 16. http firewall • The earlier you catch it ...
    17. 17. Holes Photo CC by Darwin Bell
    18. 18. SQL Injection # Prevent SQL injection attacks SecFilter "delete[[:space:]]+from" SecFilter "insert[[:space:]]+into" SecFilter "select.+from" 18
    19. 19. Make sure you ... # Inspect POST payloads SecFilterScanPOST On # Default action set SecFilterDefaultAction "deny,log,status:406" 19
    20. 20. While you’re at it # Inspect POST payloads SecFilterScanPOST On SecFilter “vidocin” 20
    21. 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. 22. Which PHP script is slagging my server? • Which process, and what is it doing? • Look at /server-status for a process list
    23. 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. 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. 25. /server-status
    26. 26. ExtendedStatus On • You’ll need “ExtendedStatus On” to get these details: <Location /server-status> SetHandler server-status </Location> ExtendedStatus On
    27. 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. 28. SSL handshake
    29. 29. SSL handshake Certificate Hostname
    30. 30. Clearly this sucks
    31. 31. SNI
    32. 32. SNI • Server Name Indication • Passes server name in initial handshake • Simple solutions are always best
    33. 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. 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. 35. More Info http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI
    36. 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. 37. However ... •Setting up WebDAV requires that content be writable ... •And owned by Apache •This is annoying
    38. 38. WebDAV <Directory /var/www/content> Dav On </Directory>
    39. 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. 40. Secure DAV • It’s possible to set up Dav without having the files written by the Apache user • Sort of 40
    41. 41. Two Apache Processes Primary Secondary server, server, running as running as user www user dav File System, owned by dav 41
    42. 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. 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. 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. 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. 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. 47. <If> Picture by BrewBooks (Flickr) My favorite new feature in 2.4
    48. 48. <If> <If ‘$req{Host} = “www.example.com”’> RedirectMatch (.*) http://example.com/$1 </If>
    49. 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. 50. <If> <If ‘$req{Host} = “www.example.com”’> RedirectMatch (.*) http://example.com/$1 </If> $req $resp $env
    51. 51. Logging - Conditional Logging • Don’t log certain things • Per-directory logging 51
    52. 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. 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. 54. Conditional CustomLog • Stick Env=xyz on the end • or Env=!xyz • Yes, that’s =! not != 54
    55. 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. 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. 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. 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. 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. 60. Per directory SetEnvIf Request_URI ^/marketing mkt CustomLog marketing.log common env=mkt 60
    61. 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. 62. Negative Lookahead • PCRE provides a regex syntax to say “not preceded by” or “not followed by” • Negative lookbehind and negative lookahead, respectively
    63. 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. 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. 65. Everything except ... • Match anything ... • RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    66. 66. Everything except ... • Match anything ... • That doesn’t start with images/ RedirectMatch ^/(?!images/)(.*) http://other.myhost.com/$1
    67. 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. 68. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9
    69. 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. 70. What the heck is it doing? RewriteLog /var/log/rewrite.log RewriteLogLevel 9 • Most entries between 1-4
    71. 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. 72. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 73
    73. 73. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 74
    74. 74. Logging - RewriteLog RewriteLog /var/log/rewrite.log RewriteLogLevel 9 75
    75. 75. 76
    76. 76. Kind of intimidating, isn’t it? 77
    77. 77. Learn to ignore the irrelevant bits 78
    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. 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. 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. 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. 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. 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. 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. 85. Wouldn’t it be nice if you could just see the useful part? 86
    86. 86. You could change the way mod_rewrite logs:
    87. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 110. Load balancing
    111. 111. Fortunately ... Photo CC by Camo53 (flickr) • mod_proxy_balancer • Added in 2.1
    112. 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. 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. 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. 115. Sticky Sessions Ensures that connections go to the same server they started with. ProxyPass / balancer://mycluster/ stickysession=PHPSESSIONID 118
    116. 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. 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. 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. 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. 120. BalancerManager <Location /balancer-manager> SetHandler balancer-manager Order Deny,Allow Deny from all Allow from .example.com </Location> 123
    121. 121. 124
    122. 122. Disable a particular host 125
    123. 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. 124. Bandwidth limiting Picture by Joachim S. Müller (Flickr) People always want their websites to run slower. Seems odd to me ...
    125. 125. In 2.4 ... • 2.4 adds two new modules for this purpose • mod_dialup • mod_ratelimit
    126. 126. mod_dialup Party like it’s 1999
    127. 127. v.92? Really? <Location /mysite> ModemStandard V.92 </Location> Also available: V.21 V.26bis V.32 V.92
    128. 128. mod_ratelimit <Location /downloads> SetHandler RATE_LIMIT SetEnv rate-limit 400 </Location> Speed is in kb/s
    129. 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. 130. Logging • mod_logio • mod_log_forensic
    131. 131. Obligatory ridiculous log photo Photo by Zevotron (Flickr)
    132. 132. Not enough • Your log files don’t tell you enough • Want more
    133. 133. Logging - mod_logio Complete INPUT and OUTPUT size 136
    134. 134. Logging - mod_logio Complete INPUT and OUTPUT size 137
    135. 135. Combined Log Format - Bytes transferred 138
    136. 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. 137. mod_logio •Adds two additional variables •%I - Input bytes •%O - Output bytes •Includes headers, both directions 140
    138. 138. LogFormat 141
    139. 139. mod_log_forensic • Did it ever finish?
    140. 140. ForensicLog ForensicLog /var/log/httpd/forensic.log
    141. 141. ForensicLog ForensicLog /var/log/httpd/forensic.log • Post-process with the check-forensic script to tell you which URLs never exited
    142. 142. mod_speling CheckSpelling On CheckCaseOnly On
    143. 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. 144. Or ... RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example.com [NC] RewriteRule .(jpe?g|gif|png)$ - [F,NC]
    145. 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. 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. 147. Query Strings and Path Info
    148. 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. 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. 150. Path Info monkeys.php?q=lemur&color=green&level=99.7&doc=info.txt /monkeys/lemur/green/99.7/info
    151. 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. 152. Engineering for failure • Why not do it right to begin with, and avoid the mess? • PHP makes this fairly easy
    153. 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. 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. 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. 156. Write a better FM • I’ll never get this far in the presentation, right?

    ×