Config files from:

https://gist.github.com/yqlbu/0bb267ef3306e3b5095fa1681049e277 https://www.hikariai.net/blog/26-mosdns-the-next-generation-dns-resolver/

Prepare works

apt update && apt install jq vim -y
 
export MOSDNS_PATH=/etc/mosdns
export MOSDNS_TAG=$(curl https://api.github.com/repos/IrineSistiana/mosdns/releases/latest --silent |  jq -r ".tag_name")
export GEOFILES_TAG=$(curl https://api.github.com/repos/techprober/v2ray-rules-dat/releases/latest --silent |  jq -r ".tag_name")
 
mkdir -p $MOSDNS_PATH/custom $MOSDNS_PATH/ips $MOSDNS_PATH/domains $MOSDNS_PATH/downloads
 
wget -q https://github.com/IrineSistiana/mosdns/releases/download/$MOSDNS_TAG/mosdns-linux-amd64.zip -O $MOSDNS_PATH/downloads/mosdns.zip
wget -q https://github.com/techprober/v2ray-rules-dat/releases/download/$GEOFILES_TAG/geoip.zip -O $MOSDNS_PATH/downloads/geoip.zip
wget -q https://github.com/techprober/v2ray-rules-dat/releases/download/$GEOFILES_TAG/geosite.zip -O $MOSDNS_PATH/downloads/geosite.zip
wget -q https://github.com/techprober/v2ray-rules-dat/releases/download/$GEOFILES_TAG/direct-list.txt -O $MOSDNS_PATH/domains/direct.txt
wget -q https://github.com/techprober/v2ray-rules-dat/releases/download/$GEOFILES_TAG/proxy-list.txt -O $MOSDNS_PATH/domains/proxy.txt
wget -q https://github.com/techprober/v2ray-rules-dat/releases/download/$GEOFILES_TAG/reject-list.txt -O $MOSDNS_PATH/domains/reject.txt
wget -q https://gist.github.com/yqlbu/0bb267ef3306e3b5095fa1681049e277/raw/mosdns-v5-config.yml -O $MOSDNS_PATH/config.yaml
 
unzip $MOSDNS_PATH/downloads/mosdns.zip mosdns -d /usr/bin
unzip $MOSDNS_PATH/downloads/geoip.zip -d $MOSDNS_PATH/ips
unzip $MOSDNS_PATH/downloads/geosite.zip -d $MOSDNS_PATH/domains
chmod +x /usr/bin/mosdns
 
rm -rf $MOSDNS_PATH/downloads

Reset 53 port

mkdir -p /etc/systemd/resolved.conf.d
vim /etc/systemd/resolved.conf.d/mosdns.conf
-----
[Resolve]
DNS=127.0.0.1
DNSStubListener=no
-----
 
mv /etc/resolv.conf /etc/resolv.conf.backup
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
 
systemctl daemon-reload
systemctl restart systemd-resolved
 
ss -tupln

Set mosdns service

mosdns service install -d /etc/mosdns -c /etc/mosdns/config.yaml
systemctl enable mosdns --now
mosdns service start
systemctl status mosdns

Mosdns config (Local DNS)

vim /etc/mosdns/config.yaml
-----
## -- Log Config -- ##
log:
  level: info # ["debug", "info", "warn", and "error"], default is set to "info"
  file: "/var/log/mosdns.log"
 
## -- API Config -- ##
api:
  http: "0.0.0.0:8080"
 
## -- Plugins Config -- ##
plugins:
  ## --- Cache --- ##
  - tag: custom_cache
    type: cache
    args:
      size: 10240
      lazy_cache_ttl: 86400 # ttl set to 1 day
      dump_file: ./cache.dump # persist cache to a local file, loaded when service starts
      dump_interval: 120 # autosave interval (s)
 
  - tag: local_seq
    type: hosts
    args:
      files: "./custom/hosts.txt"
 
  ## --- Upstream Servers --- ##
  - tag: upstreams
    type: forward
    args:
      upstreams:
        ## --- Domestic DNS Servers --- ##
        - tag: ali_dot
          addr: tls://223.5.5.5
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        # - tag: ali_doh
        #   addr: https://223.5.5.5/dns-query
        #   enable_pipeline: true
        #   enable_pipeline: true
        #   idle_timeout: 50
        #   insecure_skip_verify: true
 
        ##  --- Remote DNS Servers --- ##
        - tag: google_dot
          addr: tls://8.8.8.8
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        # - tag: google_doh
        #   addr: https://8.8.8.8/dns-query
        #   enable_pipeline: true
        #   idle_timeout: 50
        #   insecure_skip_verify: true
 
        - tag: cloudflare_dot
          addr: tls://1.1.1.1
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        # - tag: cloudflare_doh
        #   addr: https://1.1.1.1/dns-query
        #   enable_pipeline: true
        #   idle_timeout: 50
        #   insecure_skip_verify: true
 
  ## --- Domestic Sequence --- ##
  - tag: domestic_seq
    type: sequence
    args: 
      - exec: $upstreams ali_dot
 
  ## --- Remote Sequence --- ##
  - tag: remote_seq
    type: sequence
    args: 
      - exec: $upstreams google_dot
 
  ## --- CN-IP Sequence --- ##
  # if response does NOT has CN IP, drop it
  - tag: cn_ip
    type: sequence
    args:
      - exec: $upstreams ali_dot
      - matches: "!resp_ip &ips/cn.txt"
        exec: drop_resp
 
  ## --- Fallback --- ###
  # (ip split) if response has CN ip, accept it; otherwise, drop --> forward it to remote upstream servers
  - tag: fallback_ip
    type: fallback
    args:
      primary: cn_ip # empty response
      secondary: remote_seq
      always_standby: true
 
  ## --- Main Sequence --- ##
  - tag: main
    type: sequence
    args:
      - exec: query_summary entry
      - exec: prefer_ipv4 # prefer ipv4 for remote
 
      - matches: 
          - qname domain:localdomain.com
        exec: $local_seq
      - matches: has_resp
        exec: accept
 
      - matches: qtype 12
        exec: reject 3
      - matches: qtype 65
        exec: reject 3
 
      - matches:
          - qname &./domains/category-ads-all.txt # ads
          - qname &./domains/reject.txt
        exec: reject 0
 
      - exec: $custom_cache # enable cache
      - {matches: has_resp, exec: accept} # end if reponse found in cache
 
      - matches:
          - qname &./custom/remote.txt # custom remote domains
        exec: goto remote_seq
      - matches:
          - qname &./domains/cn.txt # cn domains
          - qname &./domains/direct.txt
        exec: goto domestic_seq
      - matches:
          - qname &./domains/geolocation-!cn.txt # non-cn domains
          - qname &./domains/gfw.txt
          - qname &./domains/google-scholar.txt
          - qname &./domains/category-scholar-!cn.txt
          - qname &./domains/icloud.txt
          - qname &./domains/apple-cn.txt
          - qname &./domains/twitter.txt
          - qname &./domains/telegram.txt
          - qname &./domains/google.txt
        exec: goto remote_seq
 
      - exec: $fallback_ip # use ip to split the rest domains
 
  ## --- Server Configuration --- ##
  - tag: server
    type: udp_server
    args:
      entry: main
      listen: :53
-----

Add local host file (optional)

cat ./custom/hosts.txt 
-----
pve.localdomain.com 192.168.123.110
pve-nas.localdomain.com 192.168.123.111
-----