Jekyll2021-05-22T21:52:37-05:00https://labzilla.io/feed.xmlLabZillaLabzilla
LabZillaBlock ads on your mobile device with DNS over HTTPS2021-03-26T00:00:00-05:002021-03-26T00:00:00-05:00https://labzilla.io/blog/adguard-dns-over-https<p>DNS over HTTPS (DoH) is a relatively new protocol for performing DNS queries over the HTTPS protocol. With iOS 14 (and macOS Big Sur) now natively supporting DoH, you can now force your device to use a custom DNS server - even while you’re using cellular data. You’re no longer stuck using whatever DNS server your cellular carrier maintains.</p>
<p>Previously, the only way around a cellular carrier’s hard-coded DNS settings was to use a VPN to tunnel your traffic - a massive hassle. VPN is tricky to set up correctly, can be somewhat flakey while using cellular data, and negatively impacts both device battery life and connection speed. DoH is a massive improvement.</p>
<p>You don’t even need to run your own DoH server to take advantage of this new feature; there are plenty of public DoH servers and websites with <a href="https://encrypted-dns.party">pre-built configuration profiles</a>. However, if you value privacy and the ability to tweak exactly which blocklists are used, setting up your own DoH server is relatively painless.</p>
<h1 id="instructions">Instructions</h1>
<p>While I’ve previously <a href="/blog/force-dns-pihole">used PiHole at home</a>, it doesn’t include a DoH server out of the box. It’s possible to combine PiHole with <a href="https://facebookexperimental.github.io/doh-proxy/">DoH Proxy</a>, however it adds quite a bit of complexity.</p>
<p>A much simpler solution is <a href="https://adguard.com/en/adguard-home/overview.html">AdGuard Home</a> - an open source ad-blocking DNS server that is functionally the same as PiHole when it comes to blocking ads.
In order to get this working, you will need to have:</p>
<ul>
<li>Your own domain name, with the ability to configure a subdomain.</li>
<li>A virtual private server to run Docker & AdGuard Home on.
<ul>
<li>For Digital Ocean, the $5 base droplet is more than adequate.</li>
</ul>
</li>
</ul>
<p>Any VPS provider should be able to handle AdGuard Home. I spun up a virtual machine on my colo server, but AWS, Linode, Vultr, etc would all work just as well. If you’re a new Digital Ocean customer, feel free to use my <a href="https://m.do.co/c/8256b215eb23">referral link</a> to get a free $100 credit.</p>
<p class="warning">For the purposes of this tutorial, I’m using the subdomain <code class="language-plaintext highlighter-rouge">dns.labzilla.io</code>. You should replace this subdomain with your own in the instructions below.</p>
<h2 id="create-your-virtual-machine">Create your Virtual Machine</h2>
<p>Create and deploy a virtual machine/droplet. For this tutorial, I’m using Digital Ocean to host an Ubuntu 18.04 droplet. Make a note of the IPv4/IPv6 addresses of your new virtual machine/droplet.</p>
<h4 id="get-an-ipv6-address-if-you-are-able">Get an IPv6 address if you are able</h4>
<p>If it’s available on your VPS provider, you should request an IPv6 address as well as an IPv4 address. If you’re using Digital Ocean, check the IPv6 box under <em>Additional Options</em> when creating your droplet (otherwise you’ll need to <a href="https://www.digitalocean.com/docs/networking/ipv6/how-to/enable/#on-existing-droplets">manually configure</a> the IPv6 interface).</p>
<ul>
<li>Most cellular carriers are running IPv6 networks and use carrier-grade NAT for IPv4 traffic. Having an IPv6 address allows you to bypass this, and should theoretically improve performance.</li>
</ul>
<h2 id="specify-your-subdomain">Specify your subdomain</h2>
<p>Log in to your domain registrar, and configure a new DNS record to point to your server’s IP address. If you have an IPv6 address, don’t forget to create an AAAA record as well. If you’re using Cloudflare, make sure that their proxying is turned off.</p>
<p><img src="/assets/adguard-dns-cloudflare.png" alt="" /></p>
<h2 id="get-an-ssl-certificate">Get an SSL Certificate</h2>
<p>We’re using LetsEncrypt + Certbot to automatically request an SSL certificate for our AdGuard Home server.</p>
<p>SSH into your new virtual machine and use the command <code class="language-plaintext highlighter-rouge">sudo apt-get install certbot</code> to install <a href="https://certbot.eff.org">Certbot</a>.</p>
<ul>
<li>Start Certbot with the command <code class="language-plaintext highlighter-rouge">certbot certonly</code>. When prompted, choose option 1 (spin up a temporary webserver).</li>
<li>Follow the rest of the prompts to obtain your server’s SSL certificate. Be sure to use the full subdomain that you created.</li>
<li>When the process is finished, note the location of your certificate and key file (usually <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem</code> and <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/dns.labzilla.io/privkey.pem</code>) respectively.</li>
</ul>
<h2 id="install-docker">Install Docker</h2>
<p>Docker is the easiest way to install AdGuard Home. It allows us to expose only the bare minimum ports necessary for AdGuard Home to operate. Rather than re-inventing the wheel, <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04">follow this excellent tutorial</a> and come back when you’re finished.</p>
<h2 id="enable-ipv6-support-in-docker">Enable IPv6 support in Docker</h2>
<p>If you don’t have an IPv6 address, you can skip this step. Otherwise, if it doesn’t exist already, create a file at <code class="language-plaintext highlighter-rouge">/etc/docker/daemon.json</code> and add the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
"ipv6": true,
"fixed-cidr-v6": "fd00::/80"
}
</code></pre></div></div>
<p>Save and close the file, and then restart Docker by running <code class="language-plaintext highlighter-rouge">systemctl restart docker</code>.</p>
<h2 id="install-adguard-home">Install AdGuard Home</h2>
<p>Now that Docker is installed, we can install Adguard Home:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run --name adguardhome \
-v adguard-work:/opt/adguardhome/work \
-v adguard-conf:/opt/adguardhome/conf \
-v /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem:/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem \
-v /etc/letsencrypt/live/dns.labzilla.io/privkey.pem:/etc/letsencrypt/live/dns.labzilla.io/privkey.pem \
-p 3000:3000/tcp \
-p 443:443/tcp \
-p 80:80/tcp \
-d --restart unless-stopped \
adguard/adguardhome
</code></pre></div></div>
<p>Be sure to modify the above commands to properly reference where your SSL certificate is stored.</p>
<h2 id="configure-adguard-home">Configure AdGuard Home</h2>
<p>Access your new AdGuard instance by navigating to <code class="language-plaintext highlighter-rouge">http://dns.labzilla.io:3000</code> in a browser. Follow the setup wizard to create a new account; don’t change anything from the default settings. After creating your new account, log in using the username and password you created.</p>
<h3 id="ssl-configuration">SSL Configuration</h3>
<p>Now that AdGuard Home is running, we need to configure it to use the SSL certificate we requested from Let’s Encrypt.</p>
<ul>
<li>
<p>In the AdGuard Home admin panel, navigate to <em>Settings</em> > <em>Encryption Settings</em>.</p>
</li>
<li>
<p>Check the <em>Enable Encryption</em> box, and enter your server name (<code class="language-plaintext highlighter-rouge">dns.labzilla.io</code>). Check the <em>Redirect to HTTPS automatically</em> box.</p>
</li>
</ul>
<p><img src="/assets/adguard-dns-encryptionsettings1.png" alt="" /></p>
<ul>
<li>
<p>Under Certificates, chose <em>Set a certificates file path</em> and paste in <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem</code>.</p>
</li>
<li>
<p>Under Private Key, choose <em>Set a private key file</em> and paste in <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/dns.labzilla.io/privkey.pem</code>.</p>
</li>
</ul>
<p><img src="/assets/adguard-dns-encryptionsettings2.png" alt="" /></p>
<ul>
<li>Click <em>Save Config</em>. You should be automatically redirected to the HTTPS version of the AdGuard admin panel. When logging in to the admin panel in the future, use <code class="language-plaintext highlighter-rouge">https://dns.labzilla.io</code> (no port number).</li>
</ul>
<h3 id="other-settings">Other Settings</h3>
<p>You probably will want to modify your upstream & bootstrap DNS servers in <em>Settings</em> > <em>DNS Settings</em>; I use 1.1.1.1 for both. You’ll definitely want to add your own blocklists; they’re configured under <em>Filters</em> > <em>DNS blocklists</em> (and are compatible with PiHole blocklists).</p>
<h2 id="download-the-mobile-configuration-profile">Download the mobile configuration profile</h2>
<p>DNS over HTTPS is not configurable from within iOS settings or macOS system preferences. Instead, a mobile configuration profile is used to configure your device. AdGuard Home automatically generates a valid configuration profile with the appropriate settings. AdGuard Home’s website is mobile friendly, so it’s actually easiest to complete this step right from your iOS device. Alternatively, you can download the mobile configuration profile on your macOS device, and use AirDrop to transfer it.</p>
<ul>
<li>In the AdGuard admin panel, tap <em>Setup Guide</em>, and then tap <em>DNS Privacy</em>.
<ul>
<li>If you’re on a mobile device, you may need to swipe left on the section with the icons for Router, Windows, macOS, etc. to see the DNS Privacy Option.</li>
</ul>
</li>
</ul>
<p><img src="/assets/adguard-dns-setupguide1.png" alt="" /></p>
<ul>
<li>At the bottom of the page, under <em>iOS and macOS Configuration</em>, enter in the host name (dns.labzilla.io) and optionally a client ID (no spaces or symbols).</li>
<li>Tap the green <em>Download Configuration File</em> button. Tap <em>Allow</em> if prompted by your device.</li>
</ul>
<p><img src="/assets/adguard-dns-setupguide2.png" alt="" /></p>
<ul>
<li>Install the configuration profile by navigating to <em>Settings</em> > <em>Profile Downloaded</em>.</li>
<li>Tap <em>Install</em>, and then tap <em>Install</em> (again) to complete the installation.</li>
</ul>
<p><img src="/assets/adguard-dns-setupguide3.png" alt="" /></p>
<p>To verify the DNS settings were correctly applied, open Settings and tap <em>VPN & Network</em>. A new section for DNS should be at the bottom of the window. Reverting the setting to <em>Automatic</em> will switch you back to your cellular provider’s DNS server. You should also see DNS queries from your device reflected in the query log inside AdGuard Home.</p>
<h2 id="recreate-docker-container">Recreate Docker container</h2>
<p>Now that AdGuard Home as been configured, you no longer need to have ports 3000 or port 80 open to traffic.</p>
<p>The easiest way to address this is to delete and re-create the container. All of your configuration will be preserved.</p>
<p>Run the following commands to stop AdGuard Home and remove the existing container.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">docker container stop adguardhome</code></li>
<li><code class="language-plaintext highlighter-rouge">docker container rm adguardhome</code></li>
</ul>
<p>Recreate the container with the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run --name adguardhome \
-v adguard-work:/opt/adguardhome/work \
-v adguard-conf:/opt/adguardhome/conf \
-v /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem:/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem \
-v /etc/letsencrypt/live/dns.labzilla.io/privkey.pem:/etc/letsencrypt/live/dns.labzilla.io/
-p 443:443/tcp \
-d --restart unless-stopped \
adguard/adguardhome
</code></pre></div></div>
<p>You’ll notice that in this new configuration, only port 443 (HTTPS) is open to the outside world.</p>
<h2 id="test-it-out">Test it out</h2>
<p>You should see entries filling up the query log in AdGuard Home.</p>
<p>If you don’t, double check to make sure the configuration profile is installed, and then check Settings > VPN & Network > DNS to make sure that your device knows to use your new AdGuard Home server for DNS queries.</p>
<h3 id="removing-the-profile">Removing the profile</h3>
<p>If you need to completely remove the DoH configuration profile from your device, it’s relatively straightforward.</p>
<ul>
<li><strong>iOS/iPadOS:</strong> Go to <em>Settings</em> > <em>General</em> > <em>Profiles and Device Management</em>. Locate the profile, and tap <em>Remove Profile</em>.</li>
<li><strong>macOS:</strong> <em>System Preferences</em> > <em>Profiles</em>. Locate the profile, and click the minus icon to remove it.</li>
</ul>
<h1 id="advanced-configuration">Advanced configuration</h1>
<p>AdGuard Home generates a very basic configuration profile that enables DNS over HTTPS on iOS/macOS devices. The profile that is generated is always on, unless you manually turn it off by switching back to automatic DNS settings.</p>
<p>You don’t have to use the configuration profile that AdGuard Home generates - the DNS query string (<code class="language-plaintext highlighter-rouge">https://dns.labzilla.io/dns-query</code>) is the important part. You can <a href="https://neilzone.co.uk/2021/03/dns-over-https-on-macos-and-ios">create your own</a> configuration profile (or modify the one AdGuard Home generates) to create more complex rules. For example, the <a href="https://github.com/labzilla/mobileconfig-profiles/blob/main/dns-over-doh.mobileconfig">configuration profile</a> I currently use is set up to automatically switch back to the DNS server provided by my router’s DHCP server when I’m on my home network.</p>LabZillaDNS over HTTPS (DoH) is a relatively new protocol for performing DNS queries over the HTTPS protocol. With iOS 14 (and macOS Big Sur) now natively supporting DoH, you can now force your device to use a custom DNS server - even while you’re using cellular data. You’re no longer stuck using whatever DNS server your cellular carrier maintains. Previously, the only way around a cellular carrier’s hard-coded DNS settings was to use a VPN to tunnel your traffic - a massive hassle. VPN is tricky to set up correctly, can be somewhat flakey while using cellular data, and negatively impacts both device battery life and connection speed. DoH is a massive improvement. You don’t even need to run your own DoH server to take advantage of this new feature; there are plenty of public DoH servers and websites with pre-built configuration profiles. However, if you value privacy and the ability to tweak exactly which blocklists are used, setting up your own DoH server is relatively painless. Instructions While I’ve previously used PiHole at home, it doesn’t include a DoH server out of the box. It’s possible to combine PiHole with DoH Proxy, however it adds quite a bit of complexity. A much simpler solution is AdGuard Home - an open source ad-blocking DNS server that is functionally the same as PiHole when it comes to blocking ads. In order to get this working, you will need to have: Your own domain name, with the ability to configure a subdomain. A virtual private server to run Docker & AdGuard Home on. For Digital Ocean, the $5 base droplet is more than adequate. Any VPS provider should be able to handle AdGuard Home. I spun up a virtual machine on my colo server, but AWS, Linode, Vultr, etc would all work just as well. If you’re a new Digital Ocean customer, feel free to use my referral link to get a free $100 credit. For the purposes of this tutorial, I’m using the subdomain dns.labzilla.io. You should replace this subdomain with your own in the instructions below. Create your Virtual Machine Create and deploy a virtual machine/droplet. For this tutorial, I’m using Digital Ocean to host an Ubuntu 18.04 droplet. Make a note of the IPv4/IPv6 addresses of your new virtual machine/droplet. Get an IPv6 address if you are able If it’s available on your VPS provider, you should request an IPv6 address as well as an IPv4 address. If you’re using Digital Ocean, check the IPv6 box under Additional Options when creating your droplet (otherwise you’ll need to manually configure the IPv6 interface). Most cellular carriers are running IPv6 networks and use carrier-grade NAT for IPv4 traffic. Having an IPv6 address allows you to bypass this, and should theoretically improve performance. Specify your subdomain Log in to your domain registrar, and configure a new DNS record to point to your server’s IP address. If you have an IPv6 address, don’t forget to create an AAAA record as well. If you’re using Cloudflare, make sure that their proxying is turned off. Get an SSL Certificate We’re using LetsEncrypt + Certbot to automatically request an SSL certificate for our AdGuard Home server. SSH into your new virtual machine and use the command sudo apt-get install certbot to install Certbot. Start Certbot with the command certbot certonly. When prompted, choose option 1 (spin up a temporary webserver). Follow the rest of the prompts to obtain your server’s SSL certificate. Be sure to use the full subdomain that you created. When the process is finished, note the location of your certificate and key file (usually /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem and /etc/letsencrypt/live/dns.labzilla.io/privkey.pem) respectively. Install Docker Docker is the easiest way to install AdGuard Home. It allows us to expose only the bare minimum ports necessary for AdGuard Home to operate. Rather than re-inventing the wheel, follow this excellent tutorial and come back when you’re finished. Enable IPv6 support in Docker If you don’t have an IPv6 address, you can skip this step. Otherwise, if it doesn’t exist already, create a file at /etc/docker/daemon.json and add the following: { "ipv6": true, "fixed-cidr-v6": "fd00::/80" } Save and close the file, and then restart Docker by running systemctl restart docker. Install AdGuard Home Now that Docker is installed, we can install Adguard Home: docker run --name adguardhome \ -v adguard-work:/opt/adguardhome/work \ -v adguard-conf:/opt/adguardhome/conf \ -v /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem:/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem \ -v /etc/letsencrypt/live/dns.labzilla.io/privkey.pem:/etc/letsencrypt/live/dns.labzilla.io/privkey.pem \ -p 3000:3000/tcp \ -p 443:443/tcp \ -p 80:80/tcp \ -d --restart unless-stopped \ adguard/adguardhome Be sure to modify the above commands to properly reference where your SSL certificate is stored. Configure AdGuard Home Access your new AdGuard instance by navigating to http://dns.labzilla.io:3000 in a browser. Follow the setup wizard to create a new account; don’t change anything from the default settings. After creating your new account, log in using the username and password you created. SSL Configuration Now that AdGuard Home is running, we need to configure it to use the SSL certificate we requested from Let’s Encrypt. In the AdGuard Home admin panel, navigate to Settings > Encryption Settings. Check the Enable Encryption box, and enter your server name (dns.labzilla.io). Check the Redirect to HTTPS automatically box. Under Certificates, chose Set a certificates file path and paste in /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem. Under Private Key, choose Set a private key file and paste in /etc/letsencrypt/live/dns.labzilla.io/privkey.pem. Click Save Config. You should be automatically redirected to the HTTPS version of the AdGuard admin panel. When logging in to the admin panel in the future, use https://dns.labzilla.io (no port number). Other Settings You probably will want to modify your upstream & bootstrap DNS servers in Settings > DNS Settings; I use 1.1.1.1 for both. You’ll definitely want to add your own blocklists; they’re configured under Filters > DNS blocklists (and are compatible with PiHole blocklists). Download the mobile configuration profile DNS over HTTPS is not configurable from within iOS settings or macOS system preferences. Instead, a mobile configuration profile is used to configure your device. AdGuard Home automatically generates a valid configuration profile with the appropriate settings. AdGuard Home’s website is mobile friendly, so it’s actually easiest to complete this step right from your iOS device. Alternatively, you can download the mobile configuration profile on your macOS device, and use AirDrop to transfer it. In the AdGuard admin panel, tap Setup Guide, and then tap DNS Privacy. If you’re on a mobile device, you may need to swipe left on the section with the icons for Router, Windows, macOS, etc. to see the DNS Privacy Option. At the bottom of the page, under iOS and macOS Configuration, enter in the host name (dns.labzilla.io) and optionally a client ID (no spaces or symbols). Tap the green Download Configuration File button. Tap Allow if prompted by your device. Install the configuration profile by navigating to Settings > Profile Downloaded. Tap Install, and then tap Install (again) to complete the installation. To verify the DNS settings were correctly applied, open Settings and tap VPN & Network. A new section for DNS should be at the bottom of the window. Reverting the setting to Automatic will switch you back to your cellular provider’s DNS server. You should also see DNS queries from your device reflected in the query log inside AdGuard Home. Recreate Docker container Now that AdGuard Home as been configured, you no longer need to have ports 3000 or port 80 open to traffic. The easiest way to address this is to delete and re-create the container. All of your configuration will be preserved. Run the following commands to stop AdGuard Home and remove the existing container. docker container stop adguardhome docker container rm adguardhome Recreate the container with the following: docker run --name adguardhome \ -v adguard-work:/opt/adguardhome/work \ -v adguard-conf:/opt/adguardhome/conf \ -v /etc/letsencrypt/live/dns.labzilla.io/fullchain.pem:/etc/letsencrypt/live/dns.labzilla.io/fullchain.pem \ -v /etc/letsencrypt/live/dns.labzilla.io/privkey.pem:/etc/letsencrypt/live/dns.labzilla.io/ -p 443:443/tcp \ -d --restart unless-stopped \ adguard/adguardhome You’ll notice that in this new configuration, only port 443 (HTTPS) is open to the outside world. Test it out You should see entries filling up the query log in AdGuard Home. If you don’t, double check to make sure the configuration profile is installed, and then check Settings > VPN & Network > DNS to make sure that your device knows to use your new AdGuard Home server for DNS queries. Removing the profile If you need to completely remove the DoH configuration profile from your device, it’s relatively straightforward. iOS/iPadOS: Go to Settings > General > Profiles and Device Management. Locate the profile, and tap Remove Profile. macOS: System Preferences > Profiles. Locate the profile, and click the minus icon to remove it. Advanced configuration AdGuard Home generates a very basic configuration profile that enables DNS over HTTPS on iOS/macOS devices. The profile that is generated is always on, unless you manually turn it off by switching back to automatic DNS settings. You don’t have to use the configuration profile that AdGuard Home generates - the DNS query string (https://dns.labzilla.io/dns-query) is the important part. You can create your own configuration profile (or modify the one AdGuard Home generates) to create more complex rules. For example, the configuration profile I currently use is set up to automatically switch back to the DNS server provided by my router’s DHCP server when I’m on my home network.Samsung TV Stops Automatically Connecting to Samsung Bluetooth Soundbar2021-01-31T00:00:00-06:002021-01-31T00:00:00-06:00https://labzilla.io/blog/samsung-soundbar-bluetooth-issues<p>I have a <a href="https://www.samsung.com/us/support/owners/product/2016-uhd-smart-tv-ku6300">Samsung KU6300</a> series smart TV which I bought from Best Buy a few years ago, along with a <a href="https://www.samsung.com/us/support/owners/product/2017-soundbar-w-wireless-subwoofer-hw-mm55">Samsung MM55</a> soundbar that I picked up from Costco.</p>
<p>The soundbar pairs with the TV via bluetooth, and automatically turns on with the television. The only connection to the soundbar is for power - I do not use HDMI ARC, optical input, etc. This works fantastically well with no noticeable lag/delay - until it doesn’t.</p>
<p>Every few months, the soundbar will still paired, but will refuse to turn on with the TV and connect. I have to manually turn the soundbar on, and then manually switch the TV sound output to the soundbar.</p>
<p>Here’s how to get it working again:</p>
<ol>
<li>Turn on the soundbar.</li>
<li>On the soundbar remote, press the source/input button until the soundbar display says <em>BT Ready</em>.</li>
<li>On the soundbar remote, press and hold the play/pause button for 5 seconds, until the soundbar display says <em>ON - TV Remote</em>.</li>
</ol>LabZillaI have a Samsung KU6300 series smart TV which I bought from Best Buy a few years ago, along with a Samsung MM55 soundbar that I picked up from Costco. The soundbar pairs with the TV via bluetooth, and automatically turns on with the television. The only connection to the soundbar is for power - I do not use HDMI ARC, optical input, etc. This works fantastically well with no noticeable lag/delay - until it doesn’t. Every few months, the soundbar will still paired, but will refuse to turn on with the TV and connect. I have to manually turn the soundbar on, and then manually switch the TV sound output to the soundbar. Here’s how to get it working again: Turn on the soundbar. On the soundbar remote, press the source/input button until the soundbar display says BT Ready. On the soundbar remote, press and hold the play/pause button for 5 seconds, until the soundbar display says ON - TV Remote.macOS Jumpcloud LDAP Configuration2021-01-21T00:00:00-06:002021-01-21T00:00:00-06:00https://labzilla.io/blog/jumpcloud-ldap-bind<p>I’ve been toying with the idea of setting up a directory server to handle authentication across my entire network. However, setting up a LDAP or Active Directory server comes with it’s own challenges around ensuring availablility, backups, etc. I have a somewhat complex network - three different sites, and multiple off-site users connecting via VPN - and the directory server would need to be available 24x7x365. I don’t really want to deal with the hassle, so I’m testing out a “directory-as-a-service provider” called <a href="https://jumpcloud.com">Jumpcloud</a>.</p>
<p>Jumpcloud is free for up to 10 users, and offers a cloud LDAP service that is completely hands-off. They even have a desktop agent that allows Jumpcloud to manage local user accounts - seamlessly syncing them up to Jumpcloud’s directory.</p>
<p>However, macOS supports LDAP natively, so I was curious if it was possible to skip using Jumpcloud’s agent and configure macOS to authenticate directly to Jumpcloud’s LDAP servers.</p>
<p class="error">This is not a supported configuration, only a proof of concept. Use the Jumpcloud agent in any production environment.</p>
<h1 id="create-your-account-in-jumpcloud">Create your account in Jumpcloud</h1>
<p>Sign up for Jumpcloud, and <a href="https://support.jumpcloud.com/support/s/article/using-jumpclouds-ldap-as-a-service1">create an account in your Jumpcloud directory</a>. Make sure that under permission settings, <em>Enable as LDAP Bind DN</em> is selected.</p>
<p>Find your Organization ID under the Settings tab, and copy it down for later use.</p>
<h1 id="configure-macos-ldap-settings">Configure macOS LDAP settings</h1>
<p>Open up System Preferences, and click Users and Groups. Unlock the preferences pane, and then click on Login Options.</p>
<p><img src="/assets/jumpcloud-ldap-bind/systempreferences-loginoptions.png" alt="" /></p>
<p>Click on the “Join” button next to Network Account Server. Click on the Open Directory Utility button in the bottom left.</p>
<p><img src="/assets/jumpcloud-ldap-bind/opendirectoryutility.png" alt="" /></p>
<p>In the Directory Utility window, unlock the preferences pane. Select LDAPv3, and then click on the pencil icon in the bottom left.</p>
<p><img src="/assets/jumpcloud-ldap-bind/ldapv3.png" alt="" /></p>
<p>Click on New, and enter <code class="language-plaintext highlighter-rouge">ldap.jumpcloud.com</code> for the server name. Check the SSL box, and then click Manual. Click Edit.</p>
<p>Under the Search & Mappings tab, choose RFC2307 from the dropdown at the top of the window (note that this will change to custom after we make changes). Enter in the following for search base suffix:<code class="language-plaintext highlighter-rouge">ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com</code></p>
<p>Note: Replace <code class="language-plaintext highlighter-rouge">YOUR_ORG_ID</code> with your organization ID, <a href="https://support.jumpcloud.com/support/s/article/Admin-Portal-General-Settings">which you can find in the Jumpcloud admin portal</a>.</p>
<p><img src="/assets/jumpcloud-ldap-bind/searchbasesuffix.png" alt="" /></p>
<p>Under Record Types and Attributes, select “Users” and click + button on the left hand side.</p>
<p><img src="/assets/jumpcloud-ldap-bind/usersrecordtypes.png" alt="" /></p>
<p>Select <em>GeneratedUID</em> and click OK.</p>
<p><img src="/assets/jumpcloud-ldap-bind/usersrecord-generateduid.png" alt="" /></p>
<p>Ensure that GeneratedUID is selected in the left-side list, and then click on the plus icon on the right side. Enter <code class="language-plaintext highlighter-rouge">apple-generateduid</code> in the text box, and then press enter.</p>
<p><img src="/assets/jumpcloud-ldap-bind/users-generateduid-2.png" alt="" /></p>
<p>In the list on the left-hand side, select the NFSHomeDirectory attribute. Modify the value for this attribute to <code class="language-plaintext highlighter-rouge">#/Users/$uid$</code></p>
<p><img src="/assets/jumpcloud-ldap-bind/users-nfshomedirectory.png" alt="" /></p>
<p>Switch to the Security tab, and check the “Use Authentication When Connecting” box. Under Distinguished Name, enter <code class="language-plaintext highlighter-rouge">uid=username,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com</code>. Enter the account password, and click OK. Click OK again.</p>
<p><img src="/assets/jumpcloud-ldap-bind/securitytab.png" alt="" /></p>
<p>Back in the Directory Utility window, click on Search Policy, and then click the plus icon in the bottom left. Select the Jumpcloud LDAP server, and then click Add. Click Apply, and then authenticate with your local system account to save the settings.</p>
<p><img src="/assets/jumpcloud-ldap-bind/searchpolicy2.png" alt="" /></p>
<p>You should now be able to log in using a Jumpcloud LDAP account.</p>
<h1 id="caveats">Caveats</h1>
<ul>
<li>
<p>LDAP accounts are not administrator accounts. You will need to manually grant yourself administrator rights after logging in.</p>
</li>
<li>
<p>If you don’t have a network connection (that can reach Jumpcloud’s LDAP servers), you won’t be able to log in to your Mac. You can <a href="https://support.apple.com/guide/mac-help/create-and-configure-mobile-accounts-mh32157/mac">manually create a mobile account</a> to allow you to authenticate off network.</p>
</li>
</ul>LabZillaI’ve been toying with the idea of setting up a directory server to handle authentication across my entire network. However, setting up a LDAP or Active Directory server comes with it’s own challenges around ensuring availablility, backups, etc. I have a somewhat complex network - three different sites, and multiple off-site users connecting via VPN - and the directory server would need to be available 24x7x365. I don’t really want to deal with the hassle, so I’m testing out a “directory-as-a-service provider” called Jumpcloud. Jumpcloud is free for up to 10 users, and offers a cloud LDAP service that is completely hands-off. They even have a desktop agent that allows Jumpcloud to manage local user accounts - seamlessly syncing them up to Jumpcloud’s directory. However, macOS supports LDAP natively, so I was curious if it was possible to skip using Jumpcloud’s agent and configure macOS to authenticate directly to Jumpcloud’s LDAP servers. This is not a supported configuration, only a proof of concept. Use the Jumpcloud agent in any production environment. Create your account in Jumpcloud Sign up for Jumpcloud, and create an account in your Jumpcloud directory. Make sure that under permission settings, Enable as LDAP Bind DN is selected. Find your Organization ID under the Settings tab, and copy it down for later use. Configure macOS LDAP settings Open up System Preferences, and click Users and Groups. Unlock the preferences pane, and then click on Login Options. Click on the “Join” button next to Network Account Server. Click on the Open Directory Utility button in the bottom left. In the Directory Utility window, unlock the preferences pane. Select LDAPv3, and then click on the pencil icon in the bottom left. Click on New, and enter ldap.jumpcloud.com for the server name. Check the SSL box, and then click Manual. Click Edit. Under the Search & Mappings tab, choose RFC2307 from the dropdown at the top of the window (note that this will change to custom after we make changes). Enter in the following for search base suffix:ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com Note: Replace YOUR_ORG_ID with your organization ID, which you can find in the Jumpcloud admin portal. Under Record Types and Attributes, select “Users” and click + button on the left hand side. Select GeneratedUID and click OK. Ensure that GeneratedUID is selected in the left-side list, and then click on the plus icon on the right side. Enter apple-generateduid in the text box, and then press enter. In the list on the left-hand side, select the NFSHomeDirectory attribute. Modify the value for this attribute to #/Users/$uid$ Switch to the Security tab, and check the “Use Authentication When Connecting” box. Under Distinguished Name, enter uid=username,ou=Users,o=YOUR_ORG_ID,dc=jumpcloud,dc=com. Enter the account password, and click OK. Click OK again. Back in the Directory Utility window, click on Search Policy, and then click the plus icon in the bottom left. Select the Jumpcloud LDAP server, and then click Add. Click Apply, and then authenticate with your local system account to save the settings. You should now be able to log in using a Jumpcloud LDAP account. Caveats LDAP accounts are not administrator accounts. You will need to manually grant yourself administrator rights after logging in. If you don’t have a network connection (that can reach Jumpcloud’s LDAP servers), you won’t be able to log in to your Mac. You can manually create a mobile account to allow you to authenticate off network.2019 MacBook Pro + Radeon 5500m Issues2020-12-11T00:00:00-06:002020-12-11T00:00:00-06:00https://labzilla.io/blog/2019-macbook-pro-gpu-issues<p>This post is to document a handful of issues I’ve experienced with my 2019 MacBook Pro surrounding the GPU.</p>
<p><strong>System Specs</strong></p>
<ul>
<li><strong>Mac</strong>: 2019 16” MacBook Pro</li>
<li><strong>GPU</strong>: AMD Radeon Pro 5500M</li>
<li><strong>Monitors</strong>: Dell U2718Q 27” 4K (x2)</li>
<li><strong>Dock</strong>: CalDigit TS3 Plus</li>
</ul>
<p><strong>Symptoms</strong></p>
<ul>
<li>Laptop runs hot and fans kick on.
<ul>
<li>Eventually, the GPU may fail.</li>
</ul>
</li>
<li>iStat Menus shows “Radeon High Side” power draw at ~19 watts.</li>
</ul>
<p><strong>Forum Threads</strong></p>
<ul>
<li>Massive MacRumors <a href="https://forums.macrumors.com/threads/16-is-hot-noisy-with-an-external-monitor.2211747/">thread</a> is the main thread on this issue.</li>
</ul>
<p><strong>Solution</strong></p>
<p>This appears to be caused by buggy drivers. After restart, identical monitors will connect at different refresh rates (30hz and 60hz). Use a tool like SwitchResX or <a href="https://github.com/avibrazil/RDM">RDM</a> to force the monitors back to 60hz. Radeon High Side power draw should drop back down to 7-8 watts.</p>LabZillaThis post is to document a handful of issues I’ve experienced with my 2019 MacBook Pro surrounding the GPU. System Specs Mac: 2019 16” MacBook Pro GPU: AMD Radeon Pro 5500M Monitors: Dell U2718Q 27” 4K (x2) Dock: CalDigit TS3 Plus Symptoms Laptop runs hot and fans kick on. Eventually, the GPU may fail. iStat Menus shows “Radeon High Side” power draw at ~19 watts. Forum Threads Massive MacRumors thread is the main thread on this issue. Solution This appears to be caused by buggy drivers. After restart, identical monitors will connect at different refresh rates (30hz and 60hz). Use a tool like SwitchResX or RDM to force the monitors back to 60hz. Radeon High Side power draw should drop back down to 7-8 watts.Your Smart TV is probably ignoring your PiHole2020-11-09T00:00:00-06:002020-11-09T00:00:00-06:00https://labzilla.io/blog/force-dns-pihole<p class="warning"><span style="color: #F48120;"><i class="fab fa-hacker-news"></i></span> <strong>Welcome Hacker News readers!</strong><br />
<strong>•</strong> Thank you to <a href="https://homepage.cs.uiowa.edu/~mmazhar/">M. Hammad Mazhar</a> for his <a href="https://arxiv.org/pdf/2001.08288.pdf">research</a> that inspired this guide.<br />
<strong>•</strong> <a href="https://twitter.com/healeyio">@healyio</a> made some great additional suggestions in this Twitter <a href="https://twitter.com/healeyio/status/1335347122649006080">thread</a> which I incoporated in the DNS over TLS/HTTPS <a href="#dns-over-tlshttps">section</a>.<br />
<strong>•</strong> The HN <a href="https://news.ycombinator.com/item?id=25313480">comment thread</a> is full of insightful comments from individuals who work on IoT hardware and other embedded devices, and is well worth a read.<br />
<strong>•</strong> Finally, you can subscribe to the <a href="/feed.xml">RSS feed</a> or follow on <a href="https://twitter.com/labzilla">Twitter</a> for updates.</p>
<p>If you’re using PiHole on your network to block ads and prevent your various smart devices from sending tracking information to their manufacturers, <strong>you might be surprised to find out that some of these devices are using a sneaky tactic to bypass your PiHole entirely.</strong></p>
<p>Smart devices manufacturers often “hard-code” in a public DNS server, like Google’s 8.8.8.8, and their devices ignore whatever DNS server is assigned by your router - such as your PiHole.</p>
<p><a href="https://arxiv.org/pdf/2001.08288.pdf">Nearly 70% of smart TVs and 46% of game consoles</a> were found to contain hardcoded DNS settings - allowing them to simply ignore your local network’s DNS server entirely. On average, Smart TVs generate an average of 60 megabytes of outgoing Internet traffic <em>per day</em>, all the while bypassing tools like PiHole.</p>
<h2 id="force-all-dns-queries-through-pihole">Force all DNS queries through PiHole</h2>
<p>Fortunately, with a few simple firewall rules, you can intercept these hardcoded DNS queries and redirect them to your PiHole. These instructions are for pfSense, however you should be able to adapt them for Sophos XG, Ubiquiti EdgeRouter, etc.</p>
<h3 id="create-nat-rules">Create NAT Rules</h3>
<p>Log in to your pfSense admin interface, and navigate to <em>Firewall</em> > <em>NAT</em> > <em>Port Forward</em>.</p>
<p>We’re going to create two Port Forward NAT rules - one to redirect any DNS queries originating from devices on the LAN to PiHole, and another to allow PiHole to commmunicate with external DNS servers. We will also create an additional outbound NAT rule that will make this process invisible to any clients on the network with hardcoded DNS.</p>
<p><strong>NAT Rule 1: Redirect DNS queries to PiHole</strong></p>
<p>Click the <em>Add</em> button to create your first new NAT Port Forward rule.</p>
<ul>
<li><strong>Interface:</strong> LAN</li>
<li><strong>Protcol:</strong> TCP/UDP</li>
<li><strong>Source:</strong> LAN net (you may need to click the blue show advanced button to see this option)</li>
<li><strong>Destination - Invert match:</strong> Checked</li>
<li><strong>Destination - Type:</strong> Single host or alias</li>
<li><strong>Destination - Address/mask:</strong> Your PiHole’s IP address</li>
<li><strong>Destination Port Range - From:</strong> DNS</li>
<li><strong>Destination Port Range - To:</strong> DNS</li>
<li><strong>Redirect Target IP:</strong> Your PiHole’s IP address</li>
<li><strong>Redirect Target Port:</strong> DNS</li>
<li><strong>Description:</strong> Intercept any outgoing DNS queries and redirect them to PiHole.</li>
</ul>
<p><strong>NAT Rule 2: Exempt PiHole from DNS query redirects</strong></p>
<p>Click the <em>Add</em> button to create your second new NAT Port Forward rule.</p>
<ul>
<li><strong>No RDR (NOT):</strong> Checked</li>
<li><strong>Interface:</strong> LAN</li>
<li><strong>Protcol:</strong> TCP/UDP</li>
<li><strong>Source - Type:</strong> Single host or alias</li>
<li><strong>Source - Address/Mask:</strong> Your PiHole’s IP address</li>
<li><strong>Destination:</strong> Any</li>
<li><strong>Destination Port Range - From:</strong> DNS</li>
<li><strong>Destination Port Range - From:</strong> DNS</li>
<li><strong>Description:</strong> Allow PiHole to reach external DNS servers</li>
</ul>
<p class="warning"><strong>Note:</strong> pfSense (and most other firewalls) process rules from top to bottom. Make sure you drag the second rule exempting PiHole from DNS query redirects <em>above</em> the first rule we created - otherwise PiHole will not be able to contact external DNS servers.</p>
<p><strong>NAT Rule 3: Prevent clients from giving unexpected source errors</strong></p>
<p>Finally, we need to create an outbound NAT rule. Navigate to <em>Firewall</em> > <em>NAT</em> > <em>Outbound</em>.</p>
<ul>
<li><strong>Interface:</strong> LAN</li>
<li><strong>Address Family:</strong> IPv4+IPv6</li>
<li><strong>Protocol:</strong> any</li>
<li><strong>Source - Type:</strong> Network</li>
<li><strong>Source - Network for the outbound NAT mapping:</strong> Your internal LAN network</li>
<li><strong>Destination - Type:</strong> Network</li>
<li><strong>Destination - Network for the outbound NAT Mappings:</strong> Your PiHole’s IP Address</li>
<li><strong>Destination Port Range:</strong> 53</li>
<li><strong>Translation:</strong> Interface Address</li>
<li><strong>Description:</strong> Prevents hardcoded DNS clients from giving unexpected source error after DNS redirected to PiHole.</li>
</ul>
<h3 id="test-it-out">Test it out</h3>
<p>You can easily test to make sure your DNS redirection is working properly.</p>
<ol>
<li>Create a new, temporary internal DNS entry on your network (“piholetest.example.com”), and point it to 10.0.1.1. You can do this right from PiHole under <em>Local DNS Records</em>.</li>
<li>Manually set your computer’s DNS server to <em>1.1.1.1</em>.</li>
<li>Open a terminal window (or command promt on Windows), and run <code class="language-plaintext highlighter-rouge">nslookup piholetest.example.com</code></li>
<li>
<p>If you set this up correctly, <code class="language-plaintext highlighter-rouge">nslookup</code> should return 10.0.1.1. Your computer <em>thinks</em> it’s receiving DNS records from 1.1.1.1, while in reality they are coming from your PiHole.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> macbookpro:~ labzilla$ nslookup piholetest.example.com
Server: 1.1.1.1
Address: 1.1.1.1#53
Name: piholetest.example.com
Address: 10.0.1.1
</code></pre></div> </div>
</li>
<li>
<p>You can further demonstate this by temporarily disabling the first NAT rule we created, and running the same <code class="language-plaintext highlighter-rouge">nslookup piholetest.example.com</code> command:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> macbookpro:~ labzilla$ nslookup piholetest.example.com
Server: 1.1.1.1
Address: 1.1.1.1#53
** server can't find piholetest.example.com: NXDOMAIN
</code></pre></div> </div>
<p>As “piholetest.example.com” doesn’t exist on the public Internet, the real 1.1.1.1 server has no record to provide - resulting in your <code class="language-plaintext highlighter-rouge">nslookup</code> request returning a NXDOMAIN error.</p>
</li>
</ol>
<p><strong>Don’t forget to revert your computer’s DNS settings back to their original value, and reenable any firewall rules you temporary disabled while testing.</strong></p>
<h2 id="dns-over-tlshttps">DNS over TLS/HTTPS</h2>
<p><a href="https://twitter.com/healeyio">Andrew Healey</a> <span style="color: #00acee;"><i class="fab fa-twitter"></i></span> brought up a great point in a tweet responding to this article:</p>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="light"><p lang="en" dir="ltr">Saw this article [1] on HN to block hardcoded DNS settings on Smart TVs and IoT devices. They'll just bypass this with DNS of HTTPS (DoH). If you're going this far, take 10 minutes and a couple additional steps to do it right. A thread. 🧵1/<br /><br />[1] <a href="https://t.co/TZgQhIZEer">https://t.co/TZgQhIZEer</a></p>— Andrew Healey (@healeyio) <a href="https://twitter.com/healeyio/status/1335347122649006080?ref_src=twsrc%5Etfw">December 5, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>He’s right. DNS over HTTPS travels over port 443, and would sail right through these firewall rules (as would DNS overt TLS). Blocking HTTPS/443 is not an option for obvious reasons. Instead, we can mitigate this threat by blocking all outbound traffic to known public DNS servers (except for PiHole).</p>
<p>This option isn’t perfect - the firewall rule is only as good as the source list behind it.</p>
<h3 id="create-ip-list-in-pfsense">Create IP List in pfSense</h3>
<p>You can aliases in pfSense that will automatically pull down (and update) a list of IP addresses. <a href="https://public-dns.info">Public-DNS.info</a> maintains a list of publicly accessible DNS servers that we can have pfSense copy for firewall rules.</p>
<p>From the pfSense dashboard, click <em>Firewall</em>, then click <em>Aliases</em>. Click <em>Add</em> in the bottom right corner. Configure the alias with the following uptions:</p>
<ul>
<li><strong>Name:</strong> IP_PublicDNS</li>
<li><strong>Description:</strong> Public DNS Server List</li>
<li><strong>Type:</strong> URL Table (IPs)</li>
<li><strong>URL Table (IPs):</strong> http://public-dns.info/nameservers-all.txt</li>
<li><strong>Update Frequency:</strong> 7 (this is the drop down menu after the “/” in the above field)</li>
</ul>
<h3 id="create-firewall-rules-using-ip-list">Create Firewall Rules using IP List</h3>
<p>Now that we have our alias list of public DNS servers configured in pfSense, we can make rules to block outgoing traffic (1) destined for IP addresses that are on the list (2) that didn’t come from PiHole.</p>
<blockquote>
<p>I prefer to use firewall rules that are as narrowly tailored as possible, so I’m opting to block <em>only</em> DNS over HTTPS (port 443) and DNS over TLS (port 853) traffic. You could also just block everything.</p>
</blockquote>
<p>Navigate to <em>Firewall</em> > <em>Rules</em>, and click the <em>LAN</em> tab. Click the <em>Add</em> button in the bottom right to make a new rule.</p>
<ul>
<li><strong>Action:</strong> Block</li>
<li><strong>Interface:</strong> LAN</li>
<li><strong>Address Family:</strong> IPv4+IPv6</li>
<li><strong>Protocol:</strong> TCP/UDP</li>
<li><strong>Source - Invert match:</strong> Checked</li>
<li><strong>Source:</strong> Your PiHole’s internal IP address</li>
<li><strong>Destination:</strong> Single host/alias - IP_PublicDNS (or whatever you called your alias in the previous section).</li>
<li><strong>Destination Port Range:</strong> HTTPS</li>
<li><strong>Log:</strong> Checked (optional, but helpful for troubleshooting)</li>
<li><strong>Description:</strong> Block HTTPS - PublicDNS list</li>
</ul>
<p>Save the rule, and then click the <em>Copy</em> <i class="far fa-clone"></i> icon to duplicate the rule to also block DNS over TLS. Change the following:</p>
<ul>
<li><strong>Destination Port Range:</strong> DNS over TLS (from/to)</li>
<li><strong>Description:</strong> Block DNS over TLS - PublicDNS list</li>
</ul>
<p>Save the rule, and then click <em>Apply Changes</em>.</p>
<h3 id="test-it-out-1">Test it out</h3>
<p>You can test to make sure this rule is working properly by opening a terminal window and running the following command <code class="language-plaintext highlighter-rouge">telnet 1.1.1.1 443</code>. The connection should eventually fail:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> macbookpro:~ labzilla$ telnet 1.1.1.1 443
Trying 1.1.1.1...
</code></pre></div></div>
<p>If you disable the firewall rule, the connection will succeed:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> macbookpro:~ labzilla$ telnet 1.1.1.1 443
Trying 1.1.1.1...
Connected to one.one.one.one.
</code></pre></div></div>
<p>Don’t forget to reenable your firewall rules!</p>
<h2 id="hacker-news">Hacker News</h2>
<p>This post hit the front page of Hacker News <span style="color: #F48120;"><i class="fab fa-hacker-news"></i></span> on Saturday December 5th, 2020. Thank you <a href="https://boramalper.org">@boramalper</a> for submitting it, and I hope you found the information useful!</p>
<ul>
<li>If you’re curious about what the Hacker News bump looks like - this blog normally sees about 100 hits per day. Between December 5th-6th, this post had over 70,000 views.</li>
<li>The <a href="https://news.ycombinator.com/item?id=25313480">original comment thread</a> is full of insightful comments from individuals who work on IoT hardware and other embedded devices, and is well worth a read.</li>
<li>I added an additional <a href="#dns-over-tlshttps">section</a> incorporating some of the suggestion that <a href="https://twitter.com/healeyio">@healyio</a> made in this Twitter <a href="https://twitter.com/healeyio/status/1335347122649006080">thread</a> regarding DNS over TLS/HTTPS.</li>
</ul>LabZillaWelcome Hacker News readers! • Thank you to M. Hammad Mazhar for his research that inspired this guide. • @healyio made some great additional suggestions in this Twitter thread which I incoporated in the DNS over TLS/HTTPS section. • The HN comment thread is full of insightful comments from individuals who work on IoT hardware and other embedded devices, and is well worth a read. • Finally, you can subscribe to the RSS feed or follow on Twitter for updates. If you’re using PiHole on your network to block ads and prevent your various smart devices from sending tracking information to their manufacturers, you might be surprised to find out that some of these devices are using a sneaky tactic to bypass your PiHole entirely. Smart devices manufacturers often “hard-code” in a public DNS server, like Google’s 8.8.8.8, and their devices ignore whatever DNS server is assigned by your router - such as your PiHole. Nearly 70% of smart TVs and 46% of game consoles were found to contain hardcoded DNS settings - allowing them to simply ignore your local network’s DNS server entirely. On average, Smart TVs generate an average of 60 megabytes of outgoing Internet traffic per day, all the while bypassing tools like PiHole. Force all DNS queries through PiHole Fortunately, with a few simple firewall rules, you can intercept these hardcoded DNS queries and redirect them to your PiHole. These instructions are for pfSense, however you should be able to adapt them for Sophos XG, Ubiquiti EdgeRouter, etc. Create NAT Rules Log in to your pfSense admin interface, and navigate to Firewall > NAT > Port Forward. We’re going to create two Port Forward NAT rules - one to redirect any DNS queries originating from devices on the LAN to PiHole, and another to allow PiHole to commmunicate with external DNS servers. We will also create an additional outbound NAT rule that will make this process invisible to any clients on the network with hardcoded DNS. NAT Rule 1: Redirect DNS queries to PiHole Click the Add button to create your first new NAT Port Forward rule. Interface: LAN Protcol: TCP/UDP Source: LAN net (you may need to click the blue show advanced button to see this option) Destination - Invert match: Checked Destination - Type: Single host or alias Destination - Address/mask: Your PiHole’s IP address Destination Port Range - From: DNS Destination Port Range - To: DNS Redirect Target IP: Your PiHole’s IP address Redirect Target Port: DNS Description: Intercept any outgoing DNS queries and redirect them to PiHole. NAT Rule 2: Exempt PiHole from DNS query redirects Click the Add button to create your second new NAT Port Forward rule. No RDR (NOT): Checked Interface: LAN Protcol: TCP/UDP Source - Type: Single host or alias Source - Address/Mask: Your PiHole’s IP address Destination: Any Destination Port Range - From: DNS Destination Port Range - From: DNS Description: Allow PiHole to reach external DNS servers Note: pfSense (and most other firewalls) process rules from top to bottom. Make sure you drag the second rule exempting PiHole from DNS query redirects above the first rule we created - otherwise PiHole will not be able to contact external DNS servers. NAT Rule 3: Prevent clients from giving unexpected source errors Finally, we need to create an outbound NAT rule. Navigate to Firewall > NAT > Outbound. Interface: LAN Address Family: IPv4+IPv6 Protocol: any Source - Type: Network Source - Network for the outbound NAT mapping: Your internal LAN network Destination - Type: Network Destination - Network for the outbound NAT Mappings: Your PiHole’s IP Address Destination Port Range: 53 Translation: Interface Address Description: Prevents hardcoded DNS clients from giving unexpected source error after DNS redirected to PiHole. Test it out You can easily test to make sure your DNS redirection is working properly. Create a new, temporary internal DNS entry on your network (“piholetest.example.com”), and point it to 10.0.1.1. You can do this right from PiHole under Local DNS Records. Manually set your computer’s DNS server to 1.1.1.1. Open a terminal window (or command promt on Windows), and run nslookup piholetest.example.com If you set this up correctly, nslookup should return 10.0.1.1. Your computer thinks it’s receiving DNS records from 1.1.1.1, while in reality they are coming from your PiHole. macbookpro:~ labzilla$ nslookup piholetest.example.com Server: 1.1.1.1 Address: 1.1.1.1#53 Name: piholetest.example.com Address: 10.0.1.1 You can further demonstate this by temporarily disabling the first NAT rule we created, and running the same nslookup piholetest.example.com command: macbookpro:~ labzilla$ nslookup piholetest.example.com Server: 1.1.1.1 Address: 1.1.1.1#53 ** server can't find piholetest.example.com: NXDOMAIN As “piholetest.example.com” doesn’t exist on the public Internet, the real 1.1.1.1 server has no record to provide - resulting in your nslookup request returning a NXDOMAIN error. Don’t forget to revert your computer’s DNS settings back to their original value, and reenable any firewall rules you temporary disabled while testing. DNS over TLS/HTTPS Andrew Healey brought up a great point in a tweet responding to this article: Saw this article [1] on HN to block hardcoded DNS settings on Smart TVs and IoT devices. They'll just bypass this with DNS of HTTPS (DoH). If you're going this far, take 10 minutes and a couple additional steps to do it right. A thread. 🧵1/[1] https://t.co/TZgQhIZEer— Andrew Healey (@healeyio) December 5, 2020 He’s right. DNS over HTTPS travels over port 443, and would sail right through these firewall rules (as would DNS overt TLS). Blocking HTTPS/443 is not an option for obvious reasons. Instead, we can mitigate this threat by blocking all outbound traffic to known public DNS servers (except for PiHole). This option isn’t perfect - the firewall rule is only as good as the source list behind it. Create IP List in pfSense You can aliases in pfSense that will automatically pull down (and update) a list of IP addresses. Public-DNS.info maintains a list of publicly accessible DNS servers that we can have pfSense copy for firewall rules. From the pfSense dashboard, click Firewall, then click Aliases. Click Add in the bottom right corner. Configure the alias with the following uptions: Name: IP_PublicDNS Description: Public DNS Server List Type: URL Table (IPs) URL Table (IPs): http://public-dns.info/nameservers-all.txt Update Frequency: 7 (this is the drop down menu after the “/” in the above field) Create Firewall Rules using IP List Now that we have our alias list of public DNS servers configured in pfSense, we can make rules to block outgoing traffic (1) destined for IP addresses that are on the list (2) that didn’t come from PiHole. I prefer to use firewall rules that are as narrowly tailored as possible, so I’m opting to block only DNS over HTTPS (port 443) and DNS over TLS (port 853) traffic. You could also just block everything. Navigate to Firewall > Rules, and click the LAN tab. Click the Add button in the bottom right to make a new rule. Action: Block Interface: LAN Address Family: IPv4+IPv6 Protocol: TCP/UDP Source - Invert match: Checked Source: Your PiHole’s internal IP address Destination: Single host/alias - IP_PublicDNS (or whatever you called your alias in the previous section). Destination Port Range: HTTPS Log: Checked (optional, but helpful for troubleshooting) Description: Block HTTPS - PublicDNS list Save the rule, and then click the Copy icon to duplicate the rule to also block DNS over TLS. Change the following: Destination Port Range: DNS over TLS (from/to) Description: Block DNS over TLS - PublicDNS list Save the rule, and then click Apply Changes. Test it out You can test to make sure this rule is working properly by opening a terminal window and running the following command telnet 1.1.1.1 443. The connection should eventually fail: macbookpro:~ labzilla$ telnet 1.1.1.1 443 Trying 1.1.1.1... If you disable the firewall rule, the connection will succeed: macbookpro:~ labzilla$ telnet 1.1.1.1 443 Trying 1.1.1.1... Connected to one.one.one.one. Don’t forget to reenable your firewall rules! Hacker News This post hit the front page of Hacker News on Saturday December 5th, 2020. Thank you @boramalper for submitting it, and I hope you found the information useful! If you’re curious about what the Hacker News bump looks like - this blog normally sees about 100 hits per day. Between December 5th-6th, this post had over 70,000 views. The original comment thread is full of insightful comments from individuals who work on IoT hardware and other embedded devices, and is well worth a read. I added an additional section incorporating some of the suggestion that @healyio made in this Twitter thread regarding DNS over TLS/HTTPS.Secure Home Assistant Remote Access2020-10-13T00:00:00-05:002020-10-13T00:00:00-05:00https://labzilla.io/blog/homeassistant-remote-access<p>Is your Home Assistant installation properly configured for secure remote access? Are you sure?</p>
<p>I ran a quick search on Shodan and found <strong>over 36,000 publically accessible Home Assistant installations with no SSL certificate</strong> installed. Every time one of these unlucky users logs in to Home Assistant remotely, their credentials are being transmitted in clear text across the public Internet. Any data being sent back and forth to Home Assistant - such as your location - is also being transmitted in clear text.</p>
<p class="error"><a href="#" class="button button--primary button--circle">X</a> <strong>Forwarding port 8123 on your router and calling it a day is a bad idea!</strong></p>
<p><img src="/assets/shodan-homeassistant-map.png" alt="" class="shadow" />
<em>Each red dot represents a potentially insecure Home Assistant installation</em></p>
<h1 id="requirements">Requirements</h1>
<p>You’ll need the following:</p>
<ul>
<li>Standard Home Assistant installation</li>
<li>Registered domain name</li>
<li>Free Cloudflare account</li>
<li>Domain nameservers pointed to Cloudflare</li>
<li>Ability to modify your router’s firewall settings</li>
<li>Static internal IP address/DHCP reservation for Home Assistant</li>
</ul>
<h4 id="what-is-cloudflare-and-why-use-them">What is Cloudflare, and why use them?</h4>
<p>Cloudflare provides a variety of products that help make websites faster and more secure. In a nutshell, Cloudflare sits between your server and people trying to access your server - transparently blocking bad actors before they reach your website.</p>
<p>By using Cloudflare, any access to your Home Assistant installation from the public Internet first goes through Cloudflare’s servers - hiding your true public IP address, and letting you use their advanced security tools.</p>
<h1 id="cloudflare-configuration">Cloudflare Configuration</h1>
<p>For Cloudflare to function, you’ll need to <a href="https://support.cloudflare.com/hc/en-us/articles/201720164">create a Cloudflare account</a>, and then tell your domain registrar to <a href="https://support.cloudflare.com/hc/en-us/articles/205195708">use Cloudflare’s nameservers</a> for your domain.</p>
<h2 id="add-your-subdomain">Add your subdomain</h2>
<p>You’ll need to come up with a subdomain that you will use to access Home Assistant. For this guide, I’ll use <code class="language-plaintext highlighter-rouge">homeassistant.labzilla.io</code>.</p>
<p>Log in to the <a href="https://dash.cloudflare.com">Cloudflare dashboard</a>, and click on your site. Click on <em>DNS</em> in the top menu bar, and then click <em>Add Record</em>.</p>
<p>Leave <em>Type</em> (A), <em>TTL</em> (Auto), and <em>Proxied</em> <span style="color: #F48120;"><i class="fas fa-cloud"></i></span> at their default settings. Under <em>Name</em>, enter the first part of the subdomain only. Under <em>IPv4 address</em>, enter your network’s public IP address.</p>
<ul>
<li>If you aren’t sure what your public IP address is, use <a href="https://ifconfig.me/ip">ifconfig.me </a>or <a href="https://ipchicken.com">IP Chicken</a> to find out.</li>
</ul>
<p><img src="/assets/cloudflare-dns-settings.png" alt="" class="shadow" /></p>
<p>Click the blue <em>Save</em> button.</p>
<h2 id="obtain-your-api-key">Obtain your API Key</h2>
<p>We will need your Cloudflare Global API key to configure Home Assistant.</p>
<p>From the Cloudflare dashboard, click on the <em>My Profile</em> account icon in the top right corner, and then click <em>My Profile</em>. Click on <em>API Tokens</em>, and then click the <em>View</em> button for the Global API Key item. You will be asked to enter your password, and then your Global API Key will be displayed. Save this somewhere secure - it’s equivalent to your password.</p>
<h1 id="configure-home-assistant">Configure Home Assistant</h1>
<p>Now that Cloudflare is set up, we need to configure Home Assistant to (1) automatically get an SSL certificate, (2) use the SSL certificate for the web interface, (3) periodically check to see if your external IP address changed, (4) and update Cloudflare accordingly.</p>
<p class="error">This tutorial assumes you are using the standard Home Assistant image. If you have have <em>Supervisor</em> listed on the left hand menu, you’re using the standard image. If you’re using Home Assistant <em>Core</em>, use <a href="http://certbot-dns-cloudflare.readthedocs.io">certbot-dns-cloudflare</a> to obtain an SSL certificate outside of Home Assistant, and edit your configuration.yaml file as outlined below.</p>
<h2 id="install--configure-lets-encrypt-add-on">Install & Configure Let’s Encrypt Add-On</h2>
<p>Cloudflare automatically encrypts the connection between your browser and Cloudflare’s network, however the connection between your Home Assistant server and Cloudflare still needs protection.</p>
<p>Let’s Encrypt is a service that provides free, automated TLS/SSL certificates that can be used to encrypt website traffic. These certificates need to be renewed every 90 days - which Home Assistant can automatically take care of. We will use this certificate to encrypt traffic between Home Assistant and Cloudflare.</p>
<p>First, we need to install the Let’s Encrypt add-on.</p>
<ul>
<li>Open Home Assistant, and click on <em>Supervisor</em> in the left hand menu.</li>
<li>Click <em>Add-on store</em> on the top menu, and click <em>Let’s Encrypt</em>.</li>
<li>Click <em>Install</em> and wait for the installation to complete.</li>
</ul>
<p><img src="/assets/homeassistant-add-ins.png" alt="" /></p>
<p>Toggle the <em>Start on boot</em> option to on, and then click <em>Configuration</em> in the top menu.</p>
<p>Paste in the following configuration, and then click <em>Save</em>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>email: your.email@example.com
domains:
- labzilla.io
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
provider: dns-cloudflare
cloudflare_email: your.cloudflare.account.email@example.com
cloudflare_api_key: YourGlobalAPIKey
</code></pre></div></div>
<h2 id="edit-home-assistant-configurationyaml">Edit Home Assistant configuration.yaml</h2>
<p>Next, we need to manually edit the Home Assistant configuration file to tell Home Assistant to (1) start using the new HTTPS certificate, and (2) automatically update Cloudflare with our current IP address.</p>
<h3 id="install-file-editor">Install File Editor</h3>
<p>To edit your configuration.yaml file in Home Assistant, you need to have their File Editor plug-in installed.</p>
<ul>
<li>Click on <em>Supervisor</em> in the left hand menu.</li>
<li>Click <em>Add-on store</em>, and then click on <em>File Editor</em></li>
<li>Click <em>Install</em> and wait for the installation to complete.</li>
</ul>
<p>Once the installation is complete, click <em>Start</em> and then click <em>Open Web UI</em>.</p>
<p><img src="/assets/homeassistant-file-editor-open-webui.png" alt="" /></p>
<p>Click the folder icon in the blue menu bar at the top.</p>
<p><img src="/assets/homeassistant-file-editor-folder.png" alt="" /></p>
<p>Finally, click <em>configuration.yaml</em> to open your configuration file.</p>
<p><img src="/assets/homeassistant-file-editor-open-config.png" alt="" /></p>
<h4 id="httpsssl-certificate">HTTPS/SSL Certificate</h4>
<p>Paste the following into your configuration.yaml file to tell Home Assistant to start using your new SSL certificate.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http:
server_port: 8123
ssl_certificate: /ssl/fullchain.pem
ssl_key: /ssl/privkey.pem
</code></pre></div></div>
<h4 id="cloudflare-ip-address-updater">Cloudflare IP Address Updater</h4>
<p>If you are on a residential Internet connection, you likely have a dynamic public IP address that can change at any time. Home Assistant can run a check every hour for changes, and update Cloudflare if your IP changes.</p>
<p>Paste the following into your configuration.yaml file. Your <code class="language-plaintext highlighter-rouge">zone</code> should be your domain, and the <code class="language-plaintext highlighter-rouge">records</code> will be any subdomains you wish to update. Use the same Global API Key that was used above.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cloudflare:
email: youremail@example.com
api_key: YourGlobalAPIKey
zone: labzilla.io
records:
- homeassistant
</code></pre></div></div>
<p>Click the save icon <span style="color: #FF5252;"><i class="fas fa-save"></i></span> in the top menu bar, and restart Home Assistant (Configuration > Server Controls > Restart Home Assistant).</p>
<p>You should now be able to access Home Assistant via https. You may receive a certificate error if you are accessing Home Assistant by IP address - you should configure an internal DNS record for your Home Assistant subdomain that resolves to your internal IP address for Home Assistant.</p>
<h1 id="configure-your-firewall">Configure your firewall</h1>
<p>Finally, you need to configure your router/firewall’s NAT/port forwarding settings. <strong>The specific terminology will vary based on your router/firewall model</strong>; this example is based on PFSense. Check the documentation for your specific model of router/firewall if you aren’t familiar with how to configure these settings.</p>
<table>
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Interface</strong></td>
<td>WAN</td>
</tr>
<tr>
<td><strong>Protocol</strong></td>
<td>TCP/UDP</td>
</tr>
<tr>
<td><strong>Source</strong></td>
<td><a href="https://www.cloudflare.com/ips/">Cloudflare’s IPv4 range</a> (see below)</td>
</tr>
<tr>
<td><strong>Source Port</strong></td>
<td>443</td>
</tr>
<tr>
<td><strong>Destination</strong></td>
<td>WAN Address</td>
</tr>
<tr>
<td><strong>Redirect Target IP</strong></td>
<td>Local IP address of Home Assistant</td>
</tr>
<tr>
<td><strong>Redirect Target Port</strong></td>
<td>8123</td>
</tr>
</tbody>
</table>
<p>Cloudflare has a <a href="https://www.cloudflare.com/ips/">public list</a> of the IP addresses they own and control. In the previous step, we configured Cloudflare to proxy all traffic to our <code class="language-plaintext highlighter-rouge">homeassistant.labzilla.io</code> domain name. Since all traffic is going through Cloudflare, their IP addresses will be the <em>only</em> source of legitimate outside traffic to Home Assistant. We can block everything else.</p>
<h1 id="test-it-out">Test it out</h1>
<p>Your Home Assistant installation should now be securely protected by Cloudflare, and our router’s firewall rules should block any attempts to connect that don’t come from Cloudflare. Test this out from a different Internet connection (i.e., tethering through your cell phone’s hotspot).</p>
<p><strong>Navigate to your Home Assistant installation by using your public IP address.</strong></p>
<p>The request should fail/time out, because the request did not originate from one of Cloudflare’s IP addresses.</p>
<ul>
<li>If the request does not fail/time out:
<ul>
<li>You should receive a certificate warning message.</li>
<li>Verify that the SSL certificate is from Let’s Encrypt, and that it is for your subdomain.</li>
<li>Double-check your firewall rules to make sure you are only allowing Cloudflare’s IP address range</li>
</ul>
</li>
</ul>
<p><strong>Ping your Home Assistant subdomain</strong></p>
<p>The IP address responding to the ping should be from one of Cloudflare’s <a href="https://www.cloudflare.com/ips/">IP addresses</a>, and not your home IP address.</p>
<ul>
<li>If the IP address responding matches your home IP address, <a href="#add-your-subdomain">double check your Cloudflare settings</a> and make sure that the proxy status is correct.</li>
</ul>
<p><strong>Navigate to your Home Assistant installation by using your domain name</strong></p>
<p>Your Home Assistant installation should load, and the SSL certificate should be from Cloudflare.</p>
<p><img src="/assets/homeassistant-cloudflare-sslcert.png" alt="" /></p>
<h1 id="further-configuration">Further configuration</h1>
<p>There are a few more tweaks that you can make to further protect Home Assistant.</p>
<h3 id="cloudflare-firewall-rules">Cloudflare Firewall Rules</h3>
<p>You can use Cloudflare’s firewall rules to restrict access to Home Assistant. For example, you can block access from all countries except the one that you live in. Access Cloudflare’s firewall rules from the Cloudflare dashboard; select your domain, choose <em>Firewall</em> from the top menu, and then click <em>Firewall Rules</em>.</p>
<p><img src="/assets/homeassistant-cloudflare-firewall.png" alt="" /></p>
<h3 id="turn-on-multi-factor-authentication">Turn on multi-factor authentication</h3>
<p>You should also turn on multi-factor authentication within Home Assistant. This can be configured in the <a href="https://www.home-assistant.io/docs/authentication/#your-account-profile">profile section</a> of your account.</p>LabZillaIs your Home Assistant installation properly configured for secure remote access? Are you sure? I ran a quick search on Shodan and found over 36,000 publically accessible Home Assistant installations with no SSL certificate installed. Every time one of these unlucky users logs in to Home Assistant remotely, their credentials are being transmitted in clear text across the public Internet. Any data being sent back and forth to Home Assistant - such as your location - is also being transmitted in clear text. X Forwarding port 8123 on your router and calling it a day is a bad idea! Each red dot represents a potentially insecure Home Assistant installation Requirements You’ll need the following: Standard Home Assistant installation Registered domain name Free Cloudflare account Domain nameservers pointed to Cloudflare Ability to modify your router’s firewall settings Static internal IP address/DHCP reservation for Home Assistant What is Cloudflare, and why use them? Cloudflare provides a variety of products that help make websites faster and more secure. In a nutshell, Cloudflare sits between your server and people trying to access your server - transparently blocking bad actors before they reach your website. By using Cloudflare, any access to your Home Assistant installation from the public Internet first goes through Cloudflare’s servers - hiding your true public IP address, and letting you use their advanced security tools. Cloudflare Configuration For Cloudflare to function, you’ll need to create a Cloudflare account, and then tell your domain registrar to use Cloudflare’s nameservers for your domain. Add your subdomain You’ll need to come up with a subdomain that you will use to access Home Assistant. For this guide, I’ll use homeassistant.labzilla.io. Log in to the Cloudflare dashboard, and click on your site. Click on DNS in the top menu bar, and then click Add Record. Leave Type (A), TTL (Auto), and Proxied at their default settings. Under Name, enter the first part of the subdomain only. Under IPv4 address, enter your network’s public IP address. If you aren’t sure what your public IP address is, use ifconfig.me or IP Chicken to find out. Click the blue Save button. Obtain your API Key We will need your Cloudflare Global API key to configure Home Assistant. From the Cloudflare dashboard, click on the My Profile account icon in the top right corner, and then click My Profile. Click on API Tokens, and then click the View button for the Global API Key item. You will be asked to enter your password, and then your Global API Key will be displayed. Save this somewhere secure - it’s equivalent to your password. Configure Home Assistant Now that Cloudflare is set up, we need to configure Home Assistant to (1) automatically get an SSL certificate, (2) use the SSL certificate for the web interface, (3) periodically check to see if your external IP address changed, (4) and update Cloudflare accordingly. This tutorial assumes you are using the standard Home Assistant image. If you have have Supervisor listed on the left hand menu, you’re using the standard image. If you’re using Home Assistant Core, use certbot-dns-cloudflare to obtain an SSL certificate outside of Home Assistant, and edit your configuration.yaml file as outlined below. Install & Configure Let’s Encrypt Add-On Cloudflare automatically encrypts the connection between your browser and Cloudflare’s network, however the connection between your Home Assistant server and Cloudflare still needs protection. Let’s Encrypt is a service that provides free, automated TLS/SSL certificates that can be used to encrypt website traffic. These certificates need to be renewed every 90 days - which Home Assistant can automatically take care of. We will use this certificate to encrypt traffic between Home Assistant and Cloudflare. First, we need to install the Let’s Encrypt add-on. Open Home Assistant, and click on Supervisor in the left hand menu. Click Add-on store on the top menu, and click Let’s Encrypt. Click Install and wait for the installation to complete. Toggle the Start on boot option to on, and then click Configuration in the top menu. Paste in the following configuration, and then click Save. email: your.email@example.com domains: - labzilla.io certfile: fullchain.pem keyfile: privkey.pem challenge: dns dns: provider: dns-cloudflare cloudflare_email: your.cloudflare.account.email@example.com cloudflare_api_key: YourGlobalAPIKey Edit Home Assistant configuration.yaml Next, we need to manually edit the Home Assistant configuration file to tell Home Assistant to (1) start using the new HTTPS certificate, and (2) automatically update Cloudflare with our current IP address. Install File Editor To edit your configuration.yaml file in Home Assistant, you need to have their File Editor plug-in installed. Click on Supervisor in the left hand menu. Click Add-on store, and then click on File Editor Click Install and wait for the installation to complete. Once the installation is complete, click Start and then click Open Web UI. Click the folder icon in the blue menu bar at the top. Finally, click configuration.yaml to open your configuration file. HTTPS/SSL Certificate Paste the following into your configuration.yaml file to tell Home Assistant to start using your new SSL certificate. http: server_port: 8123 ssl_certificate: /ssl/fullchain.pem ssl_key: /ssl/privkey.pem Cloudflare IP Address Updater If you are on a residential Internet connection, you likely have a dynamic public IP address that can change at any time. Home Assistant can run a check every hour for changes, and update Cloudflare if your IP changes. Paste the following into your configuration.yaml file. Your zone should be your domain, and the records will be any subdomains you wish to update. Use the same Global API Key that was used above. cloudflare: email: youremail@example.com api_key: YourGlobalAPIKey zone: labzilla.io records: - homeassistant Click the save icon in the top menu bar, and restart Home Assistant (Configuration > Server Controls > Restart Home Assistant). You should now be able to access Home Assistant via https. You may receive a certificate error if you are accessing Home Assistant by IP address - you should configure an internal DNS record for your Home Assistant subdomain that resolves to your internal IP address for Home Assistant. Configure your firewall Finally, you need to configure your router/firewall’s NAT/port forwarding settings. The specific terminology will vary based on your router/firewall model; this example is based on PFSense. Check the documentation for your specific model of router/firewall if you aren’t familiar with how to configure these settings. Setting Value Interface WAN Protocol TCP/UDP Source Cloudflare’s IPv4 range (see below) Source Port 443 Destination WAN Address Redirect Target IP Local IP address of Home Assistant Redirect Target Port 8123 Cloudflare has a public list of the IP addresses they own and control. In the previous step, we configured Cloudflare to proxy all traffic to our homeassistant.labzilla.io domain name. Since all traffic is going through Cloudflare, their IP addresses will be the only source of legitimate outside traffic to Home Assistant. We can block everything else. Test it out Your Home Assistant installation should now be securely protected by Cloudflare, and our router’s firewall rules should block any attempts to connect that don’t come from Cloudflare. Test this out from a different Internet connection (i.e., tethering through your cell phone’s hotspot). Navigate to your Home Assistant installation by using your public IP address. The request should fail/time out, because the request did not originate from one of Cloudflare’s IP addresses. If the request does not fail/time out: You should receive a certificate warning message. Verify that the SSL certificate is from Let’s Encrypt, and that it is for your subdomain. Double-check your firewall rules to make sure you are only allowing Cloudflare’s IP address range Ping your Home Assistant subdomain The IP address responding to the ping should be from one of Cloudflare’s IP addresses, and not your home IP address. If the IP address responding matches your home IP address, double check your Cloudflare settings and make sure that the proxy status is correct. Navigate to your Home Assistant installation by using your domain name Your Home Assistant installation should load, and the SSL certificate should be from Cloudflare. Further configuration There are a few more tweaks that you can make to further protect Home Assistant. Cloudflare Firewall Rules You can use Cloudflare’s firewall rules to restrict access to Home Assistant. For example, you can block access from all countries except the one that you live in. Access Cloudflare’s firewall rules from the Cloudflare dashboard; select your domain, choose Firewall from the top menu, and then click Firewall Rules. Turn on multi-factor authentication You should also turn on multi-factor authentication within Home Assistant. This can be configured in the profile section of your account.Home Assistant Door Chime via Sonos2020-10-01T00:00:00-05:002020-10-01T00:00:00-05:00https://labzilla.io/blog/homeassistant-door-chime<p>Home Assistant is an incredible piece of software. Through it’s powerful automation functionality, you can interface with devices from multiple manufacturers using completely different standards, and create extremely specific triggers, conditions, and subsequent actions.</p>
<p>I have a back door in my (one hundred year old) apartment that doesn’t always latch properly. More than once, I’ve walked back to the kitchen only to find the door ajar and my window AC working overtime. I already use the door sensors in conjunction with Home Assistant to automatically turn the lights on, so this project only required a few minutes of tinkering.</p>
<p>I’m using:</p>
<ul>
<li>Home Assistant (in a Docker container)</li>
<li>Sonos speakers</li>
<li><a href="https://www.amazon.com/Samsung-SmartThings-Multipurpose-Sensor-GP-U999SJVLAAA/dp/B07F956F3B">Samsung SmartThings</a> door & window sensors</li>
<li><a href="https://www.amazon.com/GoControl-CECOMINOD016164-HUSBZB-1-USB-Hub/dp/B01GJ826F8/">GoControl HUSBZB-1</a> USB zigbee/z-wave hub</li>
</ul>
<p>For the purposes of this guide, I’m assuming that you already have both the door sensors and your Sonos speakers set up in Home Assistant.</p>
<h2 id="configure-the-automation">Configure the automation</h2>
<p>Create a new automation by navigating to <em>Configuration</em> > <em>Automations</em> and clicking the ➕ icon down in the bottom right corner .</p>
<h3 id="trigger"><strong>Trigger</strong></h3>
<p>For the trigger, select <em>Device</em> as the type, and chose <em>Door Sensor Opened</em>. Specify a duration for how long the sensor needs to be in the “Open” state before firing an alert. For one minute, use <code class="language-plaintext highlighter-rouge">00:01:00</code>.</p>
<p><img src="/assets/kitchendoortrigger.png" alt="" class="shadow" /></p>
<h3 id="action"><strong>Action</strong></h3>
<p>The following actions tell Home Assistant to</p>
<ol>
<li>Save the current Sonos state.</li>
<li>Set the volume to a predefined level.</li>
<li>Group multiple Sonos speakers together to play the alert at the same time.</li>
<li>Play a specific audio alert sound.</li>
<li>Wait for the sound to finish.</li>
<li>Resume playback of whatever was originally playing.</li>
</ol>
<h4 id="save-current-queue"><strong>Save current queue</strong></h4>
<p>If I’m home, I usually have some music going over the Sonos system. Playing an alert chime over the Sonos will interrupt anything that’s playing (and replace the queue), which we don’t want. To get around this issue, Home Assistant can take a “snapshot” of what Sonos is playing (and at what volume) for the entire system. For Spotify, the music will resume where you left off. Unfortunately with Pandora, a new song on whatever station you were listening to will start instead.</p>
<ul>
<li>Click <em>Add Action</em>, click the options menu (<strong>⋮</strong>) on the right side, and then click <em>Edit as YAML</em>.</li>
</ul>
<p><img src="/assets/kitchendoor-add-action-yaml.png" alt="" class="shadow" /></p>
<ul>
<li>
<p>Paste in the following code:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> data: {}
entity_id: all
service: sonos.snapshot
</code></pre></div> </div>
</li>
</ul>
<p class="info">You will see a “UI editor is not supported for this config” warning - this is normal.</p>
<h4 id="set-a-global-volume"><strong>Set a global volume</strong></h4>
<p>Adjust the volume of the speakers to a predetermined level (so you don’t jump out of your skin).</p>
<ul>
<li>
<p>Click <em>Add Action</em>, and change <em>Action Type</em> to <em>Call Service</em>. Select the <code class="language-plaintext highlighter-rouge">media_player.volume_set</code> service.</p>
</li>
<li>
<p>Under <em>Name(s) of entities to set volume on</em>, find your Sonos speaker in the drop-down list.</p>
<p>For whatever reason, you can’t pick multiple items from the drop down, but you can manually type in multiple entities seperated with a comma and a space - for example:
<code class="language-plaintext highlighter-rouge">media_player.living_room_sonos, media_player.bedroom_sonos, media_player.kitchen_sonos</code>.</p>
</li>
<li>
<p>Under service data, enter <code class="language-plaintext highlighter-rouge">volume_level: 0.2</code> (20% volume - tweak as needed).</p>
</li>
</ul>
<h4 id="group-together-multiple-sonos-devices-to-play-your-announcement"><strong>Group together multiple Sonos devices to play your announcement</strong></h4>
<p>I have multiple Sonos speakers in different rooms, and I want all of them to play the alert tone. You can accomplish this by grouping the speakers together. Pick one speaker to serve as the “Master,” and then specify the rest of your speakers. In my case, the living room speaker will be the master, and the bedroom and kitchen speaker will join.</p>
<ul>
<li>
<p>Click <em>Add Action</em>, and change <em>Action Type</em> to <em>Call Service</em>. Select the <code class="language-plaintext highlighter-rouge">sonos.join</code> service.</p>
</li>
<li>
<p>Under <em>Name(s) of entities that will join the master</em>, list all of the speakers (except the master) that you want to play the alert through. In my case, that would be <code class="language-plaintext highlighter-rouge">media_player.kitchen_sonos, media_player.bedroom_sonos</code>.</p>
</li>
<li>
<p>Under <em>Service Data</em>, specify the master speaker: <code class="language-plaintext highlighter-rouge">master: media_player.living_room_sonos</code>.</p>
</li>
</ul>
<h4 id="play-the-announcement"><strong>Play the announcement</strong></h4>
<p>I created a simple MP3 file with a chime and voice message:</p>
<audio controls="true" src="/assets/alert-kitchen-door.mp3" type="audio/mpeg"> Your browser does not support MP3 playback.
</audio>
<p>The chime noise is from <a href="https://notificationsounds.com">Notification Sounds</a>, and the voice is from an online text-to-speech tool.</p>
<ul>
<li>
<p>Click <em>Add Action</em>, and change <em>Action Type</em> to <em>Call Service</em>. Select the <code class="language-plaintext highlighter-rouge">media_player.play_media</code> service.</p>
</li>
<li>
<p>Under <em>Name(s) of entities to seek media on</em>, specify the master speaker you designated in the previous step: <code class="language-plaintext highlighter-rouge">media_player.living_room_sonos</code>.</p>
</li>
<li>
<p>Under <em>Service Data</em>, specify the location of your media file and the content type:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> media_content_id: 'http://homeassistant.yourdomain.com:8123/local/kitchen-alert.mp3'
media_content_type: music
</code></pre></div> </div>
</li>
</ul>
<p class="success">You can stash your audio file in the <em>/config/www</em> folder, which translates to the <em>http://homeassistant.yourdomain.com:8123/local/kitchen-alert.mp3</em> URL above. If you’re running Home Assistant in Docker, the <em>www</em> folder should be in the root of your Home Assistant Docker volume.</p>
<h4 id="wait-for-the-announcement-to-finish"><strong>Wait for the announcement to finish</strong></h4>
<p>You need to tell Home Assistant to wait for the announcement sound to finish by creating a <em>Delay</em> action. The length of the delay should be about a second longer than the length of your alert sound.</p>
<ul>
<li>Click <em>Add Action</em>, and change <em>Action Type</em> to <em>Delay</em>. Enter your delay as HH:MM:SS. For a five second delay, use <code class="language-plaintext highlighter-rouge">00:00:05</code>.</li>
</ul>
<h4 id="get-back-to-the-music"><strong>Get back to the music</strong></h4>
<p>Finally, have Home Assistant resume playing whatever it interrupted.</p>
<ul>
<li>
<p>Click <em>Add Action</em>, click the options menu (<strong>⋮</strong>) on the right side, and then click <em>Edit as YAML</em>.</p>
</li>
<li>
<p>Paste in the following code:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> data: {}
entity_id: all
service: sonos.restore
</code></pre></div> </div>
</li>
</ul>
<h4 id="save-your-new-automation"><strong>Save your new automation</strong></h4>
<p>Click the 💾 icon in the bottom right to save your automation. You can go back to the <em>Configuration</em> > <em>Automations</em> screen, and click <em>Execute</em> to test it out. This is a good chance to see if the global volume you set previously is too loud/quiet.</p>
<h2 id="raw-automationsyaml-file">Raw automations.yaml file</h2>
<p>I posted this on Reddit’s <a href="https://reddit.com/r/homeassistant">/r/homeassistant</a>, and a <a href="https://www.reddit.com/r/homeassistant/comments/j8jcyx/using_home_assistant_to_alert_me_if_a_door_is/g8c1lvc/?utm_source=reddit&utm_medium=web2x&context=3">commenter</a> suggested posting a snapshot of the revlevant part of the automations.yaml file. A screenshot of the entire automation config page is <a href="/assets/door-chime-automation-config.png">also available.</a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>alias: 'Alert: Kitchen Door Open'
description: ''
trigger:
- type: opened
platform: device
device_id: 0123456789abcdefg
entity_id: binary_sensor.kitchen_door
domain: binary_sensor
for:
hours: 0
minutes: 1
seconds: 0
condition: []
action:
- data:
data:
priority: 1
url: https://homeassistant.example.com
message: The kitchen door was left open for longer than one minute.
title: Kitchen Door Ajar
service: notify.pushover
- data: {}
entity_id: all
service: sonos.snapshot
- data:
volume_level: 0.2
entity_id: media_player.living_room_sonos, media_player.bedroom_sonos, media_player.kitchen_sonos
service: media_player.volume_set
- data:
master: media_player.living_room_sonos
entity_id: media_player.bedroom_sonos, media_player.kitchen_sonos
service: sonos.join
- data:
media_content_id: http://homeassistant.example.com:8123/local/kitchen-alert.mp3
media_content_type: music
entity_id: media_player.living_room_sonos
service: media_player.play_media
- delay: 00:00:05
- data: {}
entity_id: all
service: sonos.restore
</code></pre></div></div>
<h2 id="bonus-ideas">Bonus Ideas</h2>
<h4 id="get-an-alert-pushed-to-your-phone">Get an alert pushed to your phone</h4>
<p>I use Pushover ($5) for a variety of different alerts, so I also added an action to my automation that notifies Pushover (which then sends an alert to my phone). You’ll need to set up a <a href="https://pushover.net">Pushover</a> account and <a href="https://www.home-assistant.io/integrations/pushover/">edit your configuration.yaml</a> file for this to work.</p>
<p>Add a new action, with the following settings:</p>
<ul>
<li><strong>Type</strong>: <code class="language-plaintext highlighter-rouge">call service</code></li>
<li><strong>Service</strong>: <code class="language-plaintext highlighter-rouge">notify_pushover</code></li>
</ul>
<p>Paste in the following code under <em>service data</em>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> data:
priority: 1
url: 'https://homeassistant.example.com'
message: The kitchen door was left open for longer than one minute.
title: Kitchen Door Ajar
</code></pre></div></div>
<h4 id="stick-a-door-sensor-on-your-mailbox">Stick a door sensor on your mailbox</h4>
<p>The SmartThings door & window sensors have a pretty decent range - try sticking one on your mailbox. Here’s what I hear when the mail gets delivered:</p>
<audio controls="true" src="/assets/aol-you-got-mail.mp3" type="audio/mpeg"> Your browser does not support MP3 playback.
</audio>
<p>(I turned this off after a few days, but you get the idea 😅)</p>LabZillaHome Assistant is an incredible piece of software. Through it’s powerful automation functionality, you can interface with devices from multiple manufacturers using completely different standards, and create extremely specific triggers, conditions, and subsequent actions. I have a back door in my (one hundred year old) apartment that doesn’t always latch properly. More than once, I’ve walked back to the kitchen only to find the door ajar and my window AC working overtime. I already use the door sensors in conjunction with Home Assistant to automatically turn the lights on, so this project only required a few minutes of tinkering. I’m using: Home Assistant (in a Docker container) Sonos speakers Samsung SmartThings door & window sensors GoControl HUSBZB-1 USB zigbee/z-wave hub For the purposes of this guide, I’m assuming that you already have both the door sensors and your Sonos speakers set up in Home Assistant. Configure the automation Create a new automation by navigating to Configuration > Automations and clicking the ➕ icon down in the bottom right corner . Trigger For the trigger, select Device as the type, and chose Door Sensor Opened. Specify a duration for how long the sensor needs to be in the “Open” state before firing an alert. For one minute, use 00:01:00. Action The following actions tell Home Assistant to Save the current Sonos state. Set the volume to a predefined level. Group multiple Sonos speakers together to play the alert at the same time. Play a specific audio alert sound. Wait for the sound to finish. Resume playback of whatever was originally playing. Save current queue If I’m home, I usually have some music going over the Sonos system. Playing an alert chime over the Sonos will interrupt anything that’s playing (and replace the queue), which we don’t want. To get around this issue, Home Assistant can take a “snapshot” of what Sonos is playing (and at what volume) for the entire system. For Spotify, the music will resume where you left off. Unfortunately with Pandora, a new song on whatever station you were listening to will start instead. Click Add Action, click the options menu (⋮) on the right side, and then click Edit as YAML. Paste in the following code: data: {} entity_id: all service: sonos.snapshot You will see a “UI editor is not supported for this config” warning - this is normal. Set a global volume Adjust the volume of the speakers to a predetermined level (so you don’t jump out of your skin). Click Add Action, and change Action Type to Call Service. Select the media_player.volume_set service. Under Name(s) of entities to set volume on, find your Sonos speaker in the drop-down list. For whatever reason, you can’t pick multiple items from the drop down, but you can manually type in multiple entities seperated with a comma and a space - for example: media_player.living_room_sonos, media_player.bedroom_sonos, media_player.kitchen_sonos. Under service data, enter volume_level: 0.2 (20% volume - tweak as needed). Group together multiple Sonos devices to play your announcement I have multiple Sonos speakers in different rooms, and I want all of them to play the alert tone. You can accomplish this by grouping the speakers together. Pick one speaker to serve as the “Master,” and then specify the rest of your speakers. In my case, the living room speaker will be the master, and the bedroom and kitchen speaker will join. Click Add Action, and change Action Type to Call Service. Select the sonos.join service. Under Name(s) of entities that will join the master, list all of the speakers (except the master) that you want to play the alert through. In my case, that would be media_player.kitchen_sonos, media_player.bedroom_sonos. Under Service Data, specify the master speaker: master: media_player.living_room_sonos. Play the announcement I created a simple MP3 file with a chime and voice message: Your browser does not support MP3 playback. The chime noise is from Notification Sounds, and the voice is from an online text-to-speech tool. Click Add Action, and change Action Type to Call Service. Select the media_player.play_media service. Under Name(s) of entities to seek media on, specify the master speaker you designated in the previous step: media_player.living_room_sonos. Under Service Data, specify the location of your media file and the content type: media_content_id: 'http://homeassistant.yourdomain.com:8123/local/kitchen-alert.mp3' media_content_type: music You can stash your audio file in the /config/www folder, which translates to the http://homeassistant.yourdomain.com:8123/local/kitchen-alert.mp3 URL above. If you’re running Home Assistant in Docker, the www folder should be in the root of your Home Assistant Docker volume. Wait for the announcement to finish You need to tell Home Assistant to wait for the announcement sound to finish by creating a Delay action. The length of the delay should be about a second longer than the length of your alert sound. Click Add Action, and change Action Type to Delay. Enter your delay as HH:MM:SS. For a five second delay, use 00:00:05. Get back to the music Finally, have Home Assistant resume playing whatever it interrupted. Click Add Action, click the options menu (⋮) on the right side, and then click Edit as YAML. Paste in the following code: data: {} entity_id: all service: sonos.restore Save your new automation Click the 💾 icon in the bottom right to save your automation. You can go back to the Configuration > Automations screen, and click Execute to test it out. This is a good chance to see if the global volume you set previously is too loud/quiet. Raw automations.yaml file I posted this on Reddit’s /r/homeassistant, and a commenter suggested posting a snapshot of the revlevant part of the automations.yaml file. A screenshot of the entire automation config page is also available. alias: 'Alert: Kitchen Door Open' description: '' trigger: - type: opened platform: device device_id: 0123456789abcdefg entity_id: binary_sensor.kitchen_door domain: binary_sensor for: hours: 0 minutes: 1 seconds: 0 condition: [] action: - data: data: priority: 1 url: https://homeassistant.example.com message: The kitchen door was left open for longer than one minute. title: Kitchen Door Ajar service: notify.pushover - data: {} entity_id: all service: sonos.snapshot - data: volume_level: 0.2 entity_id: media_player.living_room_sonos, media_player.bedroom_sonos, media_player.kitchen_sonos service: media_player.volume_set - data: master: media_player.living_room_sonos entity_id: media_player.bedroom_sonos, media_player.kitchen_sonos service: sonos.join - data: media_content_id: http://homeassistant.example.com:8123/local/kitchen-alert.mp3 media_content_type: music entity_id: media_player.living_room_sonos service: media_player.play_media - delay: 00:00:05 - data: {} entity_id: all service: sonos.restore Bonus Ideas Get an alert pushed to your phone I use Pushover ($5) for a variety of different alerts, so I also added an action to my automation that notifies Pushover (which then sends an alert to my phone). You’ll need to set up a Pushover account and edit your configuration.yaml file for this to work. Add a new action, with the following settings: Type: call service Service: notify_pushover Paste in the following code under service data: data: priority: 1 url: 'https://homeassistant.example.com' message: The kitchen door was left open for longer than one minute. title: Kitchen Door Ajar Stick a door sensor on your mailbox The SmartThings door & window sensors have a pretty decent range - try sticking one on your mailbox. Here’s what I hear when the mail gets delivered: Your browser does not support MP3 playback. (I turned this off after a few days, but you get the idea 😅)Dell U2718Q + MacBook Pro 2015 Displayport Problems2020-09-20T00:00:00-05:002020-09-20T00:00:00-05:00https://labzilla.io/blog/dell-u2718q-monitor-bug<p class="info">I upgraded to a 2019 16” MBP + a <a href="https://www.amazon.com/CalDigit-TS3-Plus-Thunderbolt-Dock/dp/B07CZPV8DF/">CalDigit TS3 dock</a>, and haven’t experienced this issue…yet.</p>
<p>I have a 2015 15” MacBook Pro, which I use with a <a href="https://www.amazon.com/Dell-Ultrasharp-U2718Q-27-Inch-Monitor/dp/B073VYVX5S/">Dell U2718Q </a>monitor.</p>
<p>For some reason every 3-6 months the monitor will stubbornly refuse to connect over the Thunderbolt 2/Mini DisplayPort, and will only function over the laptop’s built-in HDMI port.</p>
<p>To resolve this issue, you can reset the Dell monitor.</p>
<h3 id="steps-to-reset-dell-monitor">Steps to reset Dell Monitor</h3>
<ul>
<li>Shut down your MBP completely</li>
<li>Disconnect all cables from the monitor and the MBP</li>
<li>Turn on the MBP and log in normally.</li>
<li>Press and hold the monitor power button for 10 seconds</li>
<li>Reconnect power to monitor</li>
<li>Reconnect DisplayPort to mini DisplayPort cable to the monitor <strong>first</strong>, and then the MacBook Pro.</li>
<li>Turn monitor on, and switch source to DisplayPort if needed.</li>
</ul>
<p>Sidenote: the U2718Q has otherwise been fantastic. I picked up a second one a year later. Dell has an updated model <a href="https://www.amazon.com/Dell-UltraSharp-U2720Q-Backlit-Monitor/dp/B086H26XWV/">U2720Q</a> that now features USB-C (that puts out enough power to charge a 16” 2019 MBP).</p>LabZillaI upgraded to a 2019 16” MBP + a CalDigit TS3 dock, and haven’t experienced this issue…yet. I have a 2015 15” MacBook Pro, which I use with a Dell U2718Q monitor. For some reason every 3-6 months the monitor will stubbornly refuse to connect over the Thunderbolt 2/Mini DisplayPort, and will only function over the laptop’s built-in HDMI port. To resolve this issue, you can reset the Dell monitor. Steps to reset Dell Monitor Shut down your MBP completely Disconnect all cables from the monitor and the MBP Turn on the MBP and log in normally. Press and hold the monitor power button for 10 seconds Reconnect power to monitor Reconnect DisplayPort to mini DisplayPort cable to the monitor first, and then the MacBook Pro. Turn monitor on, and switch source to DisplayPort if needed. Sidenote: the U2718Q has otherwise been fantastic. I picked up a second one a year later. Dell has an updated model U2720Q that now features USB-C (that puts out enough power to charge a 16” 2019 MBP).Configuring a Cisco 8841-3PCC for FreePBX, 3CX, etc2020-09-19T00:00:00-05:002020-09-19T00:00:00-05:00https://labzilla.io/blog/cisco-8841-3pcc<p>Cisco makes two different groups of IP phone - one using Enterprise Firmware and the other using Multi-Platform Firmware (sometimes referenced as 3PCC - third party call control). Phones using MPP/3PCC firmware are relatively easy to get working with alternative PBX systems like FreePBX or 3CX.</p>
<p>I have several of the Cisco 8841-3PCC phones connected to a 3CX PBX sytem. The 8800 series IP phones are rock solid, and much nicer than the Cisco SPA series phones.</p>
<h4 id="find-the-phone-ip-address">Find the phone IP address</h4>
<p>Go to Settings > Status > Network Status > IPv4 Status. The phone’s IP address will be displayed.</p>
<h4 id="open-the-admin-console">Open the Admin Console</h4>
<p>Navigate to the phone’s admin console: http://10.0.1.1/admin (replace the IP address with what was displayed on the phone).</p>
<h4 id="configure-extensions">Configure Extensions</h4>
<p>Click the Voice tab at the top of the admin console, and then click the phone tab. Configure the following options:</p>
<ul>
<li><strong>Station Display Name</strong>: This is the name that you want to appear in the top-left corner of the phone (i.e, “Receiption” or “John Smith”).</li>
<li><strong>Line Key 1-10:</strong> If you’re adding multiple extensions on the handset, give each one a short name (x101, x201, etc). These names will display on the screen next to the line buttons.</li>
</ul>
<p>Click on the Ext 1 tab. Configure the following options:</p>
<ul>
<li><strong>Shared Line Appearance > Shared User ID:</strong> This is the extension number, and should exactly match the extension number in your PBX.</li>
<li><strong>Proxy and Registration > Proxy:</strong> This should be the IP address of your PBX server.</li>
<li><strong>Proxy and Registration > Outbound Proxy:</strong> This should be the IP address of your PBX server.</li>
<li><strong>Subscriber Information > User ID:</strong> Extension number</li>
<li><strong>Subscriber Information > Auth ID/Password:</strong> This is the extension authorization details configured in your PBX.</li>
</ul>
<p>Repeat this process for each extension you want to add on the phone, and then click Submit All Changes. The phone will reboot with the new settings provisioned.</p>LabZillaCisco makes two different groups of IP phone - one using Enterprise Firmware and the other using Multi-Platform Firmware (sometimes referenced as 3PCC - third party call control). Phones using MPP/3PCC firmware are relatively easy to get working with alternative PBX systems like FreePBX or 3CX. I have several of the Cisco 8841-3PCC phones connected to a 3CX PBX sytem. The 8800 series IP phones are rock solid, and much nicer than the Cisco SPA series phones. Find the phone IP address Go to Settings > Status > Network Status > IPv4 Status. The phone’s IP address will be displayed. Open the Admin Console Navigate to the phone’s admin console: http://10.0.1.1/admin (replace the IP address with what was displayed on the phone). Configure Extensions Click the Voice tab at the top of the admin console, and then click the phone tab. Configure the following options: Station Display Name: This is the name that you want to appear in the top-left corner of the phone (i.e, “Receiption” or “John Smith”). Line Key 1-10: If you’re adding multiple extensions on the handset, give each one a short name (x101, x201, etc). These names will display on the screen next to the line buttons. Click on the Ext 1 tab. Configure the following options: Shared Line Appearance > Shared User ID: This is the extension number, and should exactly match the extension number in your PBX. Proxy and Registration > Proxy: This should be the IP address of your PBX server. Proxy and Registration > Outbound Proxy: This should be the IP address of your PBX server. Subscriber Information > User ID: Extension number Subscriber Information > Auth ID/Password: This is the extension authorization details configured in your PBX. Repeat this process for each extension you want to add on the phone, and then click Submit All Changes. The phone will reboot with the new settings provisioned.Wildcard SSL Certificates with Certbot + Cloudflare2020-09-19T00:00:00-05:002020-09-19T00:00:00-05:00https://labzilla.io/blog/cloudflare-certbot<p>If you use Cloudflare for your DNS, Certbot makes it easy to get a wildcard SSL certificate with automatic DNS verification. A wildcard certificate allows you to use one certificate that is valid for all subdomains on your domain (i.e., example.com, wiki.example.com, files.example.com).</p>
<p>Using the Cloudflare DNS plugin, Certbot will create, validate, and them remove a TXT record via Cloudflare’s API. This process proves that you own the domain in question (and are authorized to obtain an SSL certificate for the domain).</p>
<h2 id="install-certbot">Install Certbot</h2>
<p><code class="language-plaintext highlighter-rouge">apt-get instal python3-certbot-dns-cloudflare</code></p>
<h2 id="configure-cloudflare-credentials">Configure Cloudflare Credentials</h2>
<p>You will need the email address associated with your Cloudflare account, and your <a href="https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-">Cloudflare Global API Key</a>.</p>
<h4 id="create-a-secrets-directory">Create a secrets directory</h4>
<p><code class="language-plaintext highlighter-rouge">mkdir /root/.secrets/</code>
<code class="language-plaintext highlighter-rouge">touch /root/.secrets/cloudflare.ini</code></p>
<h4 id="add-credentials-to-secrets-file">Add credentials to secrets file</h4>
<p><code class="language-plaintext highlighter-rouge">nano /root/.secrets/cloudflare.ini</code></p>
<p>The file should contain the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dns_cloudflare_email = youremail@example.com
dns_cloudflare_api_key = yourapikey
</code></pre></div></div>
<p>Save the file (Control + X, press ‘Y’ to Save, and press Enter).</p>
<h4 id="secure-the-secrets-file">Secure the secrets file</h4>
<p><code class="language-plaintext highlighter-rouge">sudo chmod 0700 /root/.secrets/</code></p>
<p><code class="language-plaintext highlighter-rouge">sudo chmod 0400 /root/.secrets/cloudflare.ini</code></p>
<h2 id="get-your-certificates">Get your Certificates</h2>
<p>Now that you’ve finished setting up Certbot, it’s time to get your certificates from LetsEncrypt.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini -d example.com,*.example.com --preferred-challenges dns-01
</code></pre></div></div>
<p>Your certificates will be saved to <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/example.com/</code>.</p>
<p class="warning">Do not move the certificates from this folder.</p>
<h4 id="renewal">Renewal</h4>
<p>Certbot creates a renewal script that runs twice per day and automatically renews certificates that are due to expire within the next 30 days. You can verify this script is running by using <code class="language-plaintext highlighter-rouge">sudo systemctl status certbot.timer</code>.</p>LabZillaIf you use Cloudflare for your DNS, Certbot makes it easy to get a wildcard SSL certificate with automatic DNS verification. A wildcard certificate allows you to use one certificate that is valid for all subdomains on your domain (i.e., example.com, wiki.example.com, files.example.com). Using the Cloudflare DNS plugin, Certbot will create, validate, and them remove a TXT record via Cloudflare’s API. This process proves that you own the domain in question (and are authorized to obtain an SSL certificate for the domain). Install Certbot apt-get instal python3-certbot-dns-cloudflare Configure Cloudflare Credentials You will need the email address associated with your Cloudflare account, and your Cloudflare Global API Key. Create a secrets directory mkdir /root/.secrets/ touch /root/.secrets/cloudflare.ini Add credentials to secrets file nano /root/.secrets/cloudflare.ini The file should contain the following: dns_cloudflare_email = youremail@example.com dns_cloudflare_api_key = yourapikey Save the file (Control + X, press ‘Y’ to Save, and press Enter). Secure the secrets file sudo chmod 0700 /root/.secrets/ sudo chmod 0400 /root/.secrets/cloudflare.ini Get your Certificates Now that you’ve finished setting up Certbot, it’s time to get your certificates from LetsEncrypt. sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini -d example.com,*.example.com --preferred-challenges dns-01 Your certificates will be saved to /etc/letsencrypt/live/example.com/. Do not move the certificates from this folder. Renewal Certbot creates a renewal script that runs twice per day and automatically renews certificates that are due to expire within the next 30 days. You can verify this script is running by using sudo systemctl status certbot.timer.