Apache 2 - Redirection (mod rewrite)

Revision as of 15:19, 7 August 2014 by WikiFreak (talk | contribs) (Created page with "Category:Linux =Redirections= ==Principle== Just a little reminder... none|Apache2 mod_rewrite principle * Redirections are '''not...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


Redirections

Principle

Just a little reminder...

Apache2 mod_rewrite principle


  • Redirections are not transparent
  • Redirections are performed by the client. The server only serves the new URL to use
  • Redirections can also be used as a security tool to filter HTTP requests and only allow some of them.


As you can see on the previous picture, redirection can be declared:

  • As Apache 2 module configuration. This will apply to all virtual hosts and web-sites
  • In a Virtual Host configuration
    • Default setting - ex: HTTP to HTTPS
    • For a specific alias |or| directory
  • In a web page
  • In a .htaccess to protect a specific directory



Enable redirections

Module "rewrite" allows you to redirect source URL to another one.

a2enmod rewrite


Virtual host: redirect all HTTP to HTTPS

The safer way to redirect HTTP to HTTPS is use to adjust the virtual host configuration.

<VirtualHost *:80>
	ServerName dev.daxiongmao.eu
	ServerAlias www.dev.daxiongmao.eu *.dev.daxiongmao.eu
	ServerAdmin guillaume@qin-diaz.com

	### LOG ###
	LogLevel warn
	ErrorLog ${APACHE_LOG_DIR}/dev.daxiongmao.eu/error.log
	CustomLog ${APACHE_LOG_DIR}/dev.daxiongmao.eu/access.log combined
	

	############################################
	## Redirect all traffic to HTTPS website
        ############################################
        RewriteEngine On
        # This checks to make sure the connection is not already HTTPS
        RewriteCond %{HTTPS} off        
        # This rule will redirect users from their original location, to the same location but using HTTPS.
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} 
	# Alternate (fail-over) solution 
	redirect permanent / https://myServer/


        ########
	# No need of a document root anymore as everything is redirect to HTTPS
        ########
	
</VirtualHost>


-Note-

As you can see you don't need a DocumentRoot anymore for the *:80 virtual host.



Take changes into account

You have to restart the server to use this settings

service apache2 restart

Test your configuration


Virtual host: Alias redirection

The following example will redirect a "/phpsecinfo" from HTTP to HTTPS.


Edit your virtual-host configuration and use that example to redirect to another server too by adjusting the rewrite rule.

<VirtualHost *:80>
...
        # PHPSecInfo
	RewriteRule ^/phpsecinfo(/.*|$)    https://%{HTTP_HOST}/phpsecinfo$1 [L,R]
	<Location /phpsecinfo>
		order deny,allow
		deny from all
                # Only allow specific IP@
                # allow from 127.0.0.1 192.168.1.0/24	
                allow from all
	</Location>
...
</VirtualHost>
<VirtualHost *:443>
...
	# PHPSecInfo
	Alias 	/phpsecinfo /var/www/phpsecinfo
	<Location /phpsecinfo>
		order deny,allow
		deny from all
                # Only allow specific IP@
                # allow from 127.0.0.1 192.168.1.0/24	
                allow from all
        </Location>
...
</VirtualHost>


Reload your configuration

/etc/init.d/apache2 reload


Apache 2 Module configuration

This configuration will apply to all virtual-hosts.


Create the module configuration file

vim /etc/apache2/mods-available/rewrite.conf


Copy / paste this configuration (adjust to your own settings!)

   RewriteEngine On
   # --------------------- SECURITY RULES (JOOMLA) ------------------------ #
   ## End of deny access to extension xml files
   RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
   # Block out any script trying to base64_encode crap to send via URL
   RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
   # Block out any script that includes a <script> tag in URL
   RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
   # Block out any script trying to set a PHP GLOBALS variable via URL
   RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
   # Block out any script trying to modify a _REQUEST variable via URL
   RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
   # Send all blocked request to homepage with 403 Forbidden error!
   RewriteRule ^(.*)$ index.php [F,L]

   # --------------------- SECURITY RULES (PERSONAL) ------------------------ #
   ## DENY REQUEST BASED ON REQUEST METHOD ###
   RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK|OPTIONS|HEAD)$ [NC]
   RewriteCond %{REQUEST_METHOD} (GET|POST) [NC]
   RewriteRule ^.*$ - [F]
   # Avoid common security flows
   RewriteCond %{QUERY_STRING} ^(.*)http(\:|\%3A)(.*)$
   RewriteCond %{QUERY_STRING} mosConfig_ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)(%3C|<)/?script(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)(%3D|=)?javascript(%3A|:)(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)document\.location\.href(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)base64_encode(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)GLOBALS(=|[|%[0-9A-Z]{0,2})(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)_REQUEST(=|[|%[0-9A-Z]{0,2})(.*)$ [NC,OR]
   RewriteCond %{QUERY_STRING} ^(.*)(SELECT|INSERT|DELETE|CHAR\(|UPDATE|REPLACE|LIMIT)(.*)$
   # Avoid common security mistakes
   RewriteCond %{QUERY_STRING} \.\.\/    [NC,OR]
   RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
   RewriteCond %{QUERY_STRING} tag\=     [NC,OR]
   RewriteCond %{QUERY_STRING} ftp\:     [NC,OR]
   RewriteCond %{QUERY_STRING} http\:    [NC,OR]
   RewriteCond %{QUERY_STRING} https\:   [NC,OR]
   RewriteCond %{QUERY_STRING} mosConfig [NC,OR]
   RewriteCond %{QUERY_STRING} ^.*(\(|\)|<|>|'|"|\?|\*).* [NC,OR]
   RewriteCond %{QUERY_STRING} ^.*(%22|%27|%3C|%3D|%3E|%7B|%7C).* [NC,OR]
   RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%F|127\.0).* [NC,OR]
   RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
   RewriteCond %{QUERY_STRING} ^.*(select|insert|union|declare|drop).* [NC]
   RewriteRule ^(.*)$ - [F,L]

   # Ban Typical Vulnerability Scanners and others
   # Kick out Script Kiddies
   RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]
   RewriteCond %{HTTP_USER_AGENT} ^.*(libwww-perl|curl|wget|python|nikto|wkito|pikto|scan|acunetix).* [NC,OR]
   RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]
   # Avoid zombies software
   RewriteCond %{HTTP_USER_AGENT} ^Anarchie [OR]
   RewriteCond %{HTTP_USER_AGENT} ^ASPSeek [OR]
   RewriteCond %{HTTP_USER_AGENT} ^attach [OR]
   RewriteCond %{HTTP_USER_AGENT} ^autoemailspider [OR]
   RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
   RewriteCond %{HTTP_USER_AGENT} ^Xenu [OR]
   RewriteCond %{HTTP_USER_AGENT} ^Zeus.*Webster [OR]
   RewriteCond %{HTTP_USER_AGENT} ^Zeus
   RewriteRule ^.* - [F,L]

   # Allow the robots to reference our website
   RewriteCond %{HTTP_USER_AGENT} !^Googlebot [NC]
   RewriteCond %{HTTP_USER_AGENT} !^Googlebot-Image [NC]
   RewriteCond %{HTTP_USER_AGENT} !^Googlebot-Mobile [NC]
   RewriteCond %{HTTP_USER_AGENT} !^Msnbot [NC]
   RewriteCond %{HTTP_USER_AGENT} !^Mediapartners-Google [NC]

   # Keep request without referer
   RewriteCond %{HTTP_REFERER} !^$

   # To allow your pictures to be displayed on Google
   RewriteCond %{HTTP_REFERER} !^http://.*google\.(comŠ(co\.)?[a-z]{2})/
   # To forbid the copy of your pictures to anyone else : display an other image !
   RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/hotlinkis.jpg [L]


Update your Apache2 configuration:

a2enmod rewrite


Restart your server:

service apache2 restart




Proxy

Special thanks to Julien Rialland for his insight regarding this part!


Principle

The proxy module allow you to expose a resource that is not directly accessible.

For instance it can redirect remote user to a specific server that can be host on a different machine or port through a simple URL.


Proxy VS redirection

Header text Proxy Redirection
Main usage
  • Expose a resource that is not directly accessible
  • Provide a nicer URL through standard HTTP port instead of http://server:port/service
Signal a change or redirect to the HTTPS web-site
Action Hidden to the user.
  • From user point of view this is just a standard URL / service
  • It's the server that performs the proxy actin
Explicit
  • The server just serve the new URL
  • It's the client that will create a new connection - See Apache_2#Principle


Internet limits: why do we need a proxy?

Some application are not available from outside…

  • For security reasons [default URL is not allowed]
Proxy for security


  • Due to network issues
Proxy to improve network


How does Apache2 mod_proxy work?

The Apache2 proxy module allow you to provide access through transparent redirection.

It relies on:

  • Already open port (80 or 443)
  • Redirection rule
  • Each service URL must be unique
  • The target service must be reachable by the web server
Proxy role


As you can see on the previous example, the services will be accessible using some dedicated URL. Remote “http://myServer/myService” will redirect to “http://localhost:8081”


→ The mod_proxy is none intrusive. You don’t have to change anything in the original service configuration. Apache2 will handle all the transformations.


Proxy / redirect / rewrite - HTTP request processing

When Apache2 receive a request it will be process in the following order:

Proxy rewrite


The evaluation order is:

  1. Mod_proxy
  2. Mod_rewrite
  3. Other modules
  4. Serve requested resources if no rule should apply


So, even if you enable a full redirection to HTTPS you can still use some HTTP service through mod_proxy (because mod_proxy is the 1st to be evaluate).



Installation

Enable proxy module

a2enmod proxy proxy_http proxy_ajp 
a2enmod proxy_html xml2enc


Configure proxy redirections

You can configure the redirections in 2 ways:

  • Through your virtual host configuration
  • Through the module configuration file


Module configuration file

You have to edit / create the configuration file.

vim /etc/apache2/mods-enabled/proxy.conf


Virtual host

Just edit again your previous V.Host:

vim /etc/apache2/sites-available/myServer.conf


V.Host proxy declaration

Adjust your V.Host configuration to:

<VirtualHost *:80>
	ServerName dev.daxiongmao.eu
	ServerAlias www.dev.daxiongmao.eu *.dev.daxiongmao.eu
	ServerAdmin guillaume@qin-diaz.com

	### LOG
	LogLevel warn
	ErrorLog ${APACHE_LOG_DIR}/dev.daxiongmao.eu/error.log
	CustomLog ${APACHE_LOG_DIR}/dev.daxiongmao.eu/access.log combined
	
        ### Redirect all traffic to HTTPS website
        RewriteEngine On
        RewriteCond %{HTTPS} off        
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} 
	redirect permanent / https://myServer/

	### No proxy here because I only want to use HTTPS
</VirtualHost>

<VirtualHost *:443>
...

        #############################
        # Proxy configuration
        #############################
        # Enable proxy
        ProxyVia On
        ProxyPreserveHost On
        ProxyRequests Off
        ProxyErrorOverride Off

        ## SSL support (allow to redirect to other SSL sites)
        SSLProxyEngine On
        SSLProxyVerify none
        SSLProxyCheckPeerCN off
        SSLProxyCheckPeerName off

        <Proxy *>
             AddDefaultCharset off
             Order deny,allow
             Allow from all
             Satisfy Any
        </Proxy> 

	########################
	# Standard Web application - No proxy required
	########################

        #### Direct access without further configuration
	ProxyPass /maintenance !
	ProxyPass /menu !
	ProxyPass /ssl !

        #### Standard URL filters
	# PhpMyAdmin
	<Location /phpmyadmin>
                Require all granted
                ProxyPass !
		Order allow,deny
		Allow from 127.0.0.1 192.168.1.0/24
	</Location>

         #### Alias 
         # PHPSecInfo
         Alias   /phpsec   /var/www/phpsecinfo
         <Location /phpsec >
                 Require all granted
                 ProxyPass !
                 order deny,allow
                 # allow from 127.0.0.1 192.168.1.0/24
                 allow from all
         </Location>


	########################
	# Proxy redirections
	########################

	# Proxy to a Java application running over Tomcat
	ProxyPass /webdav ajp://localhost:8009/webdav/
	ProxyPassReverse /webdav ajp://localhost:8009/webdav 	

	# Proxy to a Java application running over Tomcat, with IP filter
	<Location /manager>
		Order allow,deny
		Allow from 127.0.0.1 192.168.1.0/24 193.12.118.196
		ProxyPass ajp://localhost:8009/manager/
		ProxyPassReverse ajp://localhost:8009/manager/
	</Location>

        # Proxy to another server
        ProxyPass /jira http://192.168.1.12:8080/jira
        ProxyPassReverse /jira http://192.168.1.12:8080/jira


        ## Proxy to webmin
        <Location /webmin/>
           ProxyPass http://localhost:10000/
           ProxyPassReverse http://localhost:10000/
           Order deny,allow
           Deny from all
           Allow from 127.0.0.1 172.16.50.0/24 192.168.1.0/24
       </Location>

      ## Proxy to RabbitMQ
      <Location /rabbitmq/>
         ProxyPass http://smartcard-mq:15672/
         ProxyPassReverse http://smartcard-mq:15672/
         Order deny,allow
         Deny from all
         Allow from 127.0.0.1 172.16.50.0/24 192.168.1.0/24
      </Location>

</VirtualHost>


Some notes:

  • Do NOT put a / after the target URL
  • Do NOT use / as ProxyPass source, use the previous redirect permanent instead


Apply changes and test result

service apache2 restart


For example, Navigate to http://myServer/jira