Let Nginx or Apache Require And Accept any client certificate? - apache

I was wondering if it was possible to configure either of these servers to both require a client certificate while at the same time not completely verifying it?
So far, I tried looking at the SSLVerifyClient configuration fields but the options seem to either make it optional or required and actually verified.

Related

Hidden SSL Certificates in Apache overlapping? (Virtualmin)

Introduction
The problem is, in short, this. I've been using 'Virtualmin' for a while now, mainly becuse it works better (in my opinion & for my purposes) than VestaCP, Ajenti, Direct Admin (Evolution), CPanel, Sentora, and most of the 'ISP' series.
In doing this, I could already do just about everything via CLI / FTP, this was just a more coherent option for everyone to work together, and to where others could solve their own problems. Getting used to Virtualmin / Webmin didn't take long, but I've run into a problem that is, for lack of a better word, puzzling.
I run SSL certificates on all of my sites via a combination of 'Let's Encrypt' and sometimes Cloudflare, since I use it to manage DNS and mitigate DDOS attacks (when necessary to turn it on) anyway. In addition, I limit the TLS versions, set my own cipher via the global directives, and enabled HSTS.
Now however, I have a piece of software that, for some reason, can't connect to its REST API if the site is under a SSL layer and / or Proxy. So, I tried to disable the SSL certificate enforcement to temporarily rectify the problem. However, after removing it, I realized that with HSTS enabled, I could no longer travel to the normal 'HTTP' version of the site. I removed the HSTS line in the directives, but it's still persisting.
I'm also getting security warning because of a certificate mismatch happening with Virtualmin. For some reason, SSL certificates on other domains are applying to the current one. I've checked each individual site's .conf file, as well as each one's directives (and SSL Directives), as we as looking for anything that would do it in the global directives. The situation looks kind of like this.
Domains & Tiers
Example.com (Domain One)
--Analytics.Example.com (Sub-domain under the above One)
ExampleTwo.com (Different Domain, 'Domain Two')
--App.ExampleTwo.com (Sub-domain under above 'Two')
Essentially, the SSL certificate from Analytics is being pushed onto the App subdomain (That's under a different domain), in addition to App's own SSL certificate. When I shut off the SSL certificate for Analytics, and the one for App, the top layer's (Example.com) SSL certificate is then forced onto the 'App' sub-domain. I would've thought that this would've had to manifest in either the site directives, their SSL directives, or the SSL.Conf in the global directives, but there's nothing there. I have yet to find a fix for this.

setting SSL/TLS protocol version according to URL path or specific service in apache(mod_ssl)

I want to set "force to use TLS 1.2" in my server httpd-ssl.conf
SSLProtocol -all +TLSv1.2
but I'm also considering if some client modules does not support TLS 1.2,
and I would like to give it a exception that TLS 1.x can be acceptable.
Am I able to do such thing?
e.g. disable TLS_1.2 restriction in specific URL path ( https:///specific/path/ ) or specific service or something like this.
thanks!
The path component is only known after a successful TLS handshake. Additionaly multiple HTTP request (with different path) can be done within the same TCP connection. While in theory the server could first allow the TLS handshake with an older protocol version and then drop the connection if the client uses the established TLS session to access a path which requires a better TLS version I don't think that this can be configured in Apache.
This might help for APACHE: https://httpd.apache.org/docs/trunk/ssl/ssl_howto.html
How can I create an SSL server which accepts many types of ciphers in general, but requires a strong cipher for access to a particular URL?
Obviously, a server-wide SSLCipherSuite which restricts ciphers to the strong variants, isn't the answer here. However, mod_ssl can be reconfigured within Location blocks, to give a per-directory solution, and can automatically force a renegotiation of the SSL parameters to meet the new configuration. This can be done as follows:
# be liberal in general -- use Mozilla's "Intermediate" ciphersuites (weaker
# ciphersuites may also be used, but will not be documented here)
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
<Location "/strong/area">
# but https://hostname/strong/area/ and below requires strong ciphersuites
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
</Location>

Apache HTTPD/mod_proxy/Tomcat and SSL with client auth

I'm sure this is an FAQ but I couldn't find anything I recognized as being the same question.
I have several web-apps running in Tomcat, with some pages e.g. the login page protected by SSL as defined by confidentiality elements in their web.xmls. One of the apps also accepts client-authentication via certificate. I also have a rather extensive JAAS-based authorization & authentication scheme, and there is all kinds of shared code and different JAAS configurations etc between the various webapps.
I really don't want to disturb any of that while accomplishing the below.
I am now in the process of inserting Apache HTTPD with mod-proxy and mod-proxy-balancer in front of Tomcat as a load balancer, prior to adding more Tomcat instances.
What I want to accomplish for HTTPS requests is that they are redirected 'blind' to Tomcat without HTTPD being the SSL endpoint, i.e. HTTPD just passes ciphertext directly to Tomcat so that TC can keep doing what it is already doing with logins, SSL, web.xml confidentialty guarantees, and most importantly client authentication.
Is this possible with the configuration I've described?
I am very familiar with the webapps and SSL and HTTPS and Tomcat, but my knowledge of the outer reaches of Apache HTTPD is limited.
Happy to have this moved if necessary but it is kind of programming with config files ;)
This sounds similar to this question, where I've answered that it's not possible:
You can't just relay the SSL/TLS traffic to Tomcat from Apache. Either
your SSL connection ends at Apache, and then you should reverse proxy
the traffic to Tomcat (SSL [between Httpd and Tomcat] is rarely useful in this case), or you make
the clients connect to Tomcat directly and let it handle the SSL
connection.
I admit it's a bit short of links to back this claim. I guess I might be wrong (I've just never seen this done, but that doesn't strictly mean it doesn't exist...).
As you know, you need a direct connection, or a connection entirely relayed, between the user-agent and the SSL endpoint (in this case, you want it to be Tomcat). This means that Apache Httpd won't be able to look into the URL: it will know the host name at best (when using Server Name Indication).
The only option that doesn't seem to depend on a URL in the mod_proxy documentation is AllowCONNECT, which is what's used for forward proxy servers for HTTPS.
Even the options in mod_proxy_balancer expect a path at some point of the configuration. Its documentation doesn't mention SSL/HTTPS ("It provides load balancing support for HTTP, FTP and AJP13 protocols"), whereas mod_proxy talks at least about SSL when mentioning CONNECT.
I would suggest a couple of options:
Using an iptables-based load-balancer, without going through Httpd, ending the connections in Tomcat directly.
Ending the SSL/TLS connection at Httpd and using a plain HTTP reverse proxy to Tomcat.
This second option requires a bit more configuration to deal with the client certificates and Tomcat's security constraints.
If you have configured your webapp with <transport-guarantee>CONFIDENTIAL</transport-guarantee>, you will need to make Tomcat flag the connections as secure, despite the fact it sees them coming from its plain HTTP port. For Tomcat 5, here is an article (originally in French, but the automatic translations isn't too bad) describing how to implement a valve to set isSecure(). (If you're not familiar with valves, they are similar to filters, but operate within Tomcat itself, before the request is propagated to the webapp. They can be configured within Catalina) I think from Tomcat 5.5, the HTTP connector secure option does exactly that, without requiring your own valve. The AJP connector also has a similar option (if using mod_proxy_ajp or mod_jk).
If using the AJP connector, mod_proxy_ajp will forward the first certificate in the chain and make it available within Tomcat (via the normal request attribute). You'll probably need SSLOptions +ExportCertData +StdEnvVars. mod_jk (although deprecated as far as I know) can also forward the entire chain sent by the client (using JkOptions +ForwardSSLCertChain). This can be necessary when using proxy certificates (which are meaningless without the chain up to their end-entity certificate).
If you want to use mod_proxy_http, a trick is to pass the certificate via an HTTP header (mod_header), using something like RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s. I can't remember the exact details, but it's important to make sure that this header is cleared so that it never comes from the client's browser (who could forge it otherwise). If you need the full chain, you can try out this Httpd patch attempt. This approach would probably need an extra valve/filter to turn the header into the javax.servlet.request.X509Certificate (by parsing the PEM blocks).
A couple of other points that may be of interest:
If I remember well, you need to download the CRL files explicitly for Httpd and configure it to use them. Depending on the version of Httpd you're using, you may have to restart it to reload the CRLs.
If you're using re-negotiation to get your client-certificate, a CLIENT-CERT directive will not make Httpd request a client certificate as far as I know (this is otherwise done via a valve that can access the SSLSession when using the JSSE connector directly). You may have to configure the matching path in Httpd to request the client-certificate.

Apache: Conditional SSLCertificateFile depending on domain?

I am running a multi-language web store accessible from differents domains, that lead to different languages.
The apache configuration is quite complex and I would like to have one single file shared with all the stores. I had this in place until I had to introduce SSL.
When it comes to apache and SSL certificates I would need to do something like:
SetEnv is_es 0<br>
SetEnvIfNoCase Host .*es is_es 1<br>
SSLCertificateFile /etc/ssl/certs/spanish.server.crt env=is_es<br>
This is aparently not possible, apache tells me:
<i>SSLCertificateFile takes one argument, SSL Server Certificate file (`/path/to/file' - PEM or DER encoded)</i>
I was wondering if there is any workaround. My goal is to avoid having different copies of the same configuration and having to propagate manually any changes I want to make.
It is hosted on a dedicated server, so I am free to do any changes to the setup.
When you are on a https connection, the Host header is inside the SSL encapsulation, so you need the full SSL handshake before you check for an hostname for your virtualhost.
You should go for SSL certificates with SAN (Subject Alternative Names), this will allow that a single certificate for multiple hostnames. (or a wildcard cert)
All the main browsers supports it already:
http://www.digicert.com/subject-alternative-name-compatibility.htm
And you can get one of this certs from the majors CAs:
http://www.digicert.com/subject-alternative-name.htm
http://www.verisign.com/ssl/buy-ssl-certificates/subject-alternative-name-certificates/index.html
http://www.thawte.com/ssl/san-uc-ssl-certificates/index.html

How to secure an admin area for a public and private rails app

How would you secure access to the admin area for a web app?
Our Rails CMS serves pages publicly. I would like to make the backend (/admin) inaccessible using either the webserver(apache) or firewall(netfilter).
Could this be done using an SSL certificate? I would like to limit access to the backend to only those whose have the "key", similar to SSH access to a server.
Thanks in advance.
You're absolutely right that an SSL cert is the way to go. And it's not really all that tricky to set up, though it's rarely done.
It's important to remember that this problem has two components. The first is, "how do I get the darn thing working at all," and, this being a security system, the second is, "how do I set it up so that I'm not likely to accidently do something that borks my security?"
The first thing I would suggest is to write a separate Rails application for the admin stuff, and run it with a different web server on a different port. (If you really want to avoid putting a port number in the URL for the admin site, use a proxy in front of both web servers that uses the Host: header to redirect requests to for foo.com to one server, and admin.foo.com to the other.) This separation will help ensure that you don't accidently give regular users access to admin functionality, and make the SSL setup easier.
For the admin server, set it up for SSL access only. Create a new signing cert, and allow only certificates signed by the signing cert to connect. (This is web-server dependent; if you really need details on how to do this, you probably want to post a new question giving the specifics of the server and configuration you're using.) You can set up a page (on the non-SSL site, or on a page accessable to non-authenticated users on the SSL site) that will have your admins' web browsers automatically generate and upload a certificate that you can sign which will give them access.
Keep copies of all the certs you sign so that when you need to revoke access, you can put that cert in the revocation list.
DON'T use the firewall, you'll just complicate your implementation. The "correct" approach is to use .htaccess or set up authorisation in Apache Directory configuration.
It sounds like you want SSLRequire
SSLVerifyClient none
<Directory /usr/local/apache/htdocs/secure/area>
SSLVerifyClient require
SSLVerifyDepth 5
SSLCACertificateFile conf/ssl.crt/ca.crt
SSLCACertificatePath conf/ssl.crt
SSLOptions +FakeBasicAuth
SSLRequireSSL
AuthName "Snake Oil Authentication"
AuthType Basic
AuthUserFile /usr/local/apache/conf/httpd.passwd
require valid-user
</Directory>
Howto: http://eregie.premier-ministre.gouv.fr/manual/mod/mod_ssl/ssl_howto.html