Mutual TLS with Apache proxy to Tomcat - apache

The setup I am working with involves an Apache server acting as a proxy to a tomcat server which serves several web applications. I have enabled mutual TLS on apache and I can successfully connect to one of my tomcat web applications and verify the client certificate. However, I want to take this one step further... At the moment in my ssl.conf I have a default HTTPS VirtualHost configuration which looks like this:
<VirtualHost *:443>
....
SSLEngine on
SSLCertificateFile /path/to/www_yoursite_com.crt
....
#other SSL options...
</VirtualHost>
In my modproxy.conf I have a configuration as follows:
ProxyPass /webApp1 https://localhost:1234/webApp1
ProxyPassReverse /webApp1 https://localhost:1234/webApp1
ProxyPass /webApp2 https://localhost:1234/webApp2
ProxyPassReverse /webApp2 https://localhost:1234/webApp2
where 1234 is the https port configured on a connector element on tomcat's server.xml file.
Let's assume that I only want mTLS for webApp1, the problem with this configuration is that I need a client cert on my browser even if I am accessing webApp2 so in other words I want to enable mTLS only for one web application. Even better, I would like to enable mTLS for a specific URL within my web application (is this even possible??), so for example I want mTLS required when someone hits https://myserver.com/webApp1/test/mtlsEndpoint but not on https://myserver.com/webApp1/test/otherEndpoint.
Is it possible to achieve this with another VirtualHost config for SSL on my ssl.conf ? I am going to test this tomorrow (trying to achieve this with another VirtualHost config that will proxy mTLS to my webApp1) but thought I should ask here as well to avoid trial and error and reinventing the wheel maybe this is easier than I am thinking ?

Yes, you just need separate SSL directives for webApp1 and webApp2. SSL directives can be configured in Apache right down to the directory level.

Related

Apache HTTP VM Behind HTTPS Lets Encrypt

I've read a lot of questions and answers which seem exactly the same as mine, but I can't seem to get my setup to work. I have a VM running Apache with only HTTP support at 192.168.2.101:32773. I can access it on my local network as such just fine. I now am ready to expose it through my Apache web server that has Lets Encrypt setup to generate SSL certificates. So I added this to my server conf file:
<VirtualHost *:32773>
ServerName server.com
SSLEngine on
SSLProxyEngine On
SSLCertificateFile /etc/letsencrypt/live/server.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/server.com/privkey.pem
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://192.168.2.101:32773/
ProxyPassReverse / http://192.168.2.101:32773/
</VirtualHost>
However, I get an ERR_SSL_PROTOCOL_ERROR when I try to load it up as https://server.com:32773. If I however change my address to http://server.com:32773, it loads just fine. Anything look wrong in this snippet? Thanks!
HTTP and HTTPS need to be on different ports. Typically HTTPS is served on port 443.
This is embarrassing... At some point I changed my port forward rules to point 32773 directly to 192.168.2.101 so I could validate that the rules were working at all. The above config worked as soon as I realized I wasn't even sending traffic to my Apache SSL enabled server.

Create an SSL certificate for a Shiny server running on CentOS

I can't figure how to create an SSL certificate for a Shiny server that runs on a CentOS machine.
My end goal is to be able to access my app with HTTPS.
So instead of - HTTP://mydomain.com:3838/my-app/
To have something like - HTTPS://mydomain.com:3838/my-app/
Or even better - HTTPS://mydomain/my-app/
I tried my best with numerous tutorials but I'm not an expert in system administration and didn't have a lot of success.
Would really appreciate any help here!
# cat /etc/centos-release
CentOS Linux release 7.5.1804 (Core)
# shiny-server --version
Shiny Server v1.5.7.907
Thanks!
My answer in one word: letsencrypt.
Letsencrypt provides an executable that will grant you SSL certificates for all the domains your server handles. For this, it validates your machine by mounting a temporary web server and checks if can reach it with the domain names you provided.
There's more info in the official website. Once you have the certs, simply add them to nginx or Apache or whatever web server you are using.
UPDATE:
To forward http calls to your shiny web server you have to use Apache web server as a proxy, that means, that every call yo yourdomain:80, will be redirected to locahost:3838.
You have to edit your default conf. In ubuntu you can find it in this path: /etc/apache2/sites-enabled/000-default.conf
Then, in the conf file:
<VirtualHost *:80>
# These lines configures SSL
SSLEngine on
SSLCertificateFile /path/to/your/ssl.crt
SSLCertificateKeyFile /path/to/your/ssl.key
# These lines configure the proxy
ProxyPreserveHost On
ProxyPass / http://0.0.0.0:3838/
ProxyPassReverse / http://0.0.0.0:3838/
# This sets the domain name to listen for
ServerName yourdomain.com
</VirtualHost>
Then, restart apache and you're good to go.

no let's encrypt renewal with reverse-proxy in ispconfig3

I am running an ISPConfig 3 server with apache. To get HTTPS i use the certbot of let's encrypt. ISPConfig supports cert generation which is working for various cites.
One site runs locally on a different port (as it is a complex system).
To reach it, i added a new site in ISPConfig and configured apache as a reverse proxy as shown below.
The site is up an running, but unable to renew the certificates via certbot (does not work only for this site).
ProxyRequests Off
ProxyVia Off
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://my.domain.com:8080
ProxyPassReverse / http://my.domain.com:8080
I guess the problem is the unreachability of the challenge folder (/acme/.well-known/acme-challenge)
How to configure apache as reverse proxy that it is able to renew its certificate?
I have the same problem here: the proxy endpoint doesn't have the same webroot and cannot serve the .well-known directory correctly, which means Let's Encrypt fails to find it.
The trick is to skip the proxying for the well-known URL, using something like this answer. In my case, it was simply a matter of adding this line:
ProxyPass /.well-known/ !
which will disable the proxying for the certbot directory.
Good luck!

how to use force-ssl in meteor.js without deployment to meteor.com subdomains?

The document is not clear. How to install certificate and etc in localhost?
force-ssl
This package causes Meteor to redirect insecure connections (HTTP) to a secure URL (HTTPS). Use this package to ensure that communication to the server is always encrypted to protect users from active spoofing attacks.
To simplify development, unencrypted connections from localhost are always accepted over HTTP.
Application bundles (meteor bundle) do not include an HTTPS server or certificate. A proxy server that terminates SSL in front of a Meteor bundle must set the standard x-forwarded-proto header for the force-ssl package to work.
Applications deployed to meteor.com subdomains with meteor deploy are automatically served via HTTPS using Meteor's certificate.
I've slogged through setting up an Apache reverse proxy that terminates SSL in front of Meteor, and wanted to document that here as well.
I added the following to the config file for the SSL virtual host:
<VirtualHost _default_:443>
ServerName server.domain.com
## SSL Engine Switch:
# Enable/Disable SSL for this virtual host.
SSLEngine on
## Proxy to port 3000 for Meteor apps
SSLProxyEngine On
ProxyRequests Off # Disable forward proxying
ProxyPass / http://localhost:3000
ProxyPassReverse / http://localhost:3000
## Your other SSL config directives such as certificates, etc.
</VirtualHost>
You do not need to install certificates on localhost. As it says "To simplify development, unencrypted connections from localhost are always accepted over HTTP.", which means that you can develop and test the application without using SSL and without installing certificates. Just run you application and access it with http://localhost:3000 as usual.
If you are talking about installing certificates for publicly facing applications it is probably best to use a reverse proxy server such as nginx and install the certificates for that server. http://wiki.nginx.org/HttpProxyModule

Apache Jboss SSL authentication

Resummarising my question:
I have got a Apache web server fronting the Jboss.
below is the ssl part of the Httpd conf
ProxyRequests Off
SSLProxyEngine on
SSLCertificateFile
/FinMgmt/deploy/https/certs/webserver/fm.insurance.co.uk_a_cert.pem
SSLCertificateKeyFile
/FinMgmt/deploy/https/certs/webserver/fm.insurance.co.uk_a_key.pem
SSLCACertificateFile
/FinMgmt/deploy/https/certs/fm.insurance.co.uk_CA_cert.pem
SSLVerifyClient optional_no_ca
SSLOptions +ExportCertData
ProxyPass /webapp1 https://fm.insurance.co.uk:8443/webapp1
ProxyPassReverse /webapp1 https://fm.insurance.co.uk:8443/webapp1
ProxyPass /webapp2 https://fm.insurance.co.uk:8443/webapp2
ProxyPassReverse /webapp2 https://fm.insurance.co.uk:8443/webapp2
Below is the ssl part from jboss server.xml:
<!-- SSL/TLS Connector configuration using the admin devl guide keystore clientAuth=false -->
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="500" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
keystorePass="glamdev"
truststoreFile="${jboss.server.home.dir}/conf/server.truststore"
truststorePass="passwd"/>
As per my understanding, Apache is configured to use 2 way mutual authentication with SSLVerifyClient optional_no_ca meaning that client may or maynot provide the certificate.
Now jboss is configured to one way SSL authentication.
Now what I understand is ,when browser send request apache,apache will respond with the certificate and browser will try to authenticate using its root CA or throw an exception asking user to store it.
And when apache will route request to jboss,here apache will act as client and jboss as SSL server,jboss will send its certificate from keystore which will be verified by the Apache using SSLCACertificateFile directive
And if jboss has to redirect to itself ,it will have to go through the reverse proxy as we have set proxyPassReverse.In that case jboss will act as SSL client and Apache http as SSL server and Apache will will send its certificate which jboss verify using the CA certificate in trustore.
Am I right in interpreting the config files?
Also I dont exactly understand the use of optional_no_ca in SSLVerifyClient.Will apache request the certificate from browser or not or it depends upon the browser ?
Actually I have inherited this application with no documentation whatsover and I am trying hard to make some sense out of it.
I'm assuming that what you're after is to use client-certificate authentication in your JBoss application, to authenticate browsers (not Apache Httpd as a client to JBoss).
If you want to have Apache Httpd as a reverse proxy in front of you JBoss container, you need to configure Apache Httpd to request and handle client-certificate authentication. In particular, you should use its SSLCA* and SSLVerifyClient directives, part of mod_ssl.
Whether you configure SSL/TLS between Apache Httpd and your JBoss worker node is independent. It's often unnecessary if you're on a trusted network at that point. If you do want SSL/TLS there, use Apache Httpd's SSLProxy* directives to configure which CA to trust. This being said, doing so will certainly create more confusion within your application, since there would be an ambiguity as to where the client-certificate information comes from: either a real-client certificate authentication at the JBoss container level, or a relayed certificate, as handled by Apache Httpd.
Indeed, you'll need to pass on the client-certificate information to your container for further information, as described in this answer.
If instead, what you're after is client-certificate authentication between Apache Httpd and JBoss, where you need this connection to be secured with SSL/TLS and to make sure if comes from the reverse proxy (which would present its certificate), you should be able to to this using SSLProxyMachineCertificateFile available in Apache Httpd 2.4. (This configuration is certainly unusual.)
EDIT: (Following changes to the question.)
As per my understanding, Apache is configured to use 2 way mutual
authentication with SSLVerifyClient optional_no_ca meaning that client
may or maynot provide the certificate.
SSLVerifyClient optional_no_ca means that Apache Httpd will only check that the client has the private key for the certificate it presents: it won't verify that the certificate is trusted (making SSLCACertificateFile useless). If you want presentation of the certificate to be optional, but still verify it against your PKI, use SSLVerifyClient optional (with SSLCACertificateFile).
Now jboss is configured to one way SSL authentication. Now what I
understand is ,when browser send request apache,apache will respond
with the certificate and browser will try to authenticate using its
root CA or throw an exception asking user to store it.
Yes, and the connection between the browser and Apache Httpd has nothing to do with JBoss.
And when apache will route request to jboss,here apache will act as
client and jboss as SSL server,jboss will send its certificate from
keystore which will be verified by the Apache using
SSLCACertificateFile directive
No, it's SSLProxyCACertificateFile (or ...Path)
And if jboss has to redirect to itself ,it will have to go through the
reverse proxy as we have set proxyPassReverse.In that case jboss will
act as SSL client and Apache http as SSL server and Apache will will
send its certificate which jboss verify using the CA certificate in
trustore. Am I right in interpreting the config files?
I'm not sure under which circumstances JBoss would "redirect to itself" (or what you mean by this). There's nothing to suggest JBoss has a role as a client here. This is not what ProxyPassReverse is for.
Also I dont exactly understand the use of optional_no_ca in
SSLVerifyClient.Will apache request the certificate from browser or
not or it depends upon the browser ?
When you set SSLVerifyClient to optional, optional_no_ca or require, the server will request a certificate. With require, it will terminate the connection if the client doesn't send one (that it trusts).
As your configuration stands, there's nothing to suggest that the client-certificate is conveyed to the JBoss container. It's not verified in any way at the Apache Httpd level (anyone with a self-signed client-certificate could connect here). You could in principle use optional_no_ca, let any certificate through and only verify them once they arrive to the Java container, but you'd certainly need some extra custom code to do so in your JBoss application. You would also need to convey the certificate itself somehow (e.g. via mod_header and a custom header or more directly using mod_proxy_ajp. It would also be harder to break the connection to make the client try another certificate if the one it presented initially was incorrect.