=====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/