Sonatype Nexus: Proxy from SSL using Apache - apache

We're running Sonatype's Nexus to store all of our builds, cache our dependencies, etc. etc. However, I'd like to move away from the default install's port 8081 URL and instead host it over SSL via an Apache proxy. I've setup Apache's mod_proxy to proxy to it such that https://myserver.com/nexus brings up Nexus. I used the following configuration directives inside of my virtual host config:
# Configure mod_proxy to be used for proxying URLs on this site to other URLs/ports on this server.
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
<Proxy *>
AddDefaultCharset off
Order deny,allow
Allow from all
</Proxy>
# Proxy the Sonatype Nexus OSS web application running at http://localhost:8081/nexus
<Location /nexus>
ProxyPass http://localhost:8081/nexus
ProxyPassReverse http://localhost:8081/nexus
</Location>
This seems to match the instructions at Running Nexus Behind a Proxy. However, I was unable to clear the "Base URL" setting in Nexus: it wouldn't let me leave it blank.
And everything mostly works: I can access Nexus at the HTTPS URL, log in, and perform most GUI functions.
However, when logging in I get the following warning message:
WARNING: Base URL setting of http://myserver.com/nexus does not match your actual URL! If you're running Apache mod_proxy, here's more information on configuring Nexus with it.
And not everything in the GUI actually works. So far I've noticed the following:
System Feeds: Gives the following error:
Problem accessing /nexus/service/local/feeds. Reason:
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request
Nexus returned an error: ERROR 406: The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request
Deleting Hosted Repositories: I went through and deleted several empty & unneeded repositories. However, after confirming the deletions, only the first was removed. I had to login to the 8081 site to delete any of the others.

Per the documentation, it looks like a better solution may be to add a RequestHeader to the Apache configuration:
RequestHeader set X-Forwarded-Proto "https"
I tried the accepted answer, which appears to work, but once I added the RequestHeader, I was able to uncheck Force URL and the warning was cleared. I have not tested the other behavior the OP is describing, though.

You just need to adjust the baseUrl setting in the Administration->Server configuration screen. Set the url you are using and click the Force Base Url option.

Related

Cannot log into GeoServer 2.19 with SSL

I am able to reach the GeoServer log-in form on a new server instance using a URL like this: https://sub.domain.tld/geoserver.
However, entering the correct username and password causes Cannot POST /geoserver/j_spring_security_check to be displayed in plain text in the browser window and "http://localhost:8080/geoserver/j_spring_security_check" to appear on the address line (Chrome and Firefox). Logging-in works just fine from http://sub.domain.tld:8080/geoserver and, while logged in that way, the SSL URL will skip the log-in form entirely and open the full GUI -- but none of the example layer previews will work (Cannot GET /geoserver/tiger/wms ...or whatever layer).
I have 3 similar servers set up with earlier software versions that all work perfectly:
CentOS Linux release 7.5.1804 (Core)
Apache 2.4.6
Tomcat 9.0.4.0
JVM 1.8.0_171-b10 (Oracle)
GeoServer 2.15.1 (also 2.14.1)
This latest server is:
CentOS Linux release 7.9.2009 (Core)
Apache 2.4.6
Tomcat 9.0.48.0
JVM 1.8.0_292-b10 (Red Hat)
GeoServer 2.19.1
I closely followed the GeoServer install procedure found here. Apache was already installed and working with a virtual host configuration using certbot and a Let's Encrypt certificate. I added the following to the <VirtualHost *:443> section of the /etc/httpd/sites-available/sub.domain.tld.conf file:
ProxyRequests Off
ProxyPass /geoserver http://localhost:8080/geoserver
ProxyPassReverse /geoserver http://localhost:8080/geoserver
<Location "/geoserver">
Order allow,deny
Allow from all
Header set Access-Control-Allow-Origin "*"
</Location>
I also set "https://sub.domain.tld/geoserver/" as the Proxy Base URL in GeoServer. This is exactly how my working instances are set up.
The newest /opt/tomcat/webapps/geoserver/WEB-INF/web.xml file is slightly different in that it has separate CORS sections to be uncommented for Jetty vs. Tomcat. The Tomcat section and the cross-origin filter-mapping are uncommented. Unlike before, I had to enable the SELinux httpd_can_network_connect process in order to get to the GeoServer log-in form via SSL. Disabling SELinux enforcement, however, does not solve the j_spring_security_check problem.
Sensitive WMS and WFS content must be served via SSL. I am now spinning my wheels on research so any help in resolving this would be greatly appreciated!
I was running into a similar problem trying to reverse proxy a Geoserver docker container using Apache.
After bashing my head for a few days, I found I needed a couple of changes on both ends of the setup.
Apache:
<Location "/geoserver">
ProxyPreserveHost On
ProxyPass http://localhost:8080/geoserver
ProxyPassReverse http://localhost:8080/geoserver
</Location>
The ProxyPreserveHost directive should ensure that sub.domain.tld is what's used rather than localhost.
However, at this point I hit another problem, no matter what I did the login & logout URLs were using http:// and not https://
This required adjusting the server config of Tomcat, specifically the scheme used by the connector.
Tomcat:
<Connector
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
scheme="https"
/>
Note the value of scheme is https, normally it's http because it's the http connector. This connector doesn't SSL/TLS encrypt the traffic so it would, under normal circumstances (appropriately), set the protocol to http.
Since we're using a proxy for SSL/TLS encryption we don't need Tomcat to do that work but we still need to tell Tomcat to describe the server name using https instead of the usual http.
Alternatively, you could also look at using the AJP connector which is an entirely different protocol but gets around some of these issues rather neatly and can be more performant.
The issue with this approach is that it requires more Apache mods to be enabled to work as well as some security concerns given how much more powerful AJP can be VS the http connector.
Also, there are some other proxy settings that can be used in Tomcat to possibly remove the need for ProxyPreserveHost in Apache, but this should get you where you're going.
Additional reading:
Tomcat HTTP Connector docs: https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
Tomcat AJP docs: https://tomcat.apache.org/tomcat-9.0-doc/config/ajp.html

Apache ProxyPass to separate VirtualHost on the same system

I am trying to solve an issue with an internal ProxyPass setup on an apache http server, version 2.4. Everything works fine otherwise, it is just this ProxyPass issue that I fail to solve:
I operate several name based virtual hosts on a single system with example.org serving as the default host and all hosts using the https protocol on port 443 with valid (signed) certificates:
example.org
host1.example.org
host2.example.org
For one single type of request I want to setup an internal ProxyPass rule to example.org.
https://host1.example.org/_-_-_/bar => https://example.org/foo/bar
A ProxyPassReverse is not required, since no result is returned. (I also tried with, but that does not make any difference):
This is the rule set which is part of the configuration of host host1.example.org:
SSLProxyEngine On
ProxyRequests Off
ProxyVia Off
ProxyPass "/_-_-_/bar" "https://example.org/foo/bar"
The proxy does work, it proxies the request. But the issue is that it does not request the correct host! So not example.org but the originally requested host host1.example.org, so it requests itself. I can clearly see both requests in the same access log file whilst the access log of example.org stays untouched. Obviously that behavior results in a http status 404. That is also shown on the client side as an error message generated by host host1.example.org (fine) but showing the internal path /foo/bar (not fine)!So my question obviously is:
What to change so that the proxy request is internally processed by the desired virtual host?
Ok, as obviously also previously suspected by myself I had an issue with other configuration details interfering here. I post this answers as a hint for others who might stumble about a similar situation:
Another configuration file included by the host configuration set a global ProxyPreserveHost On directive. That obviously resulted in the internal proxy request to feature the same, preserved host header as the original request, which had to lead to the internal request getting processed by the same virtual host as the original request.
I solved the issue by moving (and duplicating) that directive into specific <Location> blocks, so that the global default to not preserve the host in proxy requests is not modified. Consequently the proxy requests described in the question work as expected, they are processed by the desired virtual host now.

Reverse proxy with request dispatch (to Rstudio server)

I have a multi-tier application of three layers lets say public, business and workspace (all running apache).
Client requests hits the public servers, requests are processed and dispatched on to business servers that does 'things' and response is returned back to public server which then processes the response and pass it on to the client.
I have a scenario wherein I want a request say /rstudio coming to the public server dispatched onto the business which intern reverse proxy to workspace server. There are two catch here:
the workspace server varies per request
application running on workspace server (Rstudio) uses GWT and references resources (static resources js, css etc and RPC coms) on the root url. All the in-application redirection also happens on the domain.
From the business server, I have setup reverse proxy to Rstudio server from my application server.
<Proxy *>
Allow from localhost
</Proxy>
ProxyPass /rstudio/ http://business_server/
ProxyPassReverse /rstudio/ http://business_server/
RedirectMatch permanent ^/rstudio$ /rstudio/
and this work fine (ref. https://support.rstudio.com/hc/en-us/articles/200552326-Running-with-a-Proxy). To handle dynamic workspace server, I could the following but ProxyPassReverse does not support expression in value and this no joy with this approach.
ProxyPassMatch ^/rstudio/(.*)$ http://$1
ProxyPassReverse ^/rstudio/(.*)$ http://$1
RedirectMatch permanent ^/rstudio$ /rstudio/
I have tried the same with mod_rewrite rule (following) but without ProxyPassReverse and due to domain redirection on the GWT Rstudio, this does not work. Adding ProxyPassReverse would fix the problem but I am caught up with no expression on value part to deal with dynamic workspace server issue.
RewriteRule "^/rstudio/(.*)" "http://$1" [P]
Following is the third approach to solve this problem using LocationMatch and mod_headers:
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://%{SERVER_NAME}e/rstudio/"
</LocationMatch>
But this is no joy too because value on header directive is not evaluated against environment variable (and only back-references work here). Althought I can get the reverse proxy thing working if I had code the business_server, which is :
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://private_server/rstudio/"
</LocationMatch>
Question 1: I was wondering if there are any better way to solve this problem without hardcoding the server DNS in apache conf?
Question 2: With the hard coded server DNS the reverse proxy works for me (patchy but works) but I am hit with GWT issue of resource references on root and the request dispatch is not fully working. I get to the signin page but resources are not found.
I was wondering if there is any better way to handle that?
Following is the example log from browser:
Navigated to https://public_server/rstudio
rworkspaces:43 GET https://public_server/rstudio.css
rworkspaces:108 GET https://public_server/js/encrypt.min.js
rworkspaces:167 GET https://public_server/images/rstudio.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonLeft.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonTile.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonRight.png 404 (Not Found)

Apache reverse proxy and load balancer - does not work as it should

I have 3 machines.
One (loadbalance.lan) is used as a load balancer, the other two (172.16.30.5 and 172.16.30.6) are tomcat's servers. Main page of the tomcat is listening on port 8080
Im typing in the browser loadbalance.lan/tomcat and I am able to see one of the tomcat content (default tomcat page)
The problem is page isn't displayed correctly. There's no images and when I click on any link it displays 404 Not found error.
Lets say I want to access one of the sub pages on the tomcat website. Tomcat website address: 172.16.30.5:8080
Now I can choose, lets say "status" link which redirects me to: 172.16.30.5:8080/manager/status (and works fine)
When I access the same page but via reverse proxy server (loadbalance.net) and click that link on the loadbalance.lan page, links redirect me to loadbalance.lan/manager/status and I get 404 error.
Of course when I type in the browser loadbalance.lan/tomcat/manager/status it displays correct.
Problem with the images is also weird. When I use url: loadbalance.lan/tomcat I can't see images (Tomcat logo)
When I use this one: loadbalance.lan/tomcat/ (slash at the end) it's ok. At least images because links still redirect in wrong place.
Here is my loadbalance.lan apache config:
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<VirtualHost *:80>
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy balancer://cluster>
Order Deny,Allow
Allow from all
</Proxy>
<Proxy balancer://cluster>
BalancerMember http://172.16.30.5:8080
BalancerMember http://172.16.30.6:8080
<Proxy balancer://cluster>
</Proxy>
<Location /tomcat>
ProxyPass balancer://cluster
ProxyPassReverse balancer://cluster
</Location>
</VirtualHost>
Could someone help me with this?
Obviously there is something wrong with that proxy but I have no idea how to fix that :(
From ProxyPassReverse documentation (strong added):
This directive lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses. This is essential when Apache is used as a reverse proxy (or gateway) to avoid by-passing the reverse proxy because of HTTP redirects on the backend servers which stay behind the reverse proxy.
Only the HTTP response headers specifically mentioned above will be rewritten. Apache will not rewrite other response headers, nor will it rewrite URL references inside HTML pages. This means that if the proxied content contains absolute URL references, they will by-pass the proxy. A third-party module that will look inside the HTML and rewrite URL references is Nick Kew's mod_proxy_html.
So, the proxy job is not to rewrite the html content of the pages, if the proxyied content does not know that the final url should contain /tomcat extension and the proxy does not alter the pages... you're stuck.
This is usually something you do not see because the 172.16.30.5:8080 part is well rewritten in localhost.lan, but this rewrite is not made by the proxy, quite certainly because urls are in fact only relative (<img src="/foo/bar.png">). Check the source code of the page to see if the domain name is really rewritten in urls).
There's several ways of handling that:
- You could avoid altering relative urls paths in, the proxy (so not using a tomcat/ prefix, but instead a dedicated virtualhost with a name, like tomcat.lodabalncer.lan).
- You could also use some dedicated tools, like mod_proxy_html to rewrite the content of the pages, but that's a slow and complex thing.
- The third way is to manage the final full url on the application side (here tomcat) and detect the proxy chain elements in X-Forwareded-for Header to rebuild the right domain.
- Some applications provides tools for that, like the VirtualHostMonster in Zope
For tomcat the preferred tool is mod_proxy_ajp and not mod_proxy. But for a load balancer proxy I do not think you can use mod_proxy_ajp. And, it's been a long time since I made this, but in my memory I think mod_jk was the solution to that.
Read this full documentation on tomcat proxying for details. At least you should get some hints for the solution.

Retain original request URL on mod_proxy redirect

I am running a WebApplication on a Servlet Container (port 8080) in an environment that can be accessed from the internet (external) and from company inside (intenal), e.g.
http://external.foo.bar/MyApplication
http://internal.foo.bar/MyApplication
The incomming (external/internal) requests are redirected to the servlet container using an apache http server with mod_proxy. The configuration looks like this:
ProxyPass /MyApplication http://localhost:8080/MyApplication retry=1 acquire=3000 timeout=600 Keepalive=On
ProxyPassReverse /MyApplication http://localhost:8080/MyApplication
I am now facing the problem that some MyApplication responses depend on the original request URL. Concrete: a WSDL document will be provided with a element that has a schemaLocation="<RequestUrl>?xsd=MyApplication.xsd" element.
With my current configuration it always looks like
<xs:import namespace="..." schemaLocation="http://localhost:8080/MyApplication?xsd=MyApplication.xsd"/>
but it should be
External Request: <xs:import namespace="..." schemaLocation="http://external.foo.bar/MyApplication?xsd=MyApplication.xsd"/>
Internal Request: <xs:import namespace="..." schemaLocation="http://internal.foo.bar/MyApplication?xsd=MyApplication.xsd"/>
I suppose this is a common requirement. But as I am no expert in configuration of the apache http server and its modules I would be glad if someone could give some (detailed) help.
Thanks in advance!
If you're running Apache >= 2.0.31 then you might try to set the ProxyPreserveHost directive as described here.
This should pass the original Host header trough mod_proxy into your application, and normally the request URL will be rebuild there (in your Servlet container) using the Host header, so the schema location should be build using the host and path infos from "before" the proxy.
(Posted here too for the sake of completeness)
Here is another alternative if you would like to retain both the original host name and the proxied host name.
If you are using mod_proxy disable ProxyPreserveHost in the Apache configuration. For most proxy servers, including mod_proxy, read the X-Forwarded-Host header in your application. This identifies the original Host header provided by the HTTP request.
You can read about the headers mod_proxy (and possible other standard proxy servers) set here:
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
You should be able to do a mod_rewrite in apache to encode the full URL as a query parameter, or perhaps part of the fragment. How easy this might be depends on whether you might use one or the other as part of your incoming queries.
For example, http://external.foo.bar/MyApplication might get rewritten to http://external.foo.bar/MyApplication#rewritemagic=http://external.foo.bar/MyApplication which then gets passed into the ProxyPass and then stripped out.
A bit of a hack, yes, and perhaps a little tricky to get rewrite and proxy to work in the right order and not interfere with each other, but it seems like it should work.