diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/clustering.xml b/docbook/auth-server-docs/reference/en/en-US/modules/clustering.xml
index fc9cc55..5e16788 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/clustering.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/clustering.xml
@@ -47,6 +47,11 @@
Start in HA mode
</para>
</listitem>
+ <listitem>
+ <para>
+ Loadbalancer (optional step)
+ </para>
+ </listitem>
</itemizedlist>
</para>
@@ -193,6 +198,20 @@
</section>
<section>
+ <title>Loadbalancer setup</title>
+ <para>
+ This is optional step, however in production, when you have more Keycloak nodes in cluster, you usually want to "hide" them behind frontent loadbalancer server, which will forward the
+ requests to the "backend" keycloak nodes. Consult the documentation of your loadbalancer (For example <ulink url="http://mod-cluster.jboss.org/">Mod cluster</ulink> )
+ for how to configure this.
+ </para>
+ <para>
+ But regardless of loadbalancer implementation used, it is important that you make sure the web server sets the <literal>X-Forwarded-For</literal> and
+ <literal>X-Forwarded-Proto</literal> headers on the requests made to Keycloak properly. This is described in details in <link linkend="proxy-address-forwarding">Reverse proxy</link>
+ section.
+ </para>
+ </section>
+
+ <section>
<title>Troubleshooting</title>
<para>
Note that when you run cluster, you should see message similar to this in the log of both cluster nodes:
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/security-vulnerabilities.xml b/docbook/auth-server-docs/reference/en/en-US/modules/security-vulnerabilities.xml
index 9a9b1d8..35ba499 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/security-vulnerabilities.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/security-vulnerabilities.xml
@@ -129,7 +129,7 @@
applications register as specific a URI pattern as possible to mitigate open redirector attacks.
</para>
</section>
- <section>
+ <section id="brute-force-attacks">
<title>Password guess: brute force attacks</title>
<para>
A brute force attack happens when an attacker is trying to guess a user's password. Keycloak has some
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
index 0058364..4b0e19f 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
@@ -516,7 +516,7 @@ bin/add-user-keycloak.[sh|bat] -r master -u <username> -p <password>
otherwise <literal>cacerts</literal> file that comes with java is used.
</para>
<para>
- Truststore is used when connecting securely to identity brokers, LDAP identity providers, when sending emails,
+ Truststore is used when connecting securely to identity brokers, LDAP federation providers, when sending emails,
and for backchannel communication with client applications.
Some of these facilities may - in case when no trusted certificate is found in your configured truststore -
@@ -785,7 +785,7 @@ $ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificat
<programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>]]></programlisting>
</para>
<para>
- Check the <ulink url="https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration">Wildfly Undertow</ulink> documentation for more information on fine tuning the socket connections.
+ Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">Wildfly Undertow</ulink> documentation for more information on fine tuning the socket connections.
</para>
</section>
</section>
@@ -795,9 +795,12 @@ $ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificat
<para>
Follow the documentation for your web server to enable SSL and configure reverse proxy for Keycloak.
It is important that you make sure the web server sets the <literal>X-Forwarded-For</literal> and
- <literal>X-Forwarded-Proto</literal> headers on the requests made to Keycloak. Next you need to enable
- <literal>proxy-address-forwarding</literal> on the Keycloak http connector. Assuming that your reverse
- proxy doesn't use port 8443 for SSL you also need to configure what port http traffic is redirected to.
+ <literal>X-Forwarded-Proto</literal> headers on the requests made to Keycloak and you enable
+ <literal>proxy-address-forwarding</literal> on the Keycloak http connector. This is described in <link linkend="proxy-address-forwarding">next section</link>, so
+ here we will focus just on SSL setup.
+ </para>
+ <para>
+ Assuming that your reverse proxy doesn't use port 8443 for SSL you also need to configure what port http traffic is redirected to.
</para>
<section>
@@ -808,12 +811,11 @@ $ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificat
</para>
<para>
- First add <literal>proxy-address-forwarding</literal> and <literal>redirect-socket</literal> to
+ First add <literal>redirect-socket</literal> to
the <literal>http-listener</literal> element:
<programlisting><![CDATA[<subsystem xmlns="urn:jboss:domain:undertow:1.1">
...
- <http-listener name="default" socket-binding="http"
- proxy-address-forwarding="true" redirect-socket="proxy-https"/>
+ <http-listener name="default" socket-binding="http" redirect-socket="proxy-https"/>
...
</subsystem>
]]></programlisting>
@@ -830,13 +832,115 @@ $ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificat
]]></programlisting>
</para>
<para>
- Check the <ulink url="https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration">WildFly</ulink> documentation for more information.
+ Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">WildFly</ulink> documentation for more information.
</para>
</section>
</section>
</section>
+ <section id="proxy-address-forwarding">
+ <title>Configure reverse proxy for address forwarding</title>
+ <para>
+ Keycloak has some functionalities (for example <link linkend='events'>Events</link> or <link linkend="brute-force-attacks">Brute Force protector</link>)
+ that relies on the fact, that remote address of the HTTP connection is the real IP address of the client machine. This may be a bit tricky when you have setup
+ with reverse proxy or loadbalancer.
+ </para>
+ <para>
+ Assume you have setup when users send requests to the "Frontend" server (reverse proxy), which then forwards them to the
+ "backend" server (Keycloak) on private network. Then with default setup of Wildfly Undertow subsystem, Keycloak will see <literal>request.getRemoteAddress()</literal> to be
+ resolved to the IP address of reverse proxy instead of real IP of client.
+ </para>
+ <para>
+ To address this issue and see the real IP address of client, you need 2 things:
+ <itemizedlist>
+ <listitem>
+ <para>Configure your reverse proxy (loadbalancer) to properly set <literal>X-Forwarded-For</literal> and <literal>X-Forwarded-Proto</literal> HTTP headers.</para>
+ </listitem>
+ <listitem>
+ <para>Configure Wildfly undertow subsystem on Keycloak server's side to read the client's IP address from <literal>X-Forwarded-For</literal> header.</para>
+ </listitem>
+ </itemizedlist>
+ More details for setup both things.
+ </para>
+ <section>
+ <title>Configure your reverse proxy to set X-Forwarded-For</title>
+ <para>
+ Consult the documentation of your reverse proxy implementation on how to do it.
+ </para>
+ <para>
+ Note that when your reverse proxy receives requests from the users on public network, you also need to ensure that <literal>X-Forwarded-For</literal>
+ is always overwritten by proxy with the IP address of client machine. If it's not overwritten, but just forwarded, the
+ "evil" user can manually set the <literal>X-Forwarded-For</literal> header to the false IP address to trick Keycloak.
+ </para>
+ <para>
+ For example imagine that evil user connects from IP address <literal>20.20.20.20</literal> but he manually sets the <literal>X-Forwarded-For</literal> header to
+ value <literal>30.30.30.30</literal>. If reverse proxy "forwards" the header, it will append the old value set by evil user with the IP address user connected from.
+ So <literal>X-Forwarded-For</literal> header will be incorrectly set to <literal>30.30.30.30 , 20.20.20.20</literal>. Then Keycloak will see incorrect IP
+ address <literal>30.30.30.30</literal>. So in this case, reverse proxy must overwrite the old value of header and just set the real IP
+ of the user machine to <literal>20.20.20.20</literal>. On the other hand, when you have more reverse proxies chained together, you need to configure
+ "overwriting" just for the first proxy in the chain.
+ </para>
+ <para>
+ Some example setups:
+ <variablelist>
+ <varlistentry>
+ <term>user (IP address: 20.20.20.20) -> load balancer (IP Address: 30.30.30.30 ) -> Keycloak</term>
+ <listitem>
+ <para>
+ For this setup, loadbalancer receives the IP from the end user, so it must overwrite the header. So Keycloak will correctly see
+ <literal>X-Forwarded-For: 20.20.20.20</literal> .
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>internet (IP address: 20.20.20.20) -> reverse proxy (IP Address: 30.30.30.30 ) -> load balancer (IP Address: 40.40.40.40 ) -> keycloak</term>
+ <listitem>
+ <para>
+ For this setup, just the first reverse proxy is supposed to overwrite <literal>X-Forwarded-For</literal> but second (load balancer) should just forwards it.
+ So Keycloak will correctly see <literal>X-Forwarded-For: 20.20.20.20,30.30.30.30</literal>, hence in the second step, it will be able to correctly see
+ client's remote IP address <literal>20.20.20.20</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </section>
+ <section>
+ <title>Configure Wildfly undertow subsystem</title>
+ <para>
+ This is needed, so the wildfly undertow subsystem will read the client's IP address from the <literal>X-Forwarded-For</literal> header rather than from the IP of network packet, which
+ came from loadbalancer and hence it's set to the IP of loadbalancer.
+ </para>
+ <para>
+ If your proxy sends requests to the HTTP connector, it can be configured easily by add attribute <literal>proxy-address-forwarding</literal> to the
+ <literal>http-listener</literal> subelement of undertow subsystem.
+ For example:
+ <programlisting><![CDATA[
+<http-listener name="default" socket-binding="http"
+ redirect-socket="https" proxy-address-forwarding="true" />
+]]></programlisting>
+ </para>
+ <para>
+ If you use AJP connector, which is common setup for loadbalancers, the proxy-address-forwarding is not available, hence you need to do slightly more configurations.
+ First add <literal>filter</literal> subelement of <literal>filters</literal> element with the value like this:
+ <programlisting><![CDATA[
+<filter name="proxy-peer"
+ class-name="io.undertow.server.handlers.ProxyPeerAddressHandler"
+ module="io.undertow.core" />
+]]></programlisting>
+ Then reference it from the <literal>host</literal> element:
+ <programlisting><![CDATA[
+<filter-ref name="proxy-peer"/>
+]]></programlisting>
+ If you want to check address is correctly set, you can enable <link linkend="events">events</link> and verify the IP address really points to the IP address of client machine.
+ </para>
+ <para>
+ Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">WildFly</ulink> documentation for more information.
+ </para>
+ </section>
+ </section>
+
</section>
<section>