How to write configuration Apache load balancer for many Spring-Boot? - spring-boot

We want to use Apache load balance to spread the load over several servers. We plan to do many http://load_balancer:port/app_name redirects on Apache LB e.g:
http://load_balancer:port/app1 ---> Apache LB ---> http://server1:port1, http://server2:port1
http://load_balancer:port/app2 ---> Apache LB ---> http://server1:port2, http://server2:port2
....
For Apache LB configuration file as below, when we use http://load_balancer:port in web browser then Apache LB works as expected.
How to rewrite the configuration so that you can enter http://load_balancer:port/app in web browser?
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy "balancer://mycluster">
BalancerMember "http://server1:port" route=1 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
BalancerMember "http://server2:port" route=2 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
ProxySet stickysession=ROUTEID
</Proxy>
<Proxy "balancer://myws">
BalancerMember "ws://http://server1:port" route=1 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
BalancerMember "ws://http://server2:port" route=2 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
ProxySet stickysession=ROUTEID
</Proxy>
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) balancer://myws/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) balancer://mycluster/$1 [P,L]
Second configuration
We used the hint as below for the proxy flag. Apache LoadBalancer worked fine for "http://load_balancer:port/". My configuration file:
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid scolonpathdelim=On
<Proxy "balancer://mycluster">
BalancerMember "http://server1:8727" route=1
BalancerMember "http://server2:8193" route=2
</Proxy>
When we changed the configuration to ProxyPass "/test" to refer to "http://load_balancer:port/test" from the web browser, there were errors (404) in the access.log file:
GET /test/ HTTP/1.1 200 2375
GET /static/css/app.77ac3251.css HTTP/1.1 404 196
...

You can use apache proxy pass instead of a rewriterule with proxy flag. You can find all the detail about the configuration on the official documentation: https://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html

We wrote the configuration as below and it works as expected:
<Proxy balancer://test.cl>
Header add Set-Cookie "test.ROUTEID=ROUTE.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
BalancerMember http://server1:8727 route=test_00 keepalive=On connectiontimeout=5 retry=180
BalancerMember http://server2:9393 route=test_10 keepalive=On connectiontimeout=5 retry=180
ProxySet lbmethod=bybusyness stickysession=ROUTEID
</Proxy>
<Location /test>
ProxyPreserveHost On
ProxyPass balancer://test.cl
ProxyPassReverse balancer://test.cl
</Location>

Related

Pentaho j_spring_security_check mixed content. HTTPS to HTTP

I have installed Pentaho (9.x) on Tomcat 8.5 and OpenJDK 1.8 as required.
In front of it there is Apache 2.4 with mod_proxy_http.
My website is served with HTTPS and I have these Proxy rules:
RequestHeader set X-Forwarded-Proto "https"
ProxyPreserveHost on
ProxyPass "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPass "/pentaho/" "http://tomcat_host_ip:8080/pentaho/"
ProxyPassReverse "/pentaho/" "http://tomcat_host_ip:8080/pentaho/"
ProxyPass "/pentaho/Login" "http://tomcat_host_ip:8080/pentaho/Login"
ProxyPassReverse "/pentaho/Login" "http://tomcat_host_ip:8080/pentaho/Login"
When I try to log in a get an error during the POST:
https://pentaho.mywebsite.org/pentaho/j_spring_security_check
The application try to responde with HTTP protocol instead HTTPS.
In the request header I have the correct Referer and Origin:
Origin: https://pentaho.mywebsite.org
Referer: https://pentaho.mywebsite.org/pentaho/Login
But the response header reply with HTTP and NOT https:
Location http://pentaho.mywebsite.org/pentaho/
I solved the problem just adding proxyPort="443" and scheme="https" to my http connector in Tomcat.
The rule
RequestHeader set X-Forwarded-Proto "https"
on Apache was unusefull. This is my correct Apache configuration
ProxyPreserveHost on
ProxyPass "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPass "/pentaho/" "http://tomcat_host_ip:8080/pentaho/"
ProxyPassReverse "/pentaho/" "http://tomcat_host_ip:8080/pentaho/"
And this is my Tomcat HTTP connector
<Connector URIEncoding="UTF-8"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
proxyPort="443"
scheme="https"
redirectPort="8443"
relaxedPathChars="[]|"
relaxedQueryChars="^{}[]|&"
maxHttpHeaderSize="65536"
/>
Servlet applications use the scheme, serverName and serverPort properties of a ServletRequest to generate hyperlinks. Usually Tomcat gets the latter two from the Host request header, while scheme depends on the connector.
If you use a reverse proxy, the above logic may not be enough. You have two solution:
Setting scheme statically
In your case the proxy uses HTTPS, while Tomcat uses HTTP, so you must override the scheme and secure properties:
<Connector
port="8080"
scheme="https"
secure="true"
...
while the Apache HTTP Server configuration can be shortened to:
ProxyPreserveHost on
ProxyPass "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho" "http://tomcat_host_ip:8080/pentaho"
Remark that in your answer you didn't set the secure attribute: this attribute decides whether the transport is confidential. If you don't set it to true, Tomcat will automatically redirect the browser to redirectPort whenever the application asks for a confidential transport (cf. Securing Web Applications).
This solution only works correctly, if your proxy forwards only HTTPS requests to Tomcat.
Setting scheme dynamically
If you forward both HTTP and HTTPS requests to Tomcat, the server needs a way to distinguish between them. Therefore you need to add a RemoteIpValve to your Tomcat configuration:
<Valve className="org.apache.catalina.valves.RemoteIpValve" />
<Connector
port="8080"
redirectPort="443"
...
and ask Apache HTTP Server to add an X-Forwarded-Proto header:
RequestHeader set X-Forwarded-Proto "expr=%{REQUEST_SCHEME}"
ProxyPreserveHost on
ProxyPass "/pentaho" "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho" "http://tomcat_host_ip:8080/pentaho"
This solution has also the advantage to set the client's remoteHost and remoteAddr instead of those of the proxy.

How to enable login functionality for elastic search & Kibana of Bitnami ELK Stack solution?

Below I provided both kibana vhost file. what changes I have to make so that kibana dashboard is username & password protected.
kibana-https-vhost.conf
<VirtualHost 127.0.0.1:443 _default_:443>
ServerAlias *
SSLCertificateFile "/opt/bitnami/apache/conf/bitnami/certs/server.crt"
SSLCertificateKeyFile "/opt/bitnami/apache/conf/bitnami/certs/server.key"
ProxyPass /elasticsearch http://127.0.0.1:9200
ProxyPassReverse /elasticsearch http://127.0.0.1:9200
ProxyPass / http://127.0.0.1:5601/
ProxyPassReverse / http://127.0.0.1:5601/
# HTTP Basic authentication layer
<Location />
AuthType Basic
AuthName "Introduce your ELK credentials. If you have problems,.."
AuthBasicProvider file
AuthUserFile /opt/bitnami/kibana/conf/password
Require user user
</Location>
</VirtualHost>
kibana-vhost.conf
<VirtualHost 127.0.0.1:80 _default_:80>
ServerAlias *
ProxyPass /elasticsearch http://127.0.0.1:9200
ProxyPassReverse /elasticsearch http://127.0.0.1:9200
ProxyPass / http://127.0.0.1:5601/
ProxyPassReverse / http://127.0.0.1:5601/
# HTTP Basic authentication layer
<Location />
AuthType Basic
AuthName "Introduce your ELK credentials. If you have problems, .."
AuthBasicProvider file
AuthUserFile /opt/bitnami/kibana/conf/password
Require user user
</Location>
</VirtualHost>

How to configure Apache reverse proxy domain url to specific url on localhost

I am stuck with an issue i have with configuring apache reverse proxy server.
I want to use an url eq.: https://software.testsite.net and my reverse proxy should be configured using http://localhost:82/customapp.
The problem currently when i navigate to https://www.testsite.net it is replaced with http://localhost:82/customapp.
How do i go about configuring this?
My configuration:
<VirtualHost *:443>
SSLEngine on
ServerName software.testsite.net
SSLProxyEngine On
SSLCertificateFile "${SRVROOT}/certs/testsite.crt"
SSLCertificateKeyFile "${SRVROOT}/certs/testsite.key"
SSLCertificateChainFile "${SRVROOT}/certs/testsite.ca-bundle"
RequestHeader edit Destination ^https http early
<Location />
RedirectMatch ^/$ https://localhost:82/customapp
ProxyPass http://localhost:82/customapp
ProxyPassReverse http://localhost:82/customapp
</Location>
</virtualhost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyVia on
RewriteEngine on
ProxyRequests Off
SSLProxyEngine On
SSLCertificateFile "${SRVROOT}/certs/testsite.crt"
SSLCertificateKeyFile "${SRVROOT}/certs/testsite.key"
SSLCertificateChainFile "${SRVROOT}/certs/testsite.ca-bundle"
# used for enforcing http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}$1 [R,L]
ServerName software.testsite.net
<Location />
ProxyPass http://localhost:82/customapp
ProxyPassReverse http://localhost:82/customapp
</Location>
</VirtualHost>
I finally got it working. Not sure if this is the way it is supposed to be done though.
<VirtualHost *:80>
ServerName software.testsite.net
DocumentRoot "${SRVROOT}/htdocs/software"
DirectoryIndex index.html
ProxyPreserveHost On
ProxyVia on
RewriteEngine on
ProxyRequests Off
# used for enforcing http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}$1 [R,L]
SSLProxyEngine On
SSLCertificateFile "${SRVROOT}/certs/testsite.crt"
SSLCertificateKeyFile "${SRVROOT}/certs/testsite.key"
SSLCertificateChainFile "${SRVROOT}/certs/testsite.ca-bundle"
<Location /customapp>
ProxyPass http://localhost:82/customapp
ProxyPassReverse http://localhost:82/customapp
</Location>
</VirtualHost>
<VirtualHost *:443>
ServerName software.testsite.net
DocumentRoot "${SRVROOT}/htdocs/software"
DirectoryIndex index.html
RequestHeader edit Destination ^https http early
SSLEngine on
SSLProxyEngine On
SSLCertificateFile "${SRVROOT}/certs/testsite.crt"
SSLCertificateKeyFile "${SRVROOT}/certs/testsite.key"
SSLCertificateChainFile "${SRVROOT}/certs/testsite.ca-bundle"
<Location /customapp>
RedirectMatch ^/$ https://localhost:82/customapp
ProxyPass http://localhost:82/customapp
ProxyPassReverse http://localhost:82/customapp
</Location>
</virtualhost>
<!DOCTYPE html>
<html>
<head>
<title>HTML Meta Tag</title>
<meta http-equiv = "refresh" content = "1; url =http://software.testsite.net/customapp"/>
</head>
<body>
<p>Redirecting...</p>
</body>
</html>

Configure Tomcat8 behind Apache with HTTPS

I have Tomcat 8 installed in my server in port 8080 that I am exposing with a secured Apache (using Proxy Pass).
Here is my Apache configuration:
<VirtualHost *:443>
ServerName myserver.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /odata/ http://172.31.36.251:8080/
ProxyPassReverse /odata/ http://172.31.36.251:8080/
<Proxy *>
allow from all
</Proxy>
RequestHeader set X-Forwarded-Port 443
RequestHeader set X-Forwarded-Scheme https
</VirtualHost>
Here is the Tomcat server.xml configuration
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
address="172.31.36.251"
proxyName="myserver.com"
scheme="https" proxyPort="443" />
All works well until here. If I call my application:
https://myserver.com/odata/D3a1593adae89/odata.svc/
I get:
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xml:base="https://myserver.com:443/D3a1593adae89/odata.svc/">
<workspace>
<atom:title>Default</atom:title>
<collection href="Maintables">
<atom:title>Maintables</atom:title>
</collection>
</workspace>
</service>
The problem: If you see the attribute xml:base in the result, Tomcat decorates the address with the port and I really don't know how to remove it. Also the address is wrong: It should be https://myserver.com:443/odata/D3a1593adae89/odata.svc/ . I been looking around and trying things like setting proxyPort to blank but nothing. I think this is related to broken links when using a reverse proxy as described at https://cwiki.apache.org/confluence/display/HTTPD/TomcatModProxyHTML . I tried some rewrites like:
ProxyHTMLURLMap http://172.31.33.105:8080 /odata
RewriteEngine On
RewriteRule ^/odata$ https://myserver.com/odata/ [R,L]
But I just cannot make it work. The xml:base should be https://myserver.com/odata/D3a1593adae89/odata.svc/
Any idea is appreciated
For the port thing, as you use ProxyPreserveHost On and you set X-Forwarded-* headers, you can use the RemoteIpValve:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" />
The connector will be simply:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443"
address="172.31.33.105"
/>
The valve detect the proto and will assume the connection is secured with the default port number (https://xxxxx/yyy).
For the location, you should deploy your application in the odata context so that you can use
ProxyPass /odata http://172.31.33.105:8080/odata
modifying the context on the proxy pass (from /odata/ to /) is somehow tricky as you would need to filter all text coming from your backend server to fix some url path. It can be really painful ( should I replace all "/xxx" with "/odata/xxx" ? )

Web Socket behind proxy

I have Spring Boot app with WebSocket running behind Apache 2. When trying connect I am getting the following error:
Server Log:
Handshake failed due to invalid Upgrade header: null
Client Log:
Here is the Apache 2 config:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin tom_marik#hotmail.com
ServerName www.languageexchange.eu
ProxyPass "/ws2/" "ws://www.languageexchange.eu:92/"
ProxyPass "/wss2/" "wss://www.languageexchange.eu:92/"
ProxyPass / http://31.31.74.54:92/
ProxyPassReverse / http://31.31.74.54:92/
ProxyPassReverseCookiePath / /
ErrorLog /var/log/apache2/languageexchange.log
LogLevel warn
RewriteEngine on
[END,QSA,R=permanent]
SSLCertificateFile /etc/letsencrypt/live/languageexchange.eu/cert.pem
SSLCertificateKeyFile
/etc/letsencrypt/live/languageexchange.eu/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile
/etc/letsencrypt/live/languageexchange.eu/chain.pem
</VirtualHost>
</IfModule>
Thanks for any help!
You need to have mod_proxy_wstunnel installed (mod_proxy and mod_ssl as well). Then in your Apache's configuration:
ProxyPass /ws2 ws://languageexchange.eu:92 keepalive=On
ProxyPassReverse /ws2 ws://languageexchange.eu:92
ProxyPass /wss2 wss://languageexchange.eu:92 keepalive=On
ProxyPassReverse /wss2 wss://languageexchange.eu:92
If this is a single machine it may be better to set 127.0.0.1 instead of languageexchange.eu, so:
ProxyPass /ws2 ws://127.0.0.1:92 keepalive=On
ProxyPassReverse /ws2 ws://127.0.0.1:92
ProxyPass /wss2 wss://127.0.0.1:92 keepalive=On
ProxyPassReverse /wss2 wss://127.0.0.1:92

Resources