Search This Blog

Enable HTTPS with Let’s Encrypt SSL certificate on Pi-hole web interface

By default, the Pi-hole web interface runs on HTTP, including the web admin panel URL. I want to secure the Pi-hole password with HTTPS when entering in the web browser. To enable HTTPS, I need a SSL certificate. My options are creating a self-signed SSL certificate, buying a retail SSL certificate from a public CA, or using Let’s Encrypt free SSL certificate.

For the home setup, the Let’s Encrypt SSL certificate is a perfect fit. The certificate works all the major web browsers, so no security warning in the browser; and it’s free. Just need to renew it every 90 days.

Before proceeding the following instruction, make sure you meet these two perquisites.
1. You own a public domain name.
2. You have the access to modify the public DSN setting of your domain name. The instruction on how to do this varies from the DNS hosting vendor. Please consult with your DNS hosting vendor for the detail.

1. Issue Let’s Encrypt SSL certificate

Let’s Encrypt recommends the Certbot ACME client to automate the issuance and installation. Because I don’t want my Pi-hole web interface accessible on the internet. I have to run Certbot with the manual option to issue the certificate. Here is how I do that.

  • Login my pi-hole via SSH
  • Install Certbot
    • $ sudo apt install certbot
  • Run certbot to issue a certificate for Pi-hole FQDN. In my example, the FQND is pihole.sfitpro.com.
    • $ sudo certbot certonly --manual --preferred-challenges dns --cert-name pihole.sfitpro.com -d pihole.sfitpro.com
  • During this process, certbot will prompt to add a DNS TXT record “_acme-challenge.pihole.sfitpro.com” with the value created by certbot.
  • Login my domain name DNS hosting site and add a “_acme-challenge.pihole.sfitpro.com” TXT record with the provided value to verify my ownership of the domain name.
  • After the TXT record is added, continue with certbot to finish the certificate issuance.
  • The private key and issued certificate are saved in /etc/letsencrypt/live/.

2. Enable HTTPS on Pi-hole web interface

  • Create a file called combined.pem in the Let’s Encrypt certificate directory
    • $ sudo su
    • $ cd /etc/letsencrypt/live/pihole.sfitpro.com/
    • $ cat privacy.pem cert.perm | tee combined.pem
  • Ensure the lighttpd user (www-data) can read the certificates
    • $ sudo chown www-data -R /etc/letencrypt/live
  • Create a file called external.conf in /etc/lighttpd/ with the following content

$HTTP["host"] == "pihole.sfitpro.com" {
# Ensure the Pi-hole Block Page knows that this is not a blocked domain
setenv.add-environment = ("fqdn" => "true")

# Enable the SSL engine with a LE cert, only for this specific host
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/letsencrypt/live/pihole.sfitpro.com/combined.pem"
ssl.ca-file = "/etc/letsencrypt/live/pihole.sfitpro.com/fullchain.pem"
ssl.honor-cipher-order = "enable"
ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
ssl.use-sslv2 = "disable"
ssl.use-sslv3 = "disable"
}

# Redirect HTTP to HTTPS
$HTTP["scheme"] == "http" {
$HTTP["host"] =~ ".*" {
url.redirect = (".*" => "https://%0$0")
}
}
}

  • Restart the lighttpd service
    • $ sudo systemctl restart lighttpd

3. Add the Pi-hole FQDN on Pi-hole

  • Create a file called lan.list in /etc/pihole/
  • Add the following to the file
    • <pi-hole-ip-address> <pi-hole-fqdn>
    • e.g. 192.168.1.19 pihole.sfitpro.com
  • Create a second dnsmasq config file called 02-lan.conf in /etc/dnsmasq.d/
  • Add the following to the file to reference the lan.list file created above
    • addn-hosts=/etc/pihole/lan.list
  • Restart the DNS service on pi-hole$ sudo pihole restartdns
    • $ sudo pihole restartdns

Now when entering the Pi-hole FQDN in the browser, it will be redirected to the HTTPS page with a valid SSL certificate.

Match a string ending with a dollar sign ($) and containing a variable in PowerShell

In my previous post, I can match a string ending with a dollar sign ($) using the single quote with the expression ‘\$$’. Because the single quote protects the PowerShell automatic variable $$ from being evaluated. But it brings up my next question, how about the same expression also includes other variable that should be evaluated. Like this example.

PS C:\Temp> $name = 'smith'
PS C:\Temp>
PS C:\Temp> 'contoso\john.smith$' -match "$name"
True
PS C:\Temp> 'contoso\john.smith$' -match '$name'
False

Obviously, I have to use the double quote to evaluate the variable $name before sending the expression to the regex engine. But I also need the single quote for the variable $$.

PS C:\Temp> 'contoso\john.smith$' -match '$name\$$'
False
PS C:\Temp> 'contoso\john.smith$' -match "$name\$$"
False

Here is my solution - using double quote with both the regex escape character backslash(\) and PowerShell escape character backpack(`).

PS C:\Temp> 'contoso\john.smith$' -match "$name\$`$"
True

Let me explain
  • Use double quote to evaluate the variable $name
  • Use `$ to prevent the automatic variable $$. Using the PowerShell escape character (`) because it’s the PowerShell evaluation, not regex evaluation. So do not use \$ on the second $.
  • After the variable evaluation, the expression becomes smith\$$. This is passed to the regex engine. As expected, this regex matches the string ending with smith$.

Match a string ending with a dollar sign ($) in PowerShell

I want to match a string ending with a dollar sign ($) (e.g. ‘contoso\john.smith$’) in PowerShell. Using the regular expression (regex) should be simple, like \$$.

However, I run into some problem in PowerShell. I posted my question in Reddit for help. With the comments from the community, I think I finally understand how to handle this issue. This blog post is to summarize my understanding.
  • -match operator uses the regular expression syntax.
  • The scape character in regex is the backslash(\). Normally the regular PowerShell escape character, the backtick(`), should not use in the regex expression. See my next post on using both scape characters (\ and `) in one expression.
  • To match a string ending with a dollar sign ($), the regex should be \$$. The first $ is for the literal $, so it is escaped by \. The second $ is an anchor which matches the end of a string, so it is not escaped by \.
  • However $$ is an automatic variable in PowerShell.
  • When the expression(\$$) is doubled-quoted, PowerShell evaluates the variable $$ first before sending to the regex engine. “\$$” becomes “\{value of $$}” when being parsed by the regex engine. So it returns False.
PS C:\Temp> 'contoso\john.smith$' -match "\$$"
False
  • When the expression(\$$) is single-quoted, PowerShell does not evaluate any variable. The expression \$$ is parsed by the regex engine. So it returns True.
PS C:\Temp> 'contoso\john.smith$' -match '\$$'
True

In the case, I can match a string ending with $ by using the single quote with the expression '\$$'. However, this will not work if the expression includes other variable that should be evaluated. I will post my solution in the next post.

My Pi-hole blocklists

After setting up the Pi-hole on the Raspberry Pi, I start looking for additional blocklists to block as much as unnecessary traffic on my home network. 

Searching on the Pi-hole Userspace, I found many discussions about the blocklists. I want to share my blocklists on this post, so you can save time.
My goals are to use the blocklists that
  • Are from the reliable source
  • Are updated regularly
  • Provide additional filter categories that are safe for family
  • Are free of charge
As mentioned in my “Select Upstream DNS server for Pi-hole” post, I may be able to use OpenDNS or CleanBrowsing DNS as my upstream DNS server to achieve the same goals without using the blocklists. But these blocklists become necessary after I set up DoH with Cloudflare DNS because Cloudflare DNS doesn’t provide content filtering.

The following are the blocklists in my Pi-hole. You can copy and paste them under Pi-hole’s admin page, Settings, Blocklists, and click “Save and Update”.

At the time of this writing, these lists block over 3,900,000 unique domains. I have to admit some legit domains also being blocked, e.g. the Target.com's Weekly Ad. But they can be fairly easy to identify and add to the whitelist. I will share in a future post.

Please provide your feedback if you have a better list or issue with my list. I will keep the list up-to-date.

https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt
https://blocklist.site/app/dl/ads
https://blocklist.site/app/dl/crypto
https://blocklist.site/app/dl/drugs
https://blocklist.site/app/dl/fraud
https://blocklist.site/app/dl/fakenews
https://blocklist.site/app/dl/gambling
https://blocklist.site/app/dl/malware
https://blocklist.site/app/dl/phishing
https://blocklist.site/app/dl/piracy
https://blocklist.site/app/dl/porn
https://blocklist.site/app/dl/proxy
https://blocklist.site/app/dl/ransomware
https://blocklist.site/app/dl/redirect
https://blocklist.site/app/dl/scam
https://blocklist.site/app/dl/spam
https://blocklist.site/app/dl/tracking
https://dbl.oisd.nl/

Set up Cloudfared DoH for Pi-hole

I would prefer using DNS over HTTPS (DoH) to increase privacy and security. Mozilla Firefox is the first web browser implementing DoH, and many other browsers follow. But how can I utilize DoH for the non-browser DNS request or enable DoH on each device that connects to my home network?

Pi-hole has a document to configure DNS-Over-HTTPS. To automate the install and configure Cloudfared on a Raspberry Pi running Raspbian, I create a bash script. I also add the steps to lock down the cloudfared account.

Here are how set up Cloudfared DoH using the script.
  • Make sure the Pi-hole is set up on your Raspberry Pi. See my post “Set up Pi-hole on a Raspberry Pi”.
  • Download the script from my Github on your Raspberry Pi
    • curl -O https://raw.githubusercontent.com/sfitpro/pi-hole/master/setup.cloudflared.doh.for.pi-hole.sh
  • Grant the execution permission to the script
    • chmod +x setup.cloudflared.doh.for.pi-hole.sh
  • Run the script
    • sudo ./setup.cloudflared.doh.for.pi-hole.sh
  • Configure the Pi-hole to use custom Upstream DNS server 127.0.0.1#5053
If all the setup is correct, you will notice the DNS queries on Pi-hole are answered by localhost.


Select Upstream DNS server for Pi-hole

Once the Pi-hole is up and running, the first thing I want to configure is its upstream DNS servers. The upstream DNS servers can provide additional filters (e.g. adult-related sites, social networking sites, etc) that are not included in the Pi-hole default installation.
I have been using OpenDNS as my home router's upstream DNS servers for a long time. I sign up an OpenDNS account so I can customize the kind of content to block or the sites to be whitelisted. It works great.
On the Pi-hole admin page, under Settings —> DNS. It has a list of built-in upstream DNS servers, e.g. Google, OpenDNS, Quad9, Cloudflare, etc.

  • OpenDNS: OpenDNS is my original first choice since I have been using its filter for a long time as I mentioned above. My only concern with OpenDNS is that Cisco acquired OpenDNS in 2015; and not sure whether this free service will continue to be maintained. But I don’t have other good options at the time.
  • Google DNS: Google DNS has a relatively fast response time. It doesn’t provide content filtering. Google’s ad tracking business makes me stay away from its products when I can. So I stop using Google DNS.
  • Cloudflare DNS: Cloudflare DNS has a fast response time. It doesn’t provide content filtering. After knowing Mozilla includes Cloudflare DoH in their newer version of Firefox, I trust Cloudflare’s privacy practice. Combining with Pi-hole other filtering feature, I switch to Cloudflare DNS as my upstream DNS servers until I learn about CleanBrowsing DNS.
  • CleanBrowsing DNS: CleanBrowsing DNS’s free filters (Security, Adult, and Family) are silmiar to OpenDNS, except the free plan doesn’t offer custom filters (e.g. gaming, grambling, etc). However, its free adult or family filter can filter the search engines (Google and Bing) result in safe mode, which I don’t see in other DNS filter. So CleanBrowsing DNS’s audlt filter is my choice for the Pi-hole upstream DNS at the home network. (PS. the family filter blocks Reddit site. I agree some contents on Reddit is not appropriate, but it also has many good technical disucssion.)
CleanBrowsing DNS setup on Pi-hole
  • http://<pihole.ip.address>/admin
  • Setting, DNS, Upstream DNS Servers
  • Custom 1 (IPv4): 185.228.168.10
  • Custom 2 (IPv4): 185.228.169.11

Set up Pi-hole on a Raspberry Pi

My first and main usage for a Raspberry Pi is to set up Pi-hole to block Ad for all devices on my home network.

Installation

The Pi-hole instalaltion is simple.

curl -sSL https://install.pi-hole.net | bash

Basic operation command

  • check status
    • sudo pihole status
  • check version
    • sudo pihole -v
  • update Pi-hole
    • sudo pihole -up
  • change Pi-hole admin password
    • sudo pihole -a -p
  • update Pi-hole filter list (gravity.list)
    • sudo pihole -g
  • restart Pi-hole
    • sudo pihole restartdns
  • list domains in whilelist
    • sudo pihole -w -l
  • add a domain to whitelist
    • sudo pihole -w <domain>
  • remove a domain from whitelist
    • sudo pihole -w -d <domain>
  • list domains in blacklist
    • sudo pihole -b -l

Once the pi-hole is up and running, we can change the the DNS setting of the router’s DHCP to the pi-hole IP address, or manaully set it to the devices with the static IP address.

Pi-hole comes the default ad block list. I will discuss the selection of Upstream DNS servers and add additional filter in the next post.

Use WinSCP to Transfer Files in vCSA 6.7

This is a quick update on my previous post “ Use WinSCP to Transfer Files in vCSA 6.5 ”. When I try the same SFTP server setting in vCSA 6.7...