1.63k likes | 1.64k Views
Apache Cookbook. ApacheCon Europe 2007 Amsterdam Rich Bowen - Asbury College rbowen@apache.org. Table of Contents. SSL vhosts Rewrite based on query string Preventing “image theft” Logging more information Logging to syslog WebDAV Preventing malicious requests with mod_security
E N D
Apache Cookbook • ApacheCon Europe • 2007 • Amsterdam • Rich Bowen - Asbury College • rbowen@apache.org
Table of Contents • SSL vhosts • Rewrite based on query string • Preventing “image theft” • Logging more information • Logging to syslog • WebDAV • Preventing malicious requests with mod_security • Enabling PHP • Mass virtual hosting • Customized error messages • URL handler (“rewrite everything”) • Fancy directory listings • Caching dynamic content • /server-info goodness • /server-status goodness • UserDir without the ~
Recipes • On CD • At http://people.apache.org/~rbowen/presentations/apache_coobook_recipes.tar.gz
Caveat: Versions • 2.2 is the current version of Apache • With any luck, by the end of the year, 2.4 will be the current version of Apache • If you are running 1.3, you really should upgrade • Some, not all, of these recipes will work in 2.0
SSL vhosts • Multiple SSL hosts, one IP address
Problem • One SSL cert per IP address • Certificate is negotiated before the HOST: header is sent
Solution • Three options: • Wildcard certificate • Get more IP addresses • Ignore the error messages
Wildcard certificate • Costs $$$ • Works for *.domain.tld • Cannot span multiple domains • Set up name-based vhosts the normal way
Wildcard certificate NameVirtualHost *:443 # Wildcard certificate for *.domain.com SSLCertificateFile /var/www/conf/server.crt SSLCertificateKeyFile /var/www/conf/server.key <VirtualHost *:443> ServerName one.domain.com DocumentRoot /var/www/one/htdocs SSLEngine On </VirtualHost> <VirtualHost *:443> ServerName two.domain.com DocumentRoot /var/www/two/htdocs SSLEngine On </VirtualHost> 01_wildcard_cert
Multiple IP addresses • This is the best solution • Not always an option
Multiple IP addresses <VirtualHost 172.20.4.10:443> ServerName one.domain.com DocumentRoot /var/www/one/htdocs SSLCertificateFile /var/www/conf/one.crt SSLCertificateKeyFile /var/www/conf/one.key SSLEngine On </VirtualHost> <VirtualHost 172.20.4.11:443> ServerName two.domain.com DocumentRoot /var/www/two/htdocs SSLCertificateFile /var/www/conf/two.crt SSLCertificateKeyFile /var/www/conf/two.key SSLEngine On </VirtualHost> 02_ssl_hosts
Ignore errors • SSL cert will be valid for only one hostname • Other named vhosts will be encrypted • Browser will report that the cert doesn’t match the hostname • SSL is encryption + validation. You’re losing the validation.
Ignore the errors NameVirtualHost *:443 # Certificate for one.domain.com SSLCertificateFile /var/www/conf/one.crt SSLCertificateKeyFile /var/www/conf/one.key <VirtualHost *:443> ServerName one.domain.com DocumentRoot /var/www/one/htdocs SSLEngine On </VirtualHost> # Will be secure, but will generate errors <VirtualHost *:443> ServerName two.domain.com DocumentRoot /var/www/two/htdocs SSLEngine On </VirtualHost> 03_ssl_vhosts
Other options • Efforts are underway to escape this limitation • Browser support is the big hurdle
Rewrite based on QUERY_STRING or PATH_INFO • Sometimes what gets asked is: “I want to forbid access if the QUERY_STRING doesn’t contain foo=bar”
Rewrite by QUERY_STRING • The sensible solution would be to handle this in your script/handler/program • But, if that’s not an option, mod_rewrite might be a good choice
Problem • RewriteRule doesn’t have access to the QUERY_STRING • Only the URI - the bit after http://hostname.com and before the ? - is accessible to RewriteRule
Solution • RewriteCond has access to the entire requested URL, and any other server variables RewriteCond %{VARIABLE} regex
RewriteCond • Does the QUERY_STRING contain foo=bar RewriteCond %{QUERY_STRING} foo=bar RewriteRule ^ - [F] 04_query_string
^ rather than .* • ^ means “starts with” • All strings start, even empty strings. • Thus, all strings match ^ • ^ is more efficient than .*
Backreferences • Or, you can do a rewrite based on the value of the QUERY_STRING RewriteCond %{QUERY_STRING} user=(.+)\b RewriteRule (.*) /home/%1/www$1 05_query_string
More frequently ... • People want to map http://example.com/one/two/three to http://example.com/something.php?a=one&b=two&c=three
See also • Upcoming recipe “URL Handler” • Not quite the same, but many similar techniques
PATH_INFO • Everything after the final / is the path info • “Final /” refers to the / following an actual file or resource http://example.com/index.php/one/two/three
PATH_INFO • The trick is to figure out which bit is a valid resource, and which bit is PATH_INFO • Two approaches
URL Prefix • http://example.com/prefix/one/two/three • You know that only URLs starting with prefix need special attention RewriteRule ^/prefix(.*) \ /handler.php?args=$1 06_rewrite
File existance • Check to see if the requested file exists • If not, rewrite • May interfere with other rewrite matches RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) /handler.php?args=$1 07_rewrite
Caveats • May need to prepend a directory path • Still need to do something useful with the value of $1, if you want it to be split into args. RewriteCond \ /var/www%{REQUEST_FILENAME} !-f
The full recipe RewriteRule ^/prefix/([^/]+)/([^/]+) \ /handler.php?one=$1&two=$2 [PT,L] 08_rewrite
Caveats • Exactly two arguments • No more, no less • Perhaps you want this to be more flexible?
More flexible RewriteRule ^/prefix/([^/]+)?/?([^/]+)? \ /handler.php?one=$1&two=$2 [PT,L] • Matches are now optional • Arguments will be passed null - just ignore them in handler.php, or check for null values and take appropriate measures 09_rewrite
More arguments • This technique can be repeated for up to 9 arguments. • $1 - $9 • $10 is not available
Preventing image theft • “Image theft” is the term used for other sites embedding your images in their pages. • Ideally, you want to forbid having your images in any pages but your own • There are several ways to accomplish this
SetEnvIf • SetEnvIf is provided by mod_setenvif • Sets environment variables if certain conditions are met
SetEnvIf SetEnvIf Referer “^http://myhost\.com” localref=1 <FilesMatch "\.(gif|jpg|png)"> Order Deny,Allow Deny from all Allow from env=localref </FilesMatch> 10_image_theft
Problem • Some browsers don’t set the Referer value SetEnvIf Referer “^http://myhost\.com” localref=1 SetEnfIf Referer “^$” localref=1 <FilesMatch "\.(gif|jpg|png)"> Order Deny,Allow Deny from all Allow from env=localref </FilesMatch> 11_image_theft
mod_rewrite • Or, you could do it with a RewriteRule RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example\.com [NC] RewriteRule \.(jpe?g|gif|png)$ - [F,NC] 11_image_theft
But, more usefully • If you’re just going to fail the request, use SetEnvIf. It’s more efficient • But if you wanted to do something more interesting ...
Redirect the request RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example\.com [NC] RewriteCond %{REQUEST_URI} !go_away.png RewriteRule \.(jpe?g|gif|png)$ /images/go_away.png [NC,L] 13_image_theft
Or ... RewriteEngine on RewriteCond %{HTTP_REFERER} !="" RewriteCond %{HTTP_REFERER} !example\.com [NC] RewriteRule \.(jpe?g|gif|png)$ \ http://othersite.com/images/unsavory.jpg [NC,R] 14_image_theft
Logging more information • The standard log file is sometimes not sufficient. • This recipe shows you how to get a little more information
mod_log_config • Variables available for other values • Always use ‘combined’ rather than ‘common’
combined LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" \ combined CustomLog logs/access_log combined 15_combined
Additional variables • http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats • Most of the actual useful variables are already in ‘combined’ • Most log analysis packages understand the ‘combined’ format
Important variables • %{something}C - the value of the ‘something’ cookie • %{something}i - the ‘something’ request (input) header • %{something}o - the ‘something’ response (output) header • %q - The query string • and ...
mod_logio • %b gives the size of the response in bytes • Does not include headers • Does not include the request • mod_logio gives both of these
mod_logio • %I - total size of request (Input) in bytes • %O - total size of response (Output) in bytes • Includes headers in each case.
mod_dumpio • http://httpd.apache.org/docs/2.2/mod/mod_dumpio.html • Dumps all input and output to the error log # DumpIOLogLevel notice (2.3) DumpIOInput On DumpIOOutput On 16_dumpio
mod_log_forensic • http://httpd.apache.org/docs/2.2/mod/mod_log_forensic.html • Logs at the start, end of a request • Uses unique IDs to match the two • check_forensic script alerts you to requests that did not complete
LogLevel • LogLevel changes the level at which error messages are emitted • Can increase/decrease the volume of your error_log • In practice, this seldom adds useful information