Accessing a Pi-Hole behind an Apache reverse proxy

Update 2019-09-15: Finally got around to looking into this and it turns out all I had to change was “ProxyPreserveHost Off” to “ProxyPreserveHost  On” to get things working. I’ve updated the original post to reflect the changes. I also didn’t note in my original host that I purposely restricted access to the apache virtual host to 10.0.0.0/24 and 192.168.0.0/24 (my internal networks). You’ll want to update the “Allow from” lines to reflect your internal networks OR remove the “<Location /></Location>” all together to make it accessible from anywhere (not recommended).

Update 2019-08-19: I just recently found out that this proxy configuration only allows read-only access to the Pi-Hole UI. I was attempting to white-list a domain and it was failing when accessing my Pi-Hole via the proxy. I had to go directly to the box’s FQDN to white-list a domain. I will leave this post for reference and update it when I figure out a fix to this problem.

Update 2019-09-29: My first Lets Encrypt certificate came due for auto-renewal and failed because of my original configuration. I’ve updated the apache configuration below so Lets Encrypt can access the non-SSL /.well-known directory to automatically renew certificates.

Original Post

Today I got tired of accessing my Pi-Hole over HTTP, having to remember to put /admin/ in the URL and having to load up a browse that wasn’t Vivaldi or Firefox because they don’t have an easy way to ignore Strict-Transport-Security for my domain.

I checked out some documentation about adding SSL to the Pi-Hole directly but have concerns that future updates will wipe out all the custom configuration to lighttpd. According to this you also have to be careful when enabling SSL on your Pi-Hole as it could interfere with blocking.

I already have an Apache webserver running so configuring it to reverse-proxy seemed like an easier task, plus if for some reason I wanted to access my Pi-Hole from the general internet (without VPN) it would be simple to enable that.

Here is the reverse proxy configuration I used with a restriction to my two internal networks and a redirect from HTTP to HTTPS:

<VirtualHost *:80>
       ServerName pihole.mydomain.com
       DocumentRoot /var/www/html
       CustomLog logs/pihole.mydomain.com.log combined
       ErrorLog logs/pihole.mydomain.com-error.log

	<Location /.well-known>
		Order allow,deny
		Allow from all
	</Location>

	<Location />
		Order deny,allow
		Deny from all
		Allow from 127.0.0.1
		Allow from 192.168.0.0/24
		Allow from 10.0.0.0/24
	</Location>

       RewriteEngine On
       RewriteRule ^(.well-known)($|/) - [L]
       RewriteCond %{SERVER_PORT} 80
       RewriteRule ^(.*)$ https://pihole.mydomain.com/ [R,L]
</VirtualHost>

<VirtualHost *:443>
        ServerName pihole.mydomain.com
        DocumentRoot /var/www/html
        CustomLog logs/pihole.mydomain.com.log combined
        ErrorLog logs/pihole.mydomain.com-error.log

	<Location />
		Order deny,allow
		Deny from all
		Allow from 127.0.0.1
		Allow from 192.168.0.0/24
		Allow from 10.0.0.0/24
	</Location>

        RewriteEngine On
        RewriteRule ^/$ /admin [R]

        # The below line is not required so I have commented it out but left it in place
        # in case I am wrong. I no longer use Apache so I can't test. If this config doesn't
        # work uncomment the below line.
        # ProxyRequests On
        ProxyPass /  http://pihole-internal-hostname.mydomain.com/
        ProxyPassReverse / http://pihole-internal-hostname.mydomain.com/
        ProxyPreserveHost On

        SSLEngine on
        SSLHonorCipherOrder off
        Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"

        SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

        SSLCertificateFile /etc/letsencrypt/live/pihole.mydomain.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/pihole.mydomain.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/pihole.mydomain.com/chain.pem
</VirtualHost>

I am aware that my SSL configuration is not the best. I’m waiting for CentOS 8 to come out before migrating off my existing CentOS 6 server.

To find the best SSL configuration for your OS and Web Server I recommend checking out Mozilla’s SSL Configuration Generator: https://ssl-config.mozilla.org/

How to replace the boot volume on a RaspberryPi

Just ran into what I think is called the “rainbow screen of death” where a fully functioning RaspberryPi running Raspbian stopped working on me after a reboot.

I know my MicroSD card is good quality and I wasn’t mucking with the boot file system before the reboot so it baffled me why things would just stop working.

I ran then MicroSD card through SpinRite and that didn’t solve the problem. If I connected the microSD card to another PC all the files were there.

Based on my research I found this happens from time to time where something goes wrong with the /boot volume. I could have just re-loaded and re-setup my RPi (it would have taken less time at this point) but I decided I wanted to try and fix it with out losing all of my data.

This is what worked for me:

  1. Image a fresh spare microSD card with the same distro of Raspbian you’re using on the non-functional microSD
  2. Connect the non-functional microSD to the same PC you have your freshly imaged microSD connected
  3. In Windows there is going to be one partition (disk) under My Computer you can actually view, that’s the boot partition
  4. On the non-functioning microSD copy ‘cmdline.txt’ and ‘config.txt’ to some place safe on your computer
  5. Copy the entire contents of the boot partition from the new microSD to the bad one overwriting all files when prompted
  6. Copy the backups of ‘cmdline.txt’ and ‘config.txt’ on to the bad microSD

If you’ve never run ‘rpi-update’ then you’re done. You should be able to put the microSD into your RPi and it will boot again.

If you have run ‘rpi-update’ you have a bit more work to do.

  1. Go to https://github.com/raspberrypi/firmware/releases and download the release that matches the date of the last time you ran rpi-update
    Note: If you don’t know when this is you might be able to boot the RPi now, login locally and dig through your ‘history’ or look at the date/time stamps on the files in /boot
  2. Extract the downloaded file
  3. Copy the contents of firmware-#.#######\boot into \boot on your bad microSD overwriting all files when prompted

Now you’re done. You should be able to put that bad microSD back into a RPi and have it boot

Once your RPi is backup and running I highly recommend manually running a ‘rpi-update’

References