You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
core
Describe the bug
When using IPv6 and client is sending request from link-local or unique local address (ULA), client is blocked from sending clear-text HTTP requests when realm configuration is set to require SSL for "External request" (link).
Version
main
Regression
The issue is a regression
Expected behavior
Requests sent from IPv6 link-local or unique local address should succeed.
Actual behavior
Requests are rejected with response 403 Forbidden with body
One way to reproduce is to use Kubernetes cluster with IPv6 enabled
Run Keycloak in a Kubernetes cluster with IPv6 enabled.
Run a client in another pod and check that the pod's network interface has IPv6 address either from link-local address range or unique local address range. Send request using IPv6.
Observe response 403 Forbidden
For example for local development, Kind would use link-local addresses for pods and services within the cluster and a "real" CNI like Calico would typically use unique local addresses (ULA).
Looking at the git history, it seems that initially the code aimed to cover only clients within localhost, and later it took the current form where it was extended to allow IPv4 private addresses (link).
In case of IPv6 the private address ranges are following:
address type
binary prefix
IPv6 notation
Link-local unicast
1111 1110 10
FE80::/10
Unique local (ULA)
1111 110
FC00::/7
Site-local unicast (deprecated)
1111 1110 11
FEF0::/10
While the JDK method Inet4Address.isSiteLocalAddress() covers private address ranges for IPv4 (link), the IPv6 version Inet6Address.isSiteLocalAddress() only covers site-local unicast address range (link). According to RFC4291 section2.5.7 this address range is now deprecated and should be considered as global address by new implementation
The special behavior of this prefix defined in [RFC3513] must no longer be supported in new implementations (i.e., new implementations must treat this prefix as Global Unicast).
Existing implementations and deployments may continue to use this prefix.
While the documentation for interface InetAddress.isSiteLocalAddress() says (link)
Utility routine to check if the InetAddress is a site local address.
it seems likely to me that applications may rather use it for the effect of "all private address ranges", than for the specific (now deprecated) IPv6 site-local definition, especially considering the method is used through the upper class that covers both IPv4 and IPv6. Still, the JDK IPv6 implementation seems to take strict interpretation of covering site-local only and does not offer any method for checking for IPv6 private address ranges.
The text was updated successfully, but these errors were encountered:
IMHO the concept of some request requiring TLS, while others don't, might something that worked in the past where we divided the world into external, untrusted networks and internal, trusted networks. This is IMHO no longer the case in a world where zero trust is promoted.
So I'd say this option didn't age well, and it should rather be removed from Keycloak, than being extended. Using plain HTTP in a development environment might work, still in a production environment all requests should use HTTPS.
I'd be happy to hear your thoughts on this, especially when this concept should still be used.
We sometimes use it inside Kubernetes cluster. TLS is terminated at the ingress controller, at the edge of the cluster internal network. The internal "connection leg" can be optionally configured for clear-text HTTP like this:
Thank you for providing the diagram. I assume the ingress controller adds HTTP headers which Keycloak then uses to identify the original IP address used by the external client to connect to the ingress controller, and it will also use those extra HTTP headers to identify that the request originated via HTTPS?
If we would drop the check altogether, is there any use case that would not work any more for you?
Before reporting an issue
Area
core
Describe the bug
When using IPv6 and client is sending request from link-local or unique local address (ULA), client is blocked from sending clear-text HTTP requests when realm configuration is set to require SSL for "External request" (link).
Version
main
Regression
Expected behavior
Requests sent from IPv6 link-local or unique local address should succeed.
Actual behavior
Requests are rejected with response
403 Forbidden
with bodyHow to Reproduce?
One way to reproduce is to use Kubernetes cluster with IPv6 enabled
403 Forbidden
For example for local development, Kind would use link-local addresses for pods and services within the cluster and a "real" CNI like Calico would typically use unique local addresses (ULA).
Anything else?
The code that checks for the request is here
keycloak/common/src/main/java/org/keycloak/common/enums/SslRequired.java
Lines 53 to 54 in ece72cd
Looking at the git history, it seems that initially the code aimed to cover only clients within localhost, and later it took the current form where it was extended to allow IPv4 private addresses (link).
In case of IPv6 the private address ranges are following:
While the JDK method
Inet4Address.isSiteLocalAddress()
covers private address ranges for IPv4 (link), the IPv6 versionInet6Address.isSiteLocalAddress()
only covers site-local unicast address range (link). According to RFC4291 section2.5.7 this address range is now deprecated and should be considered as global address by new implementationWhile the documentation for interface
InetAddress.isSiteLocalAddress()
says (link)it seems likely to me that applications may rather use it for the effect of "all private address ranges", than for the specific (now deprecated) IPv6 site-local definition, especially considering the method is used through the upper class that covers both IPv4 and IPv6. Still, the JDK IPv6 implementation seems to take strict interpretation of covering site-local only and does not offer any method for checking for IPv6 private address ranges.
The text was updated successfully, but these errors were encountered: