Adguard as a way to serve https via local DNS

Accessing your services inside your LAN without IPs

General Jun 18, 2022

Got a load of self-hosted services and can't remember all their ports? Only got a couple but you still prefer writing myawesome.subdomain.com instead of machineIP:ServicePort? This is for you.  

It's totally possible and pretty easy to access your services via their own URL, and have it served locally. What do I mean? Well let's take Radarr for instance. If we assume you've set up a docker container for it on the default port of 7878, and your machine's LAN IP is 192.168.0.10, you probably know you can access the GUI through your browser by typing http://192.168.0.10:7878 into the address bar. You may also know that you can set up a reverse proxy to access it remotely by an URL you would define, something like https://radarr.mycooldomain.com.

Using that last method is great, but it basically takes a longer route through a public space (the internet) rather than keeping the request inside your LAN. Well, there's a way to have both! Today we're going to look at SWAG (an nginx-based reverse proxy) and AdGuard, both on a macvlan network.

💡
I also have PiHole set up, but there's a history of difficulty with containers, especially on Synology, so I have it on a separate Raspberry Pi Zero W. If you have that, then you won't need adguard necessarily, but you may still want to play along

Prerequisites

Before we get started, you'll need the following:

  1. Docker and docker-compose installed on your machine
  2. The ability to SSH / use CLI/terminal on your machine, or use Portainer to spin up your stacks
  3. Some sort of access and relevant permissions to manage and create new directories
  4. A Fully Qualified Domain Name (FQDN, e.g. pointtosource.com)
  5. A reverse proxy already set up for the service you want, on its own docker network (for instance called proxy) with the relevant SSL certificate(s) (check out my SWAG article for some info on how to do that if you haven't already)

Setting up your MacVlan network

This is a type of network which allows us to give a docker container its own IP on our LAN's subnet (i.e. if your LAN is 192.168.0.0/24, you could assign the container an IP of 192.168.1.100 and it will be accessible at that IP without needing to use a port).

First, we need to find the parent network of your machine's IP (make sure you know what your machine's IP is already):

  • SSH into your machine and if necessary access the root user by typing sudo su - followed by your password
if you don't want to access root, then append each docker command below with sudo
  • Type ifconfig followed by Enter, and you'll get a chunk of network information
  • Scroll down the list, looking for your machine's IP in the blocks on the right. It should be towards the bottom
  • Once you've located your IP, take note of the network adapter which is on the left hand side, and will likely be something like eth0 or eth1
identifying our machine's parent network

So we've identified the parent network, here it's eth1. Next we need to specify the macvlan network and set it up. The format goes like this (everything in [ ] brackets will be specific to your setup):

docker network create -d macvlan subnet=[MyLANIP/24] --gateway=[MyLANgateway] -o parent=[eth1] [network name]
the command to create a macvlan network

So let's say the subnet was 192.168.0.0/24, the gateway would be 192.168.0.1, you've found your parent network is eth1 and you want to call the network mymacnetwork:

docker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=eth1 mymacnetwork
remember, all commands and information typed into the cli are case sensitive

That's the macvlan set up. Now to create AdGuard and add it to your macvlan:

  • Still in SSH, create your AdGuard container (you can use the following as a template, don't forget to create the relevant folders/directories)
networks:
  mymacnetwork:
    external: true
  proxy:
    external: true
      
services:
  adguard: #ad blocking and local DNS, set your router's DNS to this container's IP address
    container_name: adguard
    image: adguard/adguardhome
    ports:
      - 3000:3000/tcp
      - 54:53/tcp
      - 54:53/udp
      - 67:67/udp
      - 67:67/tcp
      - 69:68/tcp
      - 69:68/udp
      - 853:853/tcp
    volumes:
      - ./adguard/work:/opt/adguardhome/work
      - ./adguard/conf:/opt/adguardhome/conf
    restart: unless-stopped 
    networks:
      mymacnetwork:
        ipv4_address: 192.168.0.200 #change as necessary to an UNUSED IP on your network
      proxy:      
sample docker-compose file

Once up and running, you should be able to access your AdGuard instance at http://192.168.0.200 (or whatever IP you set).

Alternative Compose

If you wanted to create the macvlan network as part of your compose file, you could use this instead:

networks:
  mymacnetwork:
    name: mymacnetwork
    driver: macvlan
    driver_opts:
      parent: eth1
    ipam:
      config:
        - subnet: 192.168.0.0/24
  proxy:
    external: true

services:
  adguard: #ad blocking and local DNS, set your router's DNS to this container's IP address
    container_name: adguard
    image: adguard/adguardhome
    ports:
      - 3000:3000/tcp
      - 54:53/tcp
      - 54:53/udp
      - 67:67/udp
      - 67:67/tcp
      - 69:68/tcp
      - 69:68/udp
      - 853:853/tcp
    volumes:
      - ./adguard/work:/opt/adguardhome/work
      - ./adguard/conf:/opt/adguardhome/conf
    restart: unless-stopped 
    networks:
      mymacnetwork:
        ipv4_address: 192.168.0.200 #change as necessary to an UNUSED IP on your network
      proxy:

Setting up local routing

Let's go back to our https://radarr.mycooldomain.com example. You've already got your reverse proxy set up to serve radarr to any request for that URL when received externally. But we want to serve it when the request stays internal to our network only.

Well, the macvlan you created is going to come in useful again, as you're going to add your reverse proxy to it on its own IP (but you'll also keep it on the proxy network).

Assuming your reverse proxy container is called swag, and we're adding it to the same mymacnetwork with an IP address of 192.168.0.201 (assuming that IP is currently unused):

  • SSH into your machine
  • Type the following (modify to match your setup)
docker network connect --ip 192.168.0.201 mymacnetwork swag

And done. Why did we do this and not just leave our RP on its own network? Well AdGuard has an option to route DNS requests locally to any IP. But it CANNOT route them to specific ports. So whatever was going to serve your request needed to be on its own IP, and now it is.

Right, back to AdGuard, and we're looking for a screen called DNS rewrites:

the AdGuard home page

Once inside the DNS rewrites page:

adding a DNS rewrite
  • Click Add DNS rewrite
  • In the pop-up modal, add either your specific radarr.mycooldomain.com (no http or https) OR, to catch all subdomains you create a reverse proxy for, *.mycooldomain.com
  • Then add the IP address you set for your reverse proxy in the next box, and press Save

Ok great. Before, you would type radarr.mycooldomain.com into your browser, and it would come up with your radarr GUI. Now it.... does the same? So how do you know it's working?

There's a way to check this, using the nslookup tool in CLI/terminal:

nslookup radarr.mycooldomain.com

If you'd run this before creating the DNS rewrite, it would have popped up with the server and IP address of whichever public DNS you were using - it could have been Google and 8.8.8.8, or Cloudflare and 1.1.1.1. Now, it should show adguard as the server name, and the address would be 192.168.0.200.

Below that, you should see the name of your request radarr.mycooldomain.com followed by your reverse proxy's IP address 192.168.0.201.

If that's what's showing, then congrats, you've now got local DNS serving you your apps using your domain, all with SSL, without ever leaving your network.


PiHole instead of AdGuard

Assuming you've already got PiHole set up, it's essentially exactly the same process.

  • After logging in, click Local DNS in the left hand navigation panel, then DNS Records in the drop down
  • Add your domain (without a * and without the http or https)
  • Add the IP address (e.g. 192.168.1.201)
  • Click Add, let it do it's thing, and then test in the same way as above

Swag, Authelia and Reverse Proxies
A step-by-step walkthrough to self-host your Reverse Proxy with SWAG, and providing SSO and 2FA security using Authelia, all in docker
Preshared Keys and more - SSH on Linux and Synology
An easy guide which explains how to access and use your SSH sessions to their fullest, including clients and logging in with preshared keys
A guide to the different types of Docker Networks
The most important bits of information you need to successfully creating and managing your docker networks while ensuring container connectivity

PTS

PTS fell down the selfhosted rabbit hole after buying his first NAS in October 2020, only intending to use it as a Plex server. Find him on the Synology discord channel https://discord.gg/vgSq5pcT

Have some feedback or something to add? Comments are welcome!

Please note comments should be respectful, and may be moderated