ProxyPass with trailing slash returns 404 - apache

Consider the following configuration :
ProxyPass /myapp http://localhost:8080/myapp
ProxyPassReverse /myapp http://localhost:8080/myapp
Now requests that are made to http://www.example.com/myapp/foo/bar will be routed to my app with the expected results to the browser. However a request made to http://www.example.com/myapp/foo/bar/ will return a 404.
I observe the same results when I update the ProxyPass and ProxyPassReverse directives with the trailing forward slash.
I know that my Controller in my Spring app is set up to handle this URL pattern as calls made to http://localhost:8080/myapp/foo/bar/ work as expected.
I am using Apache 2.4 and Tomcat7. I have the following modules loaded:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Related

apache httpd 2.4.37 forward proxy not working

I have build apache httpd 2.4.37 from source in redhat and installed in home directory [/home/test/httpd-2.4.37]. as I don't have root access to install from yum. The server is running, I want to use this server only as a forward proxy.
I have the following modules in /home/test/httpd-2.4.37/conf/httpd.conf and the files in /home/test/httpd-2.4.37/modules
LoadModule proxy_module modules/mod_proxy.so LoadModule
proxy_connect_module modules/mod_proxy_connect.so LoadModule
proxy_ftp_module modules/mod_proxy_ftp.so LoadModule
proxy_http_module modules/mod_proxy_http.so LoadModule
proxy_fcgi_module modules/mod_proxy_fcgi.so LoadModule
proxy_scgi_module modules/mod_proxy_scgi.so LoadModule
proxy_uwsgi_module modules/mod_proxy_uwsgi.so LoadModule
proxy_fdpass_module modules/mod_proxy_fdpass.so LoadModule
proxy_wstunnel_module modules/mod_proxy_wstunnel.so LoadModule
proxy_ajp_module modules/mod_proxy_ajp.so LoadModule
proxy_balancer_module modules/mod_proxy_balancer.so
I have added below configuration at end of /home/test/httpd-2.4.37/conf/httpd.conf file.
Listen 127.0.0.1:8090
ProxyRequests On
ProxyVia On
ProxyPreserveHost Off
<Proxy "*">
Order deny,allow
Allow from all
</Proxy>
ErrorLog "/home/test/httpd-2.4.37/logs/proxy-error.log"
CustomLog "/home/test/httpd-2.4.37/logs/proxy-access.log" common
forward proxy is not working , when I call from a another machine using this proxy, I am getting connection refused as response.
no log is getting updated /home/test/httpd-2.4.37/logs/proxy-error.log & /home/test/httpd-2.4.37/logs/proxy-access.log
My primary objective is to tunnel ssh request over thru proxy. I have added the below change at the end of httpd.conf file. Proxy is working and forwarding the request to the destination.
Listen 8090
<VirtualHost *:8090>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^CONNECT [NC]
RewriteRule ^/(.*)$ - [F,L]
ProxyRequests On
ProxyBadHeader Ignore
ProxyVia On
AllowCONNECT 22 64
<Proxy "*">
Order deny,allow
Require ip 10
</Proxy>
ErrorLog "/home/test/httpd-2.4.37/logs/proxy-error.log"
CustomLog "/home/test/httpd-2.4.37/logs/proxy-access.log" common
</VirtualHost>

Apache websocket connection:upgrade replaced by keep-alive

I am trying to figure out a mind-numbing apache issue where requests are going through two layers of apache reverse proxies before hitting upstream services. Most traffic seems to make it through fine. The notable exception is websockets.
In particular, this is a test request
curl -i -H 'Connection: Upgrade' -H 'Upgrade: websocket' localhost:80/test.html
When proxying requests from port 80 to port 8080, I notice (using tcpdump and Wireshark) that the Upgrade header has been removed and Connection: Keep-Alive has been set instead. Moreover, any attempts I have made at resetting the Connection header to Upgrade and Upgrade: websocket have been impotent.
Note that the upstream service needs Connection: Upgrade and Upgrade: websocket to initiate the websocket (I get a 404 error without those headers).
Why is Apache forcing Connection: Keep-Alive when proxying to itself? Is there any way to force it to pass along Connection / Upgrade headers or set those values manually? RequestHeader and friends have unfortunately not been helpful. Without Connection and Upgrade making it through the reverse proxy, the upstream service pukes and throws a 404/Not found at the websocket endpoint.
ServerRoot "/usr/local/apache2"
Listen 80
Listen 8080
LogLevel rewrite:trace8
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule xml2enc_module modules/mod_xml2enc.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule auth_mellon_module modules/mod_auth_mellon.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule ssl_module modules/mod_ssl.so
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
<VirtualHost *:80>
LogLevel rewrite:trace8
ServerName localhost
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /(.*) http://localhost:8080/$1 [P,L]
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
ProxyRequests Off
</VirtualHost>
<VirtualHost *:8080>
LogLevel rewrite:trace8
ServerName localhost
UseCanonicalName On
RewriteEngine On
ProxyPass / http://proxy-debug:8080/
ProxyPassReverse / http://proxy-debug:8080/
ProxyRequests Off
</VirtualHost>
ServerAdmin you#example.com
ErrorLog /proc/self/fd/2
DocumentRoot "/"
I do not completely understand how this works, but the nuggets of wisdom I have gleaned and the solution I have devised are as follows:
Apache does not understand websockets in one sense (i.e. when it is talking to itself). As a result, you need to use mod_rewrite and set the protocol to ws:// in order to forward websockets upstream (it seems that no amount of setting headers will help you here).
If you set the protocol to ws://, then Apache will set the appropriate headers (Connection: Upgrade and Upgrade: websocket) when proxying requests upstream. However, for some reason, it does not seem to do this when proxying requests to itself / another VirtualHost.
You can see a blurb in VirtualHost *:80 (copied below) that tries to discern whether a websocket is in order and then change the protocol accordingly. This will not work for VirtualHost *:8080 (see the above bullet). Other methods are necessary.
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /(.*) http://localhost:8080/$1 [P,L]
Put all of this together, and you have to communicate to VirtualHost *:8080 that a websocket connection is needed upstream. Luckily, we are in control of VirtualHost *:80 and can discern this information / pass it along. We must do so without touching the Connection or Upgrade headers, since Apache does weird things with them. The protocol may be traceable, but I am not sure how to do that. As a result, I use a bogus, internal, custom header for the transmission. Probably best to name it in such a way that collisions are unlikely.
In VirtualHost *:80, we add a block like:
SetEnvIf Upgrade ^websocket$ websock=true
RequestHeader set X-Is-Websocket %{websock}e
And then we read that header in VirtualHost *:8080, changing the protocol if necessary:
SetEnvIf X-Is-Websocket ^true$ websock=true
RequestHeader unset X-Is-Websocket
# change protocol if necessary
RewriteCond %{ENV:websock} =true
RewriteRule /(.*) ws://proxy-debug:8080/$1 [P,L]
RewriteCond %{ENV:websock} !=true
RewriteRule /(.*) http://proxy-debug:8080/$1 [P,L]
Hope it helps! :)

Apache Reverse Proxy Preserve URL even after redirect

I have an apache reverse proxy setup from where I am redirecting to a completely different URL. The destination URL is a cloud-hosted service different from the Apache installation location. The redirect is happening properly. But how do I preserve the original URL and mask this new cloud-hosted URL?
This is my apache httpd.conf on Oracle Linux
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyRequests Off
<VirtualHost *:80>
ProxyPreserveHost On
ServerName xxx.xxx.xx.xx:80
ServerAlias https://sample-url.cloud.com/
Redirect / https://sample-url.cloud.com/
</VirtualHost>
How to achieve this.

Apache https reverse proxy with Tomcat

Well, I looked everywhere I could, but if some know where I could find a solution, sorry for asking once again the question.
We are looking to implement this solution :
HTTP client -> Apache 2.4 Reverse Proxy -> HTTP Server => Works OK
HTTPS client -> Apache 2.4 Reverse Proxy -> HTTPS Server => Works OK
But, when the HTTPS server replies with a "302" redirection header, the server name in the header is not translated to the client-side known server name. So, the client fail to connect, due to a DNS error.
We can't add the backend server name in the DNS, so we need that solution to work.
Important notice: the same works in HTTP. It means that when the server reply is a "302" redirection header in HTTP, there's no problem. It works even if the target of the redirection is a HTTPS link. So what is not working is redirecting from HTTPS to HTTPS.
The backend webserver is Tomcat.
The problem is: in HTTPS header, the redirection URL is "https://[backendname]/something.html" but we expect it to be "https://[servername]/something.html"
We've checked that we have no error in log file (error level set to "debug").
Here is our virtual site configuration:
<VirtualHost [reverse proxy IP]:443>
SSLEngine on
SSLProxyEngine on
SSLCertificateFile D:/Apache24/ssl/certs/servername.cer
SSLCertificateKeyFile D:/Apache24/ssl/private/servername.key
ServerName [servername]
ProxyPass / https://[backendname]:443/
ProxyPassReverseCookiePath / https://[backendname]:443/
ProxyPassReverse / https://[backendname]:443/
SetOutputFilter proxy-html
ProxyHTMLEnable On
ProxyHTMLURLMap https://[backendname] https://[servername]
ErrorLog D:/Apache24/logs/custom/[servername]_error.log
CustomLog D:/Apache24/logs/custom/[servername]_access.log combined
SetEnv nokeepalive ssl-unclean-shutdown
</VirtualHost>
Problem related Apache activated modules:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule xml2enc_module modules/mod_xml2enc.so
So, any help to make this work will be greatly appreciated.
Thanks.
Here is the working solution, as suggested by Michael Akerman
disable caching
write new instruction: ProxyPassReverse https://[backend]/
Thanks for your help

Apache subdomain redirect into Tomcat

I'm pretty new to Apache HTTP, and sysadmin-ing in general, so i have this question
I have a domain (www.doamin.com) with an Apache listening to port 80,
also I have an Apache Tomcat on the same domain configured to port 8080.
Is there a way to configure a subdomain (i.e, tomcat.domain.com)
so it will redirect into my tomcat specific application,
so user can access applications through app1.domain.com and app2.domain.com (and it will be served by Tomcat)?
I've seen a lot of mentioning to
mod_jk
and
mod_proxy
but all of the post assumed prior knowledge with Apache.
can someone walk me thorugh?
Many thanks, -PK.
mod_jk is outdated. It is recomended to use mod_proxy (mod_proxy_http or mod_proxy_ajp) to connect forward requests to your apache server to the tomcat.
define a virtual host in your apache config
create a proxy directive that forwards your requests to tomcat
Maybe this SO question give you some hints.
You can define two virtual hosts (app1.domain.tld and app2.domain.tld) that have proxy definitions for their designated apps. Example for app1:
<VirtualHost *:80>
ServerName app1.domain.tld
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/app1
ProxyPassReverse / http://localhost:8080/app1
</VirtualHost>
while Magomi was almost right,
Presenting an exact way to do it.
Add your subdomain to the DNS server
integrate *mod_proxy* into httpf.conf :
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
define two virtual hosts as following
NameVirtualHost *:80
<VirtualHost *:80>
ServerName application.domain.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://www.domain.com:8080/application/
ProxyPassReverse / http://www.domain.com:8080/application/
</VirtualHost>
<VirtualHost *:80>
DocumentRoot C:\<pathToApache>\www
ServerName www.domain.com
</VirtualHost>
This will direct your site (www.domain.com) to your Apache HTTP server, and redirect all calls to Application to the Tomcat.
Hope this Helps,
-PK