[
  {
    "path": ".github/workflows/public-galaxy.yml",
    "content": "name: Public to Ansible Galaxy\n\non:\n  push:\n    tags:\n      - '*'\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: checkout\n        uses: actions/checkout@v4\n      - name: Publish Ansible role to Galaxy\n        uses: robertdebock/galaxy-action@1.2.1\n        with:\n          galaxy_api_key: ${{ secrets.galaxy_api_key }}"
  },
  {
    "path": "README.EN.md",
    "content": "Domain routing OpenWrt\n=========\n\nConfiguring domain routing on Openwrt router.\n\n\nRole Variables\n--------------\n\nLists\n```\n  country: russia-inside|russia-outside|ukraine\n  list_domains: true|falase\n\n  list_subnet: false|true\n  list_ip: false|true\n  list_community: false|true\n```\n\nTunnel\n```\n  tunnel: wg|openvpn|singbox|tun2socks\n```\n\nDoH or DoT\n```\n  dns_encrypt: false|dnscrypt|stubby\n```\n\nNano package\n```\n  nano: true|false\n```\n\nAcces from wg network to router\n```\n  wg_access: false|true\n  wg_access_network: 192.168.80.0/24 (for example)\n```\n\nIf wireguard is used:\n```\n    wg_server_address: wg-server-host\n    wg_private_key: privatekey-client\n    wg_public_key: publickey-client\n    wg_preshared_key: presharedkey-client\n    wg_client_port: 51820\n    wg_client_address: ip-client\n\n    wg_access: true\n    wg_access_network: wg-network\n```\n\nDependencies\n------------\n\n[gekmihesg.openwrt](https://github.com/gekmihesg/ansible-openwrt)\n\n\nExample Playbook\n----------------\n\nThe inventory file must contain the group `[openwrt]` where your router will be located.\n\n\nWireguard, only domains, stubby, Russia, acces from wg network, host 192.168.1.1\n```\n- hosts: 192.168.1.1\n  remote_user: root\n\n  roles:\n    - itdoginfo.domain_routing_openwrt\n\n  vars:\n    tunnel: wg\n    dns_encrypt: stubby\n    country: russia-inside\n    \n    wg_access: true\n    wg_server_address: wg-server-host\n    wg_private_key: privatekey-client\n    wg_public_key: publickey-client\n    wg_preshared_key: presharedkey-client\n    wg_listen_port: 51820\n    wg_client_port: 51820\n    wg_client_address: ip-client\n    wg_access_network: wg-network\n```\n\nSing-box, stubby, Russia\n```\n- hosts: 192.168.1.1\n  remote_user: root\n\n  roles:\n    - itdoginfo.domain_routing_openwrt\n\n  vars:\n    tunnel: singbox\n    dns_encrypt: stubby\n    country: russia-inside\n\n  tasks:\n  - name: sing-box config\n    template:\n      src: \"templates/openwrt-sing-box-json.j2\"\n      dest: \"/etc/sing-box/config.json\"\n      mode: 0644\n    notify:\n      - Restart sing-box\n      - Restart network\n```\n\nLicense\n-------\n\nGNU General Public License v3.0"
  },
  {
    "path": "README.md",
    "content": "[English role README](https://github.com/itdoginfo/domain-routing-openwrt/blob/master/README.EN.md)\n\n# Описание\nShell скрипт и [роль для Ansible](https://galaxy.ansible.com/ui/standalone/roles/itdoginfo/domain_routing_openwrt). Автоматизируют настройку роутера на OpenWrt для роутинга по доменам и спискам IP-адресов.\n\nПолное описание происходящего:\n- [Статья на хабре](https://habr.com/ru/articles/767464/)\n- [Копия в моём блоге](https://itdog.info/tochechnyj-obhod-blokirovok-po-domenam-na-routere-s-openwrt/)\n\n# Скрипт для установки\n```\nsh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-install.sh)\n```\n\n# Скрипт для удаления\n```\nsh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/refs/heads/master/getdomains-uninstall.sh)\n```\n\n## AmneziaWG\nЧерез этот скрипт можно установить Amnezia wireguard. Скрипт проверяет наличие пакетов под вашу платформу в [стороннем репозитории](https://github.com/Slava-Shchipunov/awg-openwrt/releases), так как в официальном репозитории OpenWRT они отсутствуют, и автоматически их устанавливает.\n\nЕсли вам нужно установить только AWG, воспользуйтесь скриптом в репозитории: https://github.com/Slava-Shchipunov/awg-openwrt\n\nЕсли подходящих пакетов нет, перед настройкой необходимо будет самостоятельно [собрать бинарники AmneziaWG](https://github.com/itdoginfo/domain-routing-openwrt/wiki/Amnezia-WG-Build) для своего устройства и установить их.\n\n## Скрипт для проверки конфигурации\nНаписан для OpenWrt 23.05 и 22.03. На 21.02 работает только половина проверок.\n\n[x] - не обязательно означает, что эта часть не работает. Но это повод для ручной проверки.\n\n### Запуск\n```\nwget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh\n```\n\nПо-умолчанию запускается на русском языке. Если нужно запустить на английском, то после `sh` нужно добавить `-s --lang en`. Аналогично для проверок на подмену DNS и создания дампа.\n\n```\nwget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s --lang en\n```\n\n### Запустить с проверкой на подмену DNS\n```\nwget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dns\n```\n\n### Запустить с созданием dump\nВсе чувствительные переменные затираются.\n\n```\nwget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dump\n```\n\nПоиск ошибок вручную: https://habr.com/ru/post/702388/\n\n# Ansible\nУстановить роль\n```\nansible-galaxy role install itdoginfo.domain_routing_openwrt\n```\n\nПримеры playbooks\n\nWireguard, only domains, stubby, Russia, acces from wg network (пример 192.168.80.0/24), host 192.168.1.1\n```\n- hosts: 192.168.1.1\n  remote_user: root\n\n  roles:\n    - itdoginfo.domain_routing_openwrt\n\n  vars:\n    tunnel: wg\n    dns_encrypt: stubby\n    country: russia-inside\n\n    wg_server_address: wg-server-host\n    wg_private_key: privatekey-client\n    wg_public_key: publickey-client\n    wg_preshared_key: presharedkey-client\n    wg_listen_port: 51820\n    wg_client_port: 51820\n    wg_client_address: ip-client\n\n    wg_access: true\n    wg_access_network: wg-network\n```\n\nSing-box, stubby, Russia\n```\n- hosts: 192.168.1.1\n  remote_user: root\n\n  roles:\n    - itdoginfo.domain_routing_openwrt\n\n  vars:\n    tunnel: singbox\n    dns_encrypt: stubby\n    country: russia-inside\n\n  tasks:\n  - name: sing-box config\n    template:\n      src: \"templates/openwrt-sing-box-json.j2\"\n      dest: \"/etc/sing-box/config.json\"\n      mode: 0644\n    notify:\n      - Restart sing-box\n      - Restart network\n```\n\nВ inventory файле роутер обязательно должен быть в группе `[openwrt]`\n```\n[openwrt]\n192.168.1.1\n```\n\nДля работы Ansible c OpenWrt необходимо, чтоб было выполнено одно из условий:\n- Отсутствие пароля для root (не рекомендуется)\n- Настроен доступ через публичный SSH-ключ в [конфиге dropbear](https://openwrt.org/docs/guide-user/security/dropbear.public-key.auth)\n\nПосле выполнения playbook роутер сразу начнёт роутить необходмые домены в туннель/прокси.\n\nЕсли у вас были ошибки и они исправились при повторном запуске playbook, но при этом роутинг не заработал, сделайте рестарт сети и скрипта:\n```\nservice network restart\nservice getdomains start\n```\n\nТестировалось с\n- Ansible 2.10.8\n- OpenWrt 21.02.7\n- OpenWrt 22.03.5\n- OpenWrt 23.05.2\n\n## Выбор туннеля\n- Wireguard настраивается автоматически через переменные\n- OpenVPN устанавливается пакет, настраивается роутинг и зона. Само подключение (скопировать конфиг и перезапустить openvpn) нужно [настроить вручную](https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/)\n- Sing-box устанавливает пакет, настраивается роутинг и зона. Также кладётся темплейт в `/etc/sing-box/config.json`. [Нужно настроить](https://habr.com/ru/articles/767458/) `config.json` и сделать `service sing-box restart`\nНе работает под 21ой версией. Поэтому при его выборе playbook выдаст ошибку.\nДля 22ой версии нужно установить пакет вручную.\n- tun2socks настраивается только роутинг и зона. Всё остальное нужно настроить вручную\n\nДля **tunnel** шесть возможных значений:\n- wg\n- openvpn\n- singbox\n- tun2socks\n\nВ случае использования WG:\n```\n    wg_server_address: wg-server-host\n    wg_private_key: privatekey-client\n    wg_public_key: publickey-client\n    wg_preshared_key: presharedkey-client\n    wg_client_port: 51820\n    wg_client_address: ip-client\n```\n\nЕсли ваш wg сервер не использует `preshared_key`, то просто не задавайте её.\n\n**wg_access** и **wg_access_network** для доступа к роутеру через WG. Переменная wg_access_network должна иметь значение подсети, например 192.168.10.0/24.\n```\n    wg_access_network: wg-network\n    wg_access: true\n```\n\n## Шифрование DNS\nЕсли ваш провайдер не подменяет DNS-запросы, ничего устанавливать не нужно.\n\nДля **dns_encrypt** три возможных значения:\n- dnscrypt\n- stubby\n- false/закомментировано - пропуск, ничего не устанавливается и не настраивается\n\n## Выбор страны\nВыбор списка доменов.\nДля **county** три [возможных значения](https://github.com/itdoginfo/allow-domains):\n- russia-inside\n- russia-outside\n- ukraine\n\n## Списки IP-адресов\nСписки IP-адресов берутся с [antifilter.download](https://antifilter.download/)\nПеременные **list_** обозначают, какие списки нужно установить. true - установить, false - не устанавливать и удалить, если уже есть\n\nДоступные переменные\n```\n  list_domains: true\n  list_subnet: false\n  list_ip: falses\n  list_community: false\n```\n\nЯ советую использовать только домены\n```\n    list_domains: true\n```\nЕсли вам требуются списки IP-адресов, они также поддерживаются.\n\nПри использовании **list_domains** нужен пакет dnsmasq-full.\n\nДля 23.05 dnsmasq-full устанавливается автоматически.\n\nДля OpenWrt 22.03 версия dnsmasq-full должна быть => 2.87, её нет в официальном репозитории, но можно установить из dev репозитория. Если это условие не выполнено, плейбук завершится с ошибкой.\n\n[Инструкция для OpenWrt 22.03](https://t.me/itdoginf/12)\n\n[Инструкция для OpenWrt 21.02](https://t.me/itdoginfo/8)\n\n## Текстовый редактор nano\nУстанавливается по умолчанию. Можно выключить\n```\n  nano: false\n```\n\n---\n\n[Telegram-канал с обновлениями](https://t.me/+lW1HmBO_Fa00M2Iy)\n"
  },
  {
    "path": "defaults/main.yml",
    "content": "---\n  list_domains: true\n  list_subnet: false\n  list_ip: false\n  list_community: false\n  tunnel: wg\n  dns_encrypt: false\n  country: russia-inside\n  nano: true\n  wg_access: false\n\n  wg_listen_port: 51820"
  },
  {
    "path": "getdomains-check.sh",
    "content": "#!/bin/sh\n\nSCRIPTS_DIR=\"/etc/init.d\"\nTMP_DIR=\"/tmp\"\nHIVPN_SCRIPT_FILENAME=\"hivpn\"\nGETDOMAINS_SCRIPT_FILENAME=\"getdomains\"\nDUMP_FILENAME=\"dump.txt\"\n\nHIVPN_SCRIPT_PATH=\"$SCRIPTS_DIR/$HIVPN_SCRIPT_FILENAME\"\nGETDOMAINS_SCRIPT_PATH=\"$SCRIPTS_DIR/$GETDOMAINS_SCRIPT_FILENAME\"\nDUMP_PATH=\"$TMP_DIR/$DUMP_FILENAME\"\n\nCOLOR_BOLD_BLUE=\"\\033[34;1m\"\nCOLOR_BOLD_GREEN=\"\\033[32;1m\"\nCOLOR_BOLD_RED=\"\\033[31;1m\"\nCOLOR_BOLD_CYAN=\"\\033[36;1m\"\nCOLOR_RESET=\"\\033[0m\"\n\nUNSUPPORTED_OPENWRT_VERSION=\"21.02\"\nMIN_RAM=\"256\"\nDNSMASQ_FULL_REQUIRED_VERSION=\"2.87\"\n\nSINGBOX_CONFIG_PATH=\"/etc/config/sing-box\"\n\nCURL_PACKAGE=\"curl\"\nDNSMASQ_PACKAGE=\"dnsmasq\"\nDNSMASQ_FULL_PACKAGE=\"$DNSMASQ_PACKAGE-full\"\nXRAY_CORE_PACKAGE=\"xray-core\"\nLUCI_APP_XRAY_PACKAGE=\"luci-app-xray\"\nWIREGUARD_TOOLS_PACKAGE=\"wireguard-tools\"\nOPENVPN_PACKAGE=\"openvpn\"\nSINGBOX_PACKAGE=\"sing-box\"\nTUN2SOCKS_PACKAGE=\"tun2socks\"\nDNSCRYPT_PACKAGE=\"dnscrypt-proxy2\"\nSTUBBY_PACKAGE=\"stubby\"\n\nWIREGUARD_PROTOCOL=\"Wireguard\"\nOPENVPN_PROTOCOL=\"OpenVPN\"\n\nLANGUAGE=\"ru\"\nSUPPORTED_LANGUAGES=\"ru, en\"\n\nset_language_en() {\n  DEVICE_MODEL=\"Model\"\n  OPENWRT_VERSION=\"Version\"\n  CURRENT_DATE=\"Date\"\n  INSTALLED=\"is installed\"\n  NOT_INSTALLED=\"is not installed\"\n  RUNNING=\"is running\"\n  NOT_RUNNING=\"is not running\"\n  ENABLED=\"is enabled\"\n  DISABLED=\"is disabled\"\n  EXISTS=\"exists\"\n  DOESNT_EXIST=\"doesn't exist\"\n  UNSUPPORTED_OPENWRT=\"You are using OpenWrt $UNSUPPORTED_OPENWRT_VERSION. This check script does not support it.\"\n  RAM_WARNING=\"Your router has less than $MIN_RAM MB of RAM. It is recommended to use only the vpn_domains list.\"\n  CURL_INSTALLED=\"$CURL_PACKAGE $INSTALLED\"\n  CURL_NOT_INSTALLED=\"$CURL_PACKAGE $NOT_INSTALLED. Install it: opkg install $CURL_PACKAGE\"\n  DNSMASQ_FULL_INSTALLED=\"$DNSMASQ_FULL_PACKAGE $INSTALLED\"\n  DNSMASQ_FULL_NOT_INSTALLED=\"$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED\"\n  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\"\n  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\"\n  XRAY_CORE_PACKAGE_DETECTED=\"$XRAY_CORE_PACKAGE package detected\"\n  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\"\n  DNSMASQ_SERVICE_RUNNING=\"$DNSMASQ_PACKAGE service $RUNNING\"\n  DNSMASQ_SERVICE_NOT_RUNNING=\"$DNSMASQ_PACKAGE service $NOT_RUNNING. Check configuration: /etc/config/dhcp\"\n  INTERNET_IS_AVAILABLE=\"Internet is available\"\n  INTERNET_IS_NOT_AVAILABLE=\"Internet is not available\"\n  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/\"\n  IPV6_DETECTED=\"IPv6 detected. This script does not currently work with IPv6\"\n  WIREGUARD_TOOLS_INSTALLED=\"$WIREGUARD_TOOLS_PACKAGE $INSTALLED\"\n  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\"\n  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\"\n  WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED=\"$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/SaxBzH7\"\n  WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED=\"$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED\"\n  WIREGUARD_ROUTING_TABLE_EXISTS=\"$WIREGUARD_PROTOCOL routing table $EXISTS\"\n  WIREGUARD_ROUTING_TABLE_DOESNT_EXIST=\"$WIREGUARD_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3\"\n  OPENVPN_INSTALLED=\"$OPENVPN_PACKAGE $INSTALLED\"\n  OPENVPN_ROUTING_DOESNT_WORK=\"Tunnel to the $OPENVPN_PROTOCOL server works, but routing to the internet does not work. Check server configuration.\"\n  OPENVPN_TUNNEL_NOT_WORKING=\"Bad news: $OPENVPN_PROTOCOL tunnel isn't working. Check your $OPENVPN_PROTOCOL configuration.\"\n  OPENVPN_REDIRECT_GATEWAY_ENABLED=\"$OPENVPN_PROTOCOL redirect-gateway $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/vzTNq_3\"\n  OPENVPN_REDIRECT_GATEWAY_DISABLED=\"$OPENVPN_PROTOCOL redirect-gateway $DISABLED\"\n  OPENVPN_ROUTING_TABLE_EXISTS=\"$OPENVPN_PROTOCOL routing table $EXISTS\"\n  OPENVPN_ROUTING_TABLE_DOESNT_EXIST=\"$OPENVPN_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3\"\n  SINGBOX_INSTALLED=\"$SINGBOX_PACKAGE $INSTALLED\"\n  SINGBOX_ROUTING_TABLE_EXISTS=\"$SINGBOX_PACKAGE routing table $EXISTS\"\n  SINGBOX_ROUTING_TABLE_DOESNT_EXIST=\"$SINGBOX_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1\"\n  SINGBOX_UCI_CONFIG_OK=\"$SINGBOX_PACKAGE UCI configuration has been successfully validated\"\n  SINGBOX_UCI_CONFIG_ERROR=\"$SINGBOX_PACKAGE Error validation UCI configuration. Check $SINGBOX_CONFIG_PATH\"\n  SINGBOX_CONFIG_OK=\"$SINGBOX_PACKAGE configuration has been successfully validated\"\n  SINGBOX_CONFIG_ERROR=\"$SINGBOX_PACKAGE configuration validation error\"\n  SINGBOX_WORKING_TEMPLATE=\"$SINGBOX_PACKAGE works. VPN IP: %s\"\n  SINGBOX_ROUTING_DOESNT_WORK=\"$SINGBOX_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/Badmn3K\"\n  TUN2SOCKS_INSTALLED=\"$TUN2SOCKS_PACKAGE $INSTALLED\"\n  TUN2SOCKS_ROUTING_TABLE_EXISTS=\"$TUN2SOCKS_PACKAGE routing table $EXISTS\"\n  TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST=\"$TUN2SOCKS_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1\"\n  TUN2SOCKS_WORKING_TEMPLATE=\"$TUN2SOCKS_PACKAGE works. VPN IP: %s\"\n  TUN2SOCKS_ROUTING_DOESNT_WORK=\"$TUN2SOCKS_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/VNZISEM\"\n  VPN_DOMAINS_SET_EXISTS=\"vpn_domains set $EXISTS\"\n  VPN_DOMAINS_SET_DOESNT_EXIST=\"vpn_domains set $DOESNT_EXIST\"\n  IPS_IN_VPN_DOMAINS_SET_OK=\"IPs are successfully added to vpn_domains set\"\n  IPS_IN_VPN_DOMAINS_SET_ERROR=\"IPs were not added to vpn_domains set\"\n  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\"\n  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\"\n  VPN_IP_SET_EXISTS=\"vpn_ip set $EXISTS\"\n  VPN_IP_SET_DOESNT_EXIST=\"vpn_ip set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6\"\n  IPS_IN_VPN_IP_SET_OK=\"IPs are successfully added to vpn_ip set\"\n  IPS_IN_VPN_IP_SET_ERROR=\"IPs were not added to vpn_ip set. But if you want to use it, check configuration\"\n  VPN_SUBNET_SET_EXISTS=\"vpn_subnets set $EXISTS\"\n  VPN_SUBNET_SET_DOESNT_EXIST=\"vpn_subnets set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6\"\n  IPS_IN_VPN_SUBNET_SET_OK=\"IPs are successfully added to vpn_subnets set\"\n  IPS_IN_VPN_SUBNET_SET_ERROR=\"IPs were not added to vpn_subnets set. But if you want to use it, check configs\"\n  VPN_COMMUNITY_SET_EXISTS=\"vpn_community set $EXISTS\"\n  VPN_COMMUNITY_SET_DOESNT_EXIST=\"vpn_community set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6\"\n  IPS_IN_VPN_COMMUNITY_SET_OK=\"IPs are successfully added to vpn_community set\"\n  IPS_IN_VPN_COMMUNITY_SET_ERROR=\"IPs were not added to vpn_community set. But if you want to use it, check configs\"\n  GETDOMAINS_SCRIPT_EXISTS=\"Script $GETDOMAINS_SCRIPT_FILENAME $EXISTS\"\n  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\"\n  GETDOMAINS_SCRIPT_CRONTAB_OK=\"Script $GETDOMAINS_SCRIPT_FILENAME has been successfully added to crontab\"\n  GETDOMAINS_SCRIPT_CRONTAB_ERROR=\"Script $GETDOMAINS_SCRIPT_FILENAME has not been added to crontab. Check: crontab -l\"\n  DNSCRYPT_INSTALLED=\"$DNSCRYPT_PACKAGE $INSTALLED\"\n  DNSCRYPT_SERVICE_RUNNING=\"$DNSCRYPT_PACKAGE service $RUNNING\"\n  DNSCRYPT_SERVICE_NOT_RUNNING=\"$DNSCRYPT_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/wN-tc_S\"\n  DNSMASQ_CONFIG_FOR_DNSCRYPT_OK=\"$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is ok\"\n  DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR=\"$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is not ok. Check configuration: https://cli.co/rooc0uz\"\n  STUBBY_INSTALLED=\"$STUBBY_PACKAGE $INSTALLED\"\n  STUBBY_SERVICE_RUNNING=\"$STUBBY_PACKAGE service $RUNNING\"\n  STUBBY_SERVICE_NOT_RUNNING=\"$STUBBY_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/HbDBT2V\"\n  DNSMASQ_CONFIG_FOR_STUBBY_OK=\"$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is ok\"\n  DNSMASQ_CONFIG_FOR_STUBBY_ERROR=\"$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is not ok. Check configuration: https://cli.co/HbDBT2V\"\n  DUMP_CREATION=\"Creating dump without private variables\"\n  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\"\n  DNS_CHECK=\"Checking DNS servers\"\n  IS_DNS_TRAFFIC_BLOCKED=\"Checking DNS traffic blocking (Port 53/udp is available)\"\n  IS_DOH_AVAILABLE=\"Checking DOH availability\"\n  RESPONSE_NOT_CONTAINS_127_0_0_8=\"Checking that the response does not contain an address from 127.0.0.8\"\n  ONE_IP_FOR_TWO_DOMAINS=\"Checking IP for two different domains\"\n  IPS_ARE_THE_SAME=\"IPs are the same\"\n  IPS_ARE_DIFFERENT=\"IPs are different\"\n  RESPONSE_IS_NOT_BLANK=\"Checking if response is not blank\"\n  DNS_POISONING_CHECK=\"Сomparing response from unencrypted DNS and DoH (DNS poisoning)\"\n  TELEGRAM_CHANNEL=\"Telegram channel\"\n  TELEGRAM_CHAT=\"Telegram chat\"\n}\n\nset_language_ru() {\n  DEVICE_MODEL=\"Модель\"\n  OPENWRT_VERSION=\"Версия\"\n  CURRENT_DATE=\"Дата\"\n  INSTALLED=\"установлен\"\n  NOT_INSTALLED=\"не установлен\"\n  RUNNING=\"запущен\"\n  NOT_RUNNING=\"не запущен\"\n  ENABLED=\"включен\"\n  DISABLED=\"выключен\"\n  EXISTS=\"существует\"\n  DOESNT_EXIST=\"не существует\"\n  UNSUPPORTED_OPENWRT=\"Вы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт проверки её не поддерживает.\"\n  RAM_WARNING=\"У вашего роутера менее $MIN_RAM МБ ОЗУ. Рекомендуется использовать только vpn_domains set.\"\n  CURL_INSTALLED=\"$CURL_PACKAGE $INSTALLED\"\n  CURL_NOT_INSTALLED=\"$CURL_PACKAGE $NOT_INSTALLED. Установите его: opkg install $CURL_PACKAGE\"\n  DNSMASQ_FULL_INSTALLED=\"$DNSMASQ_FULL_PACKAGE $INSTALLED\"\n  DNSMASQ_FULL_NOT_INSTALLED=\"$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED\"\n  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\"\n  OPENWRT_21_DETAILS=\"\\nВы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт её не поддерживает.\\nИнструкция для OpenWrt $UNSUPPORTED_OPENWRT_VERSION: https://t.me/itdoginfo/8\"\n  XRAY_CORE_PACKAGE_DETECTED=\"Обнаружен пакет $XRAY_CORE_PACKAGE\"\n  LUCI_APP_XRAY_PACKAGE_DETECTED=\"Обнаружен пакет $LUCI_APP_XRAY_PACKAGE, который не совместим. Удалите его: opkg remove $LUCI_APP_XRAY_PACKAGE --force-removal-of-dependent-packages\"\n  DNSMASQ_SERVICE_RUNNING=\"Сервис $DNSMASQ_PACKAGE $RUNNING\"\n  DNSMASQ_SERVICE_NOT_RUNNING=\"Сервис $DNSMASQ_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: /etc/config/dhcp\"\n  INTERNET_IS_AVAILABLE=\"Интернет доступен\"\n  INTERNET_IS_NOT_AVAILABLE=\"Интернет недоступен\"\n  INTERNET_DETAILS=\"Проверьте подключение к интернету. Если оно в порядке, проверьте дату на роутере. Подробности: https://cli.co/2EaW4rO\\nДополнительно выполните: curl -Is https://community.antifilter.download/\"\n  IPV6_DETECTED=\"Обнаружен IPv6. Этот скрипт не поддерживает работу с IPv6\"\n  WIREGUARD_TOOLS_INSTALLED=\"$WIREGUARD_TOOLS_PACKAGE $INSTALLED\"\n  WIREGUARD_ROUTING_DOESNT_WORK=\"Туннель к $WIREGUARD_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера. Подробности: https://cli.co/RSCvOxI\"\n  WIREGUARD_TUNNEL_NOT_WORKING=\"Плохие новости: туннель $WIREGUARD_PROTOCOL не работает. Проверьте конфигурацию $WIREGUARD_PROTOCOL. Подробности: https://cli.co/hGUUXDs\\nЕсли вы не используете $WIREGUARD_PROTOCOL, а, например, $OPENVPN_PROTOCOL, то это нормально\"\n  WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED=\"$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/SaxBzH7\"\n  WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED=\"$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED\"\n  WIREGUARD_ROUTING_TABLE_EXISTS=\"Таблица маршрутизации $WIREGUARD_PROTOCOL $EXISTS\"\n  WIREGUARD_ROUTING_TABLE_DOESNT_EXIST=\"Таблица маршрутизации $WIREGUARD_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3\"\n  OPENVPN_INSTALLED=\"$OPENVPN_PACKAGE $INSTALLED\"\n  OPENVPN_ROUTING_DOESNT_WORK=\"Туннель к $OPENVPN_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера.\"\n  OPENVPN_TUNNEL_NOT_WORKING=\"Плохие новости: туннель $OPENVPN_PROTOCOL не работает. Проверьте конфигурацию $OPENVPN_PROTOCOL.\"\n  OPENVPN_REDIRECT_GATEWAY_ENABLED=\"$OPENVPN_PROTOCOL redirect-gateway $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/vzTNq_3\"\n  OPENVPN_REDIRECT_GATEWAY_DISABLED=\"$OPENVPN_PROTOCOL redirect-gateway $DISABLED\"\n  OPENVPN_ROUTING_TABLE_EXISTS=\"Таблица маршрутизации $OPENVPN_PROTOCOL $EXISTS\"\n  OPENVPN_ROUTING_TABLE_DOESNT_EXIST=\"Таблица маршрутизации $OPENVPN_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3\"\n  SINGBOX_INSTALLED=\"$SINGBOX_PACKAGE $INSTALLED\"\n  SINGBOX_ROUTING_TABLE_EXISTS=\"Таблица маршрутизации $SINGBOX_PACKAGE $EXISTS\"\n  SINGBOX_ROUTING_TABLE_DOESNT_EXIST=\"Таблица маршрутизации $SINGBOX_PACKAGE $DOESNT_EXIST. Попробуйте: service network restart. Подробности: https://cli.co/n7xAbc1\"\n  SINGBOX_UCI_CONFIG_OK=\"UCI конфигурация для $SINGBOX_PACKAGE успешно проверена\"\n  SINGBOX_UCI_CONFIG_ERROR=\"Ошибка валидации UCI конфигурации для $SINGBOX_PACKAGE\"\n  SINGBOX_CONFIG_OK=\"Конфигурация $SINGBOX_PACKAGE успешно проверена\"\n  SINGBOX_CONFIG_ERROR=\"Ошибка валидации конфигурации $SINGBOX_PACKAGE\"\n  SINGBOX_WORKING_TEMPLATE=\"$SINGBOX_PACKAGE работает. VPN IP: %s\"\n  SINGBOX_ROUTING_DOESNT_WORK=\"$SINGBOX_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/Badmn3K\"\n  TUN2SOCKS_INSTALLED=\"$TUN2SOCKS_PACKAGE $INSTALLED\"\n  TUN2SOCKS_ROUTING_TABLE_EXISTS=\"Таблица маршрутизации $TUN2SOCKS_PROTOCOL $EXISTS\"\n  TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST=\"Таблица маршрутизации $TUN2SOCKS_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/n7xAbc1\"\n  TUN2SOCKS_WORKING_TEMPLATE=\"$TUN2SOCKS_PACKAGE работает. VPN IP: %s\"\n  TUN2SOCKS_ROUTING_DOESNT_WORK=\"$TUN2SOCKS_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/VNZISEM\"\n  VPN_DOMAINS_SET_EXISTS=\"vpn_domains set $EXISTS\"\n  VPN_DOMAINS_SET_DOESNT_EXIST=\"vpn_domains set $DOESNT_EXIST\"\n  IPS_IN_VPN_DOMAINS_SET_OK=\"IP-адреса успешно добавлены в vpn_domains set\"\n  IPS_IN_VPN_DOMAINS_SET_ERROR=\"IP-адреса не добавлены в vpn_domains set\"\n  VPN_DOMAINS_DETAILS=\"Если вы не используете vpn_domains, все в порядке.\\nНо если вы хотите использовать его, проверьте конфигурацию и выполните: service getdomains start\"\n  VPN_DOMAINS_DETAILS_2=\"Если вы не используете vpn_domains, все в порядке.\\nНо если вы хотите использовать, проверьте конфигурацию: https://cli.co/AwUGeM6\"\n  VPN_IP_SET_EXISTS=\"vpn_ip set $EXISTS\"\n  VPN_IP_SET_DOESNT_EXIST=\"vpn_ip set $DOESNT_EXIST\"\n  IPS_IN_VPN_IP_SET_OK=\"IP-адреса успешно добавлены в set vpn_ip\"\n  IPS_IN_VPN_IP_SET_ERROR=\"IP-адреса не добавлены в set vpn_ip\"\n  VPN_SUBNET_SET_EXISTS=\"vpn_subnet set $EXISTS\"\n  VPN_SUBNET_SET_DOESNT_EXIST=\"vpn_subnet set $DOESNT_EXIST\"\n  IPS_IN_VPN_SUBNET_SET_OK=\"IP-адреса успешно добавлены в set vpn_subnet\"\n  IPS_IN_VPN_SUBNET_SET_ERROR=\"IP-адреса не добавлены в set vpn_subnet\"\n  VPN_COMMUNITY_SET_EXISTS=\"vpn_community set $EXISTS\"\n  VPN_COMMUNITY_SET_DOESNT_EXIST=\"vpn_community set $DOESNT_EXIST\"\n  IPS_IN_VPN_COMMUNITY_SET_OK=\"IP-адреса успешно добавлены в set vpn_community\"\n  IPS_IN_VPN_COMMUNITY_SET_ERROR=\"IP-адреса не добавлены в set vpn_community\"\n  GETDOMAINS_SCRIPT_EXISTS=\"Скрипт $GETDOMAINS_SCRIPT_FILENAME $EXISTS\"\n  GETDOMAINS_SCRIPT_DOESNT_EXIST=\"Скрипт $GETDOMAINS_SCRIPT_FILENAME $DOESNT_EXIST\"\n  GETDOMAINS_SCRIPT_CRONTAB_OK=\"Скрипт $GETDOMAINS_SCRIPT_FILENAME успешно добавлен в crontab\"\n  GETDOMAINS_SCRIPT_CRONTAB_ERROR=\"Скрипт $GETDOMAINS_SCRIPT_FILENAME не был добавлен в crontab. Проверьте: crontab -l\"\n  DNSCRYPT_INSTALLED=\"$DNSCRYPT_PACKAGE $INSTALLED\"\n  DNSCRYPT_SERVICE_RUNNING=\"Сервис $DNSCRYPT_PACKAGE $RUNNING\"\n  DNSCRYPT_SERVICE_NOT_RUNNING=\"Сервис $DNSCRYPT_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/wN-tc_S\"\n  DNSMASQ_CONFIG_FOR_DNSCRYPT_OK=\"Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE в порядке\"\n  DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR=\"Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/rooc0uz\"\n  STUBBY_INSTALLED=\"$STUBBY_PACKAGE $INSTALLED\"\n  STUBBY_SERVICE_RUNNING=\"Сервис $STUBBY_PACKAGE $RUNNING\"\n  STUBBY_SERVICE_NOT_RUNNING=\"Сервис $STUBBY_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/HbDBT2V\"\n  DNSMASQ_CONFIG_FOR_STUBBY_OK=\"Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE в порядке\"\n  DNSMASQ_CONFIG_FOR_STUBBY_ERROR=\"Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/HbDBT2V\"\n  DUMP_CREATION=\"Создание дампа без приватных переменных\"\n  DUMP_DETAILS=\"Дамп находится здесь: $DUMP_PATH\\nДля загрузки на Linux/Mac используйте: scp root@IP_ROUTER:$DUMP_PATH .\\nДля Windows используйте WinSCP/PSCP или WSL\"\n  DNS_CHECK=\"Проверка DNS серверов\"\n  IS_DNS_TRAFFIC_BLOCKED=\"Проверяем блокировку DNS трафика (Порт 53/udp доступен)\"\n  IS_DOH_AVAILABLE=\"Проверяем доступность DoH\"\n  RESPONSE_NOT_CONTAINS_127_0_0_8=\"Проверяем, что ответ на запрос не содержит адреса из 127.0.0.8\"\n  ONE_IP_FOR_TWO_DOMAINS=\"Проверяем IP для двух разных доменов\"\n  IPS_ARE_THE_SAME=\"IP совпадают\"\n  IPS_ARE_DIFFERENT=\"IP различаются\"\n  RESPONSE_IS_NOT_BLANK=\"Проверяем, что ответ не пустой\"\n  DNS_POISONING_CHECK=\"Сравниваем ответ от незащищенного DNS и DoH (Подмена DNS)\"\n  TELEGRAM_CHANNEL=\"Telegram канал\"\n  TELEGRAM_CHAT=\"Telegram чат\"\n}\n\ncheckpoint_true() {\n  printf \"$COLOR_BOLD_GREEN[\\342\\234\\223] $1$COLOR_RESET\\n\"\n}\n\ncheckpoint_false() {\n  printf \"$COLOR_BOLD_RED[x] $1$COLOR_RESET\\n\"\n}\n\noutput_21() {\n  if [ \"$VERSION_ID\" -eq 21 ]; then\n    echo \"$UNSUPPORTED_OPENWRT\"\n  fi\n}\n\nupdate_vpn_ip() {\n  local template=\"$1\"\n  local ip=\"$2\"\n  echo \"$(printf \"$template\" \"$ip\")\"\n}\n\nwhile [ $# -gt 0 ]; do\n  case \"$1\" in\n    --lang)\n      LANGUAGE=\"$2\"\n      shift 2\n      ;;\n    dump | dns)\n      COMMAND=\"$1\"\n      shift 1\n      ;;\n    *)\n      printf \"$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unknown option: %s\\n\" \"$1\"\n      exit 1\n      ;;\n  esac\ndone\n\ncase $LANGUAGE in\n  ru)\n    set_language_ru\n    ;;\n  en)\n    set_language_en\n    ;;\n  *)\n    printf \"$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unsupported language '$LANGUAGE'. Supported languages: $SUPPORTED_LANGUAGES %s\\n\" \"$1\"\n    exit 1\n    ;;\nesac\n\n# System Details\nMODEL=$(cat /tmp/sysinfo/model)\nsource /etc/os-release\nprintf \"$COLOR_BOLD_BLUE$DEVICE_MODEL: $MODEL$COLOR_RESET\\n\"\nprintf \"$COLOR_BOLD_BLUE$OPENWRT_VERSION: $OPENWRT_RELEASE$COLOR_RESET\\n\"\nprintf \"$COLOR_BOLD_BLUE$CURRENT_DATE: $(date)$COLOR_RESET\\n\"\n\nVERSION_ID=$(echo $VERSION | awk -F. '{print $1}')\nRAM=$(free -m | grep Mem: | awk '{print $2}')\nif [[ \"$VERSION_ID\" -ge 22 && \"$RAM\" -lt 150000 ]]; then\n  echo \"$RAM_WARNING\"\nfi\n\n# Check packages\nCURL=$(opkg list-installed | grep -c curl)\nif [ $CURL -eq 2 ]; then\n  checkpoint_true \"$CURL_INSTALLED\"\nelse\n  checkpoint_false \"$CURL_NOT_INSTALLED\"\nfi\n\nDNSMASQ=$(opkg list-installed | grep dnsmasq-full | awk -F \"-\" '{print $3}' | tr -d '.')\nif [ $DNSMASQ -ge 287 ]; then\n  checkpoint_true \"$DNSMASQ_FULL_INSTALLED\"\nelse\n  checkpoint_false \"$DNSMASQ_FULL_NOT_INSTALLED\"\n  printf \"$DNSMASQ_FULL_DETAILS\\n\"\n  if [ \"$VERSION_ID\" -eq 21 ]; then\n    printf \"$OPENWRT_21_DETAILS\\n\"\n  fi\nfi\n\n# Chek xray package\nif opkg list-installed | grep -q xray-core; then\n  checkpoint_false \"$XRAY_CORE_PACKAGE_DETECTED\"\nfi\n\nif opkg list-installed | grep -q luci-app-xray; then\n  checkpoint_false \"$LUCI_APP_XRAY_PACKAGE_DETECTED\"\nfi\n\n# Check dnsmasq\nDNSMASQ_RUN=$(service dnsmasq status | grep -c 'running')\nif [ $DNSMASQ_RUN -eq 1 ]; then\n  checkpoint_true \"$DNSMASQ_SERVICE_RUNNING\"\nelse\n  checkpoint_false \"$DNSMASQ_SERVICE_NOT_RUNNING\"\n  output_21\nfi\n\n# Check internet connection\nif curl -Is https://community.antifilter.download/ | grep -q 200; then\n  checkpoint_true \"$INTERNET_IS_AVAILABLE\"\nelse\n  checkpoint_false \"$INTERNET_IS_NOT_AVAILABLE\"\n  if [ $CURL -lt 2 ]; then\n    echo \"$CURL_NOT_INSTALLED\"\n  else\n    printf \"$INTERNET_DETAILS\\n\"\n  fi\nfi\n\n# Check IPv6\n\nif curl -6 -s https://ifconfig.io | egrep -q \"(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?\"; then\n  checkpoint_false \"$IPV6_DETECTED\"\nfi\n\n# Tunnels\nWIREGUARD=$(opkg list-installed | grep -c wireguard-tools)\nif [ $WIREGUARD -eq 1 ]; then\n  checkpoint_true \"$WIREGUARD_TOOLS_INSTALLED\"\n  WG=true\nfi\n\nif [ \"$WG\" == true ]; then\n  WG_PING=$(ping -c 1 -q -I wg0 itdog.info | grep -c \"1 packets received\")\n  if [ $WG_PING -eq 1 ]; then\n    checkpoint_true \"$WIREGUARD_PROTOCOL\"\n  else\n    checkpoint_false \"$WIREGUARD_PROTOCOL\"\n    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}')\n    if [ $WG_TRACE -eq 1 ]; then\n      echo \"$WIREGUARD_ROUTING_DOESNT_WORK\"\n    else\n      printf \"$WIREGUARD_TUNNEL_NOT_WORKING\\n\"\n    fi\n  fi\n\n  # Check WG route_allowed_ips\n  if uci show network | grep -q \".route_allowed_ips='1'\"; then\n    checkpoint_false \"$WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED\"\n  else\n    checkpoint_true \"$WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED\"\n  fi\n\n  # Check route table\n  ROUTE_TABLE=$(ip route show table vpn | grep -c \"default dev wg0\")\n  if [ $ROUTE_TABLE -eq 1 ]; then\n    checkpoint_true \"$WIREGUARD_ROUTING_TABLE_EXISTS\"\n  else\n    checkpoint_false \"$WIREGUARD_ROUTING_TABLE_DOESNT_EXIST\"\n  fi\nfi\n\nif opkg list-installed | grep -q openvpn; then\n  checkpoint_true \"$OPENVPN_INSTALLED\"\n  OVPN=true\nfi\n\n# Check OpenVPN\nif [ \"$OVPN\" == true ]; then\n  if ping -c 1 -q -I tun0 itdog.info | grep -q \"1 packets received\"; then\n    checkpoint_true \"$OPENVPN_PROTOCOL\"\n  else\n    checkpoint_false \"$OPENVPN_PROTOCOL\"\n    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\n      echo \"$OPENVPN_ROUTING_DOESNT_WORK\"\n    else\n      echo \"$OPENVPN_TUNNEL_NOT_WORKING\"\n    fi\n  fi\n\n  # Check OpenVPN redirect-gateway\n  if grep -q redirect-gateway /etc/openvpn/*; then\n    checkpoint_false \"$OPENVPN_REDIRECT_GATEWAY_ENABLED\"\n  else\n    checkpoint_true \"$OPENVPN_REDIRECT_GATEWAY_DISABLED\"\n  fi\n\n  # Check route table\n  if ip route show table vpn | grep -q \"default dev tun0\"; then\n    checkpoint_true \"$OPENVPN_ROUTING_TABLE_EXISTS\"\n  else\n    checkpoint_false \"$OPENVPN_ROUTING_TABLE_DOESNT_EXIST\"\n  fi\nfi\n\nif opkg list-installed | grep -q sing-box; then\n  checkpoint_true \"$SINGBOX_INSTALLED\"\n\n  # Check route table\n  if ip route show table vpn | grep -q \"default dev tun0\"; then\n    checkpoint_true \"$SINGBOX_ROUTING_TABLE_EXISTS\"\n  else\n    checkpoint_false \"$SINGBOX_ROUTING_TABLE_DOESNT_EXIST\"\n  fi\n\n  # Sing-box uci validation\n  if uci show sing-box 2>&1 | grep -q \"Parse error\"; then\n    checkpoint_false \"$SINGBOX_UCI_CONFIG_ERROR\"\n  else\n    checkpoint_true \"$SINGBOX_UCI_CONFIG_OK\"\n  fi\n\n  singbox_check_cmd=\"sing-box -c /etc/sing-box/config.json check\"\n  if $singbox_check_cmd >/dev/null 2>&1; then\n    checkpoint_true \"$SINGBOX_CONFIG_OK\"\n\n    # Check traffic\n    IP_EXTERNAL=$(curl -s ifconfig.me)\n    IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}')\n\n    IP_VPN=$(curl --interface tun0 -s ifconfig.me)\n\n    SINGBOX_WORKING=$(update_vpn_ip \"$SINGBOX_WORKING_TEMPLATE\" \"$IP_VPN\")\n\n    if [ \"$IP_EXTERNAL\" != $IP_VPN ]; then\n      checkpoint_true \"$SINGBOX_WORKING\"\n    else\n      checkpoint_false \"$SINGBOX_ROUTING_DOESNT_WORK\"\n    fi\n  else\n    checkpoint_false \"$SINGBOX_CONFIG_ERROR:\"\n    $singbox_check_cmd\n  fi\nfi\n\nif which tun2socks | grep -q tun2socks; then\n  checkpoint_true \"$TUN2SOCKS_INSTALLED\"\n\n  # Check route table\n  if ip route show table vpn | grep -q \"default dev tun0\"; then\n    checkpoint_true \"$TUN2SOCKS_ROUTING_TABLE_EXISTS\"\n  else\n    checkpoint_false \"$TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST\"\n  fi\n\n  IP_EXTERNAL=$(curl -s ifconfig.me)\n  IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}')\n\n  IP_VPN=$(curl --interface tun0 -s ifconfig.me)\n\n  TUN2SOCKS_WORKING=$(update_vpn_ip \"$TUN2SOCKS_WORKING_TEMPLATE\" \"$IP_VPN\")\n\n  if [ \"$IP_EXTERNAL\" != $IP_VPN ]; then\n    checkpoint_true \"$TUN2SOCKS_WORKING\"\n  else\n    checkpoint_false \"$TUN2SOCKS_ROUTING_DOESNT_WORK\"\n  fi\nfi\n\n# Check sets\n\n# vpn_domains set\nvpn_domain_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_domain_ipset_string=$(uci show firewall.@ipset[$vpn_domain_ipset_id] | grep -c \"name='vpn_domains'\\|match='dst_net'\")\nvpn_domain_rule_id=$(uci show firewall | grep -E '@rule.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_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'\")\n\nif [ $((vpn_domain_ipset_string + vpn_domain_rule_string)) -eq 10 ]; then\n  checkpoint_true \"$VPN_DOMAINS_SET_EXISTS\"\n\n  # force resolve for vpn_domains. All list\n  nslookup terraform.io 127.0.0.1 >/dev/null\n  nslookup pochta.ru 127.0.0.1 >/dev/null\n  nslookup 2gis.ru 127.0.0.1 >/dev/null\n\n  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}')\n  if [ $VPN_DOMAINS_IP -ge 1 ]; then\n    checkpoint_true \"$IPS_IN_VPN_DOMAINS_SET_OK\"\n  else\n    checkpoint_false \"$IPS_IN_VPN_DOMAINS_SET_ERROR\"\n    printf \"$VPN_DOMAINS_DETAILS\\n\"\n    output_21\n  fi\nelse\n  checkpoint_false \"$VPN_DOMAINS_SET_DOESNT_EXIST\"\n  printf \"$VPN_DOMAINS_DETAILS_2\\n\"\nfi\n\n# vpn_ip set\nvpn_ip_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_ip_ipset_string=$(uci show firewall.@ipset[$vpn_ip_ipset_id] | grep -c \"name='vpn_ip'\\|match='dst_net'\\|loadfile='/tmp/lst/ip.lst'\")\nvpn_ip_rule_id=$(uci show firewall | grep -E '@rule.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_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'\")\n\nif [ $((vpn_ip_ipset_string + vpn_ip_rule_string)) -eq 11 ]; then\n  checkpoint_true \"$VPN_IP_SET_EXISTS\"\n  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}')\n  if [ $VPN_IP_IP -ge 1 ]; then\n    checkpoint_true \"$IPS_IN_VPN_IP_SET_OK\"\n  else\n    checkpoint_false \"$IPS_IN_VPN_IP_SET_ERROR\"\n    output_21\n  fi\nelif uci show firewall | grep -q \"vpn_ip\"; then\n  checkpoint_false \"$VPN_IP_SET_DOESNT_EXIST\"\nfi\n\n# vpn_subnet set\nvpn_subnet_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_subnet_ipset_string=$(uci show firewall.@ipset[$vpn_subnet_ipset_id] | grep -c \"name='vpn_subnets'\\|match='dst_net'\\|loadfile='/tmp/lst/subnet.lst'\")\nvpn_subnet_rule_id=$(uci show firewall | grep -E '@rule.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_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'\")\n\nif [ $((vpn_subnet_ipset_string + vpn_subnet_rule_string)) -eq 11 ]; then\n  checkpoint_true \"$VPN_SUBNET_SET_EXISTS\"\n  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}')\n  if [ $VPN_IP_SUBNET -ge 1 ]; then\n    checkpoint_true \"$IPS_IN_VPN_SUBNET_SET_OK\"\n  else\n    checkpoint_false \"$IPS_IN_VPN_SUBNET_SET_ERROR\"\n    output_21\n  fi\nelif uci show firewall | grep -q \"vpn_subnet\"; then\n  checkpoint_false \"$VPN_SUBNET_SET_DOESNT_EXIST\"\nfi\n\n# vpn_community set\nvpn_community_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_community_ipset_string=$(uci show firewall.@ipset[$vpn_community_ipset_id] | grep -c \"name='vpn_community'\\|match='dst_net'\\|loadfile='/tmp/lst/community.lst'\")\nvpn_community_rule_id=$(uci show firewall | grep -E '@rule.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1)\nvpn_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'\")\n\nif [ $((vpn_community_ipset_string + vpn_community_rule_string)) -eq 11 ]; then\n  checkpoint_true \"$VPN_COMMUNITY_SET_EXISTS\"\n  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}')\n  if [ $VPN_COMMUNITY_IP -ge 1 ]; then\n    checkpoint_true \"$IPS_IN_VPN_COMMUNITY_SET_OK\"\n  else\n    checkpoint_false \"$IPS_IN_VPN_COMMUNITY_SET_ERROR\"\n    output_21\n  fi\nelif uci show firewall | grep -q \"vpn_community\"; then\n  checkpoint_false \"$VPN_COMMUNITY_SET_DOESNT_EXIST\"\nfi\n\n# getdomains script\nif [ -s \"$GETDOMAINS_SCRIPT_PATH\" ]; then\n  checkpoint_true \"$GETDOMAINS_SCRIPT_EXISTS\"\n  if crontab -l | grep -q $GETDOMAINS_SCRIPT_PATH; then\n    checkpoint_true \"$GETDOMAINS_SCRIPT_CRONTAB_OK\"\n  else\n    checkpoint_false \"$GETDOMAINS_SCRIPT_CRONTAB_ERROR\"\n  fi\nelse\n  checkpoint_false \"$GETDOMAINS_SCRIPT_DOESNT_EXIST\"\nfi\n\n# DNS\n\n# DNSCrypt\nif opkg list-installed | grep -q dnscrypt-proxy2; then\n  checkpoint_true \"$DNSCRYPT_INSTALLED\"\n  if service dnscrypt-proxy status | grep -q 'running'; then\n    checkpoint_true \"$DNSCRYPT_SERVICE_RUNNING\"\n  else\n    checkpoint_false \"$DNSCRYPT_SERVICE_NOT_RUNNING\"\n    output_21\n  fi\n\n  DNSMASQ_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c \"127.0.0.53#53\\|noresolv='1'\")\n  if [ $DNSMASQ_STRING -eq 2 ]; then\n    checkpoint_true \"$DNSMASQ_CONFIG_FOR_DNSCRYPT_OK\"\n  else\n    checkpoint_false \"$DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR\"\n  fi\nfi\n\n# Stubby\nif opkg list-installed | grep -q stubby; then\n  checkpoint_true \"$STUBBY_INSTALLED\"\n  if service stubby status | grep -q 'running'; then\n    checkpoint_true \"$STUBBY_SERVICE_RUNNING\"\n  else\n    checkpoint_false \"$STUBBY_SERVICE_NOT_RUNNING\"\n    output_21\n  fi\n\n  STUBBY_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c \"127.0.0.1#5453\\|noresolv='1'\")\n  if [ $STUBBY_STRING -eq 2 ]; then\n    checkpoint_true \"$DNSMASQ_CONFIG_FOR_STUBBY_OK\"\n  else\n    checkpoint_false \"$DNSMASQ_CONFIG_FOR_STUBBY_ERROR\"\n  fi\nfi\n\ncase $COMMAND in\n  dump)\n    # Create dump\n    printf \"\\n$COLOR_BOLD_CYAN$DUMP_CREATION$COLOR_RESET\\n\"\n    date >$DUMP_PATH\n    $HIVPN start >>$DUMP_PATH 2>&1\n    $GETDOMAINS_SCRIPT_PATH start >>$DUMP_PATH 2>&1\n    uci show firewall >>$DUMP_PATH\n    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\n    printf \"$DUMP_DETAILS\\n\"\n    ;;\n  dns)\n    # Check DNS\n    printf \"\\n$COLOR_BOLD_CYAN$DNS_CHECK$COLOR_RESET\\n\"\n    DNS_SERVERS=\"1.1.1.1 8.8.8.8 8.8.4.4\"\n    DOH_DNS_SERVERS=\"cloudflare-dns.com 1.1.1.1 mozilla.cloudflare-dns.com security.cloudflare-dns.com\"\n    DOMAINS=\"instagram.com facebook.com\"\n\n    echo \"1. $IS_DNS_TRAFFIC_BLOCKED\"\n\n    for i in $DNS_SERVERS; do\n      if nslookup -type=a -timeout=2 -retry=1 itdog.info $i | grep -q \"timed out\"; then\n        checkpoint_false \"$i\"\n      else\n        checkpoint_true \"$i\"\n      fi\n    done\n\n    echo \"2. $IS_DOH_AVAILABLE\"\n\n    for i in $DOH_DNS_SERVERS; do\n      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\n        checkpoint_true \"$i\"\n      else\n        checkpoint_false \"$i\"\n      fi\n    done\n\n    echo \"3. $RESPONSE_NOT_CONTAINS_127_0_0_8\"\n\n    for i in $DOMAINS; do\n      if nslookup -type=a -timeout=2 -retry=1 $i | awk '/^Address: / {print $2}' | grep -q -E '127\\.[0-9]{1,3}\\.'; then\n        checkpoint_false \"$i\"\n      else\n        checkpoint_true \"$i\"\n      fi\n    done\n\n    echo \"4. $ONE_IP_FOR_TWO_DOMAINS\"\n\n    FIRSTIP=$(nslookup -type=a instagram.com | awk '/^Address: / {print $2}')\n    SECONDIP=$(nslookup -type=a facebook.com | awk '/^Address: / {print $2}')\n\n    if [ \"$FIRSTIP\" = \"$SECONDIP\" ]; then\n      checkpoint_false \"$IPS_ARE_THE_SAME\"\n    else\n      checkpoint_true \"$IPS_ARE_DIFFERENT\"\n    fi\n\n    echo \"5. $RESPONSE_IS_NOT_BLANK\"\n\n    for i in $DOMAINS; do\n      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\n        checkpoint_true \"$i\"\n      else\n        checkpoint_false \"$i\"\n      fi\n    done\n\n    echo \"6. $DNS_POISONING_CHECK\"\n\n    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}')\n    OPENIP=$(nslookup -type=a -timeout=2 facebook.com 1.1.1.1 | awk '/^Address: / {print $2}')\n\n    if [ \"$DOHIP\" = \"$OPENIP\" ]; then\n      checkpoint_true \"$IPS_ARE_THE_SAME\"\n    else\n      checkpoint_false \"$IPS_ARE_DIFFERENT\"\n    fi\n    ;;\n  *) ;;\nesac\n\n# Info\necho -e \"\\n$TELEGRAM_CHANNEL: https://t.me/itdoginfo\"\necho \"$TELEGRAM_CHAT: https://t.me/itdogchat\"\n"
  },
  {
    "path": "getdomains-install.sh",
    "content": "#!/bin/sh\n\n#set -x\n\ncheck_repo() {\n    printf \"\\033[32;1mChecking OpenWrt repo availability...\\033[0m\\n\"\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\n}\n\nroute_vpn () {\n    if [ \"$TUNNEL\" == wg ]; then\ncat << EOF > /etc/hotplug.d/iface/30-vpnroute\n#!/bin/sh\n\nip route add table vpn default dev wg0\nEOF\n    elif [ \"$TUNNEL\" == awg ]; then\ncat << EOF > /etc/hotplug.d/iface/30-vpnroute\n#!/bin/sh\n\nip route add table vpn default dev awg0\nEOF\n    elif [ \"$TUNNEL\" == singbox ] || [ \"$TUNNEL\" == ovpn ] || [ \"$TUNNEL\" == tun2socks ]; then\ncat << EOF > /etc/hotplug.d/iface/30-vpnroute\n#!/bin/sh\n\nsleep 10\nip route add table vpn default dev tun0\nEOF\n    fi\n\n    cp /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute\n}\n\nadd_mark() {\n    grep -q \"99 vpn\" /etc/iproute2/rt_tables || echo '99 vpn' >> /etc/iproute2/rt_tables\n    \n    if ! uci show network | grep -q mark0x1; then\n        printf \"\\033[32;1mConfigure mark rule\\033[0m\\n\"\n        uci add network rule\n        uci set network.@rule[-1].name='mark0x1'\n        uci set network.@rule[-1].mark='0x1'\n        uci set network.@rule[-1].priority='100'\n        uci set network.@rule[-1].lookup='vpn'\n        uci commit\n    fi\n}\n\nadd_tunnel() {\n    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\"\n    echo \"Select a tunnel:\"\n    echo \"1) WireGuard\"\n    echo \"2) OpenVPN\"\n    echo \"3) Sing-box\"\n    echo \"4) tun2socks\"\n    echo \"5) wgForYoutube\"\n    echo \"6) Amnezia WireGuard\"\n    echo \"7) Amnezia WireGuard For Youtube\"\n    echo \"8) Skip this step\"\n\n    while true; do\n    read -r -p '' TUNNEL\n        case $TUNNEL in \n\n        1) \n            TUNNEL=wg\n            break\n            ;;\n\n        2)\n            TUNNEL=ovpn\n            break\n            ;;\n\n        3) \n            TUNNEL=singbox\n            break\n            ;;\n\n        4) \n            TUNNEL=tun2socks\n            break\n            ;;\n\n        5) \n            TUNNEL=wgForYoutube\n            break\n            ;;\n\n        6) \n            TUNNEL=awg\n            break\n            ;;\n\n        7) \n            TUNNEL=awgForYoutube\n            break\n            ;;\n\n        8)\n            echo \"Skip\"\n            TUNNEL=0\n            break\n            ;;\n\n        *)\n            echo \"Choose from the following options\"\n            ;;\n        esac\n    done\n\n    if [ \"$TUNNEL\" == 'wg' ]; then\n        printf \"\\033[32;1mConfigure WireGuard\\033[0m\\n\"\n        if opkg list-installed | grep -q wireguard-tools; then\n            echo \"Wireguard already installed\"\n        else\n            echo \"Installed wg...\"\n            opkg install wireguard-tools\n        fi\n\n        route_vpn\n\n        read -r -p \"Enter the private key (from [Interface]):\"$'\\n' WG_PRIVATE_KEY\n\n        while true; do\n            read -r -p \"Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):\"$'\\n' WG_IP\n            if echo \"$WG_IP\" | egrep -oq '^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]+$'; then\n                break\n            else\n                echo \"This IP is not valid. Please repeat\"\n            fi\n        done\n\n        read -r -p \"Enter the public key (from [Peer]):\"$'\\n' WG_PUBLIC_KEY\n        read -r -p \"If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:\"$'\\n' WG_PRESHARED_KEY\n        read -r -p \"Enter Endpoint host without port (Domain or IP) (from [Peer]):\"$'\\n' WG_ENDPOINT\n\n        read -r -p \"Enter Endpoint host port (from [Peer]) [51820]:\"$'\\n' WG_ENDPOINT_PORT\n        WG_ENDPOINT_PORT=${WG_ENDPOINT_PORT:-51820}\n        if [ \"$WG_ENDPOINT_PORT\" = '51820' ]; then\n            echo $WG_ENDPOINT_PORT\n        fi\n        \n        uci set network.wg0=interface\n        uci set network.wg0.proto='wireguard'\n        uci set network.wg0.private_key=$WG_PRIVATE_KEY\n        uci set network.wg0.listen_port='51820'\n        uci set network.wg0.addresses=$WG_IP\n\n        if ! uci show network | grep -q wireguard_wg0; then\n            uci add network wireguard_wg0\n        fi\n        uci set network.@wireguard_wg0[0]=wireguard_wg0\n        uci set network.@wireguard_wg0[0].name='wg0_client'\n        uci set network.@wireguard_wg0[0].public_key=$WG_PUBLIC_KEY\n        uci set network.@wireguard_wg0[0].preshared_key=$WG_PRESHARED_KEY\n        uci set network.@wireguard_wg0[0].route_allowed_ips='0'\n        uci set network.@wireguard_wg0[0].persistent_keepalive='25'\n        uci set network.@wireguard_wg0[0].endpoint_host=$WG_ENDPOINT\n        uci set network.@wireguard_wg0[0].allowed_ips='0.0.0.0/0'\n        uci set network.@wireguard_wg0[0].endpoint_port=$WG_ENDPOINT_PORT\n        uci commit\n    fi\n\n    if [ \"$TUNNEL\" == 'ovpn' ]; then\n        if opkg list-installed | grep -q openvpn-openssl; then\n            echo \"OpenVPN already installed\"\n        else\n            echo \"Installed openvpn\"\n            opkg install openvpn-openssl\n        fi\n        printf \"\\033[32;1mConfigure route for OpenVPN\\033[0m\\n\"\n        route_vpn\n    fi\n\n    if [ \"$TUNNEL\" == 'singbox' ]; then\n        if opkg list-installed | grep -q sing-box; then\n            echo \"Sing-box already installed\"\n        else\n            AVAILABLE_SPACE=$(df / | awk 'NR>1 { print $4 }')\n            if  [[ \"$AVAILABLE_SPACE\" -gt 2000 ]]; then\n                echo \"Installed sing-box\"\n                opkg install sing-box\n            else\n                printf \"\\033[31;1mNo free space for a sing-box. Sing-box is not installed.\\033[0m\\n\"\n                exit 1\n            fi\n        fi\n        if grep -q \"option enabled '0'\" /etc/config/sing-box; then\n            sed -i \"s/\toption enabled \\'0\\'/\toption enabled \\'1\\'/\" /etc/config/sing-box\n        fi\n        if grep -q \"option user 'sing-box'\" /etc/config/sing-box; then\n            sed -i \"s/\toption user \\'sing-box\\'/\toption user \\'root\\'/\" /etc/config/sing-box\n        fi\n        if grep -q \"tun0\" /etc/sing-box/config.json; then\n        printf \"\\033[32;1mConfig /etc/sing-box/config.json already exists\\033[0m\\n\"\n        else\ncat << 'EOF' > /etc/sing-box/config.json\n{\n  \"log\": {\n    \"level\": \"debug\"\n  },\n  \"inbounds\": [\n    {\n      \"type\": \"tun\",\n      \"interface_name\": \"tun0\",\n      \"domain_strategy\": \"ipv4_only\",\n      \"address\": [\"172.16.250.1/30\"],\n      \"auto_route\": false,\n      \"strict_route\": false,\n      \"sniff\": true \n   }\n  ],\n  \"outbounds\": [\n    {\n      \"type\": \"$TYPE\",\n      \"server\": \"$HOST\",\n      \"server_port\": $PORT,\n      \"method\": \"$METHOD\",\n      \"password\": \"$PASS\"\n    }\n  ],\n  \"route\": {\n    \"auto_detect_interface\": true\n  }\n}\nEOF\n        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\"\n        printf \"\\033[32;1mOfficial doc: https://sing-box.sagernet.org/configuration/outbound/\\033[0m\\n\"\n        printf \"\\033[32;1mManual with example SS: https://cli.co/Badmn3K \\033[0m\\n\"\n\n        fi\n        printf \"\\033[32;1mConfigure route for Sing-box\\033[0m\\n\"\n        route_vpn\n    fi\n\n    if [ \"$TUNNEL\" == 'wgForYoutube' ]; then\n        add_internal_wg Wireguard\n    fi\n\n    if [ \"$TUNNEL\" == 'awgForYoutube' ]; then\n        add_internal_wg AmneziaWG\n    fi\n\n    if [ \"$TUNNEL\" == 'awg' ]; then\n        printf \"\\033[32;1mConfigure Amnezia WireGuard\\033[0m\\n\"\n\n        install_awg_packages\n\n        route_vpn\n\n        read -r -p \"Enter the private key (from [Interface]):\"$'\\n' AWG_PRIVATE_KEY\n\n        while true; do\n            read -r -p \"Enter internal IP address with subnet, example 192.168.100.5/24 (Address from [Interface]):\"$'\\n' AWG_IP\n            if echo \"$AWG_IP\" | egrep -oq '^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]+$'; then\n                break\n            else\n                echo \"This IP is not valid. Please repeat\"\n            fi\n        done\n\n        read -r -p \"Enter Jc value (from [Interface]):\"$'\\n' AWG_JC\n        read -r -p \"Enter Jmin value (from [Interface]):\"$'\\n' AWG_JMIN\n        read -r -p \"Enter Jmax value (from [Interface]):\"$'\\n' AWG_JMAX\n        read -r -p \"Enter S1 value (from [Interface]):\"$'\\n' AWG_S1\n        read -r -p \"Enter S2 value (from [Interface]):\"$'\\n' AWG_S2\n        read -r -p \"Enter H1 value (from [Interface]):\"$'\\n' AWG_H1\n        read -r -p \"Enter H2 value (from [Interface]):\"$'\\n' AWG_H2\n        read -r -p \"Enter H3 value (from [Interface]):\"$'\\n' AWG_H3\n        read -r -p \"Enter H4 value (from [Interface]):\"$'\\n' AWG_H4\n    \n        read -r -p \"Enter the public key (from [Peer]):\"$'\\n' AWG_PUBLIC_KEY\n        read -r -p \"If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:\"$'\\n' AWG_PRESHARED_KEY\n        read -r -p \"Enter Endpoint host without port (Domain or IP) (from [Peer]):\"$'\\n' AWG_ENDPOINT\n\n        read -r -p \"Enter Endpoint host port (from [Peer]) [51820]:\"$'\\n' AWG_ENDPOINT_PORT\n        AWG_ENDPOINT_PORT=${AWG_ENDPOINT_PORT:-51820}\n        if [ \"$AWG_ENDPOINT_PORT\" = '51820' ]; then\n            echo $AWG_ENDPOINT_PORT\n        fi\n        \n        uci set network.awg0=interface\n        uci set network.awg0.proto='amneziawg'\n        uci set network.awg0.private_key=$AWG_PRIVATE_KEY\n        uci set network.awg0.listen_port='51820'\n        uci set network.awg0.addresses=$AWG_IP\n\n        uci set network.awg0.awg_jc=$AWG_JC\n        uci set network.awg0.awg_jmin=$AWG_JMIN\n        uci set network.awg0.awg_jmax=$AWG_JMAX\n        uci set network.awg0.awg_s1=$AWG_S1\n        uci set network.awg0.awg_s2=$AWG_S2\n        uci set network.awg0.awg_h1=$AWG_H1\n        uci set network.awg0.awg_h2=$AWG_H2\n        uci set network.awg0.awg_h3=$AWG_H3\n        uci set network.awg0.awg_h4=$AWG_H4\n\n        if ! uci show network | grep -q amneziawg_awg0; then\n            uci add network amneziawg_awg0\n        fi\n\n        uci set network.@amneziawg_awg0[0]=amneziawg_awg0\n        uci set network.@amneziawg_awg0[0].name='awg0_client'\n        uci set network.@amneziawg_awg0[0].public_key=$AWG_PUBLIC_KEY\n        uci set network.@amneziawg_awg0[0].preshared_key=$AWG_PRESHARED_KEY\n        uci set network.@amneziawg_awg0[0].route_allowed_ips='0'\n        uci set network.@amneziawg_awg0[0].persistent_keepalive='25'\n        uci set network.@amneziawg_awg0[0].endpoint_host=$AWG_ENDPOINT\n        uci set network.@amneziawg_awg0[0].allowed_ips='0.0.0.0/0'\n        uci set network.@amneziawg_awg0[0].endpoint_port=$AWG_ENDPOINT_PORT\n        uci commit\n    fi\n\n}\n\ndnsmasqfull() {\n    if opkg list-installed | grep -q dnsmasq-full; then\n        printf \"\\033[32;1mdnsmasq-full already installed\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mInstalled dnsmasq-full\\033[0m\\n\"\n        cd /tmp/ && opkg download dnsmasq-full\n        opkg remove dnsmasq && opkg install dnsmasq-full --cache /tmp/\n\n        [ -f /etc/config/dhcp-opkg ] && cp /etc/config/dhcp /etc/config/dhcp-old && mv /etc/config/dhcp-opkg /etc/config/dhcp\n    fi\n}\n\ndnsmasqconfdir() {\n    if [ $VERSION_ID -ge 24 ]; then\n        if uci get dhcp.@dnsmasq[0].confdir | grep -q /tmp/dnsmasq.d; then\n            printf \"\\033[32;1mconfdir already set\\033[0m\\n\"\n        else\n            printf \"\\033[32;1mSetting confdir\\033[0m\\n\"\n            uci set dhcp.@dnsmasq[0].confdir='/tmp/dnsmasq.d'\n            uci commit dhcp\n        fi\n    fi\n}\n\nremove_forwarding() {\n    if [ ! -z \"$forward_id\" ]; then\n        while uci -q delete firewall.@forwarding[$forward_id]; do :; done\n    fi\n}\n\nadd_zone() {\n    if  [ \"$TUNNEL\" == 0 ]; then\n        printf \"\\033[32;1mZone setting skipped\\033[0m\\n\"\n    elif uci show firewall | grep -q \"@zone.*name='$TUNNEL'\"; then\n        printf \"\\033[32;1mZone already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate zone\\033[0m\\n\"\n\n        # Delete exists zone\n        zone_tun_id=$(uci show firewall | grep -E '@zone.*tun0' | awk -F '[][{}]' '{print $2}' | head -n 1)\n        if [ \"$zone_tun_id\" == 0 ] || [ \"$zone_tun_id\" == 1 ]; then\n            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\"\n            exit 1\n        fi\n        if [ ! -z \"$zone_tun_id\" ]; then\n            while uci -q delete firewall.@zone[$zone_tun_id]; do :; done\n        fi\n\n        zone_wg_id=$(uci show firewall | grep -E '@zone.*wg0' | awk -F '[][{}]' '{print $2}' | head -n 1)\n        if [ \"$zone_wg_id\" == 0 ] || [ \"$zone_wg_id\" == 1 ]; then\n            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\"\n            exit 1\n        fi\n        if [ ! -z \"$zone_wg_id\" ]; then\n            while uci -q delete firewall.@zone[$zone_wg_id]; do :; done\n        fi\n\n        zone_awg_id=$(uci show firewall | grep -E '@zone.*awg0' | awk -F '[][{}]' '{print $2}' | head -n 1)\n        if [ \"$zone_awg_id\" == 0 ] || [ \"$zone_awg_id\" == 1 ]; then\n            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\"\n            exit 1\n        fi\n        if [ ! -z \"$zone_awg_id\" ]; then\n            while uci -q delete firewall.@zone[$zone_awg_id]; do :; done\n        fi\n\n        uci add firewall zone\n        uci set firewall.@zone[-1].name=\"$TUNNEL\"\n        if [ \"$TUNNEL\" == wg ]; then\n            uci set firewall.@zone[-1].network='wg0'\n        elif [ \"$TUNNEL\" == awg ]; then\n            uci set firewall.@zone[-1].network='awg0'\n        elif [ \"$TUNNEL\" == singbox ] || [ \"$TUNNEL\" == ovpn ] || [ \"$TUNNEL\" == tun2socks ]; then\n            uci set firewall.@zone[-1].device='tun0'\n        fi\n        if [ \"$TUNNEL\" == wg ] || [ \"$TUNNEL\" == awg ] || [ \"$TUNNEL\" == ovpn ] || [ \"$TUNNEL\" == tun2socks ]; then\n            uci set firewall.@zone[-1].forward='REJECT'\n            uci set firewall.@zone[-1].output='ACCEPT'\n            uci set firewall.@zone[-1].input='REJECT'\n        elif [ \"$TUNNEL\" == singbox ]; then\n            uci set firewall.@zone[-1].forward='ACCEPT'\n            uci set firewall.@zone[-1].output='ACCEPT'\n            uci set firewall.@zone[-1].input='ACCEPT'\n        fi\n        uci set firewall.@zone[-1].masq='1'\n        uci set firewall.@zone[-1].mtu_fix='1'\n        uci set firewall.@zone[-1].family='ipv4'\n        uci commit firewall\n    fi\n    \n    if [ \"$TUNNEL\" == 0 ]; then\n        printf \"\\033[32;1mForwarding setting skipped\\033[0m\\n\"\n    elif uci show firewall | grep -q \"@forwarding.*name='$TUNNEL-lan'\"; then\n        printf \"\\033[32;1mForwarding already configured\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mConfigured forwarding\\033[0m\\n\"\n        # Delete exists forwarding\n        if [[ $TUNNEL != \"wg\" ]]; then\n            forward_id=$(uci show firewall | grep -E \"@forwarding.*dest='wg'\" | awk -F '[][{}]' '{print $2}' | head -n 1)\n            remove_forwarding\n        fi\n\n        if [[ $TUNNEL != \"awg\" ]]; then\n            forward_id=$(uci show firewall | grep -E \"@forwarding.*dest='awg'\" | awk -F '[][{}]' '{print $2}' | head -n 1)\n            remove_forwarding\n        fi\n\n        if [[ $TUNNEL != \"ovpn\" ]]; then\n            forward_id=$(uci show firewall | grep -E \"@forwarding.*dest='ovpn'\" | awk -F '[][{}]' '{print $2}' | head -n 1)\n            remove_forwarding\n        fi\n\n        if [[ $TUNNEL != \"singbox\" ]]; then\n            forward_id=$(uci show firewall | grep -E \"@forwarding.*dest='singbox'\" | awk -F '[][{}]' '{print $2}' | head -n 1)\n            remove_forwarding\n        fi\n\n        if [[ $TUNNEL != \"tun2socks\" ]]; then\n            forward_id=$(uci show firewall | grep -E \"@forwarding.*dest='tun2socks'\" | awk -F '[][{}]' '{print $2}' | head -n 1)\n            remove_forwarding\n        fi\n\n        uci add firewall forwarding\n        uci set firewall.@forwarding[-1]=forwarding\n        uci set firewall.@forwarding[-1].name=\"$TUNNEL-lan\"\n        uci set firewall.@forwarding[-1].dest=\"$TUNNEL\"\n        uci set firewall.@forwarding[-1].src='lan'\n        uci set firewall.@forwarding[-1].family='ipv4'\n        uci commit firewall\n    fi\n}\n\nshow_manual() {\n    if [ \"$TUNNEL\" == tun2socks ]; then\n        printf \"\\033[42;1mZone for tun2socks cofigured. But you need to set up the tunnel yourself.\\033[0m\\n\"\n        echo \"Use this manual: https://cli.co/VNZISEM\"\n    elif [ \"$TUNNEL\" == ovpn ]; then\n        printf \"\\033[42;1mZone for OpenVPN cofigured. But you need to set up the tunnel yourself.\\033[0m\\n\"\n        echo \"Use this manual: https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/\"\n    fi\n}\n\nadd_set() {\n    if uci show firewall | grep -q \"@ipset.*name='vpn_domains'\"; then\n        printf \"\\033[32;1mSet already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate set\\033[0m\\n\"\n        uci add firewall ipset\n        uci set firewall.@ipset[-1].name='vpn_domains'\n        uci set firewall.@ipset[-1].match='dst_net'\n        uci commit\n    fi\n    if uci show firewall | grep -q \"@rule.*name='mark_domains'\"; then\n        printf \"\\033[32;1mRule for set already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate rule set\\033[0m\\n\"\n        uci add firewall rule\n        uci set firewall.@rule[-1]=rule\n        uci set firewall.@rule[-1].name='mark_domains'\n        uci set firewall.@rule[-1].src='lan'\n        uci set firewall.@rule[-1].dest='*'\n        uci set firewall.@rule[-1].proto='all'\n        uci set firewall.@rule[-1].ipset='vpn_domains'\n        uci set firewall.@rule[-1].set_mark='0x1'\n        uci set firewall.@rule[-1].target='MARK'\n        uci set firewall.@rule[-1].family='ipv4'\n        uci commit\n    fi\n}\n\nadd_dns_resolver() {\n    echo \"Configure DNSCrypt2 or Stubby? It does matter if your ISP is spoofing DNS requests\"\n    DISK=$(df -m / | awk 'NR==2{ print $2 }')\n    if [[ \"$DISK\" -lt 32 ]]; then \n        printf \"\\033[31;1mYour router a disk have less than 32MB. It is not recommended to install DNSCrypt, it takes 10MB\\033[0m\\n\"\n    fi\n    echo \"Select:\"\n    echo \"1) No [Default]\"\n    echo \"2) DNSCrypt2 (10.7M)\"\n    echo \"3) Stubby (36K)\"\n\n    while true; do\n    read -r -p '' DNS_RESOLVER\n        case $DNS_RESOLVER in \n\n        1) \n            echo \"Skiped\"\n            break\n            ;;\n\n        2)\n            DNS_RESOLVER=DNSCRYPT\n            break\n            ;;\n\n        3) \n            DNS_RESOLVER=STUBBY\n            break\n            ;;\n\n        *)\n            echo \"Choose from the following options\"\n            ;;\n        esac\n    done\n\n    if [ \"$DNS_RESOLVER\" == 'DNSCRYPT' ]; then\n        if opkg list-installed | grep -q dnscrypt-proxy2; then\n            printf \"\\033[32;1mDNSCrypt2 already installed\\033[0m\\n\"\n        else\n            printf \"\\033[32;1mInstalled dnscrypt-proxy2\\033[0m\\n\"\n            opkg install dnscrypt-proxy2\n            if grep -q \"# server_names\" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml; then\n                sed -i \"s/^# server_names =.*/server_names = [\\'google\\', \\'cloudflare\\', \\'scaleway-fr\\', \\'yandex\\']/g\" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml\n            fi\n\n            printf \"\\033[32;1mDNSCrypt restart\\033[0m\\n\"\n            service dnscrypt-proxy restart\n            printf \"\\033[32;1mDNSCrypt needs to load the relays list. Please wait\\033[0m\\n\"\n            sleep 30\n\n            if [ -f /etc/dnscrypt-proxy2/relays.md ]; then\n                uci set dhcp.@dnsmasq[0].noresolv=\"1\"\n                uci -q delete dhcp.@dnsmasq[0].server\n                uci add_list dhcp.@dnsmasq[0].server=\"127.0.0.53#53\"\n                uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/'\n                uci commit dhcp\n                \n                printf \"\\033[32;1mDnsmasq restart\\033[0m\\n\"\n\n                /etc/init.d/dnsmasq restart\n            else\n                printf \"\\033[31;1mDNSCrypt not download list on /etc/dnscrypt-proxy2. Repeat install DNSCrypt by script.\\033[0m\\n\"\n            fi\n    fi\n\n    fi\n\n    if [ \"$DNS_RESOLVER\" == 'STUBBY' ]; then\n        printf \"\\033[32;1mConfigure Stubby\\033[0m\\n\"\n\n        if opkg list-installed | grep -q stubby; then\n            printf \"\\033[32;1mStubby already installed\\033[0m\\n\"\n        else\n            printf \"\\033[32;1mInstalled stubby\\033[0m\\n\"\n            opkg install stubby\n\n            printf \"\\033[32;1mConfigure Dnsmasq for Stubby\\033[0m\\n\"\n            uci set dhcp.@dnsmasq[0].noresolv=\"1\"\n            uci -q delete dhcp.@dnsmasq[0].server\n            uci add_list dhcp.@dnsmasq[0].server=\"127.0.0.1#5453\"\n            uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/'\n            uci commit dhcp\n\n            printf \"\\033[32;1mDnsmasq restart\\033[0m\\n\"\n\n            /etc/init.d/dnsmasq restart\n        fi\n    fi\n}\n\nadd_packages() {\n    for package in curl nano; do\n        if opkg list-installed | grep -q \"^$package \"; then\n            printf \"\\033[32;1m$package already installed\\033[0m\\n\"\n        else\n            printf \"\\033[32;1mInstalling $package...\\033[0m\\n\"\n            opkg install \"$package\"\n            \n            if \"$package\" --version >/dev/null 2>&1; then\n                printf \"\\033[32;1m$package was successfully installed and available\\033[0m\\n\"\n            else\n                printf \"\\033[31;1mError: failed to install $package\\033[0m\\n\"\n                exit 1\n            fi\n        fi\n    done\n}\n\nadd_getdomains() {\n    echo \"Choose you country\"\n    echo \"Select:\"\n    echo \"1) Russia inside. You are inside Russia\"\n    echo \"2) Russia outside. You are outside of Russia, but you need access to Russian resources\"\n    echo \"3) Ukraine. uablacklist.net list\"\n    echo \"4) Skip script creation\"\n\n    while true; do\n    read -r -p '' COUNTRY\n        case $COUNTRY in \n\n        1) \n            COUNTRY=russia_inside\n            break\n            ;;\n\n        2)\n            COUNTRY=russia_outside\n            break\n            ;;\n\n        3) \n            COUNTRY=ukraine\n            break\n            ;;\n\n        4) \n            echo \"Skiped\"\n            COUNTRY=0\n            break\n            ;;\n\n        *)\n            echo \"Choose from the following options\"\n            ;;\n        esac\n    done\n\n    if [ \"$COUNTRY\" == 'russia_inside' ]; then\n        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst\n    elif [ \"$COUNTRY\" == 'russia_outside' ]; then\n        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst\n    elif [ \"$COUNTRY\" == 'ukraine' ]; then\n        EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst\n    fi\n\n    if [ \"$COUNTRY\" != '0' ]; then\n        printf \"\\033[32;1mCreate script /etc/init.d/getdomains\\033[0m\\n\"\n\ncat << EOF > /etc/init.d/getdomains\n#!/bin/sh /etc/rc.common\n\nSTART=99\n\nstart () {\n    $EOF_DOMAINS\nEOF\ncat << 'EOF' >> /etc/init.d/getdomains\n    count=0\n    while true; do\n        if curl -m 3 github.com; then\n            curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst\n            break\n        else\n            echo \"GitHub is not available. Check the internet availability [$count]\"\n            count=$((count+1))\n        fi\n    done\n\n    if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q \"syntax check OK\"; then\n        /etc/init.d/dnsmasq restart\n    fi\n}\nEOF\n\n        chmod +x /etc/init.d/getdomains\n        /etc/init.d/getdomains enable\n\n        if crontab -l | grep -q /etc/init.d/getdomains; then\n            printf \"\\033[32;1mCrontab already configured\\033[0m\\n\"\n\n        else\n            crontab -l | { cat; echo \"0 */8 * * * /etc/init.d/getdomains start\"; } | crontab -\n            printf \"\\033[32;1mIgnore this error. This is normal for a new installation\\033[0m\\n\"\n            /etc/init.d/cron restart\n        fi\n\n        printf \"\\033[32;1mStart script\\033[0m\\n\"\n\n        /etc/init.d/getdomains start\n    fi\n}\n\nadd_internal_wg() {\n    PROTOCOL_NAME=$1\n    printf \"\\033[32;1mConfigure ${PROTOCOL_NAME}\\033[0m\\n\"\n    if [ \"$PROTOCOL_NAME\" = 'Wireguard' ]; then\n        INTERFACE_NAME=\"wg1\"\n        CONFIG_NAME=\"wireguard_wg1\"\n        PROTO=\"wireguard\"\n        ZONE_NAME=\"wg_internal\"\n\n        if opkg list-installed | grep -q wireguard-tools; then\n            echo \"Wireguard already installed\"\n        else\n            echo \"Installed wg...\"\n            opkg install wireguard-tools\n        fi\n    fi\n\n    if [ \"$PROTOCOL_NAME\" = 'AmneziaWG' ]; then\n        INTERFACE_NAME=\"awg1\"\n        CONFIG_NAME=\"amneziawg_awg1\"\n        PROTO=\"amneziawg\"\n        ZONE_NAME=\"awg_internal\"\n\n        install_awg_packages\n    fi\n\n    read -r -p \"Enter the private key (from [Interface]):\"$'\\n' WG_PRIVATE_KEY_INT\n\n    while true; do\n        read -r -p \"Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):\"$'\\n' WG_IP\n        if echo \"$WG_IP\" | egrep -oq '^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]+$'; then\n            break\n        else\n            echo \"This IP is not valid. Please repeat\"\n        fi\n    done\n\n    read -r -p \"Enter the public key (from [Peer]):\"$'\\n' WG_PUBLIC_KEY_INT\n    read -r -p \"If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:\"$'\\n' WG_PRESHARED_KEY_INT\n    read -r -p \"Enter Endpoint host without port (Domain or IP) (from [Peer]):\"$'\\n' WG_ENDPOINT_INT\n\n    read -r -p \"Enter Endpoint host port (from [Peer]) [51820]:\"$'\\n' WG_ENDPOINT_PORT_INT\n    WG_ENDPOINT_PORT_INT=${WG_ENDPOINT_PORT_INT:-51820}\n    if [ \"$WG_ENDPOINT_PORT_INT\" = '51820' ]; then\n        echo $WG_ENDPOINT_PORT_INT\n    fi\n\n    if [ \"$PROTOCOL_NAME\" = 'AmneziaWG' ]; then\n        read -r -p \"Enter Jc value (from [Interface]):\"$'\\n' AWG_JC\n        read -r -p \"Enter Jmin value (from [Interface]):\"$'\\n' AWG_JMIN\n        read -r -p \"Enter Jmax value (from [Interface]):\"$'\\n' AWG_JMAX\n        read -r -p \"Enter S1 value (from [Interface]):\"$'\\n' AWG_S1\n        read -r -p \"Enter S2 value (from [Interface]):\"$'\\n' AWG_S2\n        read -r -p \"Enter H1 value (from [Interface]):\"$'\\n' AWG_H1\n        read -r -p \"Enter H2 value (from [Interface]):\"$'\\n' AWG_H2\n        read -r -p \"Enter H3 value (from [Interface]):\"$'\\n' AWG_H3\n        read -r -p \"Enter H4 value (from [Interface]):\"$'\\n' AWG_H4\n    fi\n    \n    uci set network.${INTERFACE_NAME}=interface\n    uci set network.${INTERFACE_NAME}.proto=$PROTO\n    uci set network.${INTERFACE_NAME}.private_key=$WG_PRIVATE_KEY_INT\n    uci set network.${INTERFACE_NAME}.listen_port='51821'\n    uci set network.${INTERFACE_NAME}.addresses=$WG_IP\n\n    if [ \"$PROTOCOL_NAME\" = 'AmneziaWG' ]; then\n        uci set network.${INTERFACE_NAME}.awg_jc=$AWG_JC\n        uci set network.${INTERFACE_NAME}.awg_jmin=$AWG_JMIN\n        uci set network.${INTERFACE_NAME}.awg_jmax=$AWG_JMAX\n        uci set network.${INTERFACE_NAME}.awg_s1=$AWG_S1\n        uci set network.${INTERFACE_NAME}.awg_s2=$AWG_S2\n        uci set network.${INTERFACE_NAME}.awg_h1=$AWG_H1\n        uci set network.${INTERFACE_NAME}.awg_h2=$AWG_H2\n        uci set network.${INTERFACE_NAME}.awg_h3=$AWG_H3\n        uci set network.${INTERFACE_NAME}.awg_h4=$AWG_H4\n    fi\n\n    if ! uci show network | grep -q ${CONFIG_NAME}; then\n        uci add network ${CONFIG_NAME}\n    fi\n\n    uci set network.@${CONFIG_NAME}[0]=$CONFIG_NAME\n    uci set network.@${CONFIG_NAME}[0].name=\"${INTERFACE_NAME}_client\"\n    uci set network.@${CONFIG_NAME}[0].public_key=$WG_PUBLIC_KEY_INT\n    uci set network.@${CONFIG_NAME}[0].preshared_key=$WG_PRESHARED_KEY_INT\n    uci set network.@${CONFIG_NAME}[0].route_allowed_ips='0'\n    uci set network.@${CONFIG_NAME}[0].persistent_keepalive='25'\n    uci set network.@${CONFIG_NAME}[0].endpoint_host=$WG_ENDPOINT_INT\n    uci set network.@${CONFIG_NAME}[0].allowed_ips='0.0.0.0/0'\n    uci set network.@${CONFIG_NAME}[0].endpoint_port=$WG_ENDPOINT_PORT_INT\n    uci commit network\n\n    grep -q \"110 vpninternal\" /etc/iproute2/rt_tables || echo '110 vpninternal' >> /etc/iproute2/rt_tables\n\n    if ! uci show network | grep -q mark0x2; then\n        printf \"\\033[32;1mConfigure mark rule\\033[0m\\n\"\n        uci add network rule\n        uci set network.@rule[-1].name='mark0x2'\n        uci set network.@rule[-1].mark='0x2'\n        uci set network.@rule[-1].priority='110'\n        uci set network.@rule[-1].lookup='vpninternal'\n        uci commit\n    fi\n\n    if ! uci show network | grep -q vpn_route_internal; then\n        printf \"\\033[32;1mAdd route\\033[0m\\n\"\n        uci set network.vpn_route_internal=route\n        uci set network.vpn_route_internal.name='vpninternal'\n        uci set network.vpn_route_internal.interface=$INTERFACE_NAME\n        uci set network.vpn_route_internal.table='vpninternal'\n        uci set network.vpn_route_internal.target='0.0.0.0/0'\n        uci commit network\n    fi\n\n    if ! uci show firewall | grep -q \"@zone.*name='${ZONE_NAME}'\"; then\n        printf \"\\033[32;1mZone Create\\033[0m\\n\"\n        uci add firewall zone\n        uci set firewall.@zone[-1].name=$ZONE_NAME\n        uci set firewall.@zone[-1].network=$INTERFACE_NAME\n        uci set firewall.@zone[-1].forward='REJECT'\n        uci set firewall.@zone[-1].output='ACCEPT'\n        uci set firewall.@zone[-1].input='REJECT'\n        uci set firewall.@zone[-1].masq='1'\n        uci set firewall.@zone[-1].mtu_fix='1'\n        uci set firewall.@zone[-1].family='ipv4'\n        uci commit firewall\n    fi\n\n    if ! uci show firewall | grep -q \"@forwarding.*name='${ZONE_NAME}'\"; then\n        printf \"\\033[32;1mConfigured forwarding\\033[0m\\n\"\n        uci add firewall forwarding\n        uci set firewall.@forwarding[-1]=forwarding\n        uci set firewall.@forwarding[-1].name=\"${ZONE_NAME}-lan\"\n        uci set firewall.@forwarding[-1].dest=${ZONE_NAME}\n        uci set firewall.@forwarding[-1].src='lan'\n        uci set firewall.@forwarding[-1].family='ipv4'\n        uci commit firewall\n    fi\n\n    if uci show firewall | grep -q \"@ipset.*name='vpn_domains_internal'\"; then\n        printf \"\\033[32;1mSet already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate set\\033[0m\\n\"\n        uci add firewall ipset\n        uci set firewall.@ipset[-1].name='vpn_domains_internal'\n        uci set firewall.@ipset[-1].match='dst_net'\n        uci commit firewall\n    fi\n\n    if uci show firewall | grep -q \"@rule.*name='mark_domains_intenal'\"; then\n        printf \"\\033[32;1mRule for set already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate rule set\\033[0m\\n\"\n        uci add firewall rule\n        uci set firewall.@rule[-1]=rule\n        uci set firewall.@rule[-1].name='mark_domains_intenal'\n        uci set firewall.@rule[-1].src='lan'\n        uci set firewall.@rule[-1].dest='*'\n        uci set firewall.@rule[-1].proto='all'\n        uci set firewall.@rule[-1].ipset='vpn_domains_internal'\n        uci set firewall.@rule[-1].set_mark='0x2'\n        uci set firewall.@rule[-1].target='MARK'\n        uci set firewall.@rule[-1].family='ipv4'\n        uci commit firewall\n    fi\n\n    if uci show dhcp | grep -q \"@ipset.*name='vpn_domains_internal'\"; then\n        printf \"\\033[32;1mDomain on vpn_domains_internal already exist\\033[0m\\n\"\n    else\n        printf \"\\033[32;1mCreate domain for vpn_domains_internal\\033[0m\\n\"\n        uci add dhcp ipset\n        uci add_list dhcp.@ipset[-1].name='vpn_domains_internal'\n        uci add_list dhcp.@ipset[-1].domain='youtube.com'\n        uci add_list dhcp.@ipset[-1].domain='googlevideo.com'\n        uci add_list dhcp.@ipset[-1].domain='youtubekids.com'\n        uci add_list dhcp.@ipset[-1].domain='googleapis.com'\n        uci add_list dhcp.@ipset[-1].domain='ytimg.com'\n        uci add_list dhcp.@ipset[-1].domain='ggpht.com'\n        uci commit dhcp\n    fi\n\n    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\"\n\n    service dnsmasq restart\n    service network restart\n\n    exit 0\n}\n\ninstall_awg_packages() {\n    # Получение pkgarch с наибольшим приоритетом\n    PKGARCH=$(opkg print-architecture | awk 'BEGIN {max=0} {if ($3 > max) {max = $3; arch = $2}} END {print arch}')\n\n    TARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 1)\n    SUBTARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 2)\n    VERSION=$(ubus call system board | jsonfilter -e '@.release.version')\n    PKGPOSTFIX=\"_v${VERSION}_${PKGARCH}_${TARGET}_${SUBTARGET}.ipk\"\n    BASE_URL=\"https://github.com/Slava-Shchipunov/awg-openwrt/releases/download/\"\n\n    AWG_DIR=\"/tmp/amneziawg\"\n    mkdir -p \"$AWG_DIR\"\n\n    if opkg list-installed | grep -q amneziawg-tools; then\n        echo \"amneziawg-tools already installed\"\n    else\n        AMNEZIAWG_TOOLS_FILENAME=\"amneziawg-tools${PKGPOSTFIX}\"\n        DOWNLOAD_URL=\"${BASE_URL}v${VERSION}/${AMNEZIAWG_TOOLS_FILENAME}\"\n        curl -L -o \"$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME\" \"$DOWNLOAD_URL\"\n\n        if [ $? -eq 0 ]; then\n            echo \"amneziawg-tools file downloaded successfully\"\n        else\n            echo \"Error downloading amneziawg-tools. Please, install amneziawg-tools manually and run the script again\"\n            exit 1\n        fi\n\n        opkg install \"$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME\"\n\n        if [ $? -eq 0 ]; then\n            echo \"amneziawg-tools file downloaded successfully\"\n        else\n            echo \"Error installing amneziawg-tools. Please, install amneziawg-tools manually and run the script again\"\n            exit 1\n        fi\n    fi\n    \n    if opkg list-installed | grep -q kmod-amneziawg; then\n        echo \"kmod-amneziawg already installed\"\n    else\n        KMOD_AMNEZIAWG_FILENAME=\"kmod-amneziawg${PKGPOSTFIX}\"\n        DOWNLOAD_URL=\"${BASE_URL}v${VERSION}/${KMOD_AMNEZIAWG_FILENAME}\"\n        curl -L -o \"$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME\" \"$DOWNLOAD_URL\"\n\n        if [ $? -eq 0 ]; then\n            echo \"kmod-amneziawg file downloaded successfully\"\n        else\n            echo \"Error downloading kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again\"\n            exit 1\n        fi\n        \n        opkg install \"$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME\"\n\n        if [ $? -eq 0 ]; then\n            echo \"kmod-amneziawg file downloaded successfully\"\n        else\n            echo \"Error installing kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again\"\n            exit 1\n        fi\n    fi\n    \n    if opkg list-installed | grep -q luci-app-amneziawg; then\n        echo \"luci-app-amneziawg already installed\"\n    else\n        LUCI_APP_AMNEZIAWG_FILENAME=\"luci-app-amneziawg${PKGPOSTFIX}\"\n        DOWNLOAD_URL=\"${BASE_URL}v${VERSION}/${LUCI_APP_AMNEZIAWG_FILENAME}\"\n        curl -L -o \"$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME\" \"$DOWNLOAD_URL\"\n\n        if [ $? -eq 0 ]; then\n            echo \"luci-app-amneziawg file downloaded successfully\"\n        else\n            echo \"Error downloading luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again\"\n            exit 1\n        fi\n\n        opkg install \"$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME\"\n\n        if [ $? -eq 0 ]; then\n            echo \"luci-app-amneziawg file downloaded successfully\"\n        else\n            echo \"Error installing luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again\"\n            exit 1\n        fi\n    fi\n\n    rm -rf \"$AWG_DIR\"\n}\n\n# System Details\nMODEL=$(cat /tmp/sysinfo/model)\nsource /etc/os-release\nprintf \"\\033[34;1mModel: $MODEL\\033[0m\\n\"\nprintf \"\\033[34;1mVersion: $OPENWRT_RELEASE\\033[0m\\n\"\n\nVERSION_ID=$(echo $VERSION | awk -F. '{print $1}')\n\nif [ \"$VERSION_ID\" -ne 23 ] && [ \"$VERSION_ID\" -ne 24 ]; then\n    printf \"\\033[31;1mScript only support OpenWrt 23.05 and 24.10\\033[0m\\n\"\n    echo \"For OpenWrt 21.02 and 22.03 you can:\"\n    echo \"1) Use ansible https://github.com/itdoginfo/domain-routing-openwrt\"\n    echo \"2) Configure manually. Old manual: https://itdog.info/tochechnaya-marshrutizaciya-na-routere-s-openwrt-wireguard-i-dnscrypt/\"\n    exit 1\nfi\n\nprintf \"\\033[31;1mAll actions performed here cannot be rolled back automatically.\\033[0m\\n\"\n\ncheck_repo\n\nadd_packages\n\nadd_tunnel\n\nadd_mark\n\nadd_zone\n\nshow_manual\n\nadd_set\n\ndnsmasqfull\n\ndnsmasqconfdir\n\nadd_dns_resolver\n\nadd_getdomains\n\nprintf \"\\033[32;1mRestart network\\033[0m\\n\"\n/etc/init.d/network restart\n\nprintf \"\\033[32;1mDone\\033[0m\\n\"\n"
  },
  {
    "path": "getdomains-uninstall.sh",
    "content": "#!/bin/ash\n\necho \"Выпиливаем скрипты\"\n/etc/init.d/getdomains disable\nrm -rf /etc/init.d/getdomains\n\nrm -f /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute\n\necho \"Выпиливаем из crontab\"\nsed -i '/getdomains start/d' /etc/crontabs/root\n\necho \"Выпиливаем домены\"\nrm -f /tmp/dnsmasq.d/domains.lst\n\necho \"Чистим firewall, раз раз 🍴\"\n\nipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$ipset_id\" ]; then\n    while uci -q delete firewall.@ipset[$ipset_id]; do :; done\nfi\n\nrule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$rule_id\" ]; then\n    while uci -q delete firewall.@rule[$rule_id]; do :; done\nfi\n\nipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains_internal.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$ipset_id\" ]; then\n    while uci -q delete firewall.@ipset[$ipset_id]; do :; done\nfi\n\nrule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains_intenal.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$rule_id\" ]; then\n    while uci -q delete firewall.@rule[$rule_id]; do :; done\nfi\n\nipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$ipset_id\" ]; then\n    while uci -q delete firewall.@ipset[$ipset_id]; do :; done\nfi\n\nrule_id=$(uci show firewall | grep -E '@rule.*name=.mark_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$rule_id\" ]; then\n    while uci -q delete firewall.@rule[$rule_id]; do :; done\nfi\n\nuci commit firewall\n/etc/init.d/firewall restart\n\necho \"Чистим сеть\"\nsed -i '/99 vpn/d' /etc/iproute2/rt_tables\n\nrule_id=$(uci show network | grep -E '@rule.*name=.mark0x1.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$rule_id\" ]; then\n    while uci -q delete network.@rule[$rule_id]; do :; done\nfi\n\nrule_id=$(uci show network | grep -E '@rule.*name=.mark0x2.' | awk -F '[][{}]' '{print $2}' | head -n 1)\nif [ ! -z \"$rule_id\" ]; then\n    while uci -q delete network.@rule[$rule_id]; do :; done\nfi\n\nwhile uci -q delete network.vpn_route_internal; do :; done\n\nuci commit network\n/etc/init.d/network restart\n\necho \"Проверяем Dnsmasq\"\nif uci show dhcp | grep -q ipset; then\n    echo \"В dnsmasq (/etc/config/dhcp) заданы домены. Нужные из них сохраните, остальные удалите вместе с ipset\"\nfi\n\necho \"Все туннели, прокси, зоны и forwarding к ним оставляем на месте, они вам не помешают и скорее пригодятся\"\necho \"Dnscrypt, stubby тоже не трогаем\"\n\necho \"  ______  _____        _____   _____  ______  _     _  _____   _____\"\necho \" |  ____ |     |      |_____] |     | |     \\ |____/  |     | |_____]\"\necho \" |_____| |_____|      |       |_____| |_____/ |    \\_ |_____| |     \"\n"
  },
  {
    "path": "handlers/main.yml",
    "content": "---\n  - name: Restart sing-box\n    service:\n      name: sing-box\n      state: restarted\n\n  - name: Restart network\n    service:\n      name: network\n      state: restarted\n\n  - name: Restart firewall\n    service:\n      name: firewall\n      state: restarted\n\n  - name: Run getdomains script\n    service:\n      name: getdomains\n      state: restarted\n\n  - name: Restart dnscrypt-proxy\n    service:\n      name: dnscrypt-proxy\n      state: restarted\n      enabled: yes\n      \n  - name: Restart dnsmasq\n    service:\n      name: dnsmasq\n      state: restarted"
  },
  {
    "path": "meta/main.yml",
    "content": "---\ngalaxy_info:\n  role_name: domain_routing_openwrt\n  namespace: itdoginfo\n  author: itdog\n  description: Configuring domain routing on Openwrt router\n  issue_tracker_url: https://github.com/itdoginfo/domain-routing-openwrt/issues\n  license: GPL-3.0\n  min_ansible_version: 2.10.7\n  platforms:\n    - name: OpenWrt\n  galaxy_tags:\n    - openwrt\n    - dnsmasq\n    - ipset\n    - wireguard\n    - sing-box\n    - openvpn\n    - bypass\n    - routing\ndependencies:\n  - role: gekmihesg.openwrt"
  },
  {
    "path": "tasks/main.yml",
    "content": "---\n\n# Dnsmasq version check\n\n  - name: Get dnsmasq version\n    shell: opkg list-installed | grep dnsmasq-full | awk '{print $3}'\n    register: dnsmasqfull_version\n\n  - name: Check confdir option\n    shell: uci get dhcp.@dnsmasq[0].confdir\n    register: dnsmasq_confdir\n    ignore_errors: true\n\n  - name: Get openwrt major release\n    shell: cat /etc/openwrt_release | grep -Eo [0-9]{2}[.][0-9]{2}[.][0-9]* | cut -d '.' -f 1 | tail -n 1\n    register: openwrt_major_release\n\n  - name: debug\n    debug:\n      var: ansible_distribution_major_version\n\n# Packages installation\n\n  - name: install wg\n    opkg:\n      name: \"{{ item }}\"\n      state: present\n    loop:\n        - kmod-wireguard\n        - wireguard-tools\n    when: tunnel == \"wg\"\n\n  - name: install openvpn\n    opkg:\n      name: \"{{ item }}\"\n      state: present\n    loop:\n        - openvpn-openssl\n    when: tunnel == \"openvpn\"\n\n  - name: install singbox\n    opkg:\n      name: \"{{ item }}\"\n      state: present\n    loop:\n        - sing-box\n    when: tunnel == \"singbox\" and ansible_distribution_major_version >= \"23\"\n\n  - name: install curl\n    opkg:\n      name: \"{{ item }}\"\n      state: present\n    loop:\n        - curl\n\n  - name: install nano\n    opkg:\n      name: \"{{ item }}\"\n      state: present\n    loop:\n        - nano\n    when: nano\n\n  - name: install ipset\n    opkg:\n      name: ipset\n      state: present\n    when: ansible_distribution_major_version < \"22\"\n\n  - name: install dnsmasq-full (23)\n    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\n    when: ansible_distribution_major_version >= \"23\" and list_domains and not dnsmasqfull_version.stdout\n    ignore_errors: true\n\n  - name: set confdir for dnsmasq\n    uci: \n      command: set\n      key: dhcp.@dnsmasq[0]\n      value:\n        confdir: \"/tmp/dnsmasq.d\"\n    when: ansible_distribution_major_version >= 24\n    notify:\n      - Restart dnsmasq  \n\n# Getdomains script configure\n      \n  - name: getdomains script copy\n    template:\n      src: \"openwrt-getdomains.j2\"\n      dest: \"/etc/init.d/getdomains\"\n      mode: a+x\n      trim_blocks: false\n    notify:\n      - Run getdomains script\n\n  - name: create simplink in rc.d\n    file:\n      src: \"/etc/init.d/getdomains\"\n      dest: \"/etc/rc.d/S99getdomains\"\n      state: link\n    notify:\n      - Run getdomains script\n\n  - name: check string in crontab\n    shell: grep \"getdomains\" /etc/crontabs/root\n    register: check_cron\n    ignore_errors: true\n     \n  - name: add script to cron\n    lineinfile:\n      path: /etc/crontabs/root\n      create: yes\n      line: \"0 4 * * * /etc/init.d/getdomains start\"\n    when: check_cron.stdout == \"\"\n    \n  - name: enable and start crontab\n    service:\n      name: cron\n      state: started\n      enabled: yes\n      \n# Configure route table\n\n  - name: Route for vpn table\n    template:\n      src: \"openwrt-30-vpnroute.j2\"\n      dest: \"/etc/hotplug.d/iface/30-vpnroute\"\n      mode: 0644\n\n  - name: Check string in rt_tables\n    shell: grep \"99 vpn\" /etc/iproute2/rt_tables\n    register: check_rt_tables\n    ignore_errors: true\n      \n  - name: add route table\n    lineinfile:\n      path: /etc/iproute2/rt_tables\n      line: \"99 vpn\"\n    when: check_rt_tables.stdout == \"\"\n    notify:\n      - Restart network\n    \n# Configure WG\n\n  - name: add wg interface\n    uci:\n      command: add\n      config: network\n      type: interface\n      name: wg0\n    when: tunnel == \"wg\"\n\n  - name: configure wg interface\n    uci:\n      command: set\n      key: network.wg0\n      value:\n        proto: wireguard\n        private_key: \"{{ wg_private_key }}\"\n        listen_port: \"{{ wg_listen_port }}\"\n        addresses:\n          - \"{{ wg_client_address }}\"\n    when: tunnel == \"wg\"\n    notify:\n      - Restart network\n      \n  - name: set wg client without wg_preshared_key\n    uci:\n      command: section\n      config: network\n      type: wireguard_wg0\n      find_by:\n        name: wg0_client\n      value:\n        public_key: \"{{ wg_public_key }}\"\n        route_allowed_ips: 0\n        persistent_keepalive: 25\n        endpoint_host: \"{{ wg_server_address }}\"\n        allowed_ips: 0.0.0.0/0\n        endpoint_port: \"{{ wg_client_port }}\"\n    when: wg_preshared_key is undefined and tunnel == \"wg\"\n    notify:\n      - Restart network     \n  \n  - name: set wg client with wg_preshared_key\n    uci:\n      command: section\n      config: network\n      type: wireguard_wg0\n      find_by:\n        name: wg0_client\n      value:\n        public_key: \"{{ wg_public_key }}\"\n        preshared_key: \"{{ wg_preshared_key }}\"\n        route_allowed_ips: 0\n        persistent_keepalive: 25\n        endpoint_host: \"{{ wg_server_address }}\"\n        allowed_ips: 0.0.0.0/0\n        endpoint_port: \"{{ wg_client_port }}\"\n    when: wg_preshared_key is defined  and tunnel == \"wg\"\n\n  - name: set WG firewall zone \n    uci:\n      command: section\n      config: firewall\n      type: zone\n      find_by:\n        name: wg\n      value:\n        forward: REJECT\n        output: ACCEPT\n        name: wg\n        input: REJECT\n        masq: 1\n        mtu_fix: 1\n        network: wg0\n        family: ipv4\n    when: tunnel == \"wg\"\n        \n  - name: add WG forwarding\n    uci:\n      command: section\n      config: firewall\n      type: forwarding\n      find_by:\n        name: wg-lan\n      value:\n        dest: wg\n        src: lan\n        family: ipv4\n    when: tunnel == \"wg\"\n\n# Configure Sing-box\n\n  - name: set sing-box firewall zone. Only >=22\n    uci:\n      command: section\n      config: firewall\n      type: zone\n      find_by:\n        name: tun\n      value:\n        forward: ACCEPT\n        output: ACCEPT\n        name: tun\n        input: ACCEPT\n        masq: 1\n        mtu_fix: 1\n        device: tun0\n        family: ipv4\n    when: tunnel == \"singbox\"\n    failed_when: ansible_distribution_major_version < \"22\"\n    notify:\n      - Restart firewall\n\n  - name: template for sing-box.json\n    template:\n      src: \"sing-box-json.j2\"\n      dest: \"/etc/sing-box/config.json\"\n      mode: 0644\n    when: tunnel == \"singbox\"\n    failed_when: ansible_distribution_major_version < \"22\"\n\n  - name: template for config/sing-box\n    template:\n      src: \"config-sing-box.j2\"\n      dest: \"/etc/config/sing-box\"\n      mode: 0600\n    when: tunnel == \"singbox\"\n    failed_when: ansible_distribution_major_version < \"22\"\n\n# Configure OpenVPN, tun2socks\n\n  - name: set {{ tunnel }} firewall zone \n    uci:\n      command: section\n      config: firewall\n      type: zone\n      find_by:\n        name: tun\n      value:\n        forward: REJECT\n        output: ACCEPT\n        name: tun\n        input: REJECT\n        masq: 1\n        mtu_fix: 1\n        device: tun0\n        family: ipv4\n    when: tunnel == \"openvpn\" or tunnel == \"tun2socks\"\n    notify:\n      - Restart firewall\n        \n  - name: add {{ tunnel }} forwarding\n    uci:\n      command: section\n      config: firewall\n      type: forwarding\n      find_by:\n        name: lan-tun\n      value:\n        dest: tun\n        src: lan\n        family: ipv4\n    when: tunnel == \"openvpn\" or tunnel == \"tun2socks\" or tunnel == \"singbox\"\n    notify:\n      - Restart firewall\n\n# Configure network\n       \n  - name: set rule mark0x1\n    uci:\n      command: section\n      config: network\n      type: rule\n      find_by:\n        name: mark0x1\n      value:\n        mark: \"0x1\"\n        priority: 100\n        lookup: vpn\n\n  - name: set disable dns for wan\n    uci:\n      command: set\n      key: network.wan\n      value:\n        peerdns: 0\n    when: ansible_distribution_major_version < \"22\"\n\n  - name: uci commit firewall\n    uci:\n      command: commit\n      config: firewall\n    notify:\n      - Restart firewall\n\n  - name: uci commit network\n    uci:\n      command: commit\n      config: network\n    notify:\n      - Restart network\n\n# Configure firewall\n\n  - name: add ipset for subnet (<22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_subnets\n       value:\n         match: dst_net\n         storage: hash\n         loadfile: /tmp/lst/subnet.lst\n    when: ansible_distribution_major_version < \"22\" and list_subnet\n         \n  - name: add ipset for ip (<22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_ip\n       value:\n         match: dst_net\n         storage: hash\n         loadfile: /tmp/lst/ip.lst\n         hashsize: 9900000\n         maxelem: 9900000\n    when: ansible_distribution_major_version < \"22\" and list_ip\n\n  - name: add ipset for community (<22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_community\n       value:\n         match: dst_net\n         storage: hash\n         loadfile: /tmp/lst/community.lst\n         hashsize: 9900000\n         maxelem: 9900000\n    when: ansible_distribution_major_version < \"22\" and list_community\n\n  - name: add nfset for subnet (22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_subnets\n       value:\n         match: dst_net\n         loadfile: /tmp/lst/subnet.lst\n    when: ansible_distribution_major_version >= \"22\" and list_subnet\n         \n  - name: add nfset for ip (22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_ip\n       value:\n         match: dst_net\n         loadfile: /tmp/lst/ip.lst\n    when: ansible_distribution_major_version >= \"22\" and list_ip\n\n  - name: add nfset for community (22)\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_community\n       value:\n         match: dst_net\n         loadfile: /tmp/lst/community.lst\n    when: ansible_distribution_major_version >= \"22\" and list_community\n\n  - name: add ipset for domains (<22). If failed, repeat playbook. If failed is repeated check dnsmasq-full. \n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_domains\n       value:\n         match: dst_net\n         storage: hash\n    when: ansible_distribution_major_version < \"22\" and list_domains\n\n  - name: add nfset for domains (>=22). If failed, repeat playbook. If failed is repeated check dnsmasq-full.\n    uci:\n       command: section\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_domains\n       value:\n         match: dst_net\n    when: ansible_distribution_major_version >= \"22\" and list_domains\n\n  - name: add mark rule vpn_subnet\n    uci:\n       command: section\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_subnet\n       value:\n         src: lan\n         dest: \"*\"\n         proto: all\n         ipset: vpn_subnets\n         set_mark: \"0x1\"\n         target: MARK\n         family: ipv4\n    when: list_subnet\n\n  - name: add mark rule vpn_ip\n    uci:\n       command: section\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_ip\n       value:\n         src: lan\n         dest: \"*\"\n         proto: all\n         ipset: vpn_ip\n         set_mark: \"0x1\"\n         target: MARK\n         family: ipv4\n    when: list_ip\n\n  - name: add mark rule vpn_community\n    uci:\n       command: section\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_community\n       value:\n         src: lan\n         dest: \"*\"\n         proto: all\n         ipset: vpn_community\n         set_mark: \"0x1\"\n         target: MARK\n         family: ipv4\n    when: list_community\n\n  - name: add mark rule vpn_domains\n    uci:\n       command: section\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_domains\n       value:\n         src: lan\n         dest: \"*\"\n         proto: all\n         ipset: vpn_domains\n         set_mark: \"0x1\"\n         target: MARK\n         family: ipv4\n    when: (ansible_distribution_major_version < \"22\" and list_domains) or (ansible_distribution_major_version >= \"22\" and list_domains)\n\n  - name: wg access route\n    uci:\n      command: section\n      config: network\n      type: route\n      find_by:\n        name: wg_access_route\n      value:\n        interface: wg0\n        target: \"{{ wg_access_network }}\"\n    when: wg_access\n\n  - name: set WG firewall zone \n    uci:\n      command: section\n      config: firewall\n      type: zone\n      find_by:\n        name: wg\n      value:\n        input: ACCEPT\n    when: wg_access\n\n# Remove unused rules and ipset\n  - name: Remove ipset for ip\n    uci:\n       command: absent\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_ip\n    when: not list_ip\n\n  - name: Remove rule for ip\n    uci:\n       command: absent\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_ip\n    when: not list_ip\n\n  - name: Remove ipset for subnet\n    uci:\n       command: absent\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_subnets\n    when: not list_subnet\n\n  - name: Remove rule for subnet\n    uci:\n       command: absent\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_subnet\n    when: not list_subnet\n\n  - name: Remove ipset for community\n    uci:\n       command: absent\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_community\n    when: not list_community\n\n  - name: Remove rule for community\n    uci:\n       command: absent\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_community\n    when: not list_community\n\n  - name: Remove ipset for domains\n    uci:\n       command: absent\n       config: firewall\n       type: ipset\n       find_by:\n         name: vpn_domains\n    when: not list_domains\n\n  - name: Remove rule for domains\n    uci:\n       command: absent\n       config: firewall\n       type: rule\n       find_by:\n         name: mark_domains\n    when: not list_domains\n\n# Configure DNS resolver\n\n  - name: install dnscrypt-proxy2\n    opkg:\n      name: dnscrypt-proxy2\n      state: present\n    when: dns_encrypt == \"dnscrypt\"\n\n  - name: check string in dnscrypt-proxy.toml\n    shell: grep \"# server_names\" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml\n    register: check_server_names\n    ignore_errors: true\n    when: dns_encrypt == \"dnscrypt\"\n\n  - name: dnscrypt2 enable exact servers\n    lineinfile:\n      path: /etc/dnscrypt-proxy2/dnscrypt-proxy.toml\n      regexp: \"# server_names =\"\n      line: \"server_names = ['google', 'cloudflare', 'scaleway-fr', 'yandex']\"\n    when: dns_encrypt == \"dnscrypt\" and check_server_names.stdout\n    notify:\n      - Restart dnscrypt-proxy\n    \n  - name: edit dhcp config. add localhost server\n    lineinfile:\n      path: /etc/config/dhcp\n      firstmatch: \"true\"\n      insertafter: \"option leasefile '/tmp/dhcp.leases'\"\n      line: \"{{ item }}\"\n    with_items:\n      - \"        list server '127.0.0.53#53'\"\n      - \"        option noresolv '1'\"\n    notify:\n      - Restart dnsmasq\n    when: dns_encrypt == \"dnscrypt\"\n\n  - name: install stubby\n    opkg:\n      name: stubby\n      state: present\n    when: dns_encrypt == \"stubby\"\n\n  - name: edit dhcp config. add localhost server\n    lineinfile:\n      path: /etc/config/dhcp\n      firstmatch: \"true\"\n      insertafter: \"option leasefile '/tmp/dhcp.leases'\"\n      line: \"{{ item }}\"\n    with_items:\n      - \"        list server '127.0.0.1#5453'\"\n      - \"        option noresolv '1'\"\n    notify:\n      - Restart dnsmasq\n    when: dns_encrypt == \"stubby\"\n\n# Commit\n\n  - name: uci commit firewall\n    uci:\n      command: commit\n      config: firewall\n    notify:\n      - Restart firewall\n\n    - name: uci commit dhcp\n    uci:\n      command: commit\n      config: dhcp\n    notify:\n      - Restart dnsmasq\n\n  - name: uci commit network\n    uci:\n      command: commit\n      config: network\n    notify:\n      - Restart network"
  },
  {
    "path": "templates/config-sing-box.j2",
    "content": "config sing-box 'main'\n\toption enabled '1'\n\toption user 'root'\n\toption conffile '/etc/sing-box/config.json'\n\toption workdir '/usr/share/sing-box'\n"
  },
  {
    "path": "templates/openwrt-30-vpnroute.j2",
    "content": "#!/bin/sh\n\n{% if tunnel == \"wg\" %}\nip route add table vpn default dev wg0\n{% elif (tunnel == \"openvpn\") or (tunnel == \"singbox\") or (tunnel == \"tun2socks\") %}\nsleep 10\nip route add table vpn default dev tun0\n{% endif %}\n"
  },
  {
    "path": "templates/openwrt-getdomains.j2",
    "content": "#!/bin/sh /etc/rc.common\n\nSTART=99\n\nstart () {\n    {% if ansible_distribution_major_version >= \"22\" and country == \"russia-inside\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst\n    {% endif %}\n    {% if ansible_distribution_major_version >= \"22\" and country == \"russia-outside\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst\n    {% endif %}\n    {% if ansible_distribution_major_version >= \"22\" and country == \"ukraine\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst\n    {% endif %}\n    {% if ansible_distribution_major_version < \"22\" and country == \"russia-inside\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-ipset.lst\n    {% endif %}\n    {% if ansible_distribution_major_version < \"22\" and country == \"russia-outside\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-ipset.lst\n    {% endif %}\n    {% if ansible_distribution_major_version < \"22\" and country == \"ukraine\" %}\n    DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-ipset.lst\n    {% endif %}\n    count=0\n    while true; do\n        if curl -m 3 github.com; then\n            curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst\n            break\n        else\n            echo \"GitHub is not available. Check the internet availability [$count]\"\n            count=$((count+1))\n        fi\n    done\n\n    if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q \"syntax check OK\"; then\n        /etc/init.d/dnsmasq restart\n    fi\n\n    {% if ansible_distribution_major_version >= \"22\" and (list_ip or list_community) %}\n    echo \"Flush sets\"\n    nft flush ruleset\n    {% endif %}\n\n    {% if list_subnet or list_ip or list_community %}\n    dir=/tmp/lst\n    mkdir -p $dir\n\n    count=0\n    while true; do\n        if curl -m 3 https://antifilter.download/; then\n            {% if list_subnet %}\n            curl -f -z $dir/subnet.lst https://antifilter.download/list/subnet.lst --output $dir/subnet.lst\n            {% endif %}\n            {% if list_ip %}\n            curl -f -z $dir/ip.lst https://antifilter.download/list/ip.lst --output $dir/ip.lst\n            {% endif %}\n            {% if list_community %}\n            curl -f -z $dir/community.lst https://community.antifilter.download/list/community.lst --output $dir/community.lst\n            {% endif %}  \n            break\n        else\n            echo \"antifilter.download is not available. Check the internet availability [$count]\"\n            count=$((count+1))\n        fi\n    done\n\n    echo \"Firewall restart\"\n    /etc/init.d/firewall restart\n    {% endif %}  \n}"
  },
  {
    "path": "templates/sing-box-json.j2",
    "content": "{\n    \"log\": {\n      \"level\": \"debug\"\n    },\n    \"inbounds\": [\n      {\n        \"type\": \"tun\",\n        \"interface_name\": \"tun0\",\n        \"domain_strategy\": \"ipv4_only\",\n        \"address\": [\"172.16.250.1/30\"],\n        \"auto_route\": false,\n        \"strict_route\": false,\n        \"sniff\": true \n     }\n    ],\n    \"outbounds\": [\n      {\n        \"type\": \"$TYPE\",\n        \"server\": \"$HOST\",\n        \"server_port\": $PORT,\n        \"method\": \"$METHOD\",\n        \"password\": \"$PASS\"\n      }\n    ],\n    \"route\": {\n      \"auto_detect_interface\": true\n    }\n  }"
  },
  {
    "path": "tests/inventory",
    "content": "[openwrt]\n192.168.56.23\n"
  },
  {
    "path": "tests/test.yml",
    "content": "---\n- hosts: openwrt\n  remote_user: root\n\n  roles:\n    - domain_routing_openwrt"
  }
]