0

Under normal circumstances, setting up an apache reverse proxy with a letsencrypt exception for /.well-known is easily done with ProxyPass /.well-known ! It seems to become much more difficult (something which I happen to have easily solved in nginx) to configure this exception along with ip restrictions for the backend:

<VirtualHost *:80>
  ServerName example.com
  DocumentRoot /var/www/html
  Redirect / https://example.com/
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com

  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
  DocumentRoot /var/www/html

  ErrorLog ${APACHE_LOG_DIR}/bfp-all_error.log
  CustomLog ${APACHE_LOG_DIR}/bfp-all_access.log combined

  RewriteEngine On
  RewriteCond %{HTTP:Connection} Upgrade [NC]
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteRule /(.*) ws://localhost:8050/$1 [P,L]



  ProxyRequests Off
  ProxyPreserveHost On
<Location />
    ProxyPass "http://localhost:8050/"
    ProxyPassReverse "http://localhost:8050/"
    Require ip 10.0.0.0/24
    Require ip 192.168.0.0/24
</Location>
</VirtualHost>

I tried using Alias and (and also the directory, which seems to be already quite redundant) before the section but the requests keep going to the backend:

DocumentRoot /var/web/letsencrypt
Alias /.well-known /var/web/letsencrypt/.well-known
  <Directory /var/web/letsencrypt/.well-known>
           Options -Indexes
           Require all granted
  </Directory>
  <Location /.well-known>
        ProxyPass !
        Require all granted
  </Location>

Any ideas how I could solve this? I would have expected it to be a problem people do come across from time to time, but I haven't found anything on the internet.

Lethargos
  • 396
  • 1
  • 4
  • 16
  • With backend you mean the service on 8050? And you want to restrict .well-known access to specific IP's? Maybe use proxy:trace5 on your ErrorLog. Also see https://serverfault.com/q/956250/188737 – Gerrit Apr 17 '19 at 14:27
  • Yes, the backend runs on 8050. No, I want to restrict only backend access to specific IPs and leave /.well-known open for everybody (The IPs of let's encrypt servers can change at any time, so I have to leave this as an exception). Verbose error log doesn't help me at all. I know exactly what's going on. The requests go directly to the backend adding the /.well-known url. – Lethargos Apr 17 '19 at 14:34
  • If you are using Apache >= 2.4.26 then you can use the no-proxy environment variable and set that with dynamic rules. Below 2.4.26 this is actually a problem with ProxyPass. Only with proxying with RewriteRule [P] can you set rules. The only filter you can apply otherwise is on the backend reading X-Forwarded-For headers. – Gerrit Apr 17 '19 at 14:40
  • I don't really understand, how would proxy rewriterules be of help in this context? I've used them in several quite different contexts, but in this one I don't see exactly how I could implement them. – Lethargos Apr 17 '19 at 15:15
  • With a RewriteRule [P] type of proxy, you can use preceding RewriteCond lines to narrow down the requests eligible for proxying, for example with IP conditions. Only you lose the options of ProxyPass for defining balancermembers and pools and such. – Gerrit Apr 17 '19 at 15:31
  • So if I have 50, 100 IPs, I'll have to write 50 or 100 IPs on a rewrite rule, with all the escapes, parantheses and whatever else would be needed. I don't understand how apache can be so limited. – Lethargos Apr 18 '19 at 08:52
  • For this you could use a RewriteMap. Something like this: RewriteMap ipmap txt:/etc/apache2/ip-mapping RewriteCond %{REMOTE_ADDR} ^(.*)$ RewriteCond ${ipmap:%1|blocked} !^blocked$ RewriteRule .* http://proxy:8050 [P,L] – Gerrit Apr 18 '19 at 09:14
  • I quite forgot, there is also the proxy.conf from the Proxy module itself. It often looks something like this by default Require all granted – Gerrit Apr 18 '19 at 09:58

1 Answers1

0

In this case the "reason" for letting the request through to the backend is because the RewriteRule with [P] bypasses the Location block with the ProxyPass directives (and any possible location block within its match). So both they and the Require rules in it will be ignored and the requests will be proxied for all ip addresses.

If you leave out the RewriteRule and put the ws://localhost:8050/ in the ProxyPass rules in the <Location> section, it would work as intended. The most specific Location block will win in the configuration merge where it concerns the Require setting and ProxyPass setting. If a more unspecific Location block has set a Require or ProxyPass you can override that with a new one in the most specific Location block.

The websocket proxy itself will already block requests without Upgrade headers.

From Apache 2.4.19 it is possible to put the .well-known Alias straight in the Location block, leaving out the first argument.

Gerrit
  • 1,347
  • 7
  • 8