1

I've been scratching my head on this for far too long.

I have what I consider a simple configuration using the proxypass rules for Apache, I want to supply a list of exclusions before using a 'catchall' rule to redirect all traffic to a local node server.

The setup follows:

ProxyPass        /contact-us !
ProxyPass        / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/

The result of the above configuration is that /contact-us is sent to node (localhost:3000), as I understand the documentation it should be ignored. If I set a destination for /contact-us then the request is correctly handled and the proxied content is returned.

Am I missing something? Does adding the catchall (/) to the ruleset change the behaviour?

Edit: Added rest of file for reference

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName  dev.site.com
    ServerAdmin [email protected]

    ProxyPass        /contact-us !
    ProxyPass        / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    DocumentRoot /var/www/site/public
    <Directory /var/www/site/public>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>

    <IfModule mod_headers.c>
        SetEnvIf Origin "^http(s)?://(.+\.)?(dev\.site\.com)$"  origin_is=$0

        Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is
        Header always set Access-Control-Allow-Credentials true env=origin_is
    </IfModule>

    ErrorLog ${APACHE_LOG_DIR}/dev.site.com-error.log
    CustomLog ${APACHE_LOG_DIR}/dev.site.com-access.log combined

    SSLCertificateFile /etc/letsencrypt/live/dev.site.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/dev.site.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
5
  • 1
    Can you post the rest of your config. For example, do you have those in a location block or not?
    – ColtonCat
    Mar 1, 2019 at 2:46
  • @ColtonCat - thanks for your reply, no these are the only proxypass rules for the virtualhost, as I understand it, any rules within a location directive are resolved before these are, so I made sure that wasn't the case. The rest of the configuration is quite vanilla, I'll add it to the OP. Mar 1, 2019 at 3:03
  • The documentation talks about directories excluded maybe that is the catch. Maybe you should try SetEnvIf Request_URI ^/contact-us$ no-proxy=1
    – Gerrit
    Mar 1, 2019 at 8:56
  • That looks like a correct configuration, but that may be impacted by additional directives in an .htaccess file in either the DocumentRoot /var/www/site/public or the /var/www/site/public/contact-us/ sub directory
    – HBruijn
    Mar 1, 2019 at 9:18
  • @user188737 - nice find, that is one thing I hadn't tried, unfortunately after updating Apache to use it (Req. 2.4.26), it didn't help, I'm glad to have tried something new though, thanks. @HBruijn Hmm, there are a few application specific rewrite rules in the top level .htaccess, I'll try cleaning those up just in case. Mar 4, 2019 at 4:13

2 Answers 2

0

I found my issue and you were right @HBruijn.

I am running the Laravel framework on the virtualhost which means requests are directed to /index.php to be routed, so after the first rule succeeded (/contact-us !) the request was rewritten to /index.php which was then being proxied in the catch all rule.

I was able to add an exclude rule for (/index.php), and also the following Fpm request (see the log below) to solve my problem. This solution may not be possible for everyone.

I was able to unravel this thanks to this comment by @yunzen - https://serverfault.com/a/895673, by adding LogLevel error proxy:trace5 I was able to see the following:

[Mon Mar 04 04:39:56.876129 2019] [proxy:trace2] [pid 5564] mod_proxy.c(683): [client 220.244.99.86:51059] AH03461: attempting to match URI path '/contact-us' against prefix '/index.php' for proxying
[Mon Mar 04 04:39:56.876170 2019] [proxy:trace2] [pid 5564] mod_proxy.c(683): [client 220.244.99.86:51059] AH03461: attempting to match URI path '/contact-us' against prefix '/contact-us' for proxying
[Mon Mar 04 04:39:56.876174 2019] [proxy:trace1] [pid 5564] mod_proxy.c(736): [client 220.244.99.86:51059] AH03463: proxying is explicitly disabled for URI path '/contact-us'; declining
[Mon Mar 04 04:39:56.876880 2019] [proxy:trace2] [pid 5564] mod_proxy.c(683): [client 220.244.99.86:51059] AH03461: attempting to match URI path '/index.php' against prefix '/index.php' for proxying
[Mon Mar 04 04:39:56.876890 2019] [proxy:trace1] [pid 5564] mod_proxy.c(736): [client 220.244.99.86:51059] AH03463: proxying is explicitly disabled for URI path '/index.php'; declining
[Mon Mar 04 04:39:56.876936 2019] [proxy:trace2] [pid 5564] mod_proxy.c(683): [client 220.244.99.86:51059] AH03461: attempting to match URI path '/php72-fcgi-www/index.php' against prefix '/index.php' for proxying

Note the context changes from this single request.

0

Based on a little comment in the docs for Apache (2.4.26 and higher only) it is possible to use no-proxy environment variable for proxy exclusions.

It gets ugly however when you need an internal rewrite to serve your excluded page, because then the ProxyPass exclusions and just setting the no-proxy variable based on REQUEST_URI has no effect, because REQUEST_URI changes after the internal rewrite and the ProxyPass is evaluated again and the environment variable is only visible as REDIRECT_no-proxy not as no-proxy.

We can use a little subterfuge here, and this will work:

RewriteEngine on
RewriteRule ^/contact-us$ - [E=no-proxy:1]
RewriteCond %{ENV:REDIRECT_no-proxy} .+
RewriteRule .* - [E=no-proxy:1]

If you put this in the Virtual Host section it will work. If you put it in the Directory section, it won't because then ProxyPass is already acted upon.

2
  • Hmm ugly, but may be less ugly than my solution, I will try this shortly and report back. Thanks. Mar 4, 2019 at 23:36
  • Yes. It is dead ugly. I was quite surprised actually that Request_URI of SetEnvIf moves with rewrite. Up till now I always believed it reflected the original request. And have been working with Apache for something like 15 years. The advantage of this is that you also proxy the direct /index.php?id= type of requests, which would otherwise stay on the origin server.
    – Gerrit
    Mar 5, 2019 at 7:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .