Making an exception for SSLVerifyClient require - ssl

I have apache2 httpd version 2.2.9 listening on port 443 with SSLEngine on. All URLs have SSLVerifyClient require and this works fine.
I want to make an exception for a specific URL (/ca.crt) so that my clients can download the certificate of the CA that the certificates we issue them are signed with. I try the following:
SSLVerifyClient require
Alias /ca.crt /my/ssl/certs/ca.crt
<Location /ca.crt>
SSLVerifyClient none
</Location>
My problem is that Apache only seems to want to increase the strength of the SSL client certificate requirement. If I flip the two requirements around, it works as specified. As it is configured above, Apache effectively ignores the SSLVerifyClient none directive.
What's going on? Is this a bug?

Ok, it turns out that the answer to this question is in the documentation (as it usually is!)
In per-server context [the SSLVerifyClient directive] applies to
the client authentication process used
in the standard SSL handshake when a
connection is established.
See Apache Docs - SSLVerifyClient
Basically the first SSLVerifyClient directive was in the per-server context. I made an explicit <Directory> declaration for the root directory and put the SSLClientVerify require directive in there. This did the trick.

Related

Browser not asking for client certificate when CA is set in Apache

UPDATED :
I updated my CA to match the CA that my client certificate was issued from and my browser now prompts me to choose a certificate (and the correct certificate is listed) but the error "ERR_BAD_SSL_CLIENT_AUTH_CERT" persists.
OLD MESSAGE :
I need to make a certificate authentication with Apache.
My problem is that no certificate list pops up when the CA is set in Apache. However, not setting it brings the popup and allows me to select a certificate... but of course the authentication doesn't work and brings the following error :
ERR_BAD_SSL_CLIENT_AUTH_CERT
The configuration I have is the following :
ssl.conf :
SSLEngine on
SSLProtocol -all +SSLv3 +TLSv1
SSLCipherSuite HIGH:MEDIUM
SSLCACertificateFile /etc/httpd/ca.cer
SSLCARevocationFile /etc/httpd/crl.pem
SSLCARevocationCheck chain
SSLVerifyClient optional
SSLVerifyDepth 10
SSLOptions +StdEnvVars
SSLUserName SSL_CLIENT_S_DN_CN
vhost :
Include ssl.conf
SSLCertificateFile /etc/httpd/sub.domain.crt
SSLCertificateKeyFile /etc/httpd/sub.domain.key
The CA is also installed on my computer along with my client certificate, ready to be used.
There's nothing in the logs, just a line mentionning a closed SSL connection.
Been searching for a while and I can't find what could be causing this.
Alright so first the SSLVerifyDepth parameter wasn't properly set. I was able to find this by checking Apache's ssl_error_log file.
And second, the log file was saying that the CRL was not reacheable. Even if set what I thought was the correct CRL... but I actualy forgot the CRL of the CA that is above the clients CA !
Thanks again for helping me with checking the CA, case closed !

Apache 2.4 SSL Config

I've got a question regarding ssl config for apache 2.4. I got the following ssl settings for my vhost. There are more than 1 Directory but the config is mostly the same, only IPs are different. If I active the the three commented lines the apache should check the requests against the cert and not just pass the request through, correct? I assume the apache breakts the encryption for all requests from the internet and re-encrypts again to pass the request on. Am I right? Is there a way to not break the encryption and just delegate the cert checks to the next system?
RequestHeader set ClientProtocol HTTPS
SSLEngine On
SSLProtocol ALL -SSLv2 -SSLv3
SSLProxyEngine On
SSLProxyProtocol ALL -SSLv2 -SSLv3
SSLHonorCipherOrder On
SSLCipherSuite ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH:!MD5:!aNULL:!EDH
SSLCertificateFile /path/to/file.crt
SSLCertificateKeyFile /path/to/file.key
<Directory /folder-name>
#SSLVerifyClient optional_no_ca
#SSLVerifyDepth 1
#SSLOptions +OptRenegotiate +ExportCertData
ProxyPass https://10.20.30.40:8443/
ProxyPassReverse https://10.20.30.40:8443/
</Directory>
Thanks for your help guys and regards. Sebastian
Yes, this Apache acting as a proxy terminates SSL. It then makes or reuses a pooled SSL connection to the backend.
There's no way to truly let the backend think it's handshaking with the client unless it accessed apache as a forward proxy using the mod_proxy_connect module.
Some application servers accept the body of the client certificate in a proprietary header, making that identity available in the backend server. But they are not actually authenticating it in the handshake like the proxy/apache has done.

SSL handshake issue with remote apache httpd server, works locally

I'm getting strange issue:
I have installed/configured ssl certificate/key and ca certs etc in apache, and now can access it on latest chrome/firefox browser from local machine, and they show the certificate is all good (total green lock icon), and also shows it using modern cipher suite.
Note that i'm accessing it from local machine via server name itself, not from localhost etc, and not by changing hosts file.. Also it is accessible from another computer in same network without any issue..
But when i try to access this from different, remote machine (not in same network) or via a vpn etc, i get ssl connection error. Firefox indicates "Peer reports it experienced an internal error. (Error code: ssl_error_internal_error_alert)".
I used openssl command on remote machine to mimic a client:
*openssl s_client -connect xyz.com:443 -state -nbio 2>&1*
it shows:
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
Loading 'screen' into random state - done
CONNECTED(00000170)
turning on non blocking io
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:error in SSLv2/v3 read server hello A
write R BLOCK
SSL3 alert read:fatal:internal error
SSL_connect:error in SSLv2/v3 read server hello A
7020:error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error:.\ssl\s23_clnt.c:762:
- - -
no peer certificate available
- - -
No client certificate CA names sent
- - -
SSL handshake has read 7 bytes and written 307 bytes
- - -
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
- - -
I have to use apache httpd to use https, and fwd requests to tomcat, which is only using http, and used ajp-proxy for this purpose.
I tried to remove proxy configuration, restarted and still no luck - on local machine it show "it works" page, and on remote machine, same ssl connection error.
Nothing in apache logs also corresponding to the tries from remote machine (i.e. they are not reaching till those logs).
BUT strangely, the existing configuration do work from remote machine for 30-40 minutes (i.e. for some time) after a long not-working period. and then same configuration go for toss again.. can't understand why. During whole this period, it always remain accessible/fine from the local machine..
Here is ssl-conf:
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:SSL_RSA_WITH_RC4_128_SHA:HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLSessionCache "shmcb:c:/Apache24/logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300
SSLUseStapling On
SSLStaplingCache "shmcb:c:/Apache24/logs/ssl_stapling(150000)"
SSLStaplingStandardCacheTimeout 3600
<VirtualHost *:443>
DocumentRoot "c:/Apache24/htdocs"
ServerName www.xyz.com
ServerAlias xyz.com
ServerAdmin info#xyz.com
ErrorLog "c:/Apache24/logs/error.log"
TransferLog "c:/Apache24/logs/access.log"
SSLEngine on
SSLCertificateFile "C:/Apache24/xyz/certs/server.crt"
SSLCertificateKeyFile "C:/Apache24/xyz/certs/private_key_no_pswd.pem"
SSLCertificateChainFile "C:/Apache24/xyz/certs/gd_bundle-g2-g1.crt"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "c:/Apache24/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
CustomLog "c:/Apache24/logs/ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
#ProxyRequests Off
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
<Proxy *>
#Order allow,deny
Allow from all
Deny from none
Require all granted
#Deny from all
#Allow from 127.0.0.0/255.0.0.0 ::1/128
# Order deny,allow
# Allow from localhost
# Require ip 127.0.0.1
</Proxy>
ProxyPass / ajp://localhost:8009/
</VirtualHost>
You can see many things tried in virtualHost configs (was getting permission denied and other problems), and tried many things till it worked from local machine..
My env is:
Win-XP sp3 (i know its old), ApacheLounge httpd- VC-10 v-2.4.x (on port 443), tomcat-1.6 (on 8080)
Please let me know if i'm doing anything wrong, or you need any other config to see.
Thanks.
This at works in the local network and not outside it sounds very much like a firewall protecting your network. Another possibility is that the same hostname resolves to different IP addresses within your local and the remote network and thus it tries to reach different hosts from local and remote. And yet another thing could be that the hostname resolves to IPv4 and IPv6 addresses but your server uses only IPv4. If you then do only IPv4 in your local network and the other network can do IPv6 you will see similar effects.
To debug this problem I would suggest to do packet captures at your local client, at the remote client and compare them. Also check with packet capturing if the data from the remote client reaches the server at all (or if a firewall blocks it).
Edit: from the comment it looks like that local and remote client see different IP addresses for the same server. To debug why this is the case first check that both sides actually use the same server, because often you see that one uses www.example.com and the other example.com (without www) but there are different IP addresses for the names. If you are sure that this is not the case check what the real IP address should be and then look in more detail at the party which has the wrong name. This wrong name might be caused by an entry in the hosts file (from testing?), by cached entries (changes to the DNS take some time to propagate, sometimes a day or longer) or because a split DNS setup is used. Split DNS is not uncommon in companies where they have servers facing extern and intern and they want the intern cients to use the internal IP address and extern clients to use the external IP address.

How to config PlayFramework2 to support SSL?

I've read
How to configure playframework server to support ssl
and I also tried to follow http://www.playframework.org/documentation/1.1.1/releasenotes-1.1#https but it doesn't work for me
many thanks~
I read the doc for Play1 because I can't find any more updated information for Play2 about https.
in application.conf, I added these lines:
https.port=9443
certificate.key.file=conf/host.key
certificate.file=conf/host.cert
I type run in the play console, and try to access the server at https://localhost:9443 the browser timed out without anything logged in the console output
It won't work with the approach you are taking. You are mistaking release notes of 1.x branch with 2.x branch.
in 1.x branch, it is possible. Release notes are sufficient, and they worked for me.
For 2.1+ branch, please refer to #Christina's comment. Support has been added in 2.1 and the discussion thread provides details.
Quoting James Roper's response
In dev mode, it's very easy, just:
JAVA_OPTS=-Dhttps.port=9443 play run
Play will generate a private key and self signed certificate, which
obviously your browser will balk at with a big red warning. It will
reuse that generated self signed certificate for each subsequent run
of Play, so you should only get the browser error once. Obviously
this self signed certificate is probably not what you want in
production. Also important to note is that the self signed
certificate generation will only work on JVMs that use the sun
security libraries (eg Oracle and OpenJDK, but most notably not IBM
J9). On JVMs that don't use these, you will get a
NoClassDefFoundError when it tries to generate the certificate.
In prod (and this config also applies to dev) you configure it much
the same way that you configure SSL ordinarily in Java, via system
properties. Here's a summary:
https.port - The port that should be used
https.keyStore - The path to
the keystore containing the private key and certificate, if not
provided generates a keystore for you
https.keyStoreType - The key
store type, defaults to "JKS"
https.keyStorePassword - The password,
defaults to ""
https.keyStoreAlgorithm - The key store algorithm,
defaults to the platforms default algorithm
https.trustStore - This
feature hasn't been fully implemented, currently it will always use
the JDKs trust store for verifying client side certificates (which you
can of course configure yourself) whether you supply a value for this
or not, unless you specify "noCA", in which case, it will use a trust
store that trusts all certificates with no validation or verification,
which is useful for if using webid client side certificate verification.
For 2.0 branch, you have to put another server infront of play i.e either apache/nginx/other which listens on https and forwards the request to play in http.
Instructions to setup a frontend server are available at http://www.playframework.org/documentation/2.0.1/HTTPServer
So run your play server on a port. Have apache forward request from domain.com to 127.0.0.1:9443.
Sample apache config
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName example.com
ServerAlias *.example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
ProxyPreserveHost On
# ProxyPass /excluded !
ProxyPass / http://127.0.0.1:9000/
ProxyPassReverse / http://127.0.0.1:9000/
# SSL Engine Switch:
# Enable/Disable SSL for this virtual host.
SSLEngine on
# A self-signed (snakeoil) certificate can be created by installing
# the ssl-cert package. See
# /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
# If both key and certificate are stored in the same file, only the
# SSLCertificateFile directive is needed.
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
# Certificate Authority (CA):
# Set the CA certificate verification path where to find CA
# certificates for client authentication or alternatively one
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
Hope it helps.
The documentation for setting up the current version of Play (2.2.x) is here:
http://www.playframework.com/documentation/2.2.x/ConfiguringHttps
Right now you seem to need a reverse proxy managing the SSL for you. I found a ticket and a thread discussing this.
This is useful for locally testing https:
activator "run -Dhttps.port=9005"
Then point your browser to https://localhost:9005.
One thing we did was to use AWS ELB to handle our SSL, then setup the SSL forwarding (HTTP -> HTTPS) using a plays filters. The main benefit, takes the SSL load off your server and you don't have to run Apache or Nginx in front of play (as some solution point out).
You can see my answer here:
https://stackoverflow.com/a/23646948/690164
I also write a bit more about it in my blog:
http://www.mentful.com/2014/05/25/play-framework-filter-for-aws-elastic-load-balancer-forward-http-to-https/
I'm using securesocial 3.0.3M. Set
securesocial.ssl = true
in securesocial.conf and you should be good to go.
Then restart your sbt or activator with
JAVA_OPTS=-Dhttps.port=9443 activator run
Go to localhost:9443
enjoy

SSLVerifyClient not asking for certificate

When I put the directives:
SSLVerifyClient require
SSLVerifyDepth 2
SSLCertificateFile cert/path/cert.crt
Inside a virtual host directive and then go to the website a pop up box does not ask for my certificate. However when I put the same directives before the virtual host it will.
Why does it act this way?
The documentation actually says the SSL directives listed should be defined inside the virtual host.