apache httpd 2.4.37 forward proxy not working - apache

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>

Related

how to enable http/2 on apache2 using ubuntu 20.04?

I have VPS server running ubuntu 20.04 (apache2) and is using http/1.1 and I want to upgrade to http/2
The domain is already configured using v-hosts (and has the ssl installed - lets encrypt).
Testing the current protocol:
$ curl -I https://my-domain.com
HTTP/1.1 200 OK
Date: Fri, 12 Mar 2021 17:32:01 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Steps that I done to upgrade to http/2:
1) sudo a2enmod http2
2) add in virtual host (ex: /etc/apache2/sites-enabled/my-domain.com-le-ssl.conf) the line:
Protocols h2 http/1.1
3) check the config
sudo apache2ctl configtest
4) Restart the web server
sudo systemctl reload apache2
Test again the ptotocol:
$ curl -I https://my-domain.com
HTTP/1.1 200 OK
Date: Fri, 12 Mar 2021 17:57:07 GMT
Server: Apache/2.4.41 (Ubuntu)
Upgrade: h2
Connection: Upgrade
Content-Type: text/html; charset=UTF-8
As you can see it still using the http/1.1
I also updated the apache2 from 2.4.41 -> 2.4.46 ... but the same problem.
What did I miss ???
** UPDATE **
apache2 loaded modules
$ sudo apachectl -M
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
unixd_module (static)
access_compat_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_core_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
expires_module (shared)
filter_module (shared)
headers_module (shared)
http2_module (shared)
mime_module (shared)
mpm_prefork_module (shared)
negotiation_module (shared)
php7_module (shared)
reqtimeout_module (shared)
rewrite_module (shared)
setenvif_module (shared)
socache_shmcb_module (shared)
ssl_module (shared)
status_module (shared)
php 7.4.3 installed
php
libapache2-mod-php
php-mysql
php-cli
php-mbstring
php-imagick
php-xml
php-gd
php-zip
php-curl
php-opcache
php-soap
php-bcmath
vhost config:
<VirtualHost *:80>
ServerAdmin admin#my-domain.com
ServerName my-domain.com
ServerAlias www.my-domain.com
DocumentRoot /var/www/my-domain.com/public
Protocols h2 http/1.1
<Directory /var/www/my-domain.com/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =my-domain.com [OR]
RewriteCond %{SERVER_NAME} =www.my-domain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
and the ssl config:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin admin#my-domain.com
ServerName my-domain.com
ServerAlias www.my-domain.com
DocumentRoot /var/www/my-domain.com/public
Protocols h2 http/1.1
<Directory /var/www/my-domain.com/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem
</VirtualHost>
</IfModule>
Replacing the mpm_prefork with mpm_event
using php-fpm (libapache2-mod-fcgid) instead of (libapache2-mod-php)
solve the problems.
You should probably add the --http2 option to your curl command

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! :)

Docker Apache installation fails

I am trying to start apache service with docker-compose up, but I get this error:
apache_1 | AH00526: Syntax error on line 15 of /usr/local/apache2/conf/httpd.conf:
apache_1 | Invalid command 'DirectoryIndex', perhaps misspelled or defined by a module not included in the server configuration
This is my Dockerfile for httpd:
FROM httpd:2.4
COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
This is my httpd.conf file:
ServerName localhost
LoadModule deflate_module /usr/local/apache2/modules/mod_deflate.so
LoadModule proxy_module /usr/local/apache2/modules/mod_proxy.so
LoadModule proxy_fcgi_module /usr/local/apache2/modules/mod_proxy_fcgi.so
LoadModule mpm_event_module /usr/local/apache2/modules/mod_mpm_event.so
#LoadModule mpm_prefork_module /usr/local/apache2/modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module /usr/local/apache2/modules/mod_mpm_worker.so
<VirtualHost *:80>
DocumentRoot /var/www/html/
<Directory /var/www/html/>
DirectoryIndex index.html
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Send apache logs to stdout and stderr
CustomLog /proc/self/fd/1 common
ErrorLog /proc/self/fd/2
</VirtualHost>
I think you need to make sure you load the mod_dir module
LoadModule dir_module libexec/apache2/mod_dir.so

Apache/AJP remote changes the URI. Why?

I'm using Apache 2.4 on Windows and Tomcat 7. Up until now I've been testing everything on my localhost. So my local Apache httpd.conf has this...
<Location /sample>
ProxyPass ajp://localhost:8079/sample
ProxyPassReverse ajp://localhost:8079/sample
</Location>
Now I'm attempting to set Apache up on a different system and point it to my Tomcat system. Here's what the remote Apache httpd.conf has...
<Location /sample>
ProxyPass ajp://192.168.2.93:8079/sample
ProxyPassReverse ajp://192.168.2.93:8079/sample
</Location>
The new Remote Apache is definitely forwarding the request to Tomcat but it's prepending the location to the request. For example...
/sample/sample
When it should be only...
/sample
The only thing that's changed between the local and remote Apache httpd.conf's is I changed the ProxyPass settings from localhost to an IP.
What am I missing here? This is driving me crazy.
Thanks!
Here's my local httpd.conf....
# =================================================
# Modules
# =================================================
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule dir_module modules/mod_dir.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule headers_module modules/mod_headers.so
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 xml2enc_module modules/mod_xml2enc.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadFile libxml2.dll
LoadModule ssl_module modules/mod_ssl.so
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule substitute_module modules/mod_substitute.so
LoadModule filter_module modules/mod_filter.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule setenvif_module modules/mod_setenvif.so
#LoadModule env_module modules/mod_env.so
Include conf/proxy_html.conf
Include conf/extra/httpd-ssl.conf
# =================================================
# Basic settings
# =================================================
Listen 80
ServerName localhost:80
ServerAdmin fred#www.somedomain.com
UseCanonicalName Off
ServerSignature Off
HostnameLookups Off
ServerTokens Prod
ServerRoot "D:/Apache24"
DocumentRoot "D:/Apache24/htdocs"
<IfModule mod_dir.c>
DirectoryIndex index.html index.htm index.php
</IfModule>
# =================================================
# HTTP and performance settings
# =================================================
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
<IfModule mpm_winnt.c>
ThreadsPerChild 64
MaxRequestsPerChild 0
</IfModule>
# =================================================
# Logs: emerg, alert, crit, error, warn, notice, info, debug
# =================================================
# Docs ~ http://httpd.apache.org/docs/2.4/mod/core.html#loglevel
LogLevel alert rewrite:trace8 proxy_html:trace7
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
#ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"
ErrorLogFormat "[%l] %F ~ %M"
ErrorLog "logs/error.log"
CustomLog "logs/access.log" combined
# =================================================
<VirtualHost *>
ServerName localhost:80
RewriteEngine On
ProxyRequests off
ProxyHTMLEnable Off
<Proxy *>
Require all granted
</Proxy>
<Location /sample>
ProxyPass ajp://localhost:8079/sample
ProxyPassReverse ajp://localhost:8079/sample
</Location>
</VirtualHost>
I don't know why the same exact Apache server (literal copy from one system to another) would produce different URI's because I changed localhost to an IP address. But I got it working by removing the <location/> wrapper from the ProxyPass parameters and using these parameters instead...
ProxyPass /sample ajp://192.168.2.93:8079/sample
ProxyPassReverse /sample ajp://192.168.2.93:8079/sample
Hope this helps someone.

ProxyPass with trailing slash returns 404

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