master 2806a26a0721 cached
16 files
101.4 KB
31.6k tokens
1 requests
Download .txt
Repository: itdoginfo/domain-routing-openwrt
Branch: master
Commit: 2806a26a0721
Files: 16
Total size: 101.4 KB

Directory structure:
gitextract_333oxhhf/

├── .github/
│   └── workflows/
│       └── public-galaxy.yml
├── README.EN.md
├── README.md
├── defaults/
│   └── main.yml
├── getdomains-check.sh
├── getdomains-install.sh
├── getdomains-uninstall.sh
├── handlers/
│   └── main.yml
├── meta/
│   └── main.yml
├── tasks/
│   └── main.yml
├── templates/
│   ├── config-sing-box.j2
│   ├── openwrt-30-vpnroute.j2
│   ├── openwrt-getdomains.j2
│   └── sing-box-json.j2
└── tests/
    ├── inventory
    └── test.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/public-galaxy.yml
================================================
name: Public to Ansible Galaxy

on:
  push:
    tags:
      - '*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v4
      - name: Publish Ansible role to Galaxy
        uses: robertdebock/galaxy-action@1.2.1
        with:
          galaxy_api_key: ${{ secrets.galaxy_api_key }}

================================================
FILE: README.EN.md
================================================
Domain routing OpenWrt
=========

Configuring domain routing on Openwrt router.


Role Variables
--------------

Lists
```
  country: russia-inside|russia-outside|ukraine
  list_domains: true|falase

  list_subnet: false|true
  list_ip: false|true
  list_community: false|true
```

Tunnel
```
  tunnel: wg|openvpn|singbox|tun2socks
```

DoH or DoT
```
  dns_encrypt: false|dnscrypt|stubby
```

Nano package
```
  nano: true|false
```

Acces from wg network to router
```
  wg_access: false|true
  wg_access_network: 192.168.80.0/24 (for example)
```

If wireguard is used:
```
    wg_server_address: wg-server-host
    wg_private_key: privatekey-client
    wg_public_key: publickey-client
    wg_preshared_key: presharedkey-client
    wg_client_port: 51820
    wg_client_address: ip-client

    wg_access: true
    wg_access_network: wg-network
```

Dependencies
------------

[gekmihesg.openwrt](https://github.com/gekmihesg/ansible-openwrt)


Example Playbook
----------------

The inventory file must contain the group `[openwrt]` where your router will be located.


Wireguard, only domains, stubby, Russia, acces from wg network, host 192.168.1.1
```
- hosts: 192.168.1.1
  remote_user: root

  roles:
    - itdoginfo.domain_routing_openwrt

  vars:
    tunnel: wg
    dns_encrypt: stubby
    country: russia-inside
    
    wg_access: true
    wg_server_address: wg-server-host
    wg_private_key: privatekey-client
    wg_public_key: publickey-client
    wg_preshared_key: presharedkey-client
    wg_listen_port: 51820
    wg_client_port: 51820
    wg_client_address: ip-client
    wg_access_network: wg-network
```

Sing-box, stubby, Russia
```
- hosts: 192.168.1.1
  remote_user: root

  roles:
    - itdoginfo.domain_routing_openwrt

  vars:
    tunnel: singbox
    dns_encrypt: stubby
    country: russia-inside

  tasks:
  - name: sing-box config
    template:
      src: "templates/openwrt-sing-box-json.j2"
      dest: "/etc/sing-box/config.json"
      mode: 0644
    notify:
      - Restart sing-box
      - Restart network
```

License
-------

GNU General Public License v3.0

================================================
FILE: README.md
================================================
[English role README](https://github.com/itdoginfo/domain-routing-openwrt/blob/master/README.EN.md)

# Описание
Shell скрипт и [роль для Ansible](https://galaxy.ansible.com/ui/standalone/roles/itdoginfo/domain_routing_openwrt). Автоматизируют настройку роутера на OpenWrt для роутинга по доменам и спискам IP-адресов.

Полное описание происходящего:
- [Статья на хабре](https://habr.com/ru/articles/767464/)
- [Копия в моём блоге](https://itdog.info/tochechnyj-obhod-blokirovok-po-domenam-na-routere-s-openwrt/)

# Скрипт для установки
```
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-install.sh)
```

# Скрипт для удаления
```
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/refs/heads/master/getdomains-uninstall.sh)
```

## AmneziaWG
Через этот скрипт можно установить Amnezia wireguard. Скрипт проверяет наличие пакетов под вашу платформу в [стороннем репозитории](https://github.com/Slava-Shchipunov/awg-openwrt/releases), так как в официальном репозитории OpenWRT они отсутствуют, и автоматически их устанавливает.

Если вам нужно установить только AWG, воспользуйтесь скриптом в репозитории: https://github.com/Slava-Shchipunov/awg-openwrt

Если подходящих пакетов нет, перед настройкой необходимо будет самостоятельно [собрать бинарники AmneziaWG](https://github.com/itdoginfo/domain-routing-openwrt/wiki/Amnezia-WG-Build) для своего устройства и установить их.

## Скрипт для проверки конфигурации
Написан для OpenWrt 23.05 и 22.03. На 21.02 работает только половина проверок.

[x] - не обязательно означает, что эта часть не работает. Но это повод для ручной проверки.

### Запуск
```
wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh
```

По-умолчанию запускается на русском языке. Если нужно запустить на английском, то после `sh` нужно добавить `-s --lang en`. Аналогично для проверок на подмену DNS и создания дампа.

```
wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s --lang en
```

### Запустить с проверкой на подмену DNS
```
wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dns
```

### Запустить с созданием dump
Все чувствительные переменные затираются.

```
wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dump
```

Поиск ошибок вручную: https://habr.com/ru/post/702388/

# Ansible
Установить роль
```
ansible-galaxy role install itdoginfo.domain_routing_openwrt
```

Примеры playbooks

Wireguard, only domains, stubby, Russia, acces from wg network (пример 192.168.80.0/24), host 192.168.1.1
```
- hosts: 192.168.1.1
  remote_user: root

  roles:
    - itdoginfo.domain_routing_openwrt

  vars:
    tunnel: wg
    dns_encrypt: stubby
    country: russia-inside

    wg_server_address: wg-server-host
    wg_private_key: privatekey-client
    wg_public_key: publickey-client
    wg_preshared_key: presharedkey-client
    wg_listen_port: 51820
    wg_client_port: 51820
    wg_client_address: ip-client

    wg_access: true
    wg_access_network: wg-network
```

Sing-box, stubby, Russia
```
- hosts: 192.168.1.1
  remote_user: root

  roles:
    - itdoginfo.domain_routing_openwrt

  vars:
    tunnel: singbox
    dns_encrypt: stubby
    country: russia-inside

  tasks:
  - name: sing-box config
    template:
      src: "templates/openwrt-sing-box-json.j2"
      dest: "/etc/sing-box/config.json"
      mode: 0644
    notify:
      - Restart sing-box
      - Restart network
```

В inventory файле роутер обязательно должен быть в группе `[openwrt]`
```
[openwrt]
192.168.1.1
```

Для работы Ansible c OpenWrt необходимо, чтоб было выполнено одно из условий:
- Отсутствие пароля для root (не рекомендуется)
- Настроен доступ через публичный SSH-ключ в [конфиге dropbear](https://openwrt.org/docs/guide-user/security/dropbear.public-key.auth)

После выполнения playbook роутер сразу начнёт роутить необходмые домены в туннель/прокси.

Если у вас были ошибки и они исправились при повторном запуске playbook, но при этом роутинг не заработал, сделайте рестарт сети и скрипта:
```
service network restart
service getdomains start
```

Тестировалось с
- Ansible 2.10.8
- OpenWrt 21.02.7
- OpenWrt 22.03.5
- OpenWrt 23.05.2

## Выбор туннеля
- Wireguard настраивается автоматически через переменные
- OpenVPN устанавливается пакет, настраивается роутинг и зона. Само подключение (скопировать конфиг и перезапустить openvpn) нужно [настроить вручную](https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/)
- Sing-box устанавливает пакет, настраивается роутинг и зона. Также кладётся темплейт в `/etc/sing-box/config.json`. [Нужно настроить](https://habr.com/ru/articles/767458/) `config.json` и сделать `service sing-box restart`
Не работает под 21ой версией. Поэтому при его выборе playbook выдаст ошибку.
Для 22ой версии нужно установить пакет вручную.
- tun2socks настраивается только роутинг и зона. Всё остальное нужно настроить вручную

Для **tunnel** шесть возможных значений:
- wg
- openvpn
- singbox
- tun2socks

В случае использования WG:
```
    wg_server_address: wg-server-host
    wg_private_key: privatekey-client
    wg_public_key: publickey-client
    wg_preshared_key: presharedkey-client
    wg_client_port: 51820
    wg_client_address: ip-client
```

Если ваш wg сервер не использует `preshared_key`, то просто не задавайте её.

**wg_access** и **wg_access_network** для доступа к роутеру через WG. Переменная wg_access_network должна иметь значение подсети, например 192.168.10.0/24.
```
    wg_access_network: wg-network
    wg_access: true
```

## Шифрование DNS
Если ваш провайдер не подменяет DNS-запросы, ничего устанавливать не нужно.

Для **dns_encrypt** три возможных значения:
- dnscrypt
- stubby
- false/закомментировано - пропуск, ничего не устанавливается и не настраивается

## Выбор страны
Выбор списка доменов.
Для **county** три [возможных значения](https://github.com/itdoginfo/allow-domains):
- russia-inside
- russia-outside
- ukraine

## Списки IP-адресов
Списки IP-адресов берутся с [antifilter.download](https://antifilter.download/)
Переменные **list_** обозначают, какие списки нужно установить. true - установить, false - не устанавливать и удалить, если уже есть

Доступные переменные
```
  list_domains: true
  list_subnet: false
  list_ip: falses
  list_community: false
```

Я советую использовать только домены
```
    list_domains: true
```
Если вам требуются списки IP-адресов, они также поддерживаются.

При использовании **list_domains** нужен пакет dnsmasq-full.

Для 23.05 dnsmasq-full устанавливается автоматически.

Для OpenWrt 22.03 версия dnsmasq-full должна быть => 2.87, её нет в официальном репозитории, но можно установить из dev репозитория. Если это условие не выполнено, плейбук завершится с ошибкой.

[Инструкция для OpenWrt 22.03](https://t.me/itdoginf/12)

[Инструкция для OpenWrt 21.02](https://t.me/itdoginfo/8)

## Текстовый редактор nano
Устанавливается по умолчанию. Можно выключить
```
  nano: false
```

---

[Telegram-канал с обновлениями](https://t.me/+lW1HmBO_Fa00M2Iy)


================================================
FILE: defaults/main.yml
================================================
---
  list_domains: true
  list_subnet: false
  list_ip: false
  list_community: false
  tunnel: wg
  dns_encrypt: false
  country: russia-inside
  nano: true
  wg_access: false

  wg_listen_port: 51820

================================================
FILE: getdomains-check.sh
================================================
#!/bin/sh

SCRIPTS_DIR="/etc/init.d"
TMP_DIR="/tmp"
HIVPN_SCRIPT_FILENAME="hivpn"
GETDOMAINS_SCRIPT_FILENAME="getdomains"
DUMP_FILENAME="dump.txt"

HIVPN_SCRIPT_PATH="$SCRIPTS_DIR/$HIVPN_SCRIPT_FILENAME"
GETDOMAINS_SCRIPT_PATH="$SCRIPTS_DIR/$GETDOMAINS_SCRIPT_FILENAME"
DUMP_PATH="$TMP_DIR/$DUMP_FILENAME"

COLOR_BOLD_BLUE="\033[34;1m"
COLOR_BOLD_GREEN="\033[32;1m"
COLOR_BOLD_RED="\033[31;1m"
COLOR_BOLD_CYAN="\033[36;1m"
COLOR_RESET="\033[0m"

UNSUPPORTED_OPENWRT_VERSION="21.02"
MIN_RAM="256"
DNSMASQ_FULL_REQUIRED_VERSION="2.87"

SINGBOX_CONFIG_PATH="/etc/config/sing-box"

CURL_PACKAGE="curl"
DNSMASQ_PACKAGE="dnsmasq"
DNSMASQ_FULL_PACKAGE="$DNSMASQ_PACKAGE-full"
XRAY_CORE_PACKAGE="xray-core"
LUCI_APP_XRAY_PACKAGE="luci-app-xray"
WIREGUARD_TOOLS_PACKAGE="wireguard-tools"
OPENVPN_PACKAGE="openvpn"
SINGBOX_PACKAGE="sing-box"
TUN2SOCKS_PACKAGE="tun2socks"
DNSCRYPT_PACKAGE="dnscrypt-proxy2"
STUBBY_PACKAGE="stubby"

WIREGUARD_PROTOCOL="Wireguard"
OPENVPN_PROTOCOL="OpenVPN"

LANGUAGE="ru"
SUPPORTED_LANGUAGES="ru, en"

set_language_en() {
  DEVICE_MODEL="Model"
  OPENWRT_VERSION="Version"
  CURRENT_DATE="Date"
  INSTALLED="is installed"
  NOT_INSTALLED="is not installed"
  RUNNING="is running"
  NOT_RUNNING="is not running"
  ENABLED="is enabled"
  DISABLED="is disabled"
  EXISTS="exists"
  DOESNT_EXIST="doesn't exist"
  UNSUPPORTED_OPENWRT="You are using OpenWrt $UNSUPPORTED_OPENWRT_VERSION. This check script does not support it."
  RAM_WARNING="Your router has less than $MIN_RAM MB of RAM. It is recommended to use only the vpn_domains list."
  CURL_INSTALLED="$CURL_PACKAGE $INSTALLED"
  CURL_NOT_INSTALLED="$CURL_PACKAGE $NOT_INSTALLED. Install it: opkg install $CURL_PACKAGE"
  DNSMASQ_FULL_INSTALLED="$DNSMASQ_FULL_PACKAGE $INSTALLED"
  DNSMASQ_FULL_NOT_INSTALLED="$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED"
  DNSMASQ_FULL_DETAILS="If you don't use vpn_domains set, it's OK\nCheck version: opkg list-installed | grep $DNSMASQ_FULL_PACKAGE\nRequired version >= $DNSMASQ_FULL_REQUIRED_VERSION. For OpenWrt 22.03 follow manual: https://t.me/itdoginfo/12"
  OPENWRT_21_DETAILS="\nYou are using OpenWrt $UNSUPPORTED_OPENWRT_VERSION. This check does not support it.\nManual for OpenWrt $UNSUPPORTED_OPENWRT_VERSION: https://t.me/itdoginfo/8"
  XRAY_CORE_PACKAGE_DETECTED="$XRAY_CORE_PACKAGE package detected"
  LUCI_APP_XRAY_PACKAGE_DETECTED="$LUCI_APP_XRAY_PACKAGE package detected which is incompatible. Remove it: opkg remove $LUCI_APP_XRAY_PACKAGE --force-removal-of-dependent-packages"
  DNSMASQ_SERVICE_RUNNING="$DNSMASQ_PACKAGE service $RUNNING"
  DNSMASQ_SERVICE_NOT_RUNNING="$DNSMASQ_PACKAGE service $NOT_RUNNING. Check configuration: /etc/config/dhcp"
  INTERNET_IS_AVAILABLE="Internet is available"
  INTERNET_IS_NOT_AVAILABLE="Internet is not available"
  INTERNET_DETAILS="Check internet connection. If it's ok, check date on router. Details: https://cli.co/2EaW4rO\nFor more info run: curl -Is https://community.antifilter.download/"
  IPV6_DETECTED="IPv6 detected. This script does not currently work with IPv6"
  WIREGUARD_TOOLS_INSTALLED="$WIREGUARD_TOOLS_PACKAGE $INSTALLED"
  WIREGUARD_ROUTING_DOESNT_WORK="Tunnel to the $WIREGUARD_PROTOCOL server works, but routing to the internet does not work. Check server configuration. Details: https://cli.co/RSCvOxI"
  WIREGUARD_TUNNEL_NOT_WORKING="Bad news: $WIREGUARD_PROTOCOL tunnel isn't working. Check your $WIREGUARD_PROTOCOL configuration. Details: https://cli.co/hGUUXDs\nIf you don't use $WIREGUARD_PROTOCOL, but $OPENVPN_PROTOCOL for example, it's OK"
  WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED="$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/SaxBzH7"
  WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED="$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED"
  WIREGUARD_ROUTING_TABLE_EXISTS="$WIREGUARD_PROTOCOL routing table $EXISTS"
  WIREGUARD_ROUTING_TABLE_DOESNT_EXIST="$WIREGUARD_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3"
  OPENVPN_INSTALLED="$OPENVPN_PACKAGE $INSTALLED"
  OPENVPN_ROUTING_DOESNT_WORK="Tunnel to the $OPENVPN_PROTOCOL server works, but routing to the internet does not work. Check server configuration."
  OPENVPN_TUNNEL_NOT_WORKING="Bad news: $OPENVPN_PROTOCOL tunnel isn't working. Check your $OPENVPN_PROTOCOL configuration."
  OPENVPN_REDIRECT_GATEWAY_ENABLED="$OPENVPN_PROTOCOL redirect-gateway $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/vzTNq_3"
  OPENVPN_REDIRECT_GATEWAY_DISABLED="$OPENVPN_PROTOCOL redirect-gateway $DISABLED"
  OPENVPN_ROUTING_TABLE_EXISTS="$OPENVPN_PROTOCOL routing table $EXISTS"
  OPENVPN_ROUTING_TABLE_DOESNT_EXIST="$OPENVPN_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3"
  SINGBOX_INSTALLED="$SINGBOX_PACKAGE $INSTALLED"
  SINGBOX_ROUTING_TABLE_EXISTS="$SINGBOX_PACKAGE routing table $EXISTS"
  SINGBOX_ROUTING_TABLE_DOESNT_EXIST="$SINGBOX_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1"
  SINGBOX_UCI_CONFIG_OK="$SINGBOX_PACKAGE UCI configuration has been successfully validated"
  SINGBOX_UCI_CONFIG_ERROR="$SINGBOX_PACKAGE Error validation UCI configuration. Check $SINGBOX_CONFIG_PATH"
  SINGBOX_CONFIG_OK="$SINGBOX_PACKAGE configuration has been successfully validated"
  SINGBOX_CONFIG_ERROR="$SINGBOX_PACKAGE configuration validation error"
  SINGBOX_WORKING_TEMPLATE="$SINGBOX_PACKAGE works. VPN IP: %s"
  SINGBOX_ROUTING_DOESNT_WORK="$SINGBOX_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/Badmn3K"
  TUN2SOCKS_INSTALLED="$TUN2SOCKS_PACKAGE $INSTALLED"
  TUN2SOCKS_ROUTING_TABLE_EXISTS="$TUN2SOCKS_PACKAGE routing table $EXISTS"
  TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST="$TUN2SOCKS_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1"
  TUN2SOCKS_WORKING_TEMPLATE="$TUN2SOCKS_PACKAGE works. VPN IP: %s"
  TUN2SOCKS_ROUTING_DOESNT_WORK="$TUN2SOCKS_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/VNZISEM"
  VPN_DOMAINS_SET_EXISTS="vpn_domains set $EXISTS"
  VPN_DOMAINS_SET_DOESNT_EXIST="vpn_domains set $DOESNT_EXIST"
  IPS_IN_VPN_DOMAINS_SET_OK="IPs are successfully added to vpn_domains set"
  IPS_IN_VPN_DOMAINS_SET_ERROR="IPs were not added to vpn_domains set"
  VPN_DOMAINS_DETAILS="If you don't use vpn_domains, it's OK.\nBut if you want to use it, check the configuration and run: service getdomains start"
  VPN_DOMAINS_DETAILS_2="If you don't use vpn_domains, it's OK.\nBut if you want use, check the configuration: https://cli.co/AwUGeM6"
  VPN_IP_SET_EXISTS="vpn_ip set $EXISTS"
  VPN_IP_SET_DOESNT_EXIST="vpn_ip set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6"
  IPS_IN_VPN_IP_SET_OK="IPs are successfully added to vpn_ip set"
  IPS_IN_VPN_IP_SET_ERROR="IPs were not added to vpn_ip set. But if you want to use it, check configuration"
  VPN_SUBNET_SET_EXISTS="vpn_subnets set $EXISTS"
  VPN_SUBNET_SET_DOESNT_EXIST="vpn_subnets set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6"
  IPS_IN_VPN_SUBNET_SET_OK="IPs are successfully added to vpn_subnets set"
  IPS_IN_VPN_SUBNET_SET_ERROR="IPs were not added to vpn_subnets set. But if you want to use it, check configs"
  VPN_COMMUNITY_SET_EXISTS="vpn_community set $EXISTS"
  VPN_COMMUNITY_SET_DOESNT_EXIST="vpn_community set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6"
  IPS_IN_VPN_COMMUNITY_SET_OK="IPs are successfully added to vpn_community set"
  IPS_IN_VPN_COMMUNITY_SET_ERROR="IPs were not added to vpn_community set. But if you want to use it, check configs"
  GETDOMAINS_SCRIPT_EXISTS="Script $GETDOMAINS_SCRIPT_FILENAME $EXISTS"
  GETDOMAINS_SCRIPT_DOESNT_EXIST="Script $GETDOMAINS_SCRIPT_FILENAME $DOESNT_EXIST. Script doesn't exists in $GETDOMAINS_SCRIPT_PATH. If you don't use getdomains, it's OK"
  GETDOMAINS_SCRIPT_CRONTAB_OK="Script $GETDOMAINS_SCRIPT_FILENAME has been successfully added to crontab"
  GETDOMAINS_SCRIPT_CRONTAB_ERROR="Script $GETDOMAINS_SCRIPT_FILENAME has not been added to crontab. Check: crontab -l"
  DNSCRYPT_INSTALLED="$DNSCRYPT_PACKAGE $INSTALLED"
  DNSCRYPT_SERVICE_RUNNING="$DNSCRYPT_PACKAGE service $RUNNING"
  DNSCRYPT_SERVICE_NOT_RUNNING="$DNSCRYPT_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/wN-tc_S"
  DNSMASQ_CONFIG_FOR_DNSCRYPT_OK="$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is ok"
  DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR="$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is not ok. Check configuration: https://cli.co/rooc0uz"
  STUBBY_INSTALLED="$STUBBY_PACKAGE $INSTALLED"
  STUBBY_SERVICE_RUNNING="$STUBBY_PACKAGE service $RUNNING"
  STUBBY_SERVICE_NOT_RUNNING="$STUBBY_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/HbDBT2V"
  DNSMASQ_CONFIG_FOR_STUBBY_OK="$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is ok"
  DNSMASQ_CONFIG_FOR_STUBBY_ERROR="$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is not ok. Check configuration: https://cli.co/HbDBT2V"
  DUMP_CREATION="Creating dump without private variables"
  DUMP_DETAILS="Dump is here: $DUMP_PATH\nFor download on Linux/Mac use: scp root@IP_ROUTER:$DUMP_PATH .\nFor Windows use WinSCP/PSCP or WSL"
  DNS_CHECK="Checking DNS servers"
  IS_DNS_TRAFFIC_BLOCKED="Checking DNS traffic blocking (Port 53/udp is available)"
  IS_DOH_AVAILABLE="Checking DOH availability"
  RESPONSE_NOT_CONTAINS_127_0_0_8="Checking that the response does not contain an address from 127.0.0.8"
  ONE_IP_FOR_TWO_DOMAINS="Checking IP for two different domains"
  IPS_ARE_THE_SAME="IPs are the same"
  IPS_ARE_DIFFERENT="IPs are different"
  RESPONSE_IS_NOT_BLANK="Checking if response is not blank"
  DNS_POISONING_CHECK="Сomparing response from unencrypted DNS and DoH (DNS poisoning)"
  TELEGRAM_CHANNEL="Telegram channel"
  TELEGRAM_CHAT="Telegram chat"
}

set_language_ru() {
  DEVICE_MODEL="Модель"
  OPENWRT_VERSION="Версия"
  CURRENT_DATE="Дата"
  INSTALLED="установлен"
  NOT_INSTALLED="не установлен"
  RUNNING="запущен"
  NOT_RUNNING="не запущен"
  ENABLED="включен"
  DISABLED="выключен"
  EXISTS="существует"
  DOESNT_EXIST="не существует"
  UNSUPPORTED_OPENWRT="Вы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт проверки её не поддерживает."
  RAM_WARNING="У вашего роутера менее $MIN_RAM МБ ОЗУ. Рекомендуется использовать только vpn_domains set."
  CURL_INSTALLED="$CURL_PACKAGE $INSTALLED"
  CURL_NOT_INSTALLED="$CURL_PACKAGE $NOT_INSTALLED. Установите его: opkg install $CURL_PACKAGE"
  DNSMASQ_FULL_INSTALLED="$DNSMASQ_FULL_PACKAGE $INSTALLED"
  DNSMASQ_FULL_NOT_INSTALLED="$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED"
  DNSMASQ_FULL_DETAILS="Если вы не используете vpn_domains set, это нормально\nПроверьте версию: opkg list-installed | grep $DNSMASQ_FULL_PACKAGE\nТребуемая версия >= $DNSMASQ_FULL_REQUIRED_VERSION. Для OpenWrt 22.03 следуйте инструкции: https://t.me/itdoginfo/12"
  OPENWRT_21_DETAILS="\nВы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт её не поддерживает.\nИнструкция для OpenWrt $UNSUPPORTED_OPENWRT_VERSION: https://t.me/itdoginfo/8"
  XRAY_CORE_PACKAGE_DETECTED="Обнаружен пакет $XRAY_CORE_PACKAGE"
  LUCI_APP_XRAY_PACKAGE_DETECTED="Обнаружен пакет $LUCI_APP_XRAY_PACKAGE, который не совместим. Удалите его: opkg remove $LUCI_APP_XRAY_PACKAGE --force-removal-of-dependent-packages"
  DNSMASQ_SERVICE_RUNNING="Сервис $DNSMASQ_PACKAGE $RUNNING"
  DNSMASQ_SERVICE_NOT_RUNNING="Сервис $DNSMASQ_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: /etc/config/dhcp"
  INTERNET_IS_AVAILABLE="Интернет доступен"
  INTERNET_IS_NOT_AVAILABLE="Интернет недоступен"
  INTERNET_DETAILS="Проверьте подключение к интернету. Если оно в порядке, проверьте дату на роутере. Подробности: https://cli.co/2EaW4rO\nДополнительно выполните: curl -Is https://community.antifilter.download/"
  IPV6_DETECTED="Обнаружен IPv6. Этот скрипт не поддерживает работу с IPv6"
  WIREGUARD_TOOLS_INSTALLED="$WIREGUARD_TOOLS_PACKAGE $INSTALLED"
  WIREGUARD_ROUTING_DOESNT_WORK="Туннель к $WIREGUARD_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера. Подробности: https://cli.co/RSCvOxI"
  WIREGUARD_TUNNEL_NOT_WORKING="Плохие новости: туннель $WIREGUARD_PROTOCOL не работает. Проверьте конфигурацию $WIREGUARD_PROTOCOL. Подробности: https://cli.co/hGUUXDs\nЕсли вы не используете $WIREGUARD_PROTOCOL, а, например, $OPENVPN_PROTOCOL, то это нормально"
  WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED="$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/SaxBzH7"
  WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED="$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED"
  WIREGUARD_ROUTING_TABLE_EXISTS="Таблица маршрутизации $WIREGUARD_PROTOCOL $EXISTS"
  WIREGUARD_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $WIREGUARD_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3"
  OPENVPN_INSTALLED="$OPENVPN_PACKAGE $INSTALLED"
  OPENVPN_ROUTING_DOESNT_WORK="Туннель к $OPENVPN_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера."
  OPENVPN_TUNNEL_NOT_WORKING="Плохие новости: туннель $OPENVPN_PROTOCOL не работает. Проверьте конфигурацию $OPENVPN_PROTOCOL."
  OPENVPN_REDIRECT_GATEWAY_ENABLED="$OPENVPN_PROTOCOL redirect-gateway $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/vzTNq_3"
  OPENVPN_REDIRECT_GATEWAY_DISABLED="$OPENVPN_PROTOCOL redirect-gateway $DISABLED"
  OPENVPN_ROUTING_TABLE_EXISTS="Таблица маршрутизации $OPENVPN_PROTOCOL $EXISTS"
  OPENVPN_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $OPENVPN_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3"
  SINGBOX_INSTALLED="$SINGBOX_PACKAGE $INSTALLED"
  SINGBOX_ROUTING_TABLE_EXISTS="Таблица маршрутизации $SINGBOX_PACKAGE $EXISTS"
  SINGBOX_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $SINGBOX_PACKAGE $DOESNT_EXIST. Попробуйте: service network restart. Подробности: https://cli.co/n7xAbc1"
  SINGBOX_UCI_CONFIG_OK="UCI конфигурация для $SINGBOX_PACKAGE успешно проверена"
  SINGBOX_UCI_CONFIG_ERROR="Ошибка валидации UCI конфигурации для $SINGBOX_PACKAGE"
  SINGBOX_CONFIG_OK="Конфигурация $SINGBOX_PACKAGE успешно проверена"
  SINGBOX_CONFIG_ERROR="Ошибка валидации конфигурации $SINGBOX_PACKAGE"
  SINGBOX_WORKING_TEMPLATE="$SINGBOX_PACKAGE работает. VPN IP: %s"
  SINGBOX_ROUTING_DOESNT_WORK="$SINGBOX_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/Badmn3K"
  TUN2SOCKS_INSTALLED="$TUN2SOCKS_PACKAGE $INSTALLED"
  TUN2SOCKS_ROUTING_TABLE_EXISTS="Таблица маршрутизации $TUN2SOCKS_PROTOCOL $EXISTS"
  TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $TUN2SOCKS_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/n7xAbc1"
  TUN2SOCKS_WORKING_TEMPLATE="$TUN2SOCKS_PACKAGE работает. VPN IP: %s"
  TUN2SOCKS_ROUTING_DOESNT_WORK="$TUN2SOCKS_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/VNZISEM"
  VPN_DOMAINS_SET_EXISTS="vpn_domains set $EXISTS"
  VPN_DOMAINS_SET_DOESNT_EXIST="vpn_domains set $DOESNT_EXIST"
  IPS_IN_VPN_DOMAINS_SET_OK="IP-адреса успешно добавлены в vpn_domains set"
  IPS_IN_VPN_DOMAINS_SET_ERROR="IP-адреса не добавлены в vpn_domains set"
  VPN_DOMAINS_DETAILS="Если вы не используете vpn_domains, все в порядке.\nНо если вы хотите использовать его, проверьте конфигурацию и выполните: service getdomains start"
  VPN_DOMAINS_DETAILS_2="Если вы не используете vpn_domains, все в порядке.\nНо если вы хотите использовать, проверьте конфигурацию: https://cli.co/AwUGeM6"
  VPN_IP_SET_EXISTS="vpn_ip set $EXISTS"
  VPN_IP_SET_DOESNT_EXIST="vpn_ip set $DOESNT_EXIST"
  IPS_IN_VPN_IP_SET_OK="IP-адреса успешно добавлены в set vpn_ip"
  IPS_IN_VPN_IP_SET_ERROR="IP-адреса не добавлены в set vpn_ip"
  VPN_SUBNET_SET_EXISTS="vpn_subnet set $EXISTS"
  VPN_SUBNET_SET_DOESNT_EXIST="vpn_subnet set $DOESNT_EXIST"
  IPS_IN_VPN_SUBNET_SET_OK="IP-адреса успешно добавлены в set vpn_subnet"
  IPS_IN_VPN_SUBNET_SET_ERROR="IP-адреса не добавлены в set vpn_subnet"
  VPN_COMMUNITY_SET_EXISTS="vpn_community set $EXISTS"
  VPN_COMMUNITY_SET_DOESNT_EXIST="vpn_community set $DOESNT_EXIST"
  IPS_IN_VPN_COMMUNITY_SET_OK="IP-адреса успешно добавлены в set vpn_community"
  IPS_IN_VPN_COMMUNITY_SET_ERROR="IP-адреса не добавлены в set vpn_community"
  GETDOMAINS_SCRIPT_EXISTS="Скрипт $GETDOMAINS_SCRIPT_FILENAME $EXISTS"
  GETDOMAINS_SCRIPT_DOESNT_EXIST="Скрипт $GETDOMAINS_SCRIPT_FILENAME $DOESNT_EXIST"
  GETDOMAINS_SCRIPT_CRONTAB_OK="Скрипт $GETDOMAINS_SCRIPT_FILENAME успешно добавлен в crontab"
  GETDOMAINS_SCRIPT_CRONTAB_ERROR="Скрипт $GETDOMAINS_SCRIPT_FILENAME не был добавлен в crontab. Проверьте: crontab -l"
  DNSCRYPT_INSTALLED="$DNSCRYPT_PACKAGE $INSTALLED"
  DNSCRYPT_SERVICE_RUNNING="Сервис $DNSCRYPT_PACKAGE $RUNNING"
  DNSCRYPT_SERVICE_NOT_RUNNING="Сервис $DNSCRYPT_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/wN-tc_S"
  DNSMASQ_CONFIG_FOR_DNSCRYPT_OK="Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE в порядке"
  DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR="Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/rooc0uz"
  STUBBY_INSTALLED="$STUBBY_PACKAGE $INSTALLED"
  STUBBY_SERVICE_RUNNING="Сервис $STUBBY_PACKAGE $RUNNING"
  STUBBY_SERVICE_NOT_RUNNING="Сервис $STUBBY_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/HbDBT2V"
  DNSMASQ_CONFIG_FOR_STUBBY_OK="Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE в порядке"
  DNSMASQ_CONFIG_FOR_STUBBY_ERROR="Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/HbDBT2V"
  DUMP_CREATION="Создание дампа без приватных переменных"
  DUMP_DETAILS="Дамп находится здесь: $DUMP_PATH\nДля загрузки на Linux/Mac используйте: scp root@IP_ROUTER:$DUMP_PATH .\nДля Windows используйте WinSCP/PSCP или WSL"
  DNS_CHECK="Проверка DNS серверов"
  IS_DNS_TRAFFIC_BLOCKED="Проверяем блокировку DNS трафика (Порт 53/udp доступен)"
  IS_DOH_AVAILABLE="Проверяем доступность DoH"
  RESPONSE_NOT_CONTAINS_127_0_0_8="Проверяем, что ответ на запрос не содержит адреса из 127.0.0.8"
  ONE_IP_FOR_TWO_DOMAINS="Проверяем IP для двух разных доменов"
  IPS_ARE_THE_SAME="IP совпадают"
  IPS_ARE_DIFFERENT="IP различаются"
  RESPONSE_IS_NOT_BLANK="Проверяем, что ответ не пустой"
  DNS_POISONING_CHECK="Сравниваем ответ от незащищенного DNS и DoH (Подмена DNS)"
  TELEGRAM_CHANNEL="Telegram канал"
  TELEGRAM_CHAT="Telegram чат"
}

checkpoint_true() {
  printf "$COLOR_BOLD_GREEN[\342\234\223] $1$COLOR_RESET\n"
}

checkpoint_false() {
  printf "$COLOR_BOLD_RED[x] $1$COLOR_RESET\n"
}

output_21() {
  if [ "$VERSION_ID" -eq 21 ]; then
    echo "$UNSUPPORTED_OPENWRT"
  fi
}

update_vpn_ip() {
  local template="$1"
  local ip="$2"
  echo "$(printf "$template" "$ip")"
}

while [ $# -gt 0 ]; do
  case "$1" in
    --lang)
      LANGUAGE="$2"
      shift 2
      ;;
    dump | dns)
      COMMAND="$1"
      shift 1
      ;;
    *)
      printf "$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unknown option: %s\n" "$1"
      exit 1
      ;;
  esac
done

case $LANGUAGE in
  ru)
    set_language_ru
    ;;
  en)
    set_language_en
    ;;
  *)
    printf "$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unsupported language '$LANGUAGE'. Supported languages: $SUPPORTED_LANGUAGES %s\n" "$1"
    exit 1
    ;;
esac

# System Details
MODEL=$(cat /tmp/sysinfo/model)
source /etc/os-release
printf "$COLOR_BOLD_BLUE$DEVICE_MODEL: $MODEL$COLOR_RESET\n"
printf "$COLOR_BOLD_BLUE$OPENWRT_VERSION: $OPENWRT_RELEASE$COLOR_RESET\n"
printf "$COLOR_BOLD_BLUE$CURRENT_DATE: $(date)$COLOR_RESET\n"

VERSION_ID=$(echo $VERSION | awk -F. '{print $1}')
RAM=$(free -m | grep Mem: | awk '{print $2}')
if [[ "$VERSION_ID" -ge 22 && "$RAM" -lt 150000 ]]; then
  echo "$RAM_WARNING"
fi

# Check packages
CURL=$(opkg list-installed | grep -c curl)
if [ $CURL -eq 2 ]; then
  checkpoint_true "$CURL_INSTALLED"
else
  checkpoint_false "$CURL_NOT_INSTALLED"
fi

DNSMASQ=$(opkg list-installed | grep dnsmasq-full | awk -F "-" '{print $3}' | tr -d '.')
if [ $DNSMASQ -ge 287 ]; then
  checkpoint_true "$DNSMASQ_FULL_INSTALLED"
else
  checkpoint_false "$DNSMASQ_FULL_NOT_INSTALLED"
  printf "$DNSMASQ_FULL_DETAILS\n"
  if [ "$VERSION_ID" -eq 21 ]; then
    printf "$OPENWRT_21_DETAILS\n"
  fi
fi

# Chek xray package
if opkg list-installed | grep -q xray-core; then
  checkpoint_false "$XRAY_CORE_PACKAGE_DETECTED"
fi

if opkg list-installed | grep -q luci-app-xray; then
  checkpoint_false "$LUCI_APP_XRAY_PACKAGE_DETECTED"
fi

# Check dnsmasq
DNSMASQ_RUN=$(service dnsmasq status | grep -c 'running')
if [ $DNSMASQ_RUN -eq 1 ]; then
  checkpoint_true "$DNSMASQ_SERVICE_RUNNING"
else
  checkpoint_false "$DNSMASQ_SERVICE_NOT_RUNNING"
  output_21
fi

# Check internet connection
if curl -Is https://community.antifilter.download/ | grep -q 200; then
  checkpoint_true "$INTERNET_IS_AVAILABLE"
else
  checkpoint_false "$INTERNET_IS_NOT_AVAILABLE"
  if [ $CURL -lt 2 ]; then
    echo "$CURL_NOT_INSTALLED"
  else
    printf "$INTERNET_DETAILS\n"
  fi
fi

# Check IPv6

if curl -6 -s https://ifconfig.io | egrep -q "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?"; then
  checkpoint_false "$IPV6_DETECTED"
fi

# Tunnels
WIREGUARD=$(opkg list-installed | grep -c wireguard-tools)
if [ $WIREGUARD -eq 1 ]; then
  checkpoint_true "$WIREGUARD_TOOLS_INSTALLED"
  WG=true
fi

if [ "$WG" == true ]; then
  WG_PING=$(ping -c 1 -q -I wg0 itdog.info | grep -c "1 packets received")
  if [ $WG_PING -eq 1 ]; then
    checkpoint_true "$WIREGUARD_PROTOCOL"
  else
    checkpoint_false "$WIREGUARD_PROTOCOL"
    WG_TRACE=$(traceroute -i wg0 itdog.info -m 1 | grep ms | awk '{print $2}' | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
    if [ $WG_TRACE -eq 1 ]; then
      echo "$WIREGUARD_ROUTING_DOESNT_WORK"
    else
      printf "$WIREGUARD_TUNNEL_NOT_WORKING\n"
    fi
  fi

  # Check WG route_allowed_ips
  if uci show network | grep -q ".route_allowed_ips='1'"; then
    checkpoint_false "$WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED"
  else
    checkpoint_true "$WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED"
  fi

  # Check route table
  ROUTE_TABLE=$(ip route show table vpn | grep -c "default dev wg0")
  if [ $ROUTE_TABLE -eq 1 ]; then
    checkpoint_true "$WIREGUARD_ROUTING_TABLE_EXISTS"
  else
    checkpoint_false "$WIREGUARD_ROUTING_TABLE_DOESNT_EXIST"
  fi
fi

if opkg list-installed | grep -q openvpn; then
  checkpoint_true "$OPENVPN_INSTALLED"
  OVPN=true
fi

# Check OpenVPN
if [ "$OVPN" == true ]; then
  if ping -c 1 -q -I tun0 itdog.info | grep -q "1 packets received"; then
    checkpoint_true "$OPENVPN_PROTOCOL"
  else
    checkpoint_false "$OPENVPN_PROTOCOL"
    if traceroute -i tun0 itdog.info -m 1 | grep ms | awk '{print $2}' | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'; then
      echo "$OPENVPN_ROUTING_DOESNT_WORK"
    else
      echo "$OPENVPN_TUNNEL_NOT_WORKING"
    fi
  fi

  # Check OpenVPN redirect-gateway
  if grep -q redirect-gateway /etc/openvpn/*; then
    checkpoint_false "$OPENVPN_REDIRECT_GATEWAY_ENABLED"
  else
    checkpoint_true "$OPENVPN_REDIRECT_GATEWAY_DISABLED"
  fi

  # Check route table
  if ip route show table vpn | grep -q "default dev tun0"; then
    checkpoint_true "$OPENVPN_ROUTING_TABLE_EXISTS"
  else
    checkpoint_false "$OPENVPN_ROUTING_TABLE_DOESNT_EXIST"
  fi
fi

if opkg list-installed | grep -q sing-box; then
  checkpoint_true "$SINGBOX_INSTALLED"

  # Check route table
  if ip route show table vpn | grep -q "default dev tun0"; then
    checkpoint_true "$SINGBOX_ROUTING_TABLE_EXISTS"
  else
    checkpoint_false "$SINGBOX_ROUTING_TABLE_DOESNT_EXIST"
  fi

  # Sing-box uci validation
  if uci show sing-box 2>&1 | grep -q "Parse error"; then
    checkpoint_false "$SINGBOX_UCI_CONFIG_ERROR"
  else
    checkpoint_true "$SINGBOX_UCI_CONFIG_OK"
  fi

  singbox_check_cmd="sing-box -c /etc/sing-box/config.json check"
  if $singbox_check_cmd >/dev/null 2>&1; then
    checkpoint_true "$SINGBOX_CONFIG_OK"

    # Check traffic
    IP_EXTERNAL=$(curl -s ifconfig.me)
    IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}')

    IP_VPN=$(curl --interface tun0 -s ifconfig.me)

    SINGBOX_WORKING=$(update_vpn_ip "$SINGBOX_WORKING_TEMPLATE" "$IP_VPN")

    if [ "$IP_EXTERNAL" != $IP_VPN ]; then
      checkpoint_true "$SINGBOX_WORKING"
    else
      checkpoint_false "$SINGBOX_ROUTING_DOESNT_WORK"
    fi
  else
    checkpoint_false "$SINGBOX_CONFIG_ERROR:"
    $singbox_check_cmd
  fi
fi

if which tun2socks | grep -q tun2socks; then
  checkpoint_true "$TUN2SOCKS_INSTALLED"

  # Check route table
  if ip route show table vpn | grep -q "default dev tun0"; then
    checkpoint_true "$TUN2SOCKS_ROUTING_TABLE_EXISTS"
  else
    checkpoint_false "$TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST"
  fi

  IP_EXTERNAL=$(curl -s ifconfig.me)
  IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}')

  IP_VPN=$(curl --interface tun0 -s ifconfig.me)

  TUN2SOCKS_WORKING=$(update_vpn_ip "$TUN2SOCKS_WORKING_TEMPLATE" "$IP_VPN")

  if [ "$IP_EXTERNAL" != $IP_VPN ]; then
    checkpoint_true "$TUN2SOCKS_WORKING"
  else
    checkpoint_false "$TUN2SOCKS_ROUTING_DOESNT_WORK"
  fi
fi

# Check sets

# vpn_domains set
vpn_domain_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_domain_ipset_string=$(uci show firewall.@ipset[$vpn_domain_ipset_id] | grep -c "name='vpn_domains'\|match='dst_net'")
vpn_domain_rule_id=$(uci show firewall | grep -E '@rule.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_domain_rule_string=$(uci show firewall.@rule[$vpn_domain_rule_id] | grep -c "name='mark_domains'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_domains'\|set_mark='0x1'\|target='MARK'\|family='ipv4'")

if [ $((vpn_domain_ipset_string + vpn_domain_rule_string)) -eq 10 ]; then
  checkpoint_true "$VPN_DOMAINS_SET_EXISTS"

  # force resolve for vpn_domains. All list
  nslookup terraform.io 127.0.0.1 >/dev/null
  nslookup pochta.ru 127.0.0.1 >/dev/null
  nslookup 2gis.ru 127.0.0.1 >/dev/null

  VPN_DOMAINS_IP=$(nft list ruleset | grep -A 10 vpn_domains | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
  if [ $VPN_DOMAINS_IP -ge 1 ]; then
    checkpoint_true "$IPS_IN_VPN_DOMAINS_SET_OK"
  else
    checkpoint_false "$IPS_IN_VPN_DOMAINS_SET_ERROR"
    printf "$VPN_DOMAINS_DETAILS\n"
    output_21
  fi
else
  checkpoint_false "$VPN_DOMAINS_SET_DOESNT_EXIST"
  printf "$VPN_DOMAINS_DETAILS_2\n"
fi

# vpn_ip set
vpn_ip_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_ip_ipset_string=$(uci show firewall.@ipset[$vpn_ip_ipset_id] | grep -c "name='vpn_ip'\|match='dst_net'\|loadfile='/tmp/lst/ip.lst'")
vpn_ip_rule_id=$(uci show firewall | grep -E '@rule.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_ip_rule_string=$(uci show firewall.@rule[$vpn_ip_rule_id] | grep -c "name='mark_ip'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_ip'\|set_mark='0x1'\|target='MARK'\|family='ipv4'")

if [ $((vpn_ip_ipset_string + vpn_ip_rule_string)) -eq 11 ]; then
  checkpoint_true "$VPN_IP_SET_EXISTS"
  VPN_IP_IP=$(nft list ruleset | grep -A 10 vpn_ip | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
  if [ $VPN_IP_IP -ge 1 ]; then
    checkpoint_true "$IPS_IN_VPN_IP_SET_OK"
  else
    checkpoint_false "$IPS_IN_VPN_IP_SET_ERROR"
    output_21
  fi
elif uci show firewall | grep -q "vpn_ip"; then
  checkpoint_false "$VPN_IP_SET_DOESNT_EXIST"
fi

# vpn_subnet set
vpn_subnet_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_subnet_ipset_string=$(uci show firewall.@ipset[$vpn_subnet_ipset_id] | grep -c "name='vpn_subnets'\|match='dst_net'\|loadfile='/tmp/lst/subnet.lst'")
vpn_subnet_rule_id=$(uci show firewall | grep -E '@rule.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_subnet_rule_string=$(uci show firewall.@rule[$vpn_subnet_rule_id] | grep -c "name='mark_subnet'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_subnets'\|set_mark='0x1'\|target='MARK'\|family='ipv4'")

if [ $((vpn_subnet_ipset_string + vpn_subnet_rule_string)) -eq 11 ]; then
  checkpoint_true "$VPN_SUBNET_SET_EXISTS"
  VPN_IP_SUBNET=$(nft list ruleset | grep -A 10 vpn_subnet | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
  if [ $VPN_IP_SUBNET -ge 1 ]; then
    checkpoint_true "$IPS_IN_VPN_SUBNET_SET_OK"
  else
    checkpoint_false "$IPS_IN_VPN_SUBNET_SET_ERROR"
    output_21
  fi
elif uci show firewall | grep -q "vpn_subnet"; then
  checkpoint_false "$VPN_SUBNET_SET_DOESNT_EXIST"
fi

# vpn_community set
vpn_community_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_community_ipset_string=$(uci show firewall.@ipset[$vpn_community_ipset_id] | grep -c "name='vpn_community'\|match='dst_net'\|loadfile='/tmp/lst/community.lst'")
vpn_community_rule_id=$(uci show firewall | grep -E '@rule.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1)
vpn_community_rule_string=$(uci show firewall.@rule[$vpn_community_rule_id] | grep -c "name='mark_community'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_community'\|set_mark='0x1'\|target='MARK'\|family='ipv4'")

if [ $((vpn_community_ipset_string + vpn_community_rule_string)) -eq 11 ]; then
  checkpoint_true "$VPN_COMMUNITY_SET_EXISTS"
  VPN_COMMUNITY_IP=$(nft list ruleset | grep -A 10 vpn_community | grep -c -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
  if [ $VPN_COMMUNITY_IP -ge 1 ]; then
    checkpoint_true "$IPS_IN_VPN_COMMUNITY_SET_OK"
  else
    checkpoint_false "$IPS_IN_VPN_COMMUNITY_SET_ERROR"
    output_21
  fi
elif uci show firewall | grep -q "vpn_community"; then
  checkpoint_false "$VPN_COMMUNITY_SET_DOESNT_EXIST"
fi

# getdomains script
if [ -s "$GETDOMAINS_SCRIPT_PATH" ]; then
  checkpoint_true "$GETDOMAINS_SCRIPT_EXISTS"
  if crontab -l | grep -q $GETDOMAINS_SCRIPT_PATH; then
    checkpoint_true "$GETDOMAINS_SCRIPT_CRONTAB_OK"
  else
    checkpoint_false "$GETDOMAINS_SCRIPT_CRONTAB_ERROR"
  fi
else
  checkpoint_false "$GETDOMAINS_SCRIPT_DOESNT_EXIST"
fi

# DNS

# DNSCrypt
if opkg list-installed | grep -q dnscrypt-proxy2; then
  checkpoint_true "$DNSCRYPT_INSTALLED"
  if service dnscrypt-proxy status | grep -q 'running'; then
    checkpoint_true "$DNSCRYPT_SERVICE_RUNNING"
  else
    checkpoint_false "$DNSCRYPT_SERVICE_NOT_RUNNING"
    output_21
  fi

  DNSMASQ_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c "127.0.0.53#53\|noresolv='1'")
  if [ $DNSMASQ_STRING -eq 2 ]; then
    checkpoint_true "$DNSMASQ_CONFIG_FOR_DNSCRYPT_OK"
  else
    checkpoint_false "$DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR"
  fi
fi

# Stubby
if opkg list-installed | grep -q stubby; then
  checkpoint_true "$STUBBY_INSTALLED"
  if service stubby status | grep -q 'running'; then
    checkpoint_true "$STUBBY_SERVICE_RUNNING"
  else
    checkpoint_false "$STUBBY_SERVICE_NOT_RUNNING"
    output_21
  fi

  STUBBY_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c "127.0.0.1#5453\|noresolv='1'")
  if [ $STUBBY_STRING -eq 2 ]; then
    checkpoint_true "$DNSMASQ_CONFIG_FOR_STUBBY_OK"
  else
    checkpoint_false "$DNSMASQ_CONFIG_FOR_STUBBY_ERROR"
  fi
fi

case $COMMAND in
  dump)
    # Create dump
    printf "\n$COLOR_BOLD_CYAN$DUMP_CREATION$COLOR_RESET\n"
    date >$DUMP_PATH
    $HIVPN start >>$DUMP_PATH 2>&1
    $GETDOMAINS_SCRIPT_PATH start >>$DUMP_PATH 2>&1
    uci show firewall >>$DUMP_PATH
    uci show network | sed -r 's/(.*private_key=|.*preshared_key=|.*public_key=|.*endpoint_host=|.*wan.ipaddr=|.*wan.netmask=|.*wan.gateway=|.*wan.dns|.*.macaddr=).*/\1REMOVED/' >>$DUMP_PATH
    printf "$DUMP_DETAILS\n"
    ;;
  dns)
    # Check DNS
    printf "\n$COLOR_BOLD_CYAN$DNS_CHECK$COLOR_RESET\n"
    DNS_SERVERS="1.1.1.1 8.8.8.8 8.8.4.4"
    DOH_DNS_SERVERS="cloudflare-dns.com 1.1.1.1 mozilla.cloudflare-dns.com security.cloudflare-dns.com"
    DOMAINS="instagram.com facebook.com"

    echo "1. $IS_DNS_TRAFFIC_BLOCKED"

    for i in $DNS_SERVERS; do
      if nslookup -type=a -timeout=2 -retry=1 itdog.info $i | grep -q "timed out"; then
        checkpoint_false "$i"
      else
        checkpoint_true "$i"
      fi
    done

    echo "2. $IS_DOH_AVAILABLE"

    for i in $DOH_DNS_SERVERS; do
      if curl --connect-timeout 5 -s -H "accept: application/dns-json" "https://$i/dns-query?name=itdog.info&type=A" | awk -F"data\":\"" '/data":"/{print $2}' | grep -q -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'; then
        checkpoint_true "$i"
      else
        checkpoint_false "$i"
      fi
    done

    echo "3. $RESPONSE_NOT_CONTAINS_127_0_0_8"

    for i in $DOMAINS; do
      if nslookup -type=a -timeout=2 -retry=1 $i | awk '/^Address: / {print $2}' | grep -q -E '127\.[0-9]{1,3}\.'; then
        checkpoint_false "$i"
      else
        checkpoint_true "$i"
      fi
    done

    echo "4. $ONE_IP_FOR_TWO_DOMAINS"

    FIRSTIP=$(nslookup -type=a instagram.com | awk '/^Address: / {print $2}')
    SECONDIP=$(nslookup -type=a facebook.com | awk '/^Address: / {print $2}')

    if [ "$FIRSTIP" = "$SECONDIP" ]; then
      checkpoint_false "$IPS_ARE_THE_SAME"
    else
      checkpoint_true "$IPS_ARE_DIFFERENT"
    fi

    echo "5. $RESPONSE_IS_NOT_BLANK"

    for i in $DOMAINS; do
      if nslookup -type=a -timeout=2 -retry=1 $i | awk '/^Address: / {print $2}' | grep -q -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'; then
        checkpoint_true "$i"
      else
        checkpoint_false "$i"
      fi
    done

    echo "6. $DNS_POISONING_CHECK"

    DOHIP=$(curl -s -H "accept: application/dns-json" "https://1.1.1.1/dns-query?name=facebook.com&type=A" | awk -F"data\":\"" '/data":"/{print $2}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
    OPENIP=$(nslookup -type=a -timeout=2 facebook.com 1.1.1.1 | awk '/^Address: / {print $2}')

    if [ "$DOHIP" = "$OPENIP" ]; then
      checkpoint_true "$IPS_ARE_THE_SAME"
    else
      checkpoint_false "$IPS_ARE_DIFFERENT"
    fi
    ;;
  *) ;;
esac

# Info
echo -e "\n$TELEGRAM_CHANNEL: https://t.me/itdoginfo"
echo "$TELEGRAM_CHAT: https://t.me/itdogchat"


================================================
FILE: getdomains-install.sh
================================================
#!/bin/sh

#set -x

check_repo() {
    printf "\033[32;1mChecking OpenWrt repo availability...\033[0m\n"
    opkg update | grep -q "Failed to download" && printf "\033[32;1mopkg failed. Check internet or date. Command for force ntp sync: ntpd -p ptbtime1.ptb.de\033[0m\n" && exit 1
}

route_vpn () {
    if [ "$TUNNEL" == wg ]; then
cat << EOF > /etc/hotplug.d/iface/30-vpnroute
#!/bin/sh

ip route add table vpn default dev wg0
EOF
    elif [ "$TUNNEL" == awg ]; then
cat << EOF > /etc/hotplug.d/iface/30-vpnroute
#!/bin/sh

ip route add table vpn default dev awg0
EOF
    elif [ "$TUNNEL" == singbox ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then
cat << EOF > /etc/hotplug.d/iface/30-vpnroute
#!/bin/sh

sleep 10
ip route add table vpn default dev tun0
EOF
    fi

    cp /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute
}

add_mark() {
    grep -q "99 vpn" /etc/iproute2/rt_tables || echo '99 vpn' >> /etc/iproute2/rt_tables
    
    if ! uci show network | grep -q mark0x1; then
        printf "\033[32;1mConfigure mark rule\033[0m\n"
        uci add network rule
        uci set network.@rule[-1].name='mark0x1'
        uci set network.@rule[-1].mark='0x1'
        uci set network.@rule[-1].priority='100'
        uci set network.@rule[-1].lookup='vpn'
        uci commit
    fi
}

add_tunnel() {
    echo "We can automatically configure only Wireguard and Amnezia WireGuard. OpenVPN, Sing-box(Shadowsocks2022, VMess, VLESS, etc) and tun2socks will need to be configured manually"
    echo "Select a tunnel:"
    echo "1) WireGuard"
    echo "2) OpenVPN"
    echo "3) Sing-box"
    echo "4) tun2socks"
    echo "5) wgForYoutube"
    echo "6) Amnezia WireGuard"
    echo "7) Amnezia WireGuard For Youtube"
    echo "8) Skip this step"

    while true; do
    read -r -p '' TUNNEL
        case $TUNNEL in 

        1) 
            TUNNEL=wg
            break
            ;;

        2)
            TUNNEL=ovpn
            break
            ;;

        3) 
            TUNNEL=singbox
            break
            ;;

        4) 
            TUNNEL=tun2socks
            break
            ;;

        5) 
            TUNNEL=wgForYoutube
            break
            ;;

        6) 
            TUNNEL=awg
            break
            ;;

        7) 
            TUNNEL=awgForYoutube
            break
            ;;

        8)
            echo "Skip"
            TUNNEL=0
            break
            ;;

        *)
            echo "Choose from the following options"
            ;;
        esac
    done

    if [ "$TUNNEL" == 'wg' ]; then
        printf "\033[32;1mConfigure WireGuard\033[0m\n"
        if opkg list-installed | grep -q wireguard-tools; then
            echo "Wireguard already installed"
        else
            echo "Installed wg..."
            opkg install wireguard-tools
        fi

        route_vpn

        read -r -p "Enter the private key (from [Interface]):"$'\n' WG_PRIVATE_KEY

        while true; do
            read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):"$'\n' WG_IP
            if echo "$WG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then
                break
            else
                echo "This IP is not valid. Please repeat"
            fi
        done

        read -r -p "Enter the public key (from [Peer]):"$'\n' WG_PUBLIC_KEY
        read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' WG_PRESHARED_KEY
        read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' WG_ENDPOINT

        read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' WG_ENDPOINT_PORT
        WG_ENDPOINT_PORT=${WG_ENDPOINT_PORT:-51820}
        if [ "$WG_ENDPOINT_PORT" = '51820' ]; then
            echo $WG_ENDPOINT_PORT
        fi
        
        uci set network.wg0=interface
        uci set network.wg0.proto='wireguard'
        uci set network.wg0.private_key=$WG_PRIVATE_KEY
        uci set network.wg0.listen_port='51820'
        uci set network.wg0.addresses=$WG_IP

        if ! uci show network | grep -q wireguard_wg0; then
            uci add network wireguard_wg0
        fi
        uci set network.@wireguard_wg0[0]=wireguard_wg0
        uci set network.@wireguard_wg0[0].name='wg0_client'
        uci set network.@wireguard_wg0[0].public_key=$WG_PUBLIC_KEY
        uci set network.@wireguard_wg0[0].preshared_key=$WG_PRESHARED_KEY
        uci set network.@wireguard_wg0[0].route_allowed_ips='0'
        uci set network.@wireguard_wg0[0].persistent_keepalive='25'
        uci set network.@wireguard_wg0[0].endpoint_host=$WG_ENDPOINT
        uci set network.@wireguard_wg0[0].allowed_ips='0.0.0.0/0'
        uci set network.@wireguard_wg0[0].endpoint_port=$WG_ENDPOINT_PORT
        uci commit
    fi

    if [ "$TUNNEL" == 'ovpn' ]; then
        if opkg list-installed | grep -q openvpn-openssl; then
            echo "OpenVPN already installed"
        else
            echo "Installed openvpn"
            opkg install openvpn-openssl
        fi
        printf "\033[32;1mConfigure route for OpenVPN\033[0m\n"
        route_vpn
    fi

    if [ "$TUNNEL" == 'singbox' ]; then
        if opkg list-installed | grep -q sing-box; then
            echo "Sing-box already installed"
        else
            AVAILABLE_SPACE=$(df / | awk 'NR>1 { print $4 }')
            if  [[ "$AVAILABLE_SPACE" -gt 2000 ]]; then
                echo "Installed sing-box"
                opkg install sing-box
            else
                printf "\033[31;1mNo free space for a sing-box. Sing-box is not installed.\033[0m\n"
                exit 1
            fi
        fi
        if grep -q "option enabled '0'" /etc/config/sing-box; then
            sed -i "s/	option enabled \'0\'/	option enabled \'1\'/" /etc/config/sing-box
        fi
        if grep -q "option user 'sing-box'" /etc/config/sing-box; then
            sed -i "s/	option user \'sing-box\'/	option user \'root\'/" /etc/config/sing-box
        fi
        if grep -q "tun0" /etc/sing-box/config.json; then
        printf "\033[32;1mConfig /etc/sing-box/config.json already exists\033[0m\n"
        else
cat << 'EOF' > /etc/sing-box/config.json
{
  "log": {
    "level": "debug"
  },
  "inbounds": [
    {
      "type": "tun",
      "interface_name": "tun0",
      "domain_strategy": "ipv4_only",
      "address": ["172.16.250.1/30"],
      "auto_route": false,
      "strict_route": false,
      "sniff": true 
   }
  ],
  "outbounds": [
    {
      "type": "$TYPE",
      "server": "$HOST",
      "server_port": $PORT,
      "method": "$METHOD",
      "password": "$PASS"
    }
  ],
  "route": {
    "auto_detect_interface": true
  }
}
EOF
        printf "\033[32;1mCreate template config in /etc/sing-box/config.json. Edit it manually. Official doc: https://sing-box.sagernet.org/configuration/outbound/\033[0m\n"
        printf "\033[32;1mOfficial doc: https://sing-box.sagernet.org/configuration/outbound/\033[0m\n"
        printf "\033[32;1mManual with example SS: https://cli.co/Badmn3K \033[0m\n"

        fi
        printf "\033[32;1mConfigure route for Sing-box\033[0m\n"
        route_vpn
    fi

    if [ "$TUNNEL" == 'wgForYoutube' ]; then
        add_internal_wg Wireguard
    fi

    if [ "$TUNNEL" == 'awgForYoutube' ]; then
        add_internal_wg AmneziaWG
    fi

    if [ "$TUNNEL" == 'awg' ]; then
        printf "\033[32;1mConfigure Amnezia WireGuard\033[0m\n"

        install_awg_packages

        route_vpn

        read -r -p "Enter the private key (from [Interface]):"$'\n' AWG_PRIVATE_KEY

        while true; do
            read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (Address from [Interface]):"$'\n' AWG_IP
            if echo "$AWG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then
                break
            else
                echo "This IP is not valid. Please repeat"
            fi
        done

        read -r -p "Enter Jc value (from [Interface]):"$'\n' AWG_JC
        read -r -p "Enter Jmin value (from [Interface]):"$'\n' AWG_JMIN
        read -r -p "Enter Jmax value (from [Interface]):"$'\n' AWG_JMAX
        read -r -p "Enter S1 value (from [Interface]):"$'\n' AWG_S1
        read -r -p "Enter S2 value (from [Interface]):"$'\n' AWG_S2
        read -r -p "Enter H1 value (from [Interface]):"$'\n' AWG_H1
        read -r -p "Enter H2 value (from [Interface]):"$'\n' AWG_H2
        read -r -p "Enter H3 value (from [Interface]):"$'\n' AWG_H3
        read -r -p "Enter H4 value (from [Interface]):"$'\n' AWG_H4
    
        read -r -p "Enter the public key (from [Peer]):"$'\n' AWG_PUBLIC_KEY
        read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' AWG_PRESHARED_KEY
        read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' AWG_ENDPOINT

        read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' AWG_ENDPOINT_PORT
        AWG_ENDPOINT_PORT=${AWG_ENDPOINT_PORT:-51820}
        if [ "$AWG_ENDPOINT_PORT" = '51820' ]; then
            echo $AWG_ENDPOINT_PORT
        fi
        
        uci set network.awg0=interface
        uci set network.awg0.proto='amneziawg'
        uci set network.awg0.private_key=$AWG_PRIVATE_KEY
        uci set network.awg0.listen_port='51820'
        uci set network.awg0.addresses=$AWG_IP

        uci set network.awg0.awg_jc=$AWG_JC
        uci set network.awg0.awg_jmin=$AWG_JMIN
        uci set network.awg0.awg_jmax=$AWG_JMAX
        uci set network.awg0.awg_s1=$AWG_S1
        uci set network.awg0.awg_s2=$AWG_S2
        uci set network.awg0.awg_h1=$AWG_H1
        uci set network.awg0.awg_h2=$AWG_H2
        uci set network.awg0.awg_h3=$AWG_H3
        uci set network.awg0.awg_h4=$AWG_H4

        if ! uci show network | grep -q amneziawg_awg0; then
            uci add network amneziawg_awg0
        fi

        uci set network.@amneziawg_awg0[0]=amneziawg_awg0
        uci set network.@amneziawg_awg0[0].name='awg0_client'
        uci set network.@amneziawg_awg0[0].public_key=$AWG_PUBLIC_KEY
        uci set network.@amneziawg_awg0[0].preshared_key=$AWG_PRESHARED_KEY
        uci set network.@amneziawg_awg0[0].route_allowed_ips='0'
        uci set network.@amneziawg_awg0[0].persistent_keepalive='25'
        uci set network.@amneziawg_awg0[0].endpoint_host=$AWG_ENDPOINT
        uci set network.@amneziawg_awg0[0].allowed_ips='0.0.0.0/0'
        uci set network.@amneziawg_awg0[0].endpoint_port=$AWG_ENDPOINT_PORT
        uci commit
    fi

}

dnsmasqfull() {
    if opkg list-installed | grep -q dnsmasq-full; then
        printf "\033[32;1mdnsmasq-full already installed\033[0m\n"
    else
        printf "\033[32;1mInstalled dnsmasq-full\033[0m\n"
        cd /tmp/ && opkg download dnsmasq-full
        opkg remove dnsmasq && opkg install dnsmasq-full --cache /tmp/

        [ -f /etc/config/dhcp-opkg ] && cp /etc/config/dhcp /etc/config/dhcp-old && mv /etc/config/dhcp-opkg /etc/config/dhcp
    fi
}

dnsmasqconfdir() {
    if [ $VERSION_ID -ge 24 ]; then
        if uci get dhcp.@dnsmasq[0].confdir | grep -q /tmp/dnsmasq.d; then
            printf "\033[32;1mconfdir already set\033[0m\n"
        else
            printf "\033[32;1mSetting confdir\033[0m\n"
            uci set dhcp.@dnsmasq[0].confdir='/tmp/dnsmasq.d'
            uci commit dhcp
        fi
    fi
}

remove_forwarding() {
    if [ ! -z "$forward_id" ]; then
        while uci -q delete firewall.@forwarding[$forward_id]; do :; done
    fi
}

add_zone() {
    if  [ "$TUNNEL" == 0 ]; then
        printf "\033[32;1mZone setting skipped\033[0m\n"
    elif uci show firewall | grep -q "@zone.*name='$TUNNEL'"; then
        printf "\033[32;1mZone already exist\033[0m\n"
    else
        printf "\033[32;1mCreate zone\033[0m\n"

        # Delete exists zone
        zone_tun_id=$(uci show firewall | grep -E '@zone.*tun0' | awk -F '[][{}]' '{print $2}' | head -n 1)
        if [ "$zone_tun_id" == 0 ] || [ "$zone_tun_id" == 1 ]; then
            printf "\033[32;1mtun0 zone has an identifier of 0 or 1. That's not ok. Fix your firewall. lan and wan zones should have identifiers 0 and 1. \033[0m\n"
            exit 1
        fi
        if [ ! -z "$zone_tun_id" ]; then
            while uci -q delete firewall.@zone[$zone_tun_id]; do :; done
        fi

        zone_wg_id=$(uci show firewall | grep -E '@zone.*wg0' | awk -F '[][{}]' '{print $2}' | head -n 1)
        if [ "$zone_wg_id" == 0 ] || [ "$zone_wg_id" == 1 ]; then
            printf "\033[32;1mwg0 zone has an identifier of 0 or 1. That's not ok. Fix your firewall. lan and wan zones should have identifiers 0 and 1. \033[0m\n"
            exit 1
        fi
        if [ ! -z "$zone_wg_id" ]; then
            while uci -q delete firewall.@zone[$zone_wg_id]; do :; done
        fi

        zone_awg_id=$(uci show firewall | grep -E '@zone.*awg0' | awk -F '[][{}]' '{print $2}' | head -n 1)
        if [ "$zone_awg_id" == 0 ] || [ "$zone_awg_id" == 1 ]; then
            printf "\033[32;1mawg0 zone has an identifier of 0 or 1. That's not ok. Fix your firewall. lan and wan zones should have identifiers 0 and 1. \033[0m\n"
            exit 1
        fi
        if [ ! -z "$zone_awg_id" ]; then
            while uci -q delete firewall.@zone[$zone_awg_id]; do :; done
        fi

        uci add firewall zone
        uci set firewall.@zone[-1].name="$TUNNEL"
        if [ "$TUNNEL" == wg ]; then
            uci set firewall.@zone[-1].network='wg0'
        elif [ "$TUNNEL" == awg ]; then
            uci set firewall.@zone[-1].network='awg0'
        elif [ "$TUNNEL" == singbox ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then
            uci set firewall.@zone[-1].device='tun0'
        fi
        if [ "$TUNNEL" == wg ] || [ "$TUNNEL" == awg ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then
            uci set firewall.@zone[-1].forward='REJECT'
            uci set firewall.@zone[-1].output='ACCEPT'
            uci set firewall.@zone[-1].input='REJECT'
        elif [ "$TUNNEL" == singbox ]; then
            uci set firewall.@zone[-1].forward='ACCEPT'
            uci set firewall.@zone[-1].output='ACCEPT'
            uci set firewall.@zone[-1].input='ACCEPT'
        fi
        uci set firewall.@zone[-1].masq='1'
        uci set firewall.@zone[-1].mtu_fix='1'
        uci set firewall.@zone[-1].family='ipv4'
        uci commit firewall
    fi
    
    if [ "$TUNNEL" == 0 ]; then
        printf "\033[32;1mForwarding setting skipped\033[0m\n"
    elif uci show firewall | grep -q "@forwarding.*name='$TUNNEL-lan'"; then
        printf "\033[32;1mForwarding already configured\033[0m\n"
    else
        printf "\033[32;1mConfigured forwarding\033[0m\n"
        # Delete exists forwarding
        if [[ $TUNNEL != "wg" ]]; then
            forward_id=$(uci show firewall | grep -E "@forwarding.*dest='wg'" | awk -F '[][{}]' '{print $2}' | head -n 1)
            remove_forwarding
        fi

        if [[ $TUNNEL != "awg" ]]; then
            forward_id=$(uci show firewall | grep -E "@forwarding.*dest='awg'" | awk -F '[][{}]' '{print $2}' | head -n 1)
            remove_forwarding
        fi

        if [[ $TUNNEL != "ovpn" ]]; then
            forward_id=$(uci show firewall | grep -E "@forwarding.*dest='ovpn'" | awk -F '[][{}]' '{print $2}' | head -n 1)
            remove_forwarding
        fi

        if [[ $TUNNEL != "singbox" ]]; then
            forward_id=$(uci show firewall | grep -E "@forwarding.*dest='singbox'" | awk -F '[][{}]' '{print $2}' | head -n 1)
            remove_forwarding
        fi

        if [[ $TUNNEL != "tun2socks" ]]; then
            forward_id=$(uci show firewall | grep -E "@forwarding.*dest='tun2socks'" | awk -F '[][{}]' '{print $2}' | head -n 1)
            remove_forwarding
        fi

        uci add firewall forwarding
        uci set firewall.@forwarding[-1]=forwarding
        uci set firewall.@forwarding[-1].name="$TUNNEL-lan"
        uci set firewall.@forwarding[-1].dest="$TUNNEL"
        uci set firewall.@forwarding[-1].src='lan'
        uci set firewall.@forwarding[-1].family='ipv4'
        uci commit firewall
    fi
}

show_manual() {
    if [ "$TUNNEL" == tun2socks ]; then
        printf "\033[42;1mZone for tun2socks cofigured. But you need to set up the tunnel yourself.\033[0m\n"
        echo "Use this manual: https://cli.co/VNZISEM"
    elif [ "$TUNNEL" == ovpn ]; then
        printf "\033[42;1mZone for OpenVPN cofigured. But you need to set up the tunnel yourself.\033[0m\n"
        echo "Use this manual: https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/"
    fi
}

add_set() {
    if uci show firewall | grep -q "@ipset.*name='vpn_domains'"; then
        printf "\033[32;1mSet already exist\033[0m\n"
    else
        printf "\033[32;1mCreate set\033[0m\n"
        uci add firewall ipset
        uci set firewall.@ipset[-1].name='vpn_domains'
        uci set firewall.@ipset[-1].match='dst_net'
        uci commit
    fi
    if uci show firewall | grep -q "@rule.*name='mark_domains'"; then
        printf "\033[32;1mRule for set already exist\033[0m\n"
    else
        printf "\033[32;1mCreate rule set\033[0m\n"
        uci add firewall rule
        uci set firewall.@rule[-1]=rule
        uci set firewall.@rule[-1].name='mark_domains'
        uci set firewall.@rule[-1].src='lan'
        uci set firewall.@rule[-1].dest='*'
        uci set firewall.@rule[-1].proto='all'
        uci set firewall.@rule[-1].ipset='vpn_domains'
        uci set firewall.@rule[-1].set_mark='0x1'
        uci set firewall.@rule[-1].target='MARK'
        uci set firewall.@rule[-1].family='ipv4'
        uci commit
    fi
}

add_dns_resolver() {
    echo "Configure DNSCrypt2 or Stubby? It does matter if your ISP is spoofing DNS requests"
    DISK=$(df -m / | awk 'NR==2{ print $2 }')
    if [[ "$DISK" -lt 32 ]]; then 
        printf "\033[31;1mYour router a disk have less than 32MB. It is not recommended to install DNSCrypt, it takes 10MB\033[0m\n"
    fi
    echo "Select:"
    echo "1) No [Default]"
    echo "2) DNSCrypt2 (10.7M)"
    echo "3) Stubby (36K)"

    while true; do
    read -r -p '' DNS_RESOLVER
        case $DNS_RESOLVER in 

        1) 
            echo "Skiped"
            break
            ;;

        2)
            DNS_RESOLVER=DNSCRYPT
            break
            ;;

        3) 
            DNS_RESOLVER=STUBBY
            break
            ;;

        *)
            echo "Choose from the following options"
            ;;
        esac
    done

    if [ "$DNS_RESOLVER" == 'DNSCRYPT' ]; then
        if opkg list-installed | grep -q dnscrypt-proxy2; then
            printf "\033[32;1mDNSCrypt2 already installed\033[0m\n"
        else
            printf "\033[32;1mInstalled dnscrypt-proxy2\033[0m\n"
            opkg install dnscrypt-proxy2
            if grep -q "# server_names" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml; then
                sed -i "s/^# server_names =.*/server_names = [\'google\', \'cloudflare\', \'scaleway-fr\', \'yandex\']/g" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml
            fi

            printf "\033[32;1mDNSCrypt restart\033[0m\n"
            service dnscrypt-proxy restart
            printf "\033[32;1mDNSCrypt needs to load the relays list. Please wait\033[0m\n"
            sleep 30

            if [ -f /etc/dnscrypt-proxy2/relays.md ]; then
                uci set dhcp.@dnsmasq[0].noresolv="1"
                uci -q delete dhcp.@dnsmasq[0].server
                uci add_list dhcp.@dnsmasq[0].server="127.0.0.53#53"
                uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/'
                uci commit dhcp
                
                printf "\033[32;1mDnsmasq restart\033[0m\n"

                /etc/init.d/dnsmasq restart
            else
                printf "\033[31;1mDNSCrypt not download list on /etc/dnscrypt-proxy2. Repeat install DNSCrypt by script.\033[0m\n"
            fi
    fi

    fi

    if [ "$DNS_RESOLVER" == 'STUBBY' ]; then
        printf "\033[32;1mConfigure Stubby\033[0m\n"

        if opkg list-installed | grep -q stubby; then
            printf "\033[32;1mStubby already installed\033[0m\n"
        else
            printf "\033[32;1mInstalled stubby\033[0m\n"
            opkg install stubby

            printf "\033[32;1mConfigure Dnsmasq for Stubby\033[0m\n"
            uci set dhcp.@dnsmasq[0].noresolv="1"
            uci -q delete dhcp.@dnsmasq[0].server
            uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#5453"
            uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/'
            uci commit dhcp

            printf "\033[32;1mDnsmasq restart\033[0m\n"

            /etc/init.d/dnsmasq restart
        fi
    fi
}

add_packages() {
    for package in curl nano; do
        if opkg list-installed | grep -q "^$package "; then
            printf "\033[32;1m$package already installed\033[0m\n"
        else
            printf "\033[32;1mInstalling $package...\033[0m\n"
            opkg install "$package"
            
            if "$package" --version >/dev/null 2>&1; then
                printf "\033[32;1m$package was successfully installed and available\033[0m\n"
            else
                printf "\033[31;1mError: failed to install $package\033[0m\n"
                exit 1
            fi
        fi
    done
}

add_getdomains() {
    echo "Choose you country"
    echo "Select:"
    echo "1) Russia inside. You are inside Russia"
    echo "2) Russia outside. You are outside of Russia, but you need access to Russian resources"
    echo "3) Ukraine. uablacklist.net list"
    echo "4) Skip script creation"

    while true; do
    read -r -p '' COUNTRY
        case $COUNTRY in 

        1) 
            COUNTRY=russia_inside
            break
            ;;

        2)
            COUNTRY=russia_outside
            break
            ;;

        3) 
            COUNTRY=ukraine
            break
            ;;

        4) 
            echo "Skiped"
            COUNTRY=0
            break
            ;;

        *)
            echo "Choose from the following options"
            ;;
        esac
    done

    if [ "$COUNTRY" == 'russia_inside' ]; then
        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst
    elif [ "$COUNTRY" == 'russia_outside' ]; then
        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst
    elif [ "$COUNTRY" == 'ukraine' ]; then
        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst
    fi

    if [ "$COUNTRY" != '0' ]; then
        printf "\033[32;1mCreate script /etc/init.d/getdomains\033[0m\n"

cat << EOF > /etc/init.d/getdomains
#!/bin/sh /etc/rc.common

START=99

start () {
    $EOF_DOMAINS
EOF
cat << 'EOF' >> /etc/init.d/getdomains
    count=0
    while true; do
        if curl -m 3 github.com; then
            curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst
            break
        else
            echo "GitHub is not available. Check the internet availability [$count]"
            count=$((count+1))
        fi
    done

    if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q "syntax check OK"; then
        /etc/init.d/dnsmasq restart
    fi
}
EOF

        chmod +x /etc/init.d/getdomains
        /etc/init.d/getdomains enable

        if crontab -l | grep -q /etc/init.d/getdomains; then
            printf "\033[32;1mCrontab already configured\033[0m\n"

        else
            crontab -l | { cat; echo "0 */8 * * * /etc/init.d/getdomains start"; } | crontab -
            printf "\033[32;1mIgnore this error. This is normal for a new installation\033[0m\n"
            /etc/init.d/cron restart
        fi

        printf "\033[32;1mStart script\033[0m\n"

        /etc/init.d/getdomains start
    fi
}

add_internal_wg() {
    PROTOCOL_NAME=$1
    printf "\033[32;1mConfigure ${PROTOCOL_NAME}\033[0m\n"
    if [ "$PROTOCOL_NAME" = 'Wireguard' ]; then
        INTERFACE_NAME="wg1"
        CONFIG_NAME="wireguard_wg1"
        PROTO="wireguard"
        ZONE_NAME="wg_internal"

        if opkg list-installed | grep -q wireguard-tools; then
            echo "Wireguard already installed"
        else
            echo "Installed wg..."
            opkg install wireguard-tools
        fi
    fi

    if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then
        INTERFACE_NAME="awg1"
        CONFIG_NAME="amneziawg_awg1"
        PROTO="amneziawg"
        ZONE_NAME="awg_internal"

        install_awg_packages
    fi

    read -r -p "Enter the private key (from [Interface]):"$'\n' WG_PRIVATE_KEY_INT

    while true; do
        read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):"$'\n' WG_IP
        if echo "$WG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then
            break
        else
            echo "This IP is not valid. Please repeat"
        fi
    done

    read -r -p "Enter the public key (from [Peer]):"$'\n' WG_PUBLIC_KEY_INT
    read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' WG_PRESHARED_KEY_INT
    read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' WG_ENDPOINT_INT

    read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' WG_ENDPOINT_PORT_INT
    WG_ENDPOINT_PORT_INT=${WG_ENDPOINT_PORT_INT:-51820}
    if [ "$WG_ENDPOINT_PORT_INT" = '51820' ]; then
        echo $WG_ENDPOINT_PORT_INT
    fi

    if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then
        read -r -p "Enter Jc value (from [Interface]):"$'\n' AWG_JC
        read -r -p "Enter Jmin value (from [Interface]):"$'\n' AWG_JMIN
        read -r -p "Enter Jmax value (from [Interface]):"$'\n' AWG_JMAX
        read -r -p "Enter S1 value (from [Interface]):"$'\n' AWG_S1
        read -r -p "Enter S2 value (from [Interface]):"$'\n' AWG_S2
        read -r -p "Enter H1 value (from [Interface]):"$'\n' AWG_H1
        read -r -p "Enter H2 value (from [Interface]):"$'\n' AWG_H2
        read -r -p "Enter H3 value (from [Interface]):"$'\n' AWG_H3
        read -r -p "Enter H4 value (from [Interface]):"$'\n' AWG_H4
    fi
    
    uci set network.${INTERFACE_NAME}=interface
    uci set network.${INTERFACE_NAME}.proto=$PROTO
    uci set network.${INTERFACE_NAME}.private_key=$WG_PRIVATE_KEY_INT
    uci set network.${INTERFACE_NAME}.listen_port='51821'
    uci set network.${INTERFACE_NAME}.addresses=$WG_IP

    if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then
        uci set network.${INTERFACE_NAME}.awg_jc=$AWG_JC
        uci set network.${INTERFACE_NAME}.awg_jmin=$AWG_JMIN
        uci set network.${INTERFACE_NAME}.awg_jmax=$AWG_JMAX
        uci set network.${INTERFACE_NAME}.awg_s1=$AWG_S1
        uci set network.${INTERFACE_NAME}.awg_s2=$AWG_S2
        uci set network.${INTERFACE_NAME}.awg_h1=$AWG_H1
        uci set network.${INTERFACE_NAME}.awg_h2=$AWG_H2
        uci set network.${INTERFACE_NAME}.awg_h3=$AWG_H3
        uci set network.${INTERFACE_NAME}.awg_h4=$AWG_H4
    fi

    if ! uci show network | grep -q ${CONFIG_NAME}; then
        uci add network ${CONFIG_NAME}
    fi

    uci set network.@${CONFIG_NAME}[0]=$CONFIG_NAME
    uci set network.@${CONFIG_NAME}[0].name="${INTERFACE_NAME}_client"
    uci set network.@${CONFIG_NAME}[0].public_key=$WG_PUBLIC_KEY_INT
    uci set network.@${CONFIG_NAME}[0].preshared_key=$WG_PRESHARED_KEY_INT
    uci set network.@${CONFIG_NAME}[0].route_allowed_ips='0'
    uci set network.@${CONFIG_NAME}[0].persistent_keepalive='25'
    uci set network.@${CONFIG_NAME}[0].endpoint_host=$WG_ENDPOINT_INT
    uci set network.@${CONFIG_NAME}[0].allowed_ips='0.0.0.0/0'
    uci set network.@${CONFIG_NAME}[0].endpoint_port=$WG_ENDPOINT_PORT_INT
    uci commit network

    grep -q "110 vpninternal" /etc/iproute2/rt_tables || echo '110 vpninternal' >> /etc/iproute2/rt_tables

    if ! uci show network | grep -q mark0x2; then
        printf "\033[32;1mConfigure mark rule\033[0m\n"
        uci add network rule
        uci set network.@rule[-1].name='mark0x2'
        uci set network.@rule[-1].mark='0x2'
        uci set network.@rule[-1].priority='110'
        uci set network.@rule[-1].lookup='vpninternal'
        uci commit
    fi

    if ! uci show network | grep -q vpn_route_internal; then
        printf "\033[32;1mAdd route\033[0m\n"
        uci set network.vpn_route_internal=route
        uci set network.vpn_route_internal.name='vpninternal'
        uci set network.vpn_route_internal.interface=$INTERFACE_NAME
        uci set network.vpn_route_internal.table='vpninternal'
        uci set network.vpn_route_internal.target='0.0.0.0/0'
        uci commit network
    fi

    if ! uci show firewall | grep -q "@zone.*name='${ZONE_NAME}'"; then
        printf "\033[32;1mZone Create\033[0m\n"
        uci add firewall zone
        uci set firewall.@zone[-1].name=$ZONE_NAME
        uci set firewall.@zone[-1].network=$INTERFACE_NAME
        uci set firewall.@zone[-1].forward='REJECT'
        uci set firewall.@zone[-1].output='ACCEPT'
        uci set firewall.@zone[-1].input='REJECT'
        uci set firewall.@zone[-1].masq='1'
        uci set firewall.@zone[-1].mtu_fix='1'
        uci set firewall.@zone[-1].family='ipv4'
        uci commit firewall
    fi

    if ! uci show firewall | grep -q "@forwarding.*name='${ZONE_NAME}'"; then
        printf "\033[32;1mConfigured forwarding\033[0m\n"
        uci add firewall forwarding
        uci set firewall.@forwarding[-1]=forwarding
        uci set firewall.@forwarding[-1].name="${ZONE_NAME}-lan"
        uci set firewall.@forwarding[-1].dest=${ZONE_NAME}
        uci set firewall.@forwarding[-1].src='lan'
        uci set firewall.@forwarding[-1].family='ipv4'
        uci commit firewall
    fi

    if uci show firewall | grep -q "@ipset.*name='vpn_domains_internal'"; then
        printf "\033[32;1mSet already exist\033[0m\n"
    else
        printf "\033[32;1mCreate set\033[0m\n"
        uci add firewall ipset
        uci set firewall.@ipset[-1].name='vpn_domains_internal'
        uci set firewall.@ipset[-1].match='dst_net'
        uci commit firewall
    fi

    if uci show firewall | grep -q "@rule.*name='mark_domains_intenal'"; then
        printf "\033[32;1mRule for set already exist\033[0m\n"
    else
        printf "\033[32;1mCreate rule set\033[0m\n"
        uci add firewall rule
        uci set firewall.@rule[-1]=rule
        uci set firewall.@rule[-1].name='mark_domains_intenal'
        uci set firewall.@rule[-1].src='lan'
        uci set firewall.@rule[-1].dest='*'
        uci set firewall.@rule[-1].proto='all'
        uci set firewall.@rule[-1].ipset='vpn_domains_internal'
        uci set firewall.@rule[-1].set_mark='0x2'
        uci set firewall.@rule[-1].target='MARK'
        uci set firewall.@rule[-1].family='ipv4'
        uci commit firewall
    fi

    if uci show dhcp | grep -q "@ipset.*name='vpn_domains_internal'"; then
        printf "\033[32;1mDomain on vpn_domains_internal already exist\033[0m\n"
    else
        printf "\033[32;1mCreate domain for vpn_domains_internal\033[0m\n"
        uci add dhcp ipset
        uci add_list dhcp.@ipset[-1].name='vpn_domains_internal'
        uci add_list dhcp.@ipset[-1].domain='youtube.com'
        uci add_list dhcp.@ipset[-1].domain='googlevideo.com'
        uci add_list dhcp.@ipset[-1].domain='youtubekids.com'
        uci add_list dhcp.@ipset[-1].domain='googleapis.com'
        uci add_list dhcp.@ipset[-1].domain='ytimg.com'
        uci add_list dhcp.@ipset[-1].domain='ggpht.com'
        uci commit dhcp
    fi

    sed -i "/done/a sed -i '/youtube.com\\\|ytimg.com\\\|ggpht.com\\\|googlevideo.com\\\|googleapis.com\\\|youtubekids.com/d' /tmp/dnsmasq.d/domains.lst" "/etc/init.d/getdomains"

    service dnsmasq restart
    service network restart

    exit 0
}

install_awg_packages() {
    # Получение pkgarch с наибольшим приоритетом
    PKGARCH=$(opkg print-architecture | awk 'BEGIN {max=0} {if ($3 > max) {max = $3; arch = $2}} END {print arch}')

    TARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 1)
    SUBTARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 2)
    VERSION=$(ubus call system board | jsonfilter -e '@.release.version')
    PKGPOSTFIX="_v${VERSION}_${PKGARCH}_${TARGET}_${SUBTARGET}.ipk"
    BASE_URL="https://github.com/Slava-Shchipunov/awg-openwrt/releases/download/"

    AWG_DIR="/tmp/amneziawg"
    mkdir -p "$AWG_DIR"

    if opkg list-installed | grep -q amneziawg-tools; then
        echo "amneziawg-tools already installed"
    else
        AMNEZIAWG_TOOLS_FILENAME="amneziawg-tools${PKGPOSTFIX}"
        DOWNLOAD_URL="${BASE_URL}v${VERSION}/${AMNEZIAWG_TOOLS_FILENAME}"
        curl -L -o "$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME" "$DOWNLOAD_URL"

        if [ $? -eq 0 ]; then
            echo "amneziawg-tools file downloaded successfully"
        else
            echo "Error downloading amneziawg-tools. Please, install amneziawg-tools manually and run the script again"
            exit 1
        fi

        opkg install "$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME"

        if [ $? -eq 0 ]; then
            echo "amneziawg-tools file downloaded successfully"
        else
            echo "Error installing amneziawg-tools. Please, install amneziawg-tools manually and run the script again"
            exit 1
        fi
    fi
    
    if opkg list-installed | grep -q kmod-amneziawg; then
        echo "kmod-amneziawg already installed"
    else
        KMOD_AMNEZIAWG_FILENAME="kmod-amneziawg${PKGPOSTFIX}"
        DOWNLOAD_URL="${BASE_URL}v${VERSION}/${KMOD_AMNEZIAWG_FILENAME}"
        curl -L -o "$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME" "$DOWNLOAD_URL"

        if [ $? -eq 0 ]; then
            echo "kmod-amneziawg file downloaded successfully"
        else
            echo "Error downloading kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again"
            exit 1
        fi
        
        opkg install "$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME"

        if [ $? -eq 0 ]; then
            echo "kmod-amneziawg file downloaded successfully"
        else
            echo "Error installing kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again"
            exit 1
        fi
    fi
    
    if opkg list-installed | grep -q luci-app-amneziawg; then
        echo "luci-app-amneziawg already installed"
    else
        LUCI_APP_AMNEZIAWG_FILENAME="luci-app-amneziawg${PKGPOSTFIX}"
        DOWNLOAD_URL="${BASE_URL}v${VERSION}/${LUCI_APP_AMNEZIAWG_FILENAME}"
        curl -L -o "$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME" "$DOWNLOAD_URL"

        if [ $? -eq 0 ]; then
            echo "luci-app-amneziawg file downloaded successfully"
        else
            echo "Error downloading luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again"
            exit 1
        fi

        opkg install "$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME"

        if [ $? -eq 0 ]; then
            echo "luci-app-amneziawg file downloaded successfully"
        else
            echo "Error installing luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again"
            exit 1
        fi
    fi

    rm -rf "$AWG_DIR"
}

# System Details
MODEL=$(cat /tmp/sysinfo/model)
source /etc/os-release
printf "\033[34;1mModel: $MODEL\033[0m\n"
printf "\033[34;1mVersion: $OPENWRT_RELEASE\033[0m\n"

VERSION_ID=$(echo $VERSION | awk -F. '{print $1}')

if [ "$VERSION_ID" -ne 23 ] && [ "$VERSION_ID" -ne 24 ]; then
    printf "\033[31;1mScript only support OpenWrt 23.05 and 24.10\033[0m\n"
    echo "For OpenWrt 21.02 and 22.03 you can:"
    echo "1) Use ansible https://github.com/itdoginfo/domain-routing-openwrt"
    echo "2) Configure manually. Old manual: https://itdog.info/tochechnaya-marshrutizaciya-na-routere-s-openwrt-wireguard-i-dnscrypt/"
    exit 1
fi

printf "\033[31;1mAll actions performed here cannot be rolled back automatically.\033[0m\n"

check_repo

add_packages

add_tunnel

add_mark

add_zone

show_manual

add_set

dnsmasqfull

dnsmasqconfdir

add_dns_resolver

add_getdomains

printf "\033[32;1mRestart network\033[0m\n"
/etc/init.d/network restart

printf "\033[32;1mDone\033[0m\n"


================================================
FILE: getdomains-uninstall.sh
================================================
#!/bin/ash

echo "Выпиливаем скрипты"
/etc/init.d/getdomains disable
rm -rf /etc/init.d/getdomains

rm -f /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute

echo "Выпиливаем из crontab"
sed -i '/getdomains start/d' /etc/crontabs/root

echo "Выпиливаем домены"
rm -f /tmp/dnsmasq.d/domains.lst

echo "Чистим firewall, раз раз 🍴"

ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$ipset_id" ]; then
    while uci -q delete firewall.@ipset[$ipset_id]; do :; done
fi

rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$rule_id" ]; then
    while uci -q delete firewall.@rule[$rule_id]; do :; done
fi

ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains_internal.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$ipset_id" ]; then
    while uci -q delete firewall.@ipset[$ipset_id]; do :; done
fi

rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains_intenal.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$rule_id" ]; then
    while uci -q delete firewall.@rule[$rule_id]; do :; done
fi

ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$ipset_id" ]; then
    while uci -q delete firewall.@ipset[$ipset_id]; do :; done
fi

rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$rule_id" ]; then
    while uci -q delete firewall.@rule[$rule_id]; do :; done
fi

uci commit firewall
/etc/init.d/firewall restart

echo "Чистим сеть"
sed -i '/99 vpn/d' /etc/iproute2/rt_tables

rule_id=$(uci show network | grep -E '@rule.*name=.mark0x1.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$rule_id" ]; then
    while uci -q delete network.@rule[$rule_id]; do :; done
fi

rule_id=$(uci show network | grep -E '@rule.*name=.mark0x2.' | awk -F '[][{}]' '{print $2}' | head -n 1)
if [ ! -z "$rule_id" ]; then
    while uci -q delete network.@rule[$rule_id]; do :; done
fi

while uci -q delete network.vpn_route_internal; do :; done

uci commit network
/etc/init.d/network restart

echo "Проверяем Dnsmasq"
if uci show dhcp | grep -q ipset; then
    echo "В dnsmasq (/etc/config/dhcp) заданы домены. Нужные из них сохраните, остальные удалите вместе с ipset"
fi

echo "Все туннели, прокси, зоны и forwarding к ним оставляем на месте, они вам не помешают и скорее пригодятся"
echo "Dnscrypt, stubby тоже не трогаем"

echo "  ______  _____        _____   _____  ______  _     _  _____   _____"
echo " |  ____ |     |      |_____] |     | |     \ |____/  |     | |_____]"
echo " |_____| |_____|      |       |_____| |_____/ |    \_ |_____| |     "


================================================
FILE: handlers/main.yml
================================================
---
  - name: Restart sing-box
    service:
      name: sing-box
      state: restarted

  - name: Restart network
    service:
      name: network
      state: restarted

  - name: Restart firewall
    service:
      name: firewall
      state: restarted

  - name: Run getdomains script
    service:
      name: getdomains
      state: restarted

  - name: Restart dnscrypt-proxy
    service:
      name: dnscrypt-proxy
      state: restarted
      enabled: yes
      
  - name: Restart dnsmasq
    service:
      name: dnsmasq
      state: restarted

================================================
FILE: meta/main.yml
================================================
---
galaxy_info:
  role_name: domain_routing_openwrt
  namespace: itdoginfo
  author: itdog
  description: Configuring domain routing on Openwrt router
  issue_tracker_url: https://github.com/itdoginfo/domain-routing-openwrt/issues
  license: GPL-3.0
  min_ansible_version: 2.10.7
  platforms:
    - name: OpenWrt
  galaxy_tags:
    - openwrt
    - dnsmasq
    - ipset
    - wireguard
    - sing-box
    - openvpn
    - bypass
    - routing
dependencies:
  - role: gekmihesg.openwrt

================================================
FILE: tasks/main.yml
================================================
---

# Dnsmasq version check

  - name: Get dnsmasq version
    shell: opkg list-installed | grep dnsmasq-full | awk '{print $3}'
    register: dnsmasqfull_version

  - name: Check confdir option
    shell: uci get dhcp.@dnsmasq[0].confdir
    register: dnsmasq_confdir
    ignore_errors: true

  - name: Get openwrt major release
    shell: cat /etc/openwrt_release | grep -Eo [0-9]{2}[.][0-9]{2}[.][0-9]* | cut -d '.' -f 1 | tail -n 1
    register: openwrt_major_release

  - name: debug
    debug:
      var: ansible_distribution_major_version

# Packages installation

  - name: install wg
    opkg:
      name: "{{ item }}"
      state: present
    loop:
        - kmod-wireguard
        - wireguard-tools
    when: tunnel == "wg"

  - name: install openvpn
    opkg:
      name: "{{ item }}"
      state: present
    loop:
        - openvpn-openssl
    when: tunnel == "openvpn"

  - name: install singbox
    opkg:
      name: "{{ item }}"
      state: present
    loop:
        - sing-box
    when: tunnel == "singbox" and ansible_distribution_major_version >= "23"

  - name: install curl
    opkg:
      name: "{{ item }}"
      state: present
    loop:
        - curl

  - name: install nano
    opkg:
      name: "{{ item }}"
      state: present
    loop:
        - nano
    when: nano

  - name: install ipset
    opkg:
      name: ipset
      state: present
    when: ansible_distribution_major_version < "22"

  - name: install dnsmasq-full (23)
    shell: opkg update && cd /tmp/ && opkg download dnsmasq-full && opkg remove dnsmasq && opkg install dnsmasq-full --cache /tmp/ && [ -f /etc/config/dhcp-opkg ] && cp etc/config/dhcp /etc/config/dhcp-old && mv /etc/config/dhcp-opkg /etc/config/dhcp
    when: ansible_distribution_major_version >= "23" and list_domains and not dnsmasqfull_version.stdout
    ignore_errors: true

  - name: set confdir for dnsmasq
    uci: 
      command: set
      key: dhcp.@dnsmasq[0]
      value:
        confdir: "/tmp/dnsmasq.d"
    when: ansible_distribution_major_version >= 24
    notify:
      - Restart dnsmasq  

# Getdomains script configure
      
  - name: getdomains script copy
    template:
      src: "openwrt-getdomains.j2"
      dest: "/etc/init.d/getdomains"
      mode: a+x
      trim_blocks: false
    notify:
      - Run getdomains script

  - name: create simplink in rc.d
    file:
      src: "/etc/init.d/getdomains"
      dest: "/etc/rc.d/S99getdomains"
      state: link
    notify:
      - Run getdomains script

  - name: check string in crontab
    shell: grep "getdomains" /etc/crontabs/root
    register: check_cron
    ignore_errors: true
     
  - name: add script to cron
    lineinfile:
      path: /etc/crontabs/root
      create: yes
      line: "0 4 * * * /etc/init.d/getdomains start"
    when: check_cron.stdout == ""
    
  - name: enable and start crontab
    service:
      name: cron
      state: started
      enabled: yes
      
# Configure route table

  - name: Route for vpn table
    template:
      src: "openwrt-30-vpnroute.j2"
      dest: "/etc/hotplug.d/iface/30-vpnroute"
      mode: 0644

  - name: Check string in rt_tables
    shell: grep "99 vpn" /etc/iproute2/rt_tables
    register: check_rt_tables
    ignore_errors: true
      
  - name: add route table
    lineinfile:
      path: /etc/iproute2/rt_tables
      line: "99 vpn"
    when: check_rt_tables.stdout == ""
    notify:
      - Restart network
    
# Configure WG

  - name: add wg interface
    uci:
      command: add
      config: network
      type: interface
      name: wg0
    when: tunnel == "wg"

  - name: configure wg interface
    uci:
      command: set
      key: network.wg0
      value:
        proto: wireguard
        private_key: "{{ wg_private_key }}"
        listen_port: "{{ wg_listen_port }}"
        addresses:
          - "{{ wg_client_address }}"
    when: tunnel == "wg"
    notify:
      - Restart network
      
  - name: set wg client without wg_preshared_key
    uci:
      command: section
      config: network
      type: wireguard_wg0
      find_by:
        name: wg0_client
      value:
        public_key: "{{ wg_public_key }}"
        route_allowed_ips: 0
        persistent_keepalive: 25
        endpoint_host: "{{ wg_server_address }}"
        allowed_ips: 0.0.0.0/0
        endpoint_port: "{{ wg_client_port }}"
    when: wg_preshared_key is undefined and tunnel == "wg"
    notify:
      - Restart network     
  
  - name: set wg client with wg_preshared_key
    uci:
      command: section
      config: network
      type: wireguard_wg0
      find_by:
        name: wg0_client
      value:
        public_key: "{{ wg_public_key }}"
        preshared_key: "{{ wg_preshared_key }}"
        route_allowed_ips: 0
        persistent_keepalive: 25
        endpoint_host: "{{ wg_server_address }}"
        allowed_ips: 0.0.0.0/0
        endpoint_port: "{{ wg_client_port }}"
    when: wg_preshared_key is defined  and tunnel == "wg"

  - name: set WG firewall zone 
    uci:
      command: section
      config: firewall
      type: zone
      find_by:
        name: wg
      value:
        forward: REJECT
        output: ACCEPT
        name: wg
        input: REJECT
        masq: 1
        mtu_fix: 1
        network: wg0
        family: ipv4
    when: tunnel == "wg"
        
  - name: add WG forwarding
    uci:
      command: section
      config: firewall
      type: forwarding
      find_by:
        name: wg-lan
      value:
        dest: wg
        src: lan
        family: ipv4
    when: tunnel == "wg"

# Configure Sing-box

  - name: set sing-box firewall zone. Only >=22
    uci:
      command: section
      config: firewall
      type: zone
      find_by:
        name: tun
      value:
        forward: ACCEPT
        output: ACCEPT
        name: tun
        input: ACCEPT
        masq: 1
        mtu_fix: 1
        device: tun0
        family: ipv4
    when: tunnel == "singbox"
    failed_when: ansible_distribution_major_version < "22"
    notify:
      - Restart firewall

  - name: template for sing-box.json
    template:
      src: "sing-box-json.j2"
      dest: "/etc/sing-box/config.json"
      mode: 0644
    when: tunnel == "singbox"
    failed_when: ansible_distribution_major_version < "22"

  - name: template for config/sing-box
    template:
      src: "config-sing-box.j2"
      dest: "/etc/config/sing-box"
      mode: 0600
    when: tunnel == "singbox"
    failed_when: ansible_distribution_major_version < "22"

# Configure OpenVPN, tun2socks

  - name: set {{ tunnel }} firewall zone 
    uci:
      command: section
      config: firewall
      type: zone
      find_by:
        name: tun
      value:
        forward: REJECT
        output: ACCEPT
        name: tun
        input: REJECT
        masq: 1
        mtu_fix: 1
        device: tun0
        family: ipv4
    when: tunnel == "openvpn" or tunnel == "tun2socks"
    notify:
      - Restart firewall
        
  - name: add {{ tunnel }} forwarding
    uci:
      command: section
      config: firewall
      type: forwarding
      find_by:
        name: lan-tun
      value:
        dest: tun
        src: lan
        family: ipv4
    when: tunnel == "openvpn" or tunnel == "tun2socks" or tunnel == "singbox"
    notify:
      - Restart firewall

# Configure network
       
  - name: set rule mark0x1
    uci:
      command: section
      config: network
      type: rule
      find_by:
        name: mark0x1
      value:
        mark: "0x1"
        priority: 100
        lookup: vpn

  - name: set disable dns for wan
    uci:
      command: set
      key: network.wan
      value:
        peerdns: 0
    when: ansible_distribution_major_version < "22"

  - name: uci commit firewall
    uci:
      command: commit
      config: firewall
    notify:
      - Restart firewall

  - name: uci commit network
    uci:
      command: commit
      config: network
    notify:
      - Restart network

# Configure firewall

  - name: add ipset for subnet (<22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_subnets
       value:
         match: dst_net
         storage: hash
         loadfile: /tmp/lst/subnet.lst
    when: ansible_distribution_major_version < "22" and list_subnet
         
  - name: add ipset for ip (<22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_ip
       value:
         match: dst_net
         storage: hash
         loadfile: /tmp/lst/ip.lst
         hashsize: 9900000
         maxelem: 9900000
    when: ansible_distribution_major_version < "22" and list_ip

  - name: add ipset for community (<22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_community
       value:
         match: dst_net
         storage: hash
         loadfile: /tmp/lst/community.lst
         hashsize: 9900000
         maxelem: 9900000
    when: ansible_distribution_major_version < "22" and list_community

  - name: add nfset for subnet (22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_subnets
       value:
         match: dst_net
         loadfile: /tmp/lst/subnet.lst
    when: ansible_distribution_major_version >= "22" and list_subnet
         
  - name: add nfset for ip (22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_ip
       value:
         match: dst_net
         loadfile: /tmp/lst/ip.lst
    when: ansible_distribution_major_version >= "22" and list_ip

  - name: add nfset for community (22)
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_community
       value:
         match: dst_net
         loadfile: /tmp/lst/community.lst
    when: ansible_distribution_major_version >= "22" and list_community

  - name: add ipset for domains (<22). If failed, repeat playbook. If failed is repeated check dnsmasq-full. 
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_domains
       value:
         match: dst_net
         storage: hash
    when: ansible_distribution_major_version < "22" and list_domains

  - name: add nfset for domains (>=22). If failed, repeat playbook. If failed is repeated check dnsmasq-full.
    uci:
       command: section
       config: firewall
       type: ipset
       find_by:
         name: vpn_domains
       value:
         match: dst_net
    when: ansible_distribution_major_version >= "22" and list_domains

  - name: add mark rule vpn_subnet
    uci:
       command: section
       config: firewall
       type: rule
       find_by:
         name: mark_subnet
       value:
         src: lan
         dest: "*"
         proto: all
         ipset: vpn_subnets
         set_mark: "0x1"
         target: MARK
         family: ipv4
    when: list_subnet

  - name: add mark rule vpn_ip
    uci:
       command: section
       config: firewall
       type: rule
       find_by:
         name: mark_ip
       value:
         src: lan
         dest: "*"
         proto: all
         ipset: vpn_ip
         set_mark: "0x1"
         target: MARK
         family: ipv4
    when: list_ip

  - name: add mark rule vpn_community
    uci:
       command: section
       config: firewall
       type: rule
       find_by:
         name: mark_community
       value:
         src: lan
         dest: "*"
         proto: all
         ipset: vpn_community
         set_mark: "0x1"
         target: MARK
         family: ipv4
    when: list_community

  - name: add mark rule vpn_domains
    uci:
       command: section
       config: firewall
       type: rule
       find_by:
         name: mark_domains
       value:
         src: lan
         dest: "*"
         proto: all
         ipset: vpn_domains
         set_mark: "0x1"
         target: MARK
         family: ipv4
    when: (ansible_distribution_major_version < "22" and list_domains) or (ansible_distribution_major_version >= "22" and list_domains)

  - name: wg access route
    uci:
      command: section
      config: network
      type: route
      find_by:
        name: wg_access_route
      value:
        interface: wg0
        target: "{{ wg_access_network }}"
    when: wg_access

  - name: set WG firewall zone 
    uci:
      command: section
      config: firewall
      type: zone
      find_by:
        name: wg
      value:
        input: ACCEPT
    when: wg_access

# Remove unused rules and ipset
  - name: Remove ipset for ip
    uci:
       command: absent
       config: firewall
       type: ipset
       find_by:
         name: vpn_ip
    when: not list_ip

  - name: Remove rule for ip
    uci:
       command: absent
       config: firewall
       type: rule
       find_by:
         name: mark_ip
    when: not list_ip

  - name: Remove ipset for subnet
    uci:
       command: absent
       config: firewall
       type: ipset
       find_by:
         name: vpn_subnets
    when: not list_subnet

  - name: Remove rule for subnet
    uci:
       command: absent
       config: firewall
       type: rule
       find_by:
         name: mark_subnet
    when: not list_subnet

  - name: Remove ipset for community
    uci:
       command: absent
       config: firewall
       type: ipset
       find_by:
         name: vpn_community
    when: not list_community

  - name: Remove rule for community
    uci:
       command: absent
       config: firewall
       type: rule
       find_by:
         name: mark_community
    when: not list_community

  - name: Remove ipset for domains
    uci:
       command: absent
       config: firewall
       type: ipset
       find_by:
         name: vpn_domains
    when: not list_domains

  - name: Remove rule for domains
    uci:
       command: absent
       config: firewall
       type: rule
       find_by:
         name: mark_domains
    when: not list_domains

# Configure DNS resolver

  - name: install dnscrypt-proxy2
    opkg:
      name: dnscrypt-proxy2
      state: present
    when: dns_encrypt == "dnscrypt"

  - name: check string in dnscrypt-proxy.toml
    shell: grep "# server_names" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml
    register: check_server_names
    ignore_errors: true
    when: dns_encrypt == "dnscrypt"

  - name: dnscrypt2 enable exact servers
    lineinfile:
      path: /etc/dnscrypt-proxy2/dnscrypt-proxy.toml
      regexp: "# server_names ="
      line: "server_names = ['google', 'cloudflare', 'scaleway-fr', 'yandex']"
    when: dns_encrypt == "dnscrypt" and check_server_names.stdout
    notify:
      - Restart dnscrypt-proxy
    
  - name: edit dhcp config. add localhost server
    lineinfile:
      path: /etc/config/dhcp
      firstmatch: "true"
      insertafter: "option leasefile '/tmp/dhcp.leases'"
      line: "{{ item }}"
    with_items:
      - "        list server '127.0.0.53#53'"
      - "        option noresolv '1'"
    notify:
      - Restart dnsmasq
    when: dns_encrypt == "dnscrypt"

  - name: install stubby
    opkg:
      name: stubby
      state: present
    when: dns_encrypt == "stubby"

  - name: edit dhcp config. add localhost server
    lineinfile:
      path: /etc/config/dhcp
      firstmatch: "true"
      insertafter: "option leasefile '/tmp/dhcp.leases'"
      line: "{{ item }}"
    with_items:
      - "        list server '127.0.0.1#5453'"
      - "        option noresolv '1'"
    notify:
      - Restart dnsmasq
    when: dns_encrypt == "stubby"

# Commit

  - name: uci commit firewall
    uci:
      command: commit
      config: firewall
    notify:
      - Restart firewall

    - name: uci commit dhcp
    uci:
      command: commit
      config: dhcp
    notify:
      - Restart dnsmasq

  - name: uci commit network
    uci:
      command: commit
      config: network
    notify:
      - Restart network

================================================
FILE: templates/config-sing-box.j2
================================================
config sing-box 'main'
	option enabled '1'
	option user 'root'
	option conffile '/etc/sing-box/config.json'
	option workdir '/usr/share/sing-box'


================================================
FILE: templates/openwrt-30-vpnroute.j2
================================================
#!/bin/sh

{% if tunnel == "wg" %}
ip route add table vpn default dev wg0
{% elif (tunnel == "openvpn") or (tunnel == "singbox") or (tunnel == "tun2socks") %}
sleep 10
ip route add table vpn default dev tun0
{% endif %}


================================================
FILE: templates/openwrt-getdomains.j2
================================================
#!/bin/sh /etc/rc.common

START=99

start () {
    {% if ansible_distribution_major_version >= "22" and country == "russia-inside" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst
    {% endif %}
    {% if ansible_distribution_major_version >= "22" and country == "russia-outside" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst
    {% endif %}
    {% if ansible_distribution_major_version >= "22" and country == "ukraine" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst
    {% endif %}
    {% if ansible_distribution_major_version < "22" and country == "russia-inside" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-ipset.lst
    {% endif %}
    {% if ansible_distribution_major_version < "22" and country == "russia-outside" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-ipset.lst
    {% endif %}
    {% if ansible_distribution_major_version < "22" and country == "ukraine" %}
    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-ipset.lst
    {% endif %}
    count=0
    while true; do
        if curl -m 3 github.com; then
            curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst
            break
        else
            echo "GitHub is not available. Check the internet availability [$count]"
            count=$((count+1))
        fi
    done

    if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q "syntax check OK"; then
        /etc/init.d/dnsmasq restart
    fi

    {% if ansible_distribution_major_version >= "22" and (list_ip or list_community) %}
    echo "Flush sets"
    nft flush ruleset
    {% endif %}

    {% if list_subnet or list_ip or list_community %}
    dir=/tmp/lst
    mkdir -p $dir

    count=0
    while true; do
        if curl -m 3 https://antifilter.download/; then
            {% if list_subnet %}
            curl -f -z $dir/subnet.lst https://antifilter.download/list/subnet.lst --output $dir/subnet.lst
            {% endif %}
            {% if list_ip %}
            curl -f -z $dir/ip.lst https://antifilter.download/list/ip.lst --output $dir/ip.lst
            {% endif %}
            {% if list_community %}
            curl -f -z $dir/community.lst https://community.antifilter.download/list/community.lst --output $dir/community.lst
            {% endif %}  
            break
        else
            echo "antifilter.download is not available. Check the internet availability [$count]"
            count=$((count+1))
        fi
    done

    echo "Firewall restart"
    /etc/init.d/firewall restart
    {% endif %}  
}

================================================
FILE: templates/sing-box-json.j2
================================================
{
    "log": {
      "level": "debug"
    },
    "inbounds": [
      {
        "type": "tun",
        "interface_name": "tun0",
        "domain_strategy": "ipv4_only",
        "address": ["172.16.250.1/30"],
        "auto_route": false,
        "strict_route": false,
        "sniff": true 
     }
    ],
    "outbounds": [
      {
        "type": "$TYPE",
        "server": "$HOST",
        "server_port": $PORT,
        "method": "$METHOD",
        "password": "$PASS"
      }
    ],
    "route": {
      "auto_detect_interface": true
    }
  }

================================================
FILE: tests/inventory
================================================
[openwrt]
192.168.56.23


================================================
FILE: tests/test.yml
================================================
---
- hosts: openwrt
  remote_user: root

  roles:
    - domain_routing_openwrt
Download .txt
gitextract_333oxhhf/

├── .github/
│   └── workflows/
│       └── public-galaxy.yml
├── README.EN.md
├── README.md
├── defaults/
│   └── main.yml
├── getdomains-check.sh
├── getdomains-install.sh
├── getdomains-uninstall.sh
├── handlers/
│   └── main.yml
├── meta/
│   └── main.yml
├── tasks/
│   └── main.yml
├── templates/
│   ├── config-sing-box.j2
│   ├── openwrt-30-vpnroute.j2
│   ├── openwrt-getdomains.j2
│   └── sing-box-json.j2
└── tests/
    ├── inventory
    └── test.yml
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (115K chars).
[
  {
    "path": ".github/workflows/public-galaxy.yml",
    "chars": 338,
    "preview": "name: Public to Ansible Galaxy\n\non:\n  push:\n    tags:\n      - '*'\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n"
  },
  {
    "path": "README.EN.md",
    "chars": 2092,
    "preview": "Domain routing OpenWrt\n=========\n\nConfiguring domain routing on Openwrt router.\n\n\nRole Variables\n--------------\n\nLists\n`"
  },
  {
    "path": "README.md",
    "chars": 7211,
    "preview": "[English role README](https://github.com/itdoginfo/domain-routing-openwrt/blob/master/README.EN.md)\n\n# Описание\nShell ск"
  },
  {
    "path": "defaults/main.yml",
    "chars": 202,
    "preview": "---\n  list_domains: true\n  list_subnet: false\n  list_ip: false\n  list_community: false\n  tunnel: wg\n  dns_encrypt: false"
  },
  {
    "path": "getdomains-check.sh",
    "chars": 34044,
    "preview": "#!/bin/sh\n\nSCRIPTS_DIR=\"/etc/init.d\"\nTMP_DIR=\"/tmp\"\nHIVPN_SCRIPT_FILENAME=\"hivpn\"\nGETDOMAINS_SCRIPT_FILENAME=\"getdomains"
  },
  {
    "path": "getdomains-install.sh",
    "chars": 36319,
    "preview": "#!/bin/sh\n\n#set -x\n\ncheck_repo() {\n    printf \"\\033[32;1mChecking OpenWrt repo availability...\\033[0m\\n\"\n    opkg update"
  },
  {
    "path": "getdomains-uninstall.sh",
    "chars": 2780,
    "preview": "#!/bin/ash\n\necho \"Выпиливаем скрипты\"\n/etc/init.d/getdomains disable\nrm -rf /etc/init.d/getdomains\n\nrm -f /etc/hotplug.d"
  },
  {
    "path": "handlers/main.yml",
    "chars": 552,
    "preview": "---\n  - name: Restart sing-box\n    service:\n      name: sing-box\n      state: restarted\n\n  - name: Restart network\n    s"
  },
  {
    "path": "meta/main.yml",
    "chars": 482,
    "preview": "---\ngalaxy_info:\n  role_name: domain_routing_openwrt\n  namespace: itdoginfo\n  author: itdog\n  description: Configuring d"
  },
  {
    "path": "tasks/main.yml",
    "chars": 15917,
    "preview": "---\n\n# Dnsmasq version check\n\n  - name: Get dnsmasq version\n    shell: opkg list-installed | grep dnsmasq-full | awk '{p"
  },
  {
    "path": "templates/config-sing-box.j2",
    "chars": 146,
    "preview": "config sing-box 'main'\n\toption enabled '1'\n\toption user 'root'\n\toption conffile '/etc/sing-box/config.json'\n\toption work"
  },
  {
    "path": "templates/openwrt-30-vpnroute.j2",
    "chars": 220,
    "preview": "#!/bin/sh\n\n{% if tunnel == \"wg\" %}\nip route add table vpn default dev wg0\n{% elif (tunnel == \"openvpn\") or (tunnel == \"s"
  },
  {
    "path": "templates/openwrt-getdomains.j2",
    "chars": 2834,
    "preview": "#!/bin/sh /etc/rc.common\n\nSTART=99\n\nstart () {\n    {% if ansible_distribution_major_version >= \"22\" and country == \"russ"
  },
  {
    "path": "templates/sing-box-json.j2",
    "chars": 546,
    "preview": "{\n    \"log\": {\n      \"level\": \"debug\"\n    },\n    \"inbounds\": [\n      {\n        \"type\": \"tun\",\n        \"interface_name\": "
  },
  {
    "path": "tests/inventory",
    "chars": 24,
    "preview": "[openwrt]\n192.168.56.23\n"
  },
  {
    "path": "tests/test.yml",
    "chars": 79,
    "preview": "---\n- hosts: openwrt\n  remote_user: root\n\n  roles:\n    - domain_routing_openwrt"
  }
]

About this extraction

This page contains the full source code of the itdoginfo/domain-routing-openwrt GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (101.4 KB), approximately 31.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!