In many web architectures it is common to access a Java EE Application through a reverse proxy server. A reverse proxy can be used for example as a dispatcher to redirect users to different servers or switch to a standby server in a failover scenario. Another typical use case is to run a dispatcher as the SSL Endpoint for a Java EE application. traefik.io or Squid are common tools to provide such a functionality. If you are running Wildfly behind such a reverse proxy server for SSL Endpoints you need to take care about some configuration issues.
Run Wildfly in HTTP only
In case you run Wildfly behind a modern reverse proxy like traefik.io things should work out of the box. It is fine for these scenarios that Wildfly is accessed by HTTP only. The reverse proxy in this scenario the SSL termination endpoint.
proxy-address-forwarding=”true”
A problem within this scenario ocures in JSF applications when a redirect is used. Such a redirect scenario is typical for JSF applications where a navigation rule uses a <redirect/>
.
In this case Wildfly is not aware of the proxy and so it sends a HTTP redirect (302) which will lead to a situation where an already established SSL connection will be lost. To avoid the loss of SSL connections inside your WildFly application you need to add the HTTP header parameter into the HTTP listener of your dispatcher:
proxy-address-forwarding="true"
This will hold the existing SSL connection also for HTTP redirect 302. The complete configuration will look like this:
<subsystem xmlns="urn:jboss:domain:undertow:11.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<http-invoker security-realm="ApplicationRealm"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
</subsystem>
The important part is the http-listener configuration wich now enables proxy-address-forwarding.
So this is the most easy configuration for wildfly running behind a reverse proxy. Only if you need to run Wildfly a an SSL Endpoint than continue reading the next section.
Run WildFly as an SSL Endpoint
To access an application running on Wildfly through a reverse proxy per SSL it may be necessary to enable also HTTPS connections in Wildfly. This means Wildfly is the SSL termination endpoint. Per default the WildFly server is only allowing HTTP connections. To enable HTTPS you need first to create a certificate and add this into the standalone.xml. Here are the steps to go:
(1) Create a Certificate
(1.1) Self-signed Certificate:
Using the linux keytool you can easily create your own private certificate and store it into the / configuration/ directory in Wildfly:
cd /opt/wildfly/standalone/configuration/ keytool -genkey -alias local-wildfly-cert -keyalg RSA -sigalg MD5withRSA -keystore local-wildfly-cert.jks -storepass adminadmin -keypass adminadmin -validity 9999 -dname "CN=Server Administrator,O=MyOrg,OU=com,C=DE"
Replace the password and organisation name with appropriate values.
(1.2) CA-Certificate
Only in case that you already have an existing CA-Certificate and you want to use it for wildfly directly you can create the keystore file for wildfly with the openssl command line tool:
openssl pkcs12 -export -in yourdomain.com.crt -inkey yourdomain.com.key -out yourdomain.com.p12 -name local-wildfly-cert -CAfile your_provider_bundle.crt -caname root -chain
You need to define a password for the generated cert file. The pk12 file can now be imported into the keystore with the following command
keytool -importkeystore -deststorepass <secret password> -destkeypass <secret password> -destkeystore yourdomain.com.jks -srckeystore yourdomain.com.p12 -srcstoretype PKCS12 -srcstorepass <secret password used in csr> -alias local-wildfly-cert
The password again is needed for the configuration in wildfly.
(2) Configure a security realm
After you have generated the .jks file you can now add a new SecurityRealm with the name “UndertowRealm” in the standalone.xml file. This security realm is used to established https connections for wildfly/undertow later. Add the following entry into the section “security-realms” of the standalone.xml file:
..... <security-realm name="UndertowRealm"> <server-identities> <ssl> <keystore path="local-wildfly-cert.jks" relative-to="jboss.server.config.dir" keystore-password="adminadmin" alias="local-wildfly-cert" key-password="adminadmin"/> </ssl> </server-identities> </security-realm> </security-realms>
The new realm is using the local SSL certificate created before.
Note: Take care about the location of your key files.
(3) Setup the HTTPS Listener
Finally you need to update the http and https-listeners for undertow in the standalone.xml. Edit the server section ‘default-server’ in the following way:
....... <server name="default-server"> <http-listener name="default" socket-binding="http" proxy-address-forwarding="true"/> <https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/> .... .....
Note: Be careful about changing both listener settings – http and https! The default setting redirect-socket=https from the http-listener must be changed in proxy-address-forwarding=true.
The default port for https in wildfly/undertow is 8443. So you can test your https setup now with a direct https request:
https://myserver:8443/myapplication
See also more discussion here.