6. CVE-2011-3192 (KillApache)
• Exploits bug in handling of range requests
• Range: requests a byte-range of a
document
• Range: 0-4,10-19,16-22,3-18
• Eg, single pages of a PDF document
• Fixed in 2.2.20 and in trunk
7. What's the problem?
• No limit to the number or size of ranges
• Ranges can overlap
• Apache builds the entire response in
memory before sending
• Very easy to construct a range set that
consumes all available RAM
8. Solutions: Best (2.2)
# Drop the Range header when more than 5 ranges.
# CVE-2011-3192
SetEnvIf Range (,.*?){5,} bad-range=1
RequestHeader unset Range env=bad-range
# optional logging.
CustomLog logs/range-CVE-2011-3192.log
common env=bad-range
9. Solution 2
# Reject request when more than 5 ranges in the
# Range: header -- CVE-2011-3192
RewriteEngine on
RewriteCond %{HTTP:range}
!(^bytes=[^,]+(,[^,]+){0,4}$|^$)
RewriteRule .* - [F]
• Use this for 1.3 and 2.0, because they
don't have the PCRE sauce in SetEnvIf
• Better yet, don't use 1.3 and 2.0
10. Other solutions
• Disallow Range requests entirely
RequestHeader unset Range
• Limit the size of the Range header
LimitRequestFieldSize 200
12. Say it with style
IndexStyleSheet /styles/dir.css
...
.odd {
background-color: #eef;
}
.even {
background-color:
#fff;
}
13. 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
14. 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">...
15. 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?
16. mod_substitite
• New module in 2.2
• Rewrite content using
regular expressions
• Syntax is identical to sed
18. 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
24. Make sure you ...
# Inspect POST payloads
SecFilterScanPOST On
# Default action set
SecFilterDefaultAction "deny,log,status:406"
24
25. While you’re at it
# Inspect POST payloads
SecFilterScanPOST On
SecFilter “vidocin”
25
26. 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>
26
27. Which PHP script is slagging my server?
• Which process, and what is
it doing?
• Look at /server-status for a
process list
28. 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
29. Step 2: /server-status
• Look at /server-status
output
• Look for the PIDs you
noted
• Move fast - the process
may be gone already
31. ExtendedStatus On
• You’ll need “ExtendedStatus On”
to get these details:
<Location /server-status>
SetHandler server-status
</Location>
ExtendedStatus On
32. 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
37. SNI
• Server Name Indication
• Passes server name in initial
handshake
• Simple solutions are always
best
38. 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
39. 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>
41. 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
42. However ...
•Setting up WebDAV
requires that content be
writable ...
•And owned by Apache
•This is annoying
43. WebDAV
<Directory /var/www/content>
Dav On
</Directory>
44. 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
45. Secure DAV
• It’s possible to set up Dav without
having the files written by the
Apache user
• Sort of
45
46. Two Apache Processes
Primary Secondary
server, server,
running as running as
user www user dav
File System,
owned by dav
46
47. 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
47
48. Two Apache Processes
Read/Write
Remove all extra modules
SSL Secondary
server,
Authenticated
running as
user dav
File System,
owned by dav
48
49. 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/
49
50. 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/
50
51. 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/
51
52. <If> Picture by BrewBooks (Flickr)
My favorite new feature in 2.4
54. <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.
56. Logging in 2.4
FYI:
• 2.4 is currently in beta
• Will release any day now
• 2.0 will be declared "end of life"
• 2.2 will be declared "maintenance only"
57. Per-module LogLevel
• mod_proxy is very chatty
• I really want to know what
mod_substitute is doing
• Each log line prefixed by the name of the
module
LogLevel warning substitute:debug
58. [Mon Aug 29 08:05:02.001881 2011] [core:warn] [pid 14974:tid
140735307352416] pid file /usr/local/apache2/logs/httpd.pid overwritten --
Unclean shutdown of previous Apache run?
[Mon Aug 29 08:05:02.009024 2011] [mpm_event:notice] [pid 14974:tid
140735307352416] Apache/2.3.12-dev (Unix) PHP/5.3.6 DAV/2 configured
-- resuming normal operations
[Mon Aug 29 08:05:02.009411 2011] [core:notice] [pid 14974:tid
140735307352416] Command line: '/usr/local/apache2/bin/httpd'
[Mon Aug 29 08:05:16.479215 2011] [negotiation:error] [pid 14977:tid
4322246656] (2)No such file or directory: [client ::1:54690] cannot access
type map file: /Users/rbowen/devel/apache/httpd-trunk/docs/manual/
logging.html
61. LogLevels
• Original LogLevel settings taken from
syslog
• New ones more simply named tracen
• Noisier than debug
• Not to be confused with TRACEEnable,
which is something completely different
62. No more RewriteLog
LogLevel alert rewrite:trace3
• Trace slows things down - use only for
debugging
• tail -f error_log | grep "rewrite:"
63. Configurable
• Error log format is configurable, like the
access log
ErrorLogFormat
"[%t] [%l] [pid %P] %F: %E: [client %a] %M"
65. Whodunnit? (%L)
• Correlate access log entries
with error log entries
• Which request caused this
error?
• Add %L to the LogFormat
and to the ErrorLogFormat
66. FallbackResource
# BEGIN WordPress
RewriteEngine On
RewriteRule ^index.php$ - [L]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
67. FallbackResource
# BEGIN WordPress
# RewriteEngine On
# RewriteRule ^index.php$ - [L]
# RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
# RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
# RewriteRule . /index.php [L]
# END WordPress
FallbackResource /index.php
# available in 2.2.8
69. 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
69
70. 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
70
71. Conditional CustomLog
• Stick Env=xyz on the end
• or Env=!xyz
• Yes, that’s =! not !=
71
72. For example ...
SetEnvIf Request_URI .gif$ gif-image
CustomLog gif-requests.log common env=gif-image
CustomLog nongif-requests.log common env=!gif-image
72
73. For example ...
SetEnvIf Request_URI .gif$ gif-image
CustomLog gif-requests.log common env=gif-image
CustomLog nongif-requests.log common env=!gif-image
73
74. For example ...
SetEnvIf Request_URI .gif$ gif-image
CustomLog gif-requests.log common env=gif-image
CustomLog nongif-requests.log common env=!gif-image
74
75. 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
75
76. 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
76
78. 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
79. Negative Lookahead
• PCRE provides a regex
syntax to say “not preceded
by” or “not followed by”
• Negative lookbehind and
negative lookahead,
respectively
80. 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
81. 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
83. Everything except ...
• Match anything ...
• That doesn’t start with images/
RedirectMatch ^/(?!images/)(.*)
http://other.myhost.com/$1
84. 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
85.
86. What the heck is it doing?
RewriteLog /var/log/rewrite.log
RewriteLogLevel 9
87. What the heck is it doing?
RewriteLog /var/log/rewrite.log
RewriteLogLevel 9
• Alas, not in .htaccess
• Logs are always opened at startup
88. What the heck is it doing?
RewriteLog /var/log/rewrite.log
RewriteLogLevel 9
• Most entries between 1-4
89. What the heck is it doing?
RewriteLog /var/log/rewrite.log
RewriteLogLevel 9
• If there’s nothing in there, your rules are
being ignored.
105. 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
105
106. RewriteLog |/usr/local/bin/rewrite_log_pipe
RewriteLogLevel 9
with ...
#!/usr/bin/perl
$|++;
open (F, ">>/tmp/rewrite");
select F;
while (<>) {
s/^.*((d).*)/$1/;
print;
}
106
108. #!/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
108
109. 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
109
110. 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
110
111. 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
111
112. 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
112
113. 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
113
114. And now
• We can actually make some
sense of what’s happening
• Less inscrutable noise
• Yes, it means something, but
not to normal people
114
115. 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]
115
116. 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]
116
117. 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]
117
118. 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]
118
119. 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]
119
120. 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]
120
121. 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]
121
122. 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]
122
123. 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]
123
124. 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]
124
125. 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]
125
126. [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]
126
127. 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
127
135. Sticky Sessions
Ensures that connections go to the same server they
started with.
ProxyPass / balancer://mycluster/
stickysession=PHPSESSIONID
135
136. 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>
136
137. 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>
137
138. 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>
138
139. 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>
139
140. BalancerManager
<Location /balancer-manager>
SetHandler balancer-manager
Order Deny,Allow
Deny from all
Allow from .example.com
</Location>
140
151. RequireAll
<RequireAll>
Require ip 10.1
Require Group marketing
</RequireAll>
152. RequireAny
<RequireAny>
Require ip 10.1
Require Group marketing
</RequireAny>
153. RequireNone
<RequireNone>
Require ip 10.1
Require Group marketing
</RequireNone>
154. Combined
<Directory /www/mydocs>
<RequireAll>
<RequireAny>
Require user superadmin
<RequireAll>
Require group admins
Require ldap-group
cn=Administrators,o=Airius
<RequireAny>
Require group sales
Require ldap-attribute dept="sales"
</RequireAny>
</RequireAll>
</RequireAny>
<RequireNone>
Require group temps
Require ldap-group cn=Temporary
Employees,o=Airius
</RequireNone>
</RequireAll>
</Directory>
155. Expressions
• New expression parser in 2.4
• Available in most directives that do any
kind of comparison or matching
• Will be available more places as time goes
on
156.
157.
158.
159.
160. Other ...
• http://localhost/manual/expr.html
161. Bandwidth limiting
Picture by Joachim S. Müller (Flickr)
People always want their websites to run
slower. Seems odd to me ...
162. In 2.4 ...
• 2.4 adds two new modules for this
purpose
• mod_dialup
• mod_ratelimit
173. 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
173
174. mod_logio
•Adds two additional
variables
•%I - Input bytes
•%O - Output bytes
•Includes headers, both
directions
174
183. 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>
184. Or ...
RewriteEngine on
RewriteCond %{HTTP_REFERER} !=""
RewriteCond %{HTTP_REFERER} !example.com [NC]
RewriteRule .(jpe?g|gif|png)$ - [F,NC]
185. 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]
186. 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]
187. Or ...
In 2.4:
<Location /images>
<If "$req{Referer} !~ /mysite.com/">
Require all denied
</If>
</Location>
193. Engineering for failure
• Why not do it right to begin
with, and avoid the mess?
• PHP makes this fairly easy
• Use exactly the same
technique in whatever your
preferred language is
194. 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
195. 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];
...
196. 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]
197. ...
• If, by some miracle, we get this far ...
• Questions?
198. Addresses you need
• http://slideshare.net/rbowen
• http://wiki.apache.org/httpd
• http://httpd.apache.org/docs/trunk/
• rbowen@apache.org
• http://omniti.com/is/hiring