Apache reverse proxy - URL without / is refused - apache

I use reverse proxy to show backend server content for a subdomain.
The subdomain.mydomain.com (server A) should display content of server with IP 123.123.123.123 port 1111 (server B).
Virtual host of subdomain.mydomain.com (server A):
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName subdomain.mydomain.com
SSLEngine on
SecAuditEngine On
RewriteEngine On
SSLProxyEngine on
ProxyPreserveHost On
LogLevel warn
<Directory />
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<Location />
ProxyPass https://123.123.123.123:1111
ProxyPassReverse https://123.123.123.123:1111
</Location>
ErrorLog /var/log/apache2/error.log
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLVerifyClient none
SSLVerifyDepth 1
SSLCertificateFile /etc/apache2/cert.site/chain_wildcard_site_combined.crt
SSLCertificateKeyFile /etc/apache2/cert.site/key_wildcard_site.key
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
</VirtualHost>
</IfModule>
Virtual host of 123.123.123.123:1111 (server B):
<IfModule mod_ssl.c>
<VirtualHost 123.123.123.123:1111>
DocumentRoot /srv/www/site/htdocs
SSLEngine on
RewriteEngine On
SSLProxyEngine on
ProxyPreserveHost On
LogLevel warn
<Location "/">
Require ip 222.222.222.222
</Location>
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /srv/www/site/htdocs>
Options -Indexes +FollowSymLinks +MultiViews
DirectoryIndex index.php
AllowOverride None
Require all granted
</Directory>
ErrorLog /srv/www/site/log/error.log
CustomLog /srv/www/site/log/access.log combined
CustomLog /srv/www/site/log/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLVerifyClient none
SSLVerifyDepth 1
SSLCertificateFile /etc/apache2/cert.site/chain_wildcard_site_combined.crt
SSLCertificateKeyFile /etc/apache2/cert.site/key_wildcard_site.key
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>
If I load URL:
https://subdomain.mydomain.com/dir/
it loads successfully.
If I load URL (without trailing slash):
https://subdomain.mydomain.com/dir
it results error page: ERR_CONNECTION_REFUSED.
EDIT1:
I execute command:
curl -IL https://subdomain.mydomain.com/dir
and I get this result:
HTTP/1.1 301 Moved Permanently
Date: Mon, 23 Aug 2021 13:45:13 GMT
Server: Apache
Strict-Transport-Security: max-age=15768000; includeSubDomains
Strict-Transport-Security: max-age=15768000; includeSubDomains
Location: https://subdomain.mydomain.com:1111/dir/
Content-Type: text/html; charset=iso-8859-1
curl: (7) Failed to connect to subdomain.mydomain.com port 1111: Connection refused
EDIT2:
I added trailing slash
<Location />
ProxyPass https://123.123.123.123:1111/
ProxyPassReverse https://123.123.123.123:1111/
</Location>
But I still get the Connection refused error.
Any idea why is it resulting error, when trailing slash is missing?
Thanks!

Since you used ProxyPreserveHost ON, your ProxyPassReverse should be ProxyPassReverse https://subdomain.mydomain.com:1111/ because this is the Location: header your backend is producing that you need the frontend to fixup.
The backend unfortunately sees no port in the Host: header and picks the port of the local connection. It is a problem that only happens when the default port is used on the frontend + ProxyPreserveHost. ServerName with an explicit port :443 might help on the backend.

You cannot use port 1111 for SSL - it MUST be 443 (modern certificates and CORS do not work or accept different ports)

Related

How can i redirect HTTP requests to custom port to HTTPS/443 via Apache2?

I'm trying to configure apache2 for a specific use case. An old web server only runs in HTTP on port 8788. I want to put it behind an apache reverse-proxy (Debian) which will ensure the encryption of exchanges with the client and will make requests to the web server in HTTP/port 8788.
The reverse proxy already works for other web servers and i changed the DNS for oldserver.example.com to point to the reverse-proxy IP address.
Connections to http://oldserver.example.com and https://oldserver.example.com work correctly and display the old server's web page.
But when I try to access http://oldserver.example.com:8788 (I have to keep this access via port 8788 because the link has been posted like this for years) the browser redirects to https://oldserver.example.com:8788 and shows this error:
Secure Connection Failed
In the configuration files and logs below, I replaced the reverse proxy IP address with X.X.X.X; the IP address of the oldserver by Y.Y.Y.Y and the IP addresses of the clients by Z.Z.Z.Z.
When I try with wget, everything seems OK:
wget -v http://oldserver.example.com:8788
--2022-09-14 14:36:15-- http://oldserver.example.com:8788/
Resolving oldserver.example.com (oldserver.example.com)... X.X.X.X
Connecting to oldserver.example.com (oldserver.example.com)|X.X.X.X|:8788... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://oldserver.example.com/ [following]
--2022-09-14 14:36:15-- https://oldserver.example.com/
Connecting to oldserver.example.com (oldserver.example.com)|X.X.X.X|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11628 (11K) [text/html]
Saving to: 'index.html'
index.html.3 100%[=================================================================================================================>] 11.36K --.-KB/s in 0s
2022-09-14 14:36:15 (42.0 MB/s) - 'index.html' saved [11628/11628]
Configuration files
/etc/apache2/sites-available/oldserver.conf :
<VirtualHost *:80 *:8788>
ServerName oldserver.example.com
include /etc/apache2/xyz/general.conf
include /etc/apache2/xyz/redirect-ssl.conf
ErrorLog ${APACHE_LOG_DIR}/error_oldserver.log
CustomLog ${APACHE_LOG_DIR}/access_oldserver.log combined
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName oldserver.example.com
ErrorLog ${APACHE_LOG_DIR}/error_oldserver.log
CustomLog ${APACHE_LOG_DIR}/access_oldserver.log combined
include /etc/apache2/xyz/general.conf
include /etc/apache2/xyz/ssl.conf
include /etc/apache2/xyz/revproxy.conf
ProxyPass / http://Y.Y.Y.Y:8788/
ProxyPassreverse / http://Y.Y.Y.Y:8788/
</Virtualhost>
</IfModule>
/etc/apache2/xyz/general.conf :
ServerAdmin system#example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Protocols h2 http/1.1
DocumentRoot /var/www/html
ErrorDocument 500 https://reverseproxy.example.com/
ErrorDocument 503 https://reverseproxy.example.com/
/etc/apache2/xyz/redirect-ssl.conf :
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
/etc/apache2/xyz/revproxy.conf :
ProxyPreserveHost On
ProxyRequests Off
SSLProxyEngine on
/etc/apache2/xyz/ssl.conf:
#####▒| SSL #####
SSLEngine on
Header always set Strict-Transport-Security "max-age=15768000"
SSLCertificateFile /etc/ssl/wildcard.example.com.crt
SSLCertificateKeyFile /etc/ssl/wildcard.example.com.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
Logs
Strangely, on the reverse proxy, I have nothing in the /var/log/apache2/error_oldserver.log file but I find traces of the connections in the /var/log/apache2/error.log file:
error.log:[Wed Sep 14 14:43:53.497291 2022] [proxy_http:error] [pid 36806:tid 139808714381056] (20014)Internal error (specific information not available): [client Z.Z.Z.Z:51225] AH01102: error reading status line from remote server Y.Y.Y.Y:8788, referer: https://oldserver.example.com/
I don't have access to the logs of the oldserver.
Thank you in advance for your help.
Add new block with port *:8788 in the same virtual host and add LISTEN 8788 in the same block in virtual host file. And port should be opened from Security Group.
<VirtualHost *:443>
ServerName oldserver.example.com
DocumentRoot /var/www/oldserver.example.com/public
<Directory /var/www/oldserver.example.com>
Options FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
ErrorLog /var/www/oldserver.example.com/error.log
CustomLog /var/www/oldserver.example.com/access.log combined
SSLEngine on
SSLCertificateKeyFile /SSL Certificate path/xxx.pem
SSLCertificateFile /SSL Certificate path/xxx.pem
SSLCertificateChainFile /SSL Certificate path/xxx.pem
</VirtualHost>
LISTEN 8788
<VirtualHost *:8788>
ServerName oldserver.example.com
DocumentRoot /var/www/oldserver.example.com/public
<Directory /var/www/oldserver.example.com>
Options FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
SSLEngine on
SSLCertificateKeyFile /SSL Certificate path/xxx.pem
SSLCertificateFile /SSL Certificate path/xxx.pem
SSLCertificateChainFile /SSL Certificate path/xxx.pem
</VirtualHost>

Why is Apache ignoring :80 vhost file and only matching sites in :443 vhost file?

I have 2 vhost files: 1 with all our sites admin URLS on port 443, 1 with all our sites main URLs on port 80.
Both files are known by apache as shown by apachectl -S.
net stat shows Apache listening on :80 and :443
I am using host file from my MacBook for now.
However, only URLs that match vhosts lines in the 443 vhost file are working. Otherwise the site will load the first site in the 443 vhost file. (301 Moved Permanently)
I even try going to site-name.com:80 - but none of the site URLS from the :80 vhost file are getting matched by apache. What am I missing?
EDIT: adding code
Listen 1xx.2xx.3xx.4xx:80 is defined in httpd.conf
From vhost.conf for main site URLS (This one is NOT working)
NameVirtualHost *:80
<VirtualHost 1xx.2xx.3xx.4xx:80>
ServerAdmin admin#site1.com
ServerAlias www.site1.com
DocumentRoot /var/www/site1.com/public
ServerName site1.com
ErrorLog /var/log/httpd/site1.com-error_log
CustomLog /var/log/httpd/site1.com-access_log common
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
<Directory /var/www/site1.com/public>
Options FollowSymLinks
AllowOverride All
DirectoryIndex index.php
</Directory>
</VirtualHost>
From sslvhost.conf for admin sites (This one IS working)
Listen 443 https
NameVirtualHost *:443
<VirtualHost *:443>
DocumentRoot "/var/www/site1.com/public"
ServerName site1.com
ServerAlias site1.com admin-site1.com
LogLevel warn
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
SSLEngine on
SSLProtocol all -SSLv3 -SSLv2 -TLSv1 -TLSv1.1
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Directory /var/www/site1.com/public>
Options FollowSymLinks
AllowOverride All
DirectoryIndex index.php
</Directory>
</VirtualHost>
From the config it seems you are missing the following
Listen 80
You Can add it just below the NameVirtualHost *:80

How to setup reverse proxy for Apache and Jetty host with non root context path

I need to setup Apache 2.4 as a reverse proxy to Jetty 9 backend server so I will have the public site:
https://jenkins.mysite.com
and it will be proxied to the internal
http://localhost:8080/jenkins
I tried different settings as well as:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName jenkins.mysite.com
DocumentRoot /home/jenkins/web
Alias / /home/jenkins/web/
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
SSLEngine on
SSLProxyEngine On
BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
<Directory "/home/jenkins/web/WEB-INF/">
AllowOverride None
Require all denied
</Directory>
ProxyRequests Off
ProxyVia Off
#Tried On and Off. With ProxyPassReverse and without
ProxyPreserveHost Off
#Tried all below settings with no luck
#AllowEncodedSlashes NoDecode
#RequestHeader set X-Forwarded-Proto "https" env=HTTPS
#RequestHeader set X-Forwarded-Port 443
<Proxy *>
AddDefaultCharset off
AllowOverride None
Require all granted
</Proxy>
#Tried below instead of nocanon in ProxyPass
#RewriteEngine on
#RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
#RewriteRule .* http://127.0.0.1:8080/jenkins/%{REQUEST_URI} [NE,P,QSA]
ProxyPass / http://localhost:8080/jenkins nocanon
ProxyPassReverse / http://localhost:8080/jenkins
#That was useful to remove contextPath from Cookie path
#ProxyPassReverseCookiePath "/jenkins" "/"
<Location />
Options FollowSymLinks
AddDefaultCharset off
AllowOverride None
Require all granted
</Location>
SSLCertificateFile /etc/letsencrypt/live/jenkins.mysite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/jenkins.mysite.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
For Jetty I tried to use http-forwarded module. It was not helpful with it or without it.
The best I could achieve that direct links worked. But all referenced urls and redirects(like login one) had the extra internal contextPath: /jenkins/*
Is there any way to setup it as I wish? Particularly to avoid complaints from the Jenkins that reverse proxy is broken?
I can make it work if I use the virtual host for jetty context with contextPath=/. But it requires to change the /etc/hosts which I'm trying to avoid.
Of course mysite.com is hypothetic name. I used some real domain name.
Thank you.

Apache Virtual host document root AND proxy file access forbidden

I am setting up my personal domain and I have this config:
ServerAdmin contact#brentc.in
Listen 80
<VirtualHost *:80>
DocumentRoot "/www/brentc.in"
ServerName brentc.in
ServerAlias www.brentc.in
</VirtualHost>
Listen 443 https
SSLPassPhraseDialog builtin
SSLSessionCache shmcb:/opt/rh/httpd24/root/var/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost *:443>
ServerName brentc.in
ServerAlias www.brentc.in
DocumentRoot /www/brentc.in/
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/brentc.in/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/brentc.in/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/brentc.in/fullchain.pem
</VirtualHost>
<VirtualHost *:443>
ServerName atlassian.brentc.in
ServerAlias www.atlassian.brentc.in
DocumentRoot /www/atlassian.brentc.in/
Options Indexes FollowSymLinks Includes ExecCGI
SSLProtocol all -SSLv2
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /jira/secure/admin/IntegrityChecker.jspa http://localhost:8081/jira/secure/admin/IntegrityChecker.jspa timeout=3600
ProxyPassReverse /jira/secure/admin/IntegrityChecker.jspa http://localhost:8081/jira/secure/admin/IntegrityChecker.jspa
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/brentc.in/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/brentc.in/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/brentc.in/fullchain.pem
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location /jira>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
ProxyPass http://localhost:8081/jira retry=0
ProxyPassReverse http://localhost:8081/jira
SetOutputFilter DEFLATE
</Location>
</VirtualHost>
For the first domain (brentc.in) I can access index.html just fine.
For the second domain (atlassian.brentc.in) it shows the apache sample (test 123) page and when I explicitly go to index.html it says I'm not allowed to access the file.
My file permissions are exactly the same as the working index.html. Am I missing something here?
The atlassian.brentc.in is also a proxy to a behind the scenes tomcat server. My intention is, when you go to atlassian.brentc.in it shows you a landing page. Then from there you can go to atlassian.brentc.in/jira.
The error_log contains this:
[Wed Jun 14 10:43:47.714099 2017] [authz_core:error] [pid 4399] [client <ip>:58299] AH01630: client denied by server configuration: /www/atlassian.brentc.in/index.html
[Wed Jun 14 10:43:47.952670 2017] [authz_core:error] [pid 4399] [client <ip>:58299] AH01630: client denied by server configuration: /www/atlassian.brentc.in/favicon.ico, referer: https://atlassian.brentc.in/index.html
i think you need to add something like this
<Directory "your/sample/directory">
# AllowOverride All # Deprecated
# Order Allow,Deny # Deprecated
# Allow from all # Deprecated
# --New way of doing it this is the important part
Require all granted
</Directory>

How to install ssl certificate on Flask in apache2/ubuntu14.04 with different ports

i have installed ssl to my apache2 and created https for port of 443, its working. when i tried to install ssl to Flask i could not make it as successful. here are things i have done so far.
i have created file using sudo nano /etc/apache2/sites-available/flask.conf
VirtualHost *:80>
ServerName example.com
ServerAdmin admin#example.com
WSGIScriptAlias / /var/www/FlaskApp/flaskapp.wsgi
<Directory /var/www/FlaskApp/FlaskApp/>
Order allow,deny
Allow from all
</Directory>
Alias /static /var/www/FlaskApp/FlaskApp/static
<Directory /var/www/FlaskApp/FlaskApp/static/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:5000>
ServerName example.com
<Directory /var/www/FlaskApp/FlaskApp/>
Order allow,deny
Allow from all
</Directory>
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/STAR_file.crt
SSLCertificateKeyFile /etc/apache2/ssl/STAR_file.key
SSLCertificateChainFile /etc/apache2/ssl/STAR_file_bundle.pem
<Location />
SSLRequireSSL On
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars +StrictRequire
</Location>
ErrorLog ${APACHE_LOG_DIR}/sslerror.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/sslaccess.log combined
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>'
then i have done the enable example.com and restarted the apache2
but when i am check in browser its not working for the port 5000 and get error as
An error occurred during a connection
SSL received a record that exceeded the maximum permissible length. (Error code: ssl_error_rx_record_too_long)
I suggest separating the 2 virtual hosts (port 80 and port 5000) to different virtual host files, such as /etc/apache2/sites-available/flask.conf and /etc/apache2/sites-available/flask-ssl.conf. I suspect apache is confused and is serving an HTTP response to an HTTPS request, which can cause that error. It is also possible that you might have a local proxy that's misconfigured, if you use a proxy.
I didn't notice anything wrong with the config file other than that.