Apache SSL in htaccess examples
« Fresh .htaccess Examples: Cookies, Variables, Custom HeadersHacking VLAN switched networks »
Apache SSL examples in htaccess files
Options +FollowSymLinks RewriteEngine On RewriteBase /
Additional https/ssl information
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "google.com"
ErrorDocument 403 https://google.com
This code is really, really nice because it fixes multiple issues with almost every other SSL redirect technique in htaccess files. (I discovered this one on my own)
The problem with most techniques is REWRITING the URL.. so if you check the request to see if its being sent on port 443… guess what? in the interim it got sent! Most of the times the double login prompt error happens because users type in http://secureurl.com instead of https://secureurl.com. Most modern browsers automatically request the /favicon.ico file from the resource. In this case the resource is http instead of https like it should be.
Now with some of the other techniques below you can solve this problem, but you will still face a potential ssl security issue. What if a user types in https://secureurl.com:80 There are a lot of these types of weird ways to bypass security so I recommend using the SSLRequireSSL option always.
This will check to make sure that the connection IS using SSL, or it will fail. This works regardless of if your serving SSL on port 443, 80, 81, etc. This is the most secure setting for SSL logins.
This also fixes having to type in the username and password twice by requiring the HTTP_HOST to match the HTTP_HOST that your SSL certificate is set-up for, in the case above, the SSL is for https://google.com not https://www.google.com
If any of the required conditions are not met the server returns a 403 Forbidden Status Code (before mod_rewrite starts) and the ErrorDocument directive catches the 403 to send the visitor a Redirect to https://google.com
The HTTPS variable is always present, even if mod_ssl isn’t loaded!
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
The SERVER_PORT variable is always present, and generally SSL runs on certain ports like 443.
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule ^/normal/secure(/.*) https://%{HTTP_HOST}$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^(/secure/.*) https://%{HTTP_HOST}$1 [R=301,L]
Article: Redirect
Redirect / https://google.com/
Redirect 301 / https://google.com/
This lets you use hyperlinks of the form
/document.html:SSL -- https://google.com/document.html
/document.html:NOSSL -- http://google.com/document.html
RewriteRule ^/(.*):SSL$ https://%{SERVER_NAME}/$1 [R,L]
RewriteRule ^/(.*):NOSSL$ http://%{SERVER_NAME}/$1 [R,L]
When mod_ssl is built into Apache or at least loaded (under DSO situation) additional functions exist for the Custom Log Format of mod_log_config. First there is an additional %{varname} extension format function which can be used to expand any variables provided by any module, especially those provided by mod_ssl which can you find in the above table.
For backward compatibility there is additionally a special %{name} cryptography format function provided. Information about this function is provided in the Compatibility chapter.
CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
This directive toggles the usage of the SSL/TLS Protocol Engine. This is usually used inside a section to enable SSL/TLS for a particular virtual host. By default the SSL/TLS Protocol Engine is disabled for both the main server and all configured virtual hosts.
SSLEngine on
This directive can be used to control various run-time options on a per-directory basis. Normally, if multiple SSLOptions could apply to a directory, then the most specific one is taken completely; the options are not merged. However if all the options on the SSLOptions directive are preceded by a plus (+) or minus (-) symbol, the options are merged. Any options preceded by a + are added to the options currently in force, and any options preceded by a – are removed from the options currently in force.
xxj31ZMTZzkVA, which is the DES-encrypted version of the word `password”. Those who live under MD5-based encryption (for instance under FreeBSD or BSD/OS, etc.) should use the following MD5 hash of the same word: $1$OXLyS...$Owx8s2/m9/gfkcRVXzgoE/.Satisfy any directive is used, and other access restrictions are passed, denial of access due to SSLRequireSSL or SSLRequire is overridden (because that’s how the Apache Satisfy mechanism should work.) But for strict access restriction you can use SSLRequireSSL and/or SSLRequire in combination with an SSLOptions +StrictRequire. Then an additional Satisfy Any has no chance once mod_ssl has decided to deny access.SSLOptions +FakeBasicAuth -StrictRequire +StdEnvVars +CompatEnvVars -ExportCertData
This directive specifies a general access requirement which has to be fulfilled in order to allow access. It’s a very powerful directive because the requirement specification is an arbitrarily complex boolean expression containing any number of access checks.
This function takes one string argument and expands to the contents of the file. This is especially useful for matching this contents against a regular expression, etc. Notice that expression is first parsed into an internal machine representation and then evaluated in a second step. Actually, in Global and Per-Server Class context expression is parsed at startup time and at runtime only the machine representation is executed. For Per-Directory context this is different: here expression has to be parsed and immediately executed for every request.
SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ \
and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
This directive forbids access unless HTTP over SSL (i.e. HTTPS) is enabled for the current connection. This is very handy inside the SSL-enabled virtual host or directories for defending against configuration errors that expose stuff that should be protected. When this directive is present all requests are denied which are not using SSL. Example SSLRequireSSL
This directive sets the “user” field in the Apache request object. This is used by lower modules to identify the user with a character string. In particular, this may cause the environment variable REMOTE_USER to be set. The varname can be any of the SSL environment variables.
SSLUserName SSL_CLIENT_S_DN_CN
This directive sets the Certificate verification level for the Client Authentication. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the client authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured client verification level after the HTTP request was read but before the HTTP response is sent.
In practice only levels none and require are really interesting, because level optional doesn’t work with all browsers and level optional_no_ca is actually against the idea of authentication (but can be used to establish SSL test pages, etc.)
SSLVerifyClient require
This directive sets how deeply mod_ssl should verify before deciding that the clients don’t have a valid certificate. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the client authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured client verification depth after the HTTP request was read but before the HTTP response is sent. The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates which are max allowed to be followed while verifying the client certificate. A depth of 0 means that self-signed client certificates are accepted only, the default depth of 1 means the client certificate can be self-signed or has to be signed by a CA which is directly known to the server (i.e. the CA’s certificate is under SSLCACertificatePath), etc.
SSLVerifyDepth 10
This complex directive uses a colon-separated cipher-spec string consisting of OpenSSL cipher specifications to configure the Cipher Suite the client is permitted to negotiate in the SSL handshake phase. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured Cipher Suite after the HTTP request was read but before the HTTP response is sent.
An SSL cipher can also be an export cipher and is either a SSLv2 or SSLv3/TLSv1 cipher (here TLSv1 is equivalent to SSLv3). To specify which ciphers to use, one can either specify all the Ciphers, one at a time, or use aliases to specify the preference and order for the ciphers.
Now where this becomes interesting is that these can be put together to specify the order and ciphers you wish to use. To speed this up there are also aliases (SSLv2, SSLv3, TLSv1, EXP, LOW, MEDIUM, HIGH) for certain groups of ciphers. These tags can be joined together with prefixes to form the cipher-spec.
A simpler way to look at all of this is to use the openssl ciphers -v command which provides a nice way to successively create the correct cipher-spec string. The default cipher-spec string is ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP which means the following: first, remove from consideration any ciphers that do not authenticate, i.e. for SSL only the Anonymous Diffie-Hellman ciphers.
Next, use ciphers using RC4 and RSA. Next include the high, medium and then the low security ciphers.
Finally pull all SSLv2 and export ciphers to the end of the list.
$ openssl ciphers -v 'ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP' NULL-SHA SSLv3 Kx=RSA Au=RSA Enc=None Mac=SHA1 NULL-MD5 SSLv3 Kx=RSA Au=RSA Enc=None Mac=MD5 EDH-RSA-DES-CBC3-SHA SSLv3 Kx=DH Au=RSA Enc=3DES(168) Mac=SHA1 EXP-RC4-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export EXP-RC2-CBC-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export EXP-RC4-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
SSLCipherSuite RSA:!EXP:!NULL:+HIGH:+MEDIUM:-LOW
HTTP_USER_AGENT PATH_INFO AUTH_TYPE HTTP_REFERER QUERY_STRING SERVER_SOFTWARE HTTP_COOKIE REMOTE_HOST API_VERSION HTTP_FORWARDED REMOTE_IDENT TIME_YEAR HTTP_HOST IS_SUBREQ TIME_MON HTTP_PROXY_CONNECTION DOCUMENT_ROOT TIME_DAY HTTP_ACCEPT SERVER_ADMIN TIME_HOUR HTTP:headername SERVER_NAME TIME_MIN THE_REQUEST SERVER_PORT TIME_SEC REQUEST_METHOD SERVER_PROTOCOL TIME_WDAY REQUEST_SCHEME REMOTE_ADDR TIME REQUEST_URI REMOTE_USER ENV:variablename REQUEST_FILENAME
HTTPS SSL_CLIENT_M_VERSION SSL_SERVER_M_VERSION SSL_CLIENT_M_SERIAL SSL_SERVER_M_SERIAL SSL_PROTOCOL SSL_CLIENT_V_START SSL_SERVER_V_START SSL_SESSION_ID SSL_CLIENT_V_END SSL_SERVER_V_END SSL_CIPHER SSL_CLIENT_S_DN SSL_SERVER_S_DN SSL_CIPHER_EXPORT SSL_CLIENT_S_DN_C SSL_SERVER_S_DN_C SSL_CIPHER_ALGKEYSIZE SSL_CLIENT_S_DN_ST SSL_SERVER_S_DN_ST SSL_CIPHER_USEKEYSIZE SSL_CLIENT_S_DN_L SSL_SERVER_S_DN_L SSL_VERSION_LIBRARY SSL_CLIENT_S_DN_O SSL_SERVER_S_DN_O SSL_VERSION_INTERFACE SSL_CLIENT_S_DN_OU SSL_SERVER_S_DN_OU SSL_CLIENT_S_DN_CN SSL_SERVER_S_DN_CN SSL_CLIENT_S_DN_T SSL_SERVER_S_DN_T SSL_CLIENT_S_DN_I SSL_SERVER_S_DN_I SSL_CLIENT_S_DN_G SSL_SERVER_S_DN_G SSL_CLIENT_S_DN_S SSL_SERVER_S_DN_S SSL_CLIENT_S_DN_D SSL_SERVER_S_DN_D SSL_CLIENT_S_DN_UID SSL_SERVER_S_DN_UID SSL_CLIENT_S_DN_Email SSL_SERVER_S_DN_Email SSL_CLIENT_I_DN SSL_SERVER_I_DN SSL_CLIENT_I_DN_C SSL_SERVER_I_DN_C SSL_CLIENT_I_DN_ST SSL_SERVER_I_DN_ST SSL_CLIENT_I_DN_L SSL_SERVER_I_DN_L SSL_CLIENT_I_DN_O SSL_SERVER_I_DN_O SSL_CLIENT_I_DN_OU SSL_SERVER_I_DN_OU SSL_CLIENT_I_DN_CN SSL_SERVER_I_DN_CN SSL_CLIENT_I_DN_T SSL_SERVER_I_DN_T SSL_CLIENT_I_DN_I SSL_SERVER_I_DN_I SSL_CLIENT_I_DN_G SSL_SERVER_I_DN_G SSL_CLIENT_I_DN_S SSL_SERVER_I_DN_S SSL_CLIENT_I_DN_D SSL_SERVER_I_DN_D SSL_CLIENT_I_DN_UID SSL_SERVER_I_DN_UID SSL_CLIENT_I_DN_Email SSL_SERVER_I_DN_Email SSL_CLIENT_A_SIG SSL_SERVER_A_SIG SSL_CLIENT_A_KEY SSL_SERVER_A_KEY SSL_CLIENT_CERT SSL_SERVER_CERT SSL_CLIENT_CERT_CHAINn SSL_CLIENT_VERIFY
« Fresh .htaccess Examples: Cookies, Variables, Custom Headers
Hacking VLAN switched networks »
Tags: apache ssl
Please consider donating to support active development of the free software and articles here.![]()
The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect. Tim Berners-Lee
Hi,
We are using Apache 2 for secure mode and using MOD jk to redirect our request to tomcat 6.0.
We are using client certificate created with ca-authority application. We have following entries in our ssl.conf like…
DocumentRoot "/var/apache2/htdocs"
ServerName sun1111.abc.com:443
ServerAdmin Ab@abc.com
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
ErrorLog logs/myprodcheck_error_log
TransferLog logs/myprodcheck_access_log
AddType text/html .asp
# SSL Engine Switch:
SSLEngine on
# SSL Cipher Suite:
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
# Server Certificate:
SSLCertificateFile /var/apache2/conf/ssl.crt/abc.crt
# Server Private Key:
SSLCertificateKeyFile /var/apache2/conf/ssl.key/abc.key
# Server Certificate Chain:
#SSLCertificateChainFile /var/apache2/conf/ssl.crt/ca.crt
# Certificate Authority (CA):
SSLCACertificateFile /var/apache2/conf/ssl.crt/ca-bundle.crt
# Client Authentication (Type):
SSLVerifyClient optional
SSLVerifyDepth 3
# Access Control:
#
#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} = 8 and %{TIME_HOUR} <= 20 ) \
# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
#
SSLOptions +StdEnvVars
# SSL Engine Options:
#SSLOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire
SSLOptions +StdEnvVars
And it’s working fine and it’s showing the server certification when we’ll access our site with HTTPS.
But issue is that now we need the values from client certificate from client machine. So how we can read these variable from request with java api.
Thanks in advanced,
Ajay
Very comprehensive. Thank you.
Wow! This is the best site on Apache redirects and rewrites on the Internet! I have looked everywhere
I just have a quick question.. you know when a request is made to a secure area, and for that directory there is a SSLRequire directive. If the user has the digital certificate installed it’s all fine. However, if they don’t have the certificate installed you get a big Apache error:
(Error code: ssl_error_handshake_failure_alert)
Is it possible to do a rewrite so that if they don’t have the certificate installed it redirects them to a page informing them of this?
/John
We are setting up an SSL area for our website and face this issue that the link is accessable through various methos causing SSL by passes. I like to gracefully solve this. But the complexity is that the SSL link is not the same as the HTTP links. The certificate is from our website provider.
The good link:
https://pepr-com.ssl.eatserver.nl/
The alternative way that does not compute to the SSL environment:
http://buydirect.pepr.com
The browsing method that does nto compute to the SSL environment:
http://www.pepr.com/buydirect
How do I combine the standard recommendation with the SEO version of it?
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "google.com"
ErrorDocument 403 https://google.com
and
RewriteRule ^/normal/secure(/.*) https://%{HTTP_HOST}$1 [R=301,L]
I am a bit lost in this area and would ask the proper htaccess content to fix it. The complexity also sits in the fact that SSL is on a different link.
Thanks, this article provided some great info and helped me to get where I wanted to be. I really appreciate it.
I was trying to do something I thought was simple,but have so far been unable to figure out.
I wanted set up a temp server just to host a “we are down for the moment” web page. It’s pretty easy to set it up so it responds to all http requests with a single page. But I can’t figure out how to set it up to answer all HTTPS requests with the same page without actually setting up SSL with a valid cert on my temporary server, which I don’t want to do.
Any suggestions? A wiser way of going about this?
On an Apache 1.3x system, “and” & “or” isn’t valid inside an .htaccess file. The use of “&&” and “||” are required instead.
So where you list:
SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/
and %{SSL_CLIENT_S_DN_O} eq “Snake Oil, Ltd.”
and %{SSL_CLIENT_S_DN_OU} in {“Staff”, “CA”, “Dev”}
and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5
and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 )
or %{REMOTE_ADDR} =~ m/^192.76.162.[0-9]+$/
It would have to be written as:
SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ && \
%{SSL_CLIENT_S_DN_O} eq “Snake Oil, Ltd.” && \
%{SSL_CLIENT_S_DN_OU} in {“Staff”, “CA”, “Dev”} && \
%{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 && \
%{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20) || \
%{REMOTE_ADDR} =~ m/^192.76.162.[0-9]+$/
It's very simple - you read the protocol and write the code. -Bill Joy
HTML | DCMI | GRDDL | XOXO | XDMP | XFN | DOM | XML | XHTML 1.1 Strict | CSS 2.1 | W3C | TLDP | WAI | DISA | ICSI | GIAC | SANS RR | GHOST | DEFCON | NIST | DHS CYBER | NIST | .:: Phrack Magazine ::.
↑ TOPExcept where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. HTTPD based on NCSA HTTPd
SSLOptions +StrictRequire SSLRequireSSL SSLRequire %{HTTP_HOST} eq "google.com" ErrorDocument 403 https://google.comThanks! This works great but I want to use this for a folder that is shared by every vhost. It’s actually my awstats directory. If I access awstats via any of my websites (e.g,
/awstats), I get the stats for that paticular website. The server was preconfigured so I guess there is a rewrite rule somewhere in one of the many config files.Line
SSLRequire %{HTTP_HOST} eq "google.com"only lists one host name (google.com). Is there a way to set this up so SSL is required no matter the host name?