=====Eine Tomcat 9 / ORDS 23 / APEX 23 Umgebung unter Oracle Linux mit dem HAProxy betreiben=====
**Aufgabe:** Eine Oracle APEX in der Version 23 soll hinter einem HAProxy betreiben werden auf mehreren Applikation Server betrieben werden.
Leider stellt sich heraus das diese überhaupt keine gute Idee als SSL Frontend ist, da der ORDS zu viel Logik enthält und sich nicht vernünftig betreiben läßt! Besser ORDS hinter Standard Konfiguration Apache HTTP / Tomcat / ORDS betreiben und nur SSL auf den Apache HTTP per HAProxy als Load balancer umleiten!
**Umgebung:**
Da der HAProxy schon im Einsatz ist und unterandern weitere Oracle Produkte wie Forms/Reports bedient soll auch für die APEX Tomcat Umgebung dieser Proxy eingesetzt werden.
Die Apex Server sind nach diesem Muster aufgesetzt [[prog:oracle_apex_20_2_install_windows_19c_linux_8|Oracle APEX 23 / ORDS 23 / Tomcat 9 mit Java 21 / Apache 2.4 mit der Oracle Datenbank 23c unter Oracle Linux 8 - Installation]], das heißt die statischen Komponenten werden über Apache ausgeliefert (dieser ist bereits mit SSL verschlüsselt, daher ist die Konfiguration so angepasst!), der Tomcat ist testweise freigeschaltet und über 8080 erreichbar ohne SSL!
Idealer wäre es umgekehrt, in einer Produktiven Umgebung sollte der Tomcat dann auch mit SSL betrieben werden oder beides ohne.
=== HAProxy Grundlagen ===
{{ :sec:haproxy_tomcat_ssl_terminator.jpg | HAProxy als SSL Tomcat }}
Der HAProxy ist ein SSL Terminator / Loadbalancer der für verschiedenen Protokolle eingesetzt werden kann, unterandern für SSL.
D.h. der Oracle ORDS wird kann klassisch ein einer Tomcat Umgebung betrieben und statt dem Apache httpd wird alternativ der HAProxy für die SSL Verschlüsselung und als Einstieg über den Port 443 eingesetzt.
Mehr zu HAProxy = https://www.haproxy.org/
=== Ablauf ===
* HAProxy Installation
* Autostart und Log konfigurieren
* HTTP Standard Verhalten einstellen und testen
* SSL Konfigurieren
* HAProxy härten / prüfen
----
==== Basis Installation unter Oracle Linux ====
=== dnf Installation ===
Der HAproxy für Oracle Linux liegt im "ol8_appstream" Repository.
Installation des Proxy:
dnf install haproxy
Was haben wir am Ende:
haproxy -v
HA-Proxy version 1.8.27-493ce0b 2020/11/06
D.h. die Version ist 2020-11-06 ? Siehe vom https://www.haproxy.org/bugs/bugs-1.8.27.html
Eine neuere Version ist in dem Oracle Repository nicht zu finden, nicht gut da aktuell Version 2.7 mindestens.
Hier ist zu überlegen, einen expliziten Server nur für diese Aufgaben aufzusetzen und auf dem Server diesen aus den Quellen neu zu übersetzen.
=== Installation über alternatives Repo ====
Oder alternativ über https://github.com/zenetys/rpm-haproxy ein alternatives Repo mit einbinden.
cd /etc/yum.repos.d/
wget https://packages.zenetys.com/latest/redhat/zenetys-latest.repo
dnf search haproxy*
..
haproxy29z.x86_64 : HAProxy reverse proxy for high availability environments
haproxy29z+quic.x86_64 : HAProxy reverse proxy for high availability environments
# => was ist quic?
# -- HTTP/3 is the latest iteration of the HTTP protocol with one fundamental difference: streams and flow control, # which were introduced in HTTP/2, have been moved outside of HTTP to the new lower transport protocol called QUIC.
..
# wir brauchen also für unsere Standard Umgebung erstmal nur den normalen HAProxy
dnf info haproxy29z.x86_64
Last metadata expiration check: 0:06:00 ago on Wed 06 Mar 2024 11:57:16 CET.
Available Packages
Name : haproxy29z
Version : 2.9.6
Release : 1.el8.zenetys
Architecture : x86_64
Size : 2.9 M
Source : haproxy29z-2.9.6-1.el8.zenetys.src.rpm
Repository : zenetys-latest
Summary : HAProxy reverse proxy for high availability environments
URL : http://www.haproxy.org/
License : GPLv2+
Description : HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high
: availability environments. Indeed, it can:
: - route HTTP requests depending on statically assigned cookies
: - spread load among several servers while assuring server persistence
: through the use of HTTP cookies
: - switch to backup servers in the event a main one fails
: - accept connections to special ports dedicated to service monitoring
: - stop accepting connections without breaking existing ones
: - add, modify, and delete HTTP headers in both directions
: - block requests matching particular patterns
: - report detailed status to authenticated users from a URI
: intercepted from the application
=== Auto Start ===
Autostart einrichten:
systemctl enable haproxy
systemctl start haproxy
systemctl status haproxy
Was läuft jetzt:
netstat -tulpe | grep haproxy
----
==== Konfiguration ====
Nach der Installation kann über den Folder "/etc/haproxy" die Konfiguration erfolgen.
Für die Konfigurationsparameter siehe => https://www.haproxy.org/download/1.8/doc/configuration.txt
Orginal sichern:
cd /etc/haproxy
cp haproxy.cfg haproxy.cfg-org
Die Konfiguration ist in zwei Bereiche eingeteilt, dem "frontend" und dem "backend".
Das "frontend" wird vom Client Browser angesprochen und die Anfrage vom Proxy an das "backend" weitergeleitet.
Beispiel für eine erste Basis Konfiguration mit Statistik Report:
frontend http_balancer
bind 10.10.10.96:80
option http-server-close
option forwardfor
stats enable # Enable stats page
stats realm GPI- HAProxy Statistics # Title text for popup window
stats uri /haproxy?stats_ssl # Stats URI for each backend
stats auth haproxyuser:proxypwd # Authentication credentials
acl url_static path_beg -i /i
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend tomcat_ords
backend static
balance roundrobin
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:443 check ssl verify none cookie 1
server oracledb23c01 10.10.10.112:443 check ssl verify none cookie 2
backend tomcat_ords
mode http
balance roundrobin
# Wird nur benötigt wenn der HA auf dem gleichen Host läuft
# Und dieser auf Localhost Zugriffe gehärtet ist!
#
#option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:8080 check cookie 1
server oracledb23c01 10.10.10.112:8080 check cookie 2
Syntax überprüfen mit;
haproxy -f /etc/haproxy/haproxy.cfg -c
Der check Parameter sagt aus das regelmäßig geprüft wird ob der Server noch zur Verfügung steht, siehe => https://www.haproxy.com/blog/how-to-enable-health-checks-in-haproxy
----
==== Logging über syslog ====
Datei /etc/rsyslog.conf anpassen und folgende Zeilen einkommentieren:
/etc/rsyslog.conf
module(load="imudp")
input(type="imudp" port="514")
Datei /etc/rsyslog.d/haproxy.conf anlegen:
vi /etc/rsyslog.d/haproxy.conf
local2.=info /var/log/haproxy-access.log
local2.notice /var/log/haproxy-info.log
Aktivieren:
systemctl enable rsyslog
systemctl start rsyslog
Log Rotate prüfen (auf die richtige Angabe der Datei Namen achten!) über :
vi /etc/logrotate.d/haproxy
/var/log/haproxy-access.log /var/log/haproxy-info.log {
daily
rotate 10
missingok
notifempty
compress
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
/bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
#testen
logrotate -d /etc/logrotate.d/haproxy
----
==== SSL Konfiguration ====
Nach der Basis Konfguration von HTTP kann die Konfiguration von SSL erfolgen.
Siehe auch:
* https://gridscale.io/en/community/tutorials/haproxy-ssl/
Basis Pakete:
dnf install openssl
Testzertifikat anlegen:
mkdir /etc/ssl/private
openssl req -nodes -x509 -newkey rsa:2048 -keyout /etc/ssl/private/haproxy.key -out /etc/ssl/private/haproxy.crt -days 365
pem erzeugen:
cat /etc/ssl/private/haproxy.key /etc/ssl/private/haproxy.crt > /etc/ssl/private/haproxy.pem
HAProxy Konfiguration für SSL erweitern:
cd /etc/haproxy
cp haproxy.cfg haproxy.cfg_http
vi haproxy.cfg
# ---------------------------------------
# https
# ---------------------------------------
frontend https_balancer_ssl
bind 10.10.10.96:443 ssl crt /etc/ssl/private/haproxy.pem
mode http
http-request set-header X-Forwarded-For %[src]
reqadd X-Forwarded-Proto:\ https
option http-server-close
acl url_static path_beg -i /i
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend tomcat_ords
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend static
balance roundrobin
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:443 check ssl verify none cookie 1
server oracledb23c01 10.10.10.112:443 check ssl verify none cookie 2
backend tomcat_ords
mode http
balance roundrobin
# Wird nur benötigt wenn der HA auf dem gleichen Host läuft
# Und dieser auf Localhost Zugriffe gehärtet ist!
#
#option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:8080 check cookie 1
server oracledb23c01 10.10.10.112:8080 check cookie 2
# testen
haproxy -f /etc/haproxy/haproxy.cfg -c
Backend ist auch schon weiter open definiert worden!
=== Warning: Unable to load default 1024 bits DH parameter for certificate ===
Meldung:
haproxy -f /etc/haproxy/haproxy.cfg -c
[WARNING] 050/175637 (38926) : parsing [/etc/haproxy/haproxy.cfg:81] : 'bind 10.10.10.112:443' :
unable to load default 1024 bits DH parameter for certificate '/etc/ssl/private/haproxy.pem'.
, SSL library will use an automatically generated DH parameter.
[WARNING] 050/175637 (38926) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.
Configuration file is valid
dhparams.pem erzeugen (dauert etwas):
openssl dhparam -out /etc/haproxy/dhparams.pem 2048
Konfiguration erweitern/anpassen:
vi haproxy.cfg
#unter default eine zeile auskommentieren und eine einfügen
# utilize system-wide crypto-policies
#ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
ssl-dh-param-file /etc/haproxy/dhparams.pem
haproxy -f /etc/haproxy/haproxy.cfg -c
Configuration file is valid
Siehe => https://www.digitalocean.com/community/tutorials/haproxy-ssl-tls-warning-setting-tune-ssl-default-dh-param-to-1024-by-default
----
==== Statistik Report anzeigen ====
Der Proxy hat auch eine Oberfläche, die den aktuellen Status anzeigt.
Konfiguriert wird das über folgende Parameter in das erste Frontend (http):
stats enable # Enable stats page
stats realm GPI- HAProxy Statistics # Title text for popup window
stats uri /haproxy?stats_ssl # Stats URI for each backend
stats auth haproxyuser:proxypwd # Authentication credentials
Aufrufen über **http://haproxy.pipperr.local/haproxy?stats_ssl**
{{ :linux:statistics_report_haproxy.jpg | Statistik Report HA Proxy}}
----
==== HAProxy härten ====
Siehe:
* https://delta.blue/blog/haproxy-timeouts/
* https://www.axelit.fr/wp-content/uploads/2019/09/HAProxy-The-Guide-to-Multi-Layer-Security.pdf
----
==== HAProxy im laufenden Betrieb neustarten ====
Einfachste Lösung:
systemctl start haproxy
Es muss geprüft werden ob auch ein "echter" Restart erfolgt, anscheinend ist das nicht immer so implementiert
siehe dazu => https://fordodone.com/2013/07/17/hot-reconfigure-haproxy-without-restart/
----
==== Probleme ====
===504 Gateway Timeout===
Parameter "timeout server" unter "default" auf höheren Wert anpassen:
timeout server 2m
Siehe auch: https://www.papertrail.com/solution/tips/haproxy-logging-how-to-tune-timeouts-for-performance/
----
=== Problem Cross Origin Sharing - Anforderungen - 403===
Ab der ORDS Version 20.2.1 kann es zu diesem Problem kommen, der ORDS prüft die ursprüngliche Quelle der Anfrage (wurde über SSL angefragt und im Backend per HTTP weitergereicht) und sieht das hier ein Mismatch der Protokolle und der anfragenden Server vorliegt.
**Fehlermeldung**
Die Anforderung kann nicht verarbeitet werden, da diese Ressource keine Cross Origin Sharing-Anforderungen unterstützt
oder da der Anforderungsursprung nicht autorisiert ist, auf diese Ressource zuzugreifen.
Wenn ords als Reverse-Proxy verwendet wird, stellen Sie sicher, dass der Frontend-Server den Hostnamen propagiert.
Stellen Sie für mod_proxy sicher, dass "ProxyPreserveHost" eingeschaltet ist
# bzw.
The request cannot be processed because this resource does not support Cross Origin Sharing requests,
or the request Origin is not authorized to access this resource.
If ords is being reverse proxied ensure the front end server is propagating the host name, for mod_proxy ensure ProxyPreserveHost is set to On
siehe dazu auch den Oracle Support Artikel => https://support.oracle.com/knowledge/Middleware/2926638_1.html und die Support Node "ORDS Cross-Origin Resource Sharing (CORS) Feature and 403 Forbidden Error (Doc ID 2874872.1)"
Der Fehler ist auf ein HTTPS-Problem zurückzuführen.
Anfragen von Browsern an den HAProxy-Server erfolgen über HTTPS, aber die weitergeleitete Anfrage vom HAProxy an Tomcat/ORDS erfolgt über HTTP.
Der Browser kommuniziert mit dem HAProxy über HTTPS, und zwar über dessen öffentliche Adresse, z. B. proxy.pipperr.local über den Standard-HTTPS-Port 443.
Der Ursprung für die Anfragen ist also https://proxy.pipperr.local.
Wenn der HAProxy-Server die Anfrage erhält, leitet er sie über HTTP an den Backend-Server / Anwendungsserver (Tomcat) weiter.
Nur der Hostname wird weitergegeben wird, das Schema (d. h. HTTPS) wird nicht weitergegeben.
Der Anwendungsserver (Tomcat) hat eine Anfrage erhalten, deren Ursprung lautet:
http://proxy.pipperr.local, da er die Anfrage über seinen HTTP-Port erhalten hat.
Der Application Server (Tomcat-Server) leitet die Anfrage an ORDS weiter über HTTP.
Daher denkt ORDS, dass die Herkunft der Anfrage http://proxy.pipperr.local ist, obwohl sie https://proxy.pipperr.local sein sollte.
ORDS weigert sich nun die Anfrage zu bearbeiten und gibt den Status 403 Forbidden aus, da der Wert des Origin-Headers (https://proxy.pipperr.local) nicht mit der erwarteten Herkunft (http://proxy.pipperr.local) übereinstimmt.
**Lösung:**
D.h. der Header muss beim weiterleiten ins Backend so umgeschrieben werden das der ORDS die Anfrage akzeptiert.
Die Frage ist nun aber wie wir das konfigurieren!
Keine Anweisung hat bisher das Verhalten verbessert ....
Lösung nur über Konfiguration vom ORDS gelungen, keine Variante für den HAProxy gefunden die erfolgreich war (Version 1.5 ist im Einsatz in Prod - evlt. ist das eine der Ursachen!)
== ORDS anpassen ==
Datei **setting.xml** anpassen:
https://proxy.pipperr.local,http://proxy.pipperr.local
Über das Komandozeilen Tool:
ords --config [path]/config config set security.externalSessionTrustedOrigins "https://proxy.pipperr.local,http://proxy.pipperr.local"
===ODRS schalte wieder auf HTTP zurück===
**Problem:**
ORDS URL lässt sich über HTTPS aufrufen, in einigen Umgebung erhält der Browser eine 302 und switcht auf HTTP wieder um, in anderen Umgebung lässt sich das Verhalten aber nicht nachvollziehen.
Es wird ein Zusammenhang mit den obigen Parameter "security.externalSessionTrustedOrigins" vermutet, da ja der ORDS in dieser Umgebung über den HAProxy mit HTTP angesprochen wird.
Lösung:
Noch offen
----
----
==== Komplette HAProxy Konfiguration für diese Beispiel =====
vi haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
#ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
ssl-dh-param-file /etc/haproxy/dhparams.pem
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 2m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend http_balancer
bind 10.10.10.96:80
option http-server-close
option forwardfor
stats enable # Enable stats page
stats realm GPI- HAProxy Statistics # Title text for popup window
stats uri /haproxy?stats_ssl # Stats URI for each backend
stats auth haproxyuser:proxypwd # Authentication credentials
acl url_static path_beg -i /i
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend tomcat_ords
#---------------------------------------------------------------------
frontend https_balancer_ssl
bind 10.10.10.96:443 ssl crt /etc/ssl/private/haproxy.pem
mode http
http-request set-header X-Forwarded-For %[src]
reqadd X-Forwarded-Proto:\ https
option http-server-close
acl url_static path_beg -i /i
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend tomcat_ords
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend static
balance roundrobin
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:443 check ssl verify none cookie 1
server oracledb23c01 10.10.10.112:443 check ssl verify none cookie 2
backend tomcat_ords
mode http
balance roundrobin
# Wird nur benötigt wenn der HA auf dem gleichen Host läuft
# Und dieser auf Localhost Zugriffe gehärtet ist!
#
#option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
cookie SERVERID insert indirect nocache
server apex01 10.10.10.90:8080 check cookie 1
server oracledb23c01 10.10.10.112:8080 check cookie 2
----
==== Quellen ====
Projektseite => https://www.haproxy.org/
Web:
* https://youhavethewrong.wordpress.com/2012/05/04/configuring-haproxy-for-use-with-apache-tomcat/
* https://krams915.blogspot.com/2011/10/tomcat-clustering-and-load-balancing_9324.html
* https://www.linuxtechi.com/install-configure-haproxy-centos-8-rhel-8/
* https://github.com/ant-media/Ant-Media-Server/wiki/Load-Balancer-with-HAProxy-SSL-Termination
* https://learn.microsoft.com/en-us/previous-versions/troubleshoot/winautomation/product-documentation/processrobot-help-files/haproxy-sample-configuration
Installation:
* https://maggiminutes.com/install-latest-haproxy-on-linux-step-by-step/
* https://tylersguides.com/guides/installing-haproxy-from-source-on-centos-8/