├── .github └── workflows │ └── public-galaxy.yml ├── README.EN.md ├── README.md ├── defaults └── main.yml ├── getdomains-check.sh ├── getdomains-install.sh ├── getdomains-uninstall.sh ├── handlers └── main.yml ├── meta └── main.yml ├── tasks └── main.yml ├── templates ├── config-sing-box.j2 ├── openwrt-30-vpnroute.j2 ├── openwrt-getdomains.j2 └── sing-box-json.j2 └── tests ├── inventory └── test.yml /.github/workflows/public-galaxy.yml: -------------------------------------------------------------------------------- 1 | name: Public to Ansible Galaxy 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: checkout 13 | uses: actions/checkout@v4 14 | - name: Publish Ansible role to Galaxy 15 | uses: robertdebock/galaxy-action@1.2.1 16 | with: 17 | galaxy_api_key: ${{ secrets.galaxy_api_key }} -------------------------------------------------------------------------------- /README.EN.md: -------------------------------------------------------------------------------- 1 | Domain routing OpenWrt 2 | ========= 3 | 4 | Configuring domain routing on Openwrt router. 5 | 6 | 7 | Role Variables 8 | -------------- 9 | 10 | Lists 11 | ``` 12 | country: russia-inside|russia-outside|ukraine 13 | list_domains: true|falase 14 | 15 | list_subnet: false|true 16 | list_ip: false|true 17 | list_community: false|true 18 | ``` 19 | 20 | Tunnel 21 | ``` 22 | tunnel: wg|openvpn|singbox|tun2socks 23 | ``` 24 | 25 | DoH or DoT 26 | ``` 27 | dns_encrypt: false|dnscrypt|stubby 28 | ``` 29 | 30 | Nano package 31 | ``` 32 | nano: true|false 33 | ``` 34 | 35 | Acces from wg network to router 36 | ``` 37 | wg_access: false|true 38 | wg_access_network: 192.168.80.0/24 (for example) 39 | ``` 40 | 41 | If wireguard is used: 42 | ``` 43 | wg_server_address: wg-server-host 44 | wg_private_key: privatekey-client 45 | wg_public_key: publickey-client 46 | wg_preshared_key: presharedkey-client 47 | wg_client_port: 51820 48 | wg_client_address: ip-client 49 | 50 | wg_access: true 51 | wg_access_network: wg-network 52 | ``` 53 | 54 | Dependencies 55 | ------------ 56 | 57 | [gekmihesg.openwrt](https://github.com/gekmihesg/ansible-openwrt) 58 | 59 | 60 | Example Playbook 61 | ---------------- 62 | 63 | The inventory file must contain the group `[openwrt]` where your router will be located. 64 | 65 | 66 | Wireguard, only domains, stubby, Russia, acces from wg network, host 192.168.1.1 67 | ``` 68 | - hosts: 192.168.1.1 69 | remote_user: root 70 | 71 | roles: 72 | - itdoginfo.domain_routing_openwrt 73 | 74 | vars: 75 | tunnel: wg 76 | dns_encrypt: stubby 77 | country: russia-inside 78 | 79 | wg_access: true 80 | wg_server_address: wg-server-host 81 | wg_private_key: privatekey-client 82 | wg_public_key: publickey-client 83 | wg_preshared_key: presharedkey-client 84 | wg_listen_port: 51820 85 | wg_client_port: 51820 86 | wg_client_address: ip-client 87 | wg_access_network: wg-network 88 | ``` 89 | 90 | Sing-box, stubby, Russia 91 | ``` 92 | - hosts: 192.168.1.1 93 | remote_user: root 94 | 95 | roles: 96 | - itdoginfo.domain_routing_openwrt 97 | 98 | vars: 99 | tunnel: singbox 100 | dns_encrypt: stubby 101 | country: russia-inside 102 | 103 | tasks: 104 | - name: sing-box config 105 | template: 106 | src: "templates/openwrt-sing-box-json.j2" 107 | dest: "/etc/sing-box/config.json" 108 | mode: 0644 109 | notify: 110 | - Restart sing-box 111 | - Restart network 112 | ``` 113 | 114 | License 115 | ------- 116 | 117 | GNU General Public License v3.0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [English role README](https://github.com/itdoginfo/domain-routing-openwrt/blob/master/README.EN.md) 2 | 3 | # Описание 4 | Shell скрипт и [роль для Ansible](https://galaxy.ansible.com/ui/standalone/roles/itdoginfo/domain_routing_openwrt). Автоматизируют настройку роутера на OpenWrt для роутинга по доменам и спискам IP-адресов. 5 | 6 | Полное описание происходящего: 7 | - [Статья на хабре](https://habr.com/ru/articles/767464/) 8 | - [Копия в моём блоге](https://itdog.info/tochechnyj-obhod-blokirovok-po-domenam-na-routere-s-openwrt/) 9 | 10 | # Скрипт для установки 11 | ``` 12 | sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-install.sh) 13 | ``` 14 | 15 | # Скрипт для удаления 16 | ``` 17 | sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/refs/heads/master/getdomains-uninstall.sh) 18 | ``` 19 | 20 | ## AmneziaWG 21 | Через этот скрипт можно установить Amnezia wireguard. Скрипт проверяет наличие пакетов под вашу платформу в [стороннем репозитории](https://github.com/Slava-Shchipunov/awg-openwrt/releases), так как в официальном репозитории OpenWRT они отсутствуют, и автоматически их устанавливает. 22 | 23 | Если вам нужно установить только AWG, воспользуйтесь скриптом в репозитории: https://github.com/Slava-Shchipunov/awg-openwrt 24 | 25 | Если подходящих пакетов нет, перед настройкой необходимо будет самостоятельно [собрать бинарники AmneziaWG](https://github.com/itdoginfo/domain-routing-openwrt/wiki/Amnezia-WG-Build) для своего устройства и установить их. 26 | 27 | ## Скрипт для проверки конфигурации 28 | Написан для OpenWrt 23.05 и 22.03. На 21.02 работает только половина проверок. 29 | 30 | [x] - не обязательно означает, что эта часть не работает. Но это повод для ручной проверки. 31 | 32 | ### Запуск 33 | ``` 34 | wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh 35 | ``` 36 | 37 | По-умолчанию запускается на русском языке. Если нужно запустить на английском, то после `sh` нужно добавить `-s --lang en`. Аналогично для проверок на подмену DNS и создания дампа. 38 | 39 | ``` 40 | wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s --lang en 41 | ``` 42 | 43 | ### Запустить с проверкой на подмену DNS 44 | ``` 45 | wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dns 46 | ``` 47 | 48 | ### Запустить с созданием dump 49 | Все чувствительные переменные затираются. 50 | 51 | ``` 52 | wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwrt/master/getdomains-check.sh | sh -s dump 53 | ``` 54 | 55 | Поиск ошибок вручную: https://habr.com/ru/post/702388/ 56 | 57 | # Ansible 58 | Установить роль 59 | ``` 60 | ansible-galaxy role install itdoginfo.domain_routing_openwrt 61 | ``` 62 | 63 | Примеры playbooks 64 | 65 | Wireguard, only domains, stubby, Russia, acces from wg network (пример 192.168.80.0/24), host 192.168.1.1 66 | ``` 67 | - hosts: 192.168.1.1 68 | remote_user: root 69 | 70 | roles: 71 | - itdoginfo.domain_routing_openwrt 72 | 73 | vars: 74 | tunnel: wg 75 | dns_encrypt: stubby 76 | country: russia-inside 77 | 78 | wg_server_address: wg-server-host 79 | wg_private_key: privatekey-client 80 | wg_public_key: publickey-client 81 | wg_preshared_key: presharedkey-client 82 | wg_listen_port: 51820 83 | wg_client_port: 51820 84 | wg_client_address: ip-client 85 | 86 | wg_access: true 87 | wg_access_network: wg-network 88 | ``` 89 | 90 | Sing-box, stubby, Russia 91 | ``` 92 | - hosts: 192.168.1.1 93 | remote_user: root 94 | 95 | roles: 96 | - itdoginfo.domain_routing_openwrt 97 | 98 | vars: 99 | tunnel: singbox 100 | dns_encrypt: stubby 101 | country: russia-inside 102 | 103 | tasks: 104 | - name: sing-box config 105 | template: 106 | src: "templates/openwrt-sing-box-json.j2" 107 | dest: "/etc/sing-box/config.json" 108 | mode: 0644 109 | notify: 110 | - Restart sing-box 111 | - Restart network 112 | ``` 113 | 114 | В inventory файле роутер обязательно должен быть в группе `[openwrt]` 115 | ``` 116 | [openwrt] 117 | 192.168.1.1 118 | ``` 119 | 120 | Для работы Ansible c OpenWrt необходимо, чтоб было выполнено одно из условий: 121 | - Отсутствие пароля для root (не рекомендуется) 122 | - Настроен доступ через публичный SSH-ключ в [конфиге dropbear](https://openwrt.org/docs/guide-user/security/dropbear.public-key.auth) 123 | 124 | После выполнения playbook роутер сразу начнёт роутить необходмые домены в туннель/прокси. 125 | 126 | Если у вас были ошибки и они исправились при повторном запуске playbook, но при этом роутинг не заработал, сделайте рестарт сети и скрипта: 127 | ``` 128 | service network restart 129 | service getdomains start 130 | ``` 131 | 132 | Тестировалось с 133 | - Ansible 2.10.8 134 | - OpenWrt 21.02.7 135 | - OpenWrt 22.03.5 136 | - OpenWrt 23.05.2 137 | 138 | ## Выбор туннеля 139 | - Wireguard настраивается автоматически через переменные 140 | - OpenVPN устанавливается пакет, настраивается роутинг и зона. Само подключение (скопировать конфиг и перезапустить openvpn) нужно [настроить вручную](https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/) 141 | - Sing-box устанавливает пакет, настраивается роутинг и зона. Также кладётся темплейт в `/etc/sing-box/config.json`. [Нужно настроить](https://habr.com/ru/articles/767458/) `config.json` и сделать `service sing-box restart` 142 | Не работает под 21ой версией. Поэтому при его выборе playbook выдаст ошибку. 143 | Для 22ой версии нужно установить пакет вручную. 144 | - tun2socks настраивается только роутинг и зона. Всё остальное нужно настроить вручную 145 | 146 | Для **tunnel** шесть возможных значений: 147 | - wg 148 | - openvpn 149 | - singbox 150 | - tun2socks 151 | 152 | В случае использования WG: 153 | ``` 154 | wg_server_address: wg-server-host 155 | wg_private_key: privatekey-client 156 | wg_public_key: publickey-client 157 | wg_preshared_key: presharedkey-client 158 | wg_client_port: 51820 159 | wg_client_address: ip-client 160 | ``` 161 | 162 | Если ваш wg сервер не использует `preshared_key`, то просто не задавайте её. 163 | 164 | **wg_access** и **wg_access_network** для доступа к роутеру через WG. Переменная wg_access_network должна иметь значение подсети, например 192.168.10.0/24. 165 | ``` 166 | wg_access_network: wg-network 167 | wg_access: true 168 | ``` 169 | 170 | ## Шифрование DNS 171 | Если ваш провайдер не подменяет DNS-запросы, ничего устанавливать не нужно. 172 | 173 | Для **dns_encrypt** три возможных значения: 174 | - dnscrypt 175 | - stubby 176 | - false/закомментировано - пропуск, ничего не устанавливается и не настраивается 177 | 178 | ## Выбор страны 179 | Выбор списка доменов. 180 | Для **county** три [возможных значения](https://github.com/itdoginfo/allow-domains): 181 | - russia-inside 182 | - russia-outside 183 | - ukraine 184 | 185 | ## Списки IP-адресов 186 | Списки IP-адресов берутся с [antifilter.download](https://antifilter.download/) 187 | Переменные **list_** обозначают, какие списки нужно установить. true - установить, false - не устанавливать и удалить, если уже есть 188 | 189 | Доступные переменные 190 | ``` 191 | list_domains: true 192 | list_subnet: false 193 | list_ip: falses 194 | list_community: false 195 | ``` 196 | 197 | Я советую использовать только домены 198 | ``` 199 | list_domains: true 200 | ``` 201 | Если вам требуются списки IP-адресов, они также поддерживаются. 202 | 203 | При использовании **list_domains** нужен пакет dnsmasq-full. 204 | 205 | Для 23.05 dnsmasq-full устанавливается автоматически. 206 | 207 | Для OpenWrt 22.03 версия dnsmasq-full должна быть => 2.87, её нет в официальном репозитории, но можно установить из dev репозитория. Если это условие не выполнено, плейбук завершится с ошибкой. 208 | 209 | [Инструкция для OpenWrt 22.03](https://t.me/itdoginf/12) 210 | 211 | [Инструкция для OpenWrt 21.02](https://t.me/itdoginfo/8) 212 | 213 | ## Текстовый редактор nano 214 | Устанавливается по умолчанию. Можно выключить 215 | ``` 216 | nano: false 217 | ``` 218 | 219 | --- 220 | 221 | [Telegram-канал с обновлениями](https://t.me/+lW1HmBO_Fa00M2Iy) 222 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | list_domains: true 3 | list_subnet: false 4 | list_ip: false 5 | list_community: false 6 | tunnel: wg 7 | dns_encrypt: false 8 | country: russia-inside 9 | nano: true 10 | wg_access: false 11 | 12 | wg_listen_port: 51820 -------------------------------------------------------------------------------- /getdomains-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCRIPTS_DIR="/etc/init.d" 4 | TMP_DIR="/tmp" 5 | HIVPN_SCRIPT_FILENAME="hivpn" 6 | GETDOMAINS_SCRIPT_FILENAME="getdomains" 7 | DUMP_FILENAME="dump.txt" 8 | 9 | HIVPN_SCRIPT_PATH="$SCRIPTS_DIR/$HIVPN_SCRIPT_FILENAME" 10 | GETDOMAINS_SCRIPT_PATH="$SCRIPTS_DIR/$GETDOMAINS_SCRIPT_FILENAME" 11 | DUMP_PATH="$TMP_DIR/$DUMP_FILENAME" 12 | 13 | COLOR_BOLD_BLUE="\033[34;1m" 14 | COLOR_BOLD_GREEN="\033[32;1m" 15 | COLOR_BOLD_RED="\033[31;1m" 16 | COLOR_BOLD_CYAN="\033[36;1m" 17 | COLOR_RESET="\033[0m" 18 | 19 | UNSUPPORTED_OPENWRT_VERSION="21.02" 20 | MIN_RAM="256" 21 | DNSMASQ_FULL_REQUIRED_VERSION="2.87" 22 | 23 | SINGBOX_CONFIG_PATH="/etc/config/sing-box" 24 | 25 | CURL_PACKAGE="curl" 26 | DNSMASQ_PACKAGE="dnsmasq" 27 | DNSMASQ_FULL_PACKAGE="$DNSMASQ_PACKAGE-full" 28 | XRAY_CORE_PACKAGE="xray-core" 29 | LUCI_APP_XRAY_PACKAGE="luci-app-xray" 30 | WIREGUARD_TOOLS_PACKAGE="wireguard-tools" 31 | OPENVPN_PACKAGE="openvpn" 32 | SINGBOX_PACKAGE="sing-box" 33 | TUN2SOCKS_PACKAGE="tun2socks" 34 | DNSCRYPT_PACKAGE="dnscrypt-proxy2" 35 | STUBBY_PACKAGE="stubby" 36 | 37 | WIREGUARD_PROTOCOL="Wireguard" 38 | OPENVPN_PROTOCOL="OpenVPN" 39 | 40 | LANGUAGE="ru" 41 | SUPPORTED_LANGUAGES="ru, en" 42 | 43 | set_language_en() { 44 | DEVICE_MODEL="Model" 45 | OPENWRT_VERSION="Version" 46 | CURRENT_DATE="Date" 47 | INSTALLED="is installed" 48 | NOT_INSTALLED="is not installed" 49 | RUNNING="is running" 50 | NOT_RUNNING="is not running" 51 | ENABLED="is enabled" 52 | DISABLED="is disabled" 53 | EXISTS="exists" 54 | DOESNT_EXIST="doesn't exist" 55 | UNSUPPORTED_OPENWRT="You are using OpenWrt $UNSUPPORTED_OPENWRT_VERSION. This check script does not support it." 56 | RAM_WARNING="Your router has less than $MIN_RAM MB of RAM. It is recommended to use only the vpn_domains list." 57 | CURL_INSTALLED="$CURL_PACKAGE $INSTALLED" 58 | CURL_NOT_INSTALLED="$CURL_PACKAGE $NOT_INSTALLED. Install it: opkg install $CURL_PACKAGE" 59 | DNSMASQ_FULL_INSTALLED="$DNSMASQ_FULL_PACKAGE $INSTALLED" 60 | DNSMASQ_FULL_NOT_INSTALLED="$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED" 61 | 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" 62 | 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" 63 | XRAY_CORE_PACKAGE_DETECTED="$XRAY_CORE_PACKAGE package detected" 64 | 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" 65 | DNSMASQ_SERVICE_RUNNING="$DNSMASQ_PACKAGE service $RUNNING" 66 | DNSMASQ_SERVICE_NOT_RUNNING="$DNSMASQ_PACKAGE service $NOT_RUNNING. Check configuration: /etc/config/dhcp" 67 | INTERNET_IS_AVAILABLE="Internet is available" 68 | INTERNET_IS_NOT_AVAILABLE="Internet is not available" 69 | 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/" 70 | IPV6_DETECTED="IPv6 detected. This script does not currently work with IPv6" 71 | WIREGUARD_TOOLS_INSTALLED="$WIREGUARD_TOOLS_PACKAGE $INSTALLED" 72 | 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" 73 | 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" 74 | WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED="$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/SaxBzH7" 75 | WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED="$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED" 76 | WIREGUARD_ROUTING_TABLE_EXISTS="$WIREGUARD_PROTOCOL routing table $EXISTS" 77 | WIREGUARD_ROUTING_TABLE_DOESNT_EXIST="$WIREGUARD_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3" 78 | OPENVPN_INSTALLED="$OPENVPN_PACKAGE $INSTALLED" 79 | OPENVPN_ROUTING_DOESNT_WORK="Tunnel to the $OPENVPN_PROTOCOL server works, but routing to the internet does not work. Check server configuration." 80 | OPENVPN_TUNNEL_NOT_WORKING="Bad news: $OPENVPN_PROTOCOL tunnel isn't working. Check your $OPENVPN_PROTOCOL configuration." 81 | OPENVPN_REDIRECT_GATEWAY_ENABLED="$OPENVPN_PROTOCOL redirect-gateway $ENABLED. All traffic goes into the tunnel. Read more at: https://cli.co/vzTNq_3" 82 | OPENVPN_REDIRECT_GATEWAY_DISABLED="$OPENVPN_PROTOCOL redirect-gateway $DISABLED" 83 | OPENVPN_ROUTING_TABLE_EXISTS="$OPENVPN_PROTOCOL routing table $EXISTS" 84 | OPENVPN_ROUTING_TABLE_DOESNT_EXIST="$OPENVPN_PROTOCOL routing table $DOESNT_EXIST. Details: https://cli.co/Atxr6U3" 85 | SINGBOX_INSTALLED="$SINGBOX_PACKAGE $INSTALLED" 86 | SINGBOX_ROUTING_TABLE_EXISTS="$SINGBOX_PACKAGE routing table $EXISTS" 87 | SINGBOX_ROUTING_TABLE_DOESNT_EXIST="$SINGBOX_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1" 88 | SINGBOX_UCI_CONFIG_OK="$SINGBOX_PACKAGE UCI configuration has been successfully validated" 89 | SINGBOX_UCI_CONFIG_ERROR="$SINGBOX_PACKAGE Error validation UCI configuration. Check $SINGBOX_CONFIG_PATH" 90 | SINGBOX_CONFIG_OK="$SINGBOX_PACKAGE configuration has been successfully validated" 91 | SINGBOX_CONFIG_ERROR="$SINGBOX_PACKAGE configuration validation error" 92 | SINGBOX_WORKING_TEMPLATE="$SINGBOX_PACKAGE works. VPN IP: %s" 93 | SINGBOX_ROUTING_DOESNT_WORK="$SINGBOX_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/Badmn3K" 94 | TUN2SOCKS_INSTALLED="$TUN2SOCKS_PACKAGE $INSTALLED" 95 | TUN2SOCKS_ROUTING_TABLE_EXISTS="$TUN2SOCKS_PACKAGE routing table $EXISTS" 96 | TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST="$TUN2SOCKS_PACKAGE routing table $DOESNT_EXIST. Try: service network restart. Details: https://cli.co/n7xAbc1" 97 | TUN2SOCKS_WORKING_TEMPLATE="$TUN2SOCKS_PACKAGE works. VPN IP: %s" 98 | TUN2SOCKS_ROUTING_DOESNT_WORK="$TUN2SOCKS_PACKAGE: Your traffic is not routed through the VPN. Check configuration: https://cli.co/VNZISEM" 99 | VPN_DOMAINS_SET_EXISTS="vpn_domains set $EXISTS" 100 | VPN_DOMAINS_SET_DOESNT_EXIST="vpn_domains set $DOESNT_EXIST" 101 | IPS_IN_VPN_DOMAINS_SET_OK="IPs are successfully added to vpn_domains set" 102 | IPS_IN_VPN_DOMAINS_SET_ERROR="IPs were not added to vpn_domains set" 103 | 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" 104 | 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" 105 | VPN_IP_SET_EXISTS="vpn_ip set $EXISTS" 106 | VPN_IP_SET_DOESNT_EXIST="vpn_ip set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6" 107 | IPS_IN_VPN_IP_SET_OK="IPs are successfully added to vpn_ip set" 108 | IPS_IN_VPN_IP_SET_ERROR="IPs were not added to vpn_ip set. But if you want to use it, check configuration" 109 | VPN_SUBNET_SET_EXISTS="vpn_subnets set $EXISTS" 110 | VPN_SUBNET_SET_DOESNT_EXIST="vpn_subnets set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6" 111 | IPS_IN_VPN_SUBNET_SET_OK="IPs are successfully added to vpn_subnets set" 112 | IPS_IN_VPN_SUBNET_SET_ERROR="IPs were not added to vpn_subnets set. But if you want to use it, check configs" 113 | VPN_COMMUNITY_SET_EXISTS="vpn_community set $EXISTS" 114 | VPN_COMMUNITY_SET_DOESNT_EXIST="vpn_community set $DOESNT_EXIST. Check configuration: https://cli.co/AwUGeM6" 115 | IPS_IN_VPN_COMMUNITY_SET_OK="IPs are successfully added to vpn_community set" 116 | IPS_IN_VPN_COMMUNITY_SET_ERROR="IPs were not added to vpn_community set. But if you want to use it, check configs" 117 | GETDOMAINS_SCRIPT_EXISTS="Script $GETDOMAINS_SCRIPT_FILENAME $EXISTS" 118 | 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" 119 | GETDOMAINS_SCRIPT_CRONTAB_OK="Script $GETDOMAINS_SCRIPT_FILENAME has been successfully added to crontab" 120 | GETDOMAINS_SCRIPT_CRONTAB_ERROR="Script $GETDOMAINS_SCRIPT_FILENAME has not been added to crontab. Check: crontab -l" 121 | DNSCRYPT_INSTALLED="$DNSCRYPT_PACKAGE $INSTALLED" 122 | DNSCRYPT_SERVICE_RUNNING="$DNSCRYPT_PACKAGE service $RUNNING" 123 | DNSCRYPT_SERVICE_NOT_RUNNING="$DNSCRYPT_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/wN-tc_S" 124 | DNSMASQ_CONFIG_FOR_DNSCRYPT_OK="$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is ok" 125 | DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR="$DNSMASQ_PACKAGE configuration for $DNSCRYPT_PACKAGE is not ok. Check configuration: https://cli.co/rooc0uz" 126 | STUBBY_INSTALLED="$STUBBY_PACKAGE $INSTALLED" 127 | STUBBY_SERVICE_RUNNING="$STUBBY_PACKAGE service $RUNNING" 128 | STUBBY_SERVICE_NOT_RUNNING="$STUBBY_PACKAGE service $NOT_RUNNING. Check configuration: https://cli.co/HbDBT2V" 129 | DNSMASQ_CONFIG_FOR_STUBBY_OK="$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is ok" 130 | DNSMASQ_CONFIG_FOR_STUBBY_ERROR="$DNSMASQ_PACKAGE configuration for $STUBBY_PACKAGE is not ok. Check configuration: https://cli.co/HbDBT2V" 131 | DUMP_CREATION="Creating dump without private variables" 132 | 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" 133 | DNS_CHECK="Checking DNS servers" 134 | IS_DNS_TRAFFIC_BLOCKED="Checking DNS traffic blocking (Port 53/udp is available)" 135 | IS_DOH_AVAILABLE="Checking DOH availability" 136 | RESPONSE_NOT_CONTAINS_127_0_0_8="Checking that the response does not contain an address from 127.0.0.8" 137 | ONE_IP_FOR_TWO_DOMAINS="Checking IP for two different domains" 138 | IPS_ARE_THE_SAME="IPs are the same" 139 | IPS_ARE_DIFFERENT="IPs are different" 140 | RESPONSE_IS_NOT_BLANK="Checking if response is not blank" 141 | DNS_POISONING_CHECK="Сomparing response from unencrypted DNS and DoH (DNS poisoning)" 142 | TELEGRAM_CHANNEL="Telegram channel" 143 | TELEGRAM_CHAT="Telegram chat" 144 | } 145 | 146 | set_language_ru() { 147 | DEVICE_MODEL="Модель" 148 | OPENWRT_VERSION="Версия" 149 | CURRENT_DATE="Дата" 150 | INSTALLED="установлен" 151 | NOT_INSTALLED="не установлен" 152 | RUNNING="запущен" 153 | NOT_RUNNING="не запущен" 154 | ENABLED="включен" 155 | DISABLED="выключен" 156 | EXISTS="существует" 157 | DOESNT_EXIST="не существует" 158 | UNSUPPORTED_OPENWRT="Вы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт проверки её не поддерживает." 159 | RAM_WARNING="У вашего роутера менее $MIN_RAM МБ ОЗУ. Рекомендуется использовать только vpn_domains set." 160 | CURL_INSTALLED="$CURL_PACKAGE $INSTALLED" 161 | CURL_NOT_INSTALLED="$CURL_PACKAGE $NOT_INSTALLED. Установите его: opkg install $CURL_PACKAGE" 162 | DNSMASQ_FULL_INSTALLED="$DNSMASQ_FULL_PACKAGE $INSTALLED" 163 | DNSMASQ_FULL_NOT_INSTALLED="$DNSMASQ_FULL_PACKAGE $NOT_INSTALLED" 164 | 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" 165 | OPENWRT_21_DETAILS="\nВы используете OpenWrt $UNSUPPORTED_OPENWRT_VERSION. Этот скрипт её не поддерживает.\nИнструкция для OpenWrt $UNSUPPORTED_OPENWRT_VERSION: https://t.me/itdoginfo/8" 166 | XRAY_CORE_PACKAGE_DETECTED="Обнаружен пакет $XRAY_CORE_PACKAGE" 167 | LUCI_APP_XRAY_PACKAGE_DETECTED="Обнаружен пакет $LUCI_APP_XRAY_PACKAGE, который не совместим. Удалите его: opkg remove $LUCI_APP_XRAY_PACKAGE --force-removal-of-dependent-packages" 168 | DNSMASQ_SERVICE_RUNNING="Сервис $DNSMASQ_PACKAGE $RUNNING" 169 | DNSMASQ_SERVICE_NOT_RUNNING="Сервис $DNSMASQ_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: /etc/config/dhcp" 170 | INTERNET_IS_AVAILABLE="Интернет доступен" 171 | INTERNET_IS_NOT_AVAILABLE="Интернет недоступен" 172 | INTERNET_DETAILS="Проверьте подключение к интернету. Если оно в порядке, проверьте дату на роутере. Подробности: https://cli.co/2EaW4rO\nДополнительно выполните: curl -Is https://community.antifilter.download/" 173 | IPV6_DETECTED="Обнаружен IPv6. Этот скрипт не поддерживает работу с IPv6" 174 | WIREGUARD_TOOLS_INSTALLED="$WIREGUARD_TOOLS_PACKAGE $INSTALLED" 175 | WIREGUARD_ROUTING_DOESNT_WORK="Туннель к $WIREGUARD_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера. Подробности: https://cli.co/RSCvOxI" 176 | WIREGUARD_TUNNEL_NOT_WORKING="Плохие новости: туннель $WIREGUARD_PROTOCOL не работает. Проверьте конфигурацию $WIREGUARD_PROTOCOL. Подробности: https://cli.co/hGUUXDs\nЕсли вы не используете $WIREGUARD_PROTOCOL, а, например, $OPENVPN_PROTOCOL, то это нормально" 177 | WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED="$WIREGUARD_PROTOCOL route_allowed_ips $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/SaxBzH7" 178 | WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED="$WIREGUARD_PROTOCOL route_allowed_ips $DISABLED" 179 | WIREGUARD_ROUTING_TABLE_EXISTS="Таблица маршрутизации $WIREGUARD_PROTOCOL $EXISTS" 180 | WIREGUARD_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $WIREGUARD_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3" 181 | OPENVPN_INSTALLED="$OPENVPN_PACKAGE $INSTALLED" 182 | OPENVPN_ROUTING_DOESNT_WORK="Туннель к $OPENVPN_PROTOCOL серверу работает, но маршрутизация в интернет не работает. Проверьте конфигурацию сервера." 183 | OPENVPN_TUNNEL_NOT_WORKING="Плохие новости: туннель $OPENVPN_PROTOCOL не работает. Проверьте конфигурацию $OPENVPN_PROTOCOL." 184 | OPENVPN_REDIRECT_GATEWAY_ENABLED="$OPENVPN_PROTOCOL redirect-gateway $ENABLED. Весь трафик идет в туннель. Подробнее: https://cli.co/vzTNq_3" 185 | OPENVPN_REDIRECT_GATEWAY_DISABLED="$OPENVPN_PROTOCOL redirect-gateway $DISABLED" 186 | OPENVPN_ROUTING_TABLE_EXISTS="Таблица маршрутизации $OPENVPN_PROTOCOL $EXISTS" 187 | OPENVPN_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $OPENVPN_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/Atxr6U3" 188 | SINGBOX_INSTALLED="$SINGBOX_PACKAGE $INSTALLED" 189 | SINGBOX_ROUTING_TABLE_EXISTS="Таблица маршрутизации $SINGBOX_PACKAGE $EXISTS" 190 | SINGBOX_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $SINGBOX_PACKAGE $DOESNT_EXIST. Попробуйте: service network restart. Подробности: https://cli.co/n7xAbc1" 191 | SINGBOX_UCI_CONFIG_OK="UCI конфигурация для $SINGBOX_PACKAGE успешно проверена" 192 | SINGBOX_UCI_CONFIG_ERROR="Ошибка валидации UCI конфигурации для $SINGBOX_PACKAGE" 193 | SINGBOX_CONFIG_OK="Конфигурация $SINGBOX_PACKAGE успешно проверена" 194 | SINGBOX_CONFIG_ERROR="Ошибка валидации конфигурации $SINGBOX_PACKAGE" 195 | SINGBOX_WORKING_TEMPLATE="$SINGBOX_PACKAGE работает. VPN IP: %s" 196 | SINGBOX_ROUTING_DOESNT_WORK="$SINGBOX_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/Badmn3K" 197 | TUN2SOCKS_INSTALLED="$TUN2SOCKS_PACKAGE $INSTALLED" 198 | TUN2SOCKS_ROUTING_TABLE_EXISTS="Таблица маршрутизации $TUN2SOCKS_PROTOCOL $EXISTS" 199 | TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST="Таблица маршрутизации $TUN2SOCKS_PROTOCOL $DOESNT_EXIST. Подробности: https://cli.co/n7xAbc1" 200 | TUN2SOCKS_WORKING_TEMPLATE="$TUN2SOCKS_PACKAGE работает. VPN IP: %s" 201 | TUN2SOCKS_ROUTING_DOESNT_WORK="$TUN2SOCKS_PACKAGE: Ваш трафик не идёт через VPN. Проверьте конфигурацию: https://cli.co/VNZISEM" 202 | VPN_DOMAINS_SET_EXISTS="vpn_domains set $EXISTS" 203 | VPN_DOMAINS_SET_DOESNT_EXIST="vpn_domains set $DOESNT_EXIST" 204 | IPS_IN_VPN_DOMAINS_SET_OK="IP-адреса успешно добавлены в vpn_domains set" 205 | IPS_IN_VPN_DOMAINS_SET_ERROR="IP-адреса не добавлены в vpn_domains set" 206 | VPN_DOMAINS_DETAILS="Если вы не используете vpn_domains, все в порядке.\nНо если вы хотите использовать его, проверьте конфигурацию и выполните: service getdomains start" 207 | VPN_DOMAINS_DETAILS_2="Если вы не используете vpn_domains, все в порядке.\nНо если вы хотите использовать, проверьте конфигурацию: https://cli.co/AwUGeM6" 208 | VPN_IP_SET_EXISTS="vpn_ip set $EXISTS" 209 | VPN_IP_SET_DOESNT_EXIST="vpn_ip set $DOESNT_EXIST" 210 | IPS_IN_VPN_IP_SET_OK="IP-адреса успешно добавлены в set vpn_ip" 211 | IPS_IN_VPN_IP_SET_ERROR="IP-адреса не добавлены в set vpn_ip" 212 | VPN_SUBNET_SET_EXISTS="vpn_subnet set $EXISTS" 213 | VPN_SUBNET_SET_DOESNT_EXIST="vpn_subnet set $DOESNT_EXIST" 214 | IPS_IN_VPN_SUBNET_SET_OK="IP-адреса успешно добавлены в set vpn_subnet" 215 | IPS_IN_VPN_SUBNET_SET_ERROR="IP-адреса не добавлены в set vpn_subnet" 216 | VPN_COMMUNITY_SET_EXISTS="vpn_community set $EXISTS" 217 | VPN_COMMUNITY_SET_DOESNT_EXIST="vpn_community set $DOESNT_EXIST" 218 | IPS_IN_VPN_COMMUNITY_SET_OK="IP-адреса успешно добавлены в set vpn_community" 219 | IPS_IN_VPN_COMMUNITY_SET_ERROR="IP-адреса не добавлены в set vpn_community" 220 | GETDOMAINS_SCRIPT_EXISTS="Скрипт $GETDOMAINS_SCRIPT_FILENAME $EXISTS" 221 | GETDOMAINS_SCRIPT_DOESNT_EXIST="Скрипт $GETDOMAINS_SCRIPT_FILENAME $DOESNT_EXIST" 222 | GETDOMAINS_SCRIPT_CRONTAB_OK="Скрипт $GETDOMAINS_SCRIPT_FILENAME успешно добавлен в crontab" 223 | GETDOMAINS_SCRIPT_CRONTAB_ERROR="Скрипт $GETDOMAINS_SCRIPT_FILENAME не был добавлен в crontab. Проверьте: crontab -l" 224 | DNSCRYPT_INSTALLED="$DNSCRYPT_PACKAGE $INSTALLED" 225 | DNSCRYPT_SERVICE_RUNNING="Сервис $DNSCRYPT_PACKAGE $RUNNING" 226 | DNSCRYPT_SERVICE_NOT_RUNNING="Сервис $DNSCRYPT_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/wN-tc_S" 227 | DNSMASQ_CONFIG_FOR_DNSCRYPT_OK="Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE в порядке" 228 | DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR="Конфигурация $DNSMASQ_PACKAGE для $DNSCRYPT_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/rooc0uz" 229 | STUBBY_INSTALLED="$STUBBY_PACKAGE $INSTALLED" 230 | STUBBY_SERVICE_RUNNING="Сервис $STUBBY_PACKAGE $RUNNING" 231 | STUBBY_SERVICE_NOT_RUNNING="Сервис $STUBBY_PACKAGE $NOT_RUNNING. Проверьте конфигурацию: https://cli.co/HbDBT2V" 232 | DNSMASQ_CONFIG_FOR_STUBBY_OK="Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE в порядке" 233 | DNSMASQ_CONFIG_FOR_STUBBY_ERROR="Конфигурация $DNSMASQ_PACKAGE для $STUBBY_PACKAGE не в порядке. Проверьте конфигурацию: https://cli.co/HbDBT2V" 234 | DUMP_CREATION="Создание дампа без приватных переменных" 235 | DUMP_DETAILS="Дамп находится здесь: $DUMP_PATH\nДля загрузки на Linux/Mac используйте: scp root@IP_ROUTER:$DUMP_PATH .\nДля Windows используйте WinSCP/PSCP или WSL" 236 | DNS_CHECK="Проверка DNS серверов" 237 | IS_DNS_TRAFFIC_BLOCKED="Проверяем блокировку DNS трафика (Порт 53/udp доступен)" 238 | IS_DOH_AVAILABLE="Проверяем доступность DoH" 239 | RESPONSE_NOT_CONTAINS_127_0_0_8="Проверяем, что ответ на запрос не содержит адреса из 127.0.0.8" 240 | ONE_IP_FOR_TWO_DOMAINS="Проверяем IP для двух разных доменов" 241 | IPS_ARE_THE_SAME="IP совпадают" 242 | IPS_ARE_DIFFERENT="IP различаются" 243 | RESPONSE_IS_NOT_BLANK="Проверяем, что ответ не пустой" 244 | DNS_POISONING_CHECK="Сравниваем ответ от незащищенного DNS и DoH (Подмена DNS)" 245 | TELEGRAM_CHANNEL="Telegram канал" 246 | TELEGRAM_CHAT="Telegram чат" 247 | } 248 | 249 | checkpoint_true() { 250 | printf "$COLOR_BOLD_GREEN[\342\234\223] $1$COLOR_RESET\n" 251 | } 252 | 253 | checkpoint_false() { 254 | printf "$COLOR_BOLD_RED[x] $1$COLOR_RESET\n" 255 | } 256 | 257 | output_21() { 258 | if [ "$VERSION_ID" -eq 21 ]; then 259 | echo "$UNSUPPORTED_OPENWRT" 260 | fi 261 | } 262 | 263 | update_vpn_ip() { 264 | local template="$1" 265 | local ip="$2" 266 | echo "$(printf "$template" "$ip")" 267 | } 268 | 269 | while [ $# -gt 0 ]; do 270 | case "$1" in 271 | --lang) 272 | LANGUAGE="$2" 273 | shift 2 274 | ;; 275 | dump | dns) 276 | COMMAND="$1" 277 | shift 1 278 | ;; 279 | *) 280 | printf "$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unknown option: %s\n" "$1" 281 | exit 1 282 | ;; 283 | esac 284 | done 285 | 286 | case $LANGUAGE in 287 | ru) 288 | set_language_ru 289 | ;; 290 | en) 291 | set_language_en 292 | ;; 293 | *) 294 | printf "$COLOR_BOLD_RED[ERROR]$COLOR_RESET Unsupported language '$LANGUAGE'. Supported languages: $SUPPORTED_LANGUAGES %s\n" "$1" 295 | exit 1 296 | ;; 297 | esac 298 | 299 | # System Details 300 | MODEL=$(cat /tmp/sysinfo/model) 301 | source /etc/os-release 302 | printf "$COLOR_BOLD_BLUE$DEVICE_MODEL: $MODEL$COLOR_RESET\n" 303 | printf "$COLOR_BOLD_BLUE$OPENWRT_VERSION: $OPENWRT_RELEASE$COLOR_RESET\n" 304 | printf "$COLOR_BOLD_BLUE$CURRENT_DATE: $(date)$COLOR_RESET\n" 305 | 306 | VERSION_ID=$(echo $VERSION | awk -F. '{print $1}') 307 | RAM=$(free -m | grep Mem: | awk '{print $2}') 308 | if [[ "$VERSION_ID" -ge 22 && "$RAM" -lt 150000 ]]; then 309 | echo "$RAM_WARNING" 310 | fi 311 | 312 | # Check packages 313 | CURL=$(opkg list-installed | grep -c curl) 314 | if [ $CURL -eq 2 ]; then 315 | checkpoint_true "$CURL_INSTALLED" 316 | else 317 | checkpoint_false "$CURL_NOT_INSTALLED" 318 | fi 319 | 320 | DNSMASQ=$(opkg list-installed | grep dnsmasq-full | awk -F "-" '{print $3}' | tr -d '.') 321 | if [ $DNSMASQ -ge 287 ]; then 322 | checkpoint_true "$DNSMASQ_FULL_INSTALLED" 323 | else 324 | checkpoint_false "$DNSMASQ_FULL_NOT_INSTALLED" 325 | printf "$DNSMASQ_FULL_DETAILS\n" 326 | if [ "$VERSION_ID" -eq 21 ]; then 327 | printf "$OPENWRT_21_DETAILS\n" 328 | fi 329 | fi 330 | 331 | # Chek xray package 332 | if opkg list-installed | grep -q xray-core; then 333 | checkpoint_false "$XRAY_CORE_PACKAGE_DETECTED" 334 | fi 335 | 336 | if opkg list-installed | grep -q luci-app-xray; then 337 | checkpoint_false "$LUCI_APP_XRAY_PACKAGE_DETECTED" 338 | fi 339 | 340 | # Check dnsmasq 341 | DNSMASQ_RUN=$(service dnsmasq status | grep -c 'running') 342 | if [ $DNSMASQ_RUN -eq 1 ]; then 343 | checkpoint_true "$DNSMASQ_SERVICE_RUNNING" 344 | else 345 | checkpoint_false "$DNSMASQ_SERVICE_NOT_RUNNING" 346 | output_21 347 | fi 348 | 349 | # Check internet connection 350 | if curl -Is https://community.antifilter.download/ | grep -q 200; then 351 | checkpoint_true "$INTERNET_IS_AVAILABLE" 352 | else 353 | checkpoint_false "$INTERNET_IS_NOT_AVAILABLE" 354 | if [ $CURL -lt 2 ]; then 355 | echo "$CURL_NOT_INSTALLED" 356 | else 357 | printf "$INTERNET_DETAILS\n" 358 | fi 359 | fi 360 | 361 | # Check IPv6 362 | 363 | if curl -6 -s https://ifconfig.io | egrep -q "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?"; then 364 | checkpoint_false "$IPV6_DETECTED" 365 | fi 366 | 367 | # Tunnels 368 | WIREGUARD=$(opkg list-installed | grep -c wireguard-tools) 369 | if [ $WIREGUARD -eq 1 ]; then 370 | checkpoint_true "$WIREGUARD_TOOLS_INSTALLED" 371 | WG=true 372 | fi 373 | 374 | if [ "$WG" == true ]; then 375 | WG_PING=$(ping -c 1 -q -I wg0 itdog.info | grep -c "1 packets received") 376 | if [ $WG_PING -eq 1 ]; then 377 | checkpoint_true "$WIREGUARD_PROTOCOL" 378 | else 379 | checkpoint_false "$WIREGUARD_PROTOCOL" 380 | 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}') 381 | if [ $WG_TRACE -eq 1 ]; then 382 | echo "$WIREGUARD_ROUTING_DOESNT_WORK" 383 | else 384 | printf "$WIREGUARD_TUNNEL_NOT_WORKING\n" 385 | fi 386 | fi 387 | 388 | # Check WG route_allowed_ips 389 | if uci show network | grep -q ".route_allowed_ips='1'"; then 390 | checkpoint_false "$WIREGUARD_ROUTE_ALLOWED_IPS_ENABLED" 391 | else 392 | checkpoint_true "$WIREGUARD_ROUTE_ALLOWED_IPS_DISABLED" 393 | fi 394 | 395 | # Check route table 396 | ROUTE_TABLE=$(ip route show table vpn | grep -c "default dev wg0") 397 | if [ $ROUTE_TABLE -eq 1 ]; then 398 | checkpoint_true "$WIREGUARD_ROUTING_TABLE_EXISTS" 399 | else 400 | checkpoint_false "$WIREGUARD_ROUTING_TABLE_DOESNT_EXIST" 401 | fi 402 | fi 403 | 404 | if opkg list-installed | grep -q openvpn; then 405 | checkpoint_true "$OPENVPN_INSTALLED" 406 | OVPN=true 407 | fi 408 | 409 | # Check OpenVPN 410 | if [ "$OVPN" == true ]; then 411 | if ping -c 1 -q -I tun0 itdog.info | grep -q "1 packets received"; then 412 | checkpoint_true "$OPENVPN_PROTOCOL" 413 | else 414 | checkpoint_false "$OPENVPN_PROTOCOL" 415 | 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 416 | echo "$OPENVPN_ROUTING_DOESNT_WORK" 417 | else 418 | echo "$OPENVPN_TUNNEL_NOT_WORKING" 419 | fi 420 | fi 421 | 422 | # Check OpenVPN redirect-gateway 423 | if grep -q redirect-gateway /etc/openvpn/*; then 424 | checkpoint_false "$OPENVPN_REDIRECT_GATEWAY_ENABLED" 425 | else 426 | checkpoint_true "$OPENVPN_REDIRECT_GATEWAY_DISABLED" 427 | fi 428 | 429 | # Check route table 430 | if ip route show table vpn | grep -q "default dev tun0"; then 431 | checkpoint_true "$OPENVPN_ROUTING_TABLE_EXISTS" 432 | else 433 | checkpoint_false "$OPENVPN_ROUTING_TABLE_DOESNT_EXIST" 434 | fi 435 | fi 436 | 437 | if opkg list-installed | grep -q sing-box; then 438 | checkpoint_true "$SINGBOX_INSTALLED" 439 | 440 | # Check route table 441 | if ip route show table vpn | grep -q "default dev tun0"; then 442 | checkpoint_true "$SINGBOX_ROUTING_TABLE_EXISTS" 443 | else 444 | checkpoint_false "$SINGBOX_ROUTING_TABLE_DOESNT_EXIST" 445 | fi 446 | 447 | # Sing-box uci validation 448 | if uci show sing-box 2>&1 | grep -q "Parse error"; then 449 | checkpoint_false "$SINGBOX_UCI_CONFIG_ERROR" 450 | else 451 | checkpoint_true "$SINGBOX_UCI_CONFIG_OK" 452 | fi 453 | 454 | singbox_check_cmd="sing-box -c /etc/sing-box/config.json check" 455 | if $singbox_check_cmd >/dev/null 2>&1; then 456 | checkpoint_true "$SINGBOX_CONFIG_OK" 457 | 458 | # Check traffic 459 | IP_EXTERNAL=$(curl -s ifconfig.me) 460 | IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}') 461 | 462 | IP_VPN=$(curl --interface tun0 -s ifconfig.me) 463 | 464 | SINGBOX_WORKING=$(update_vpn_ip "$SINGBOX_WORKING_TEMPLATE" "$IP_VPN") 465 | 466 | if [ "$IP_EXTERNAL" != $IP_VPN ]; then 467 | checkpoint_true "$SINGBOX_WORKING" 468 | else 469 | checkpoint_false "$SINGBOX_ROUTING_DOESNT_WORK" 470 | fi 471 | else 472 | checkpoint_false "$SINGBOX_CONFIG_ERROR:" 473 | $singbox_check_cmd 474 | fi 475 | fi 476 | 477 | if which tun2socks | grep -q tun2socks; then 478 | checkpoint_true "$TUN2SOCKS_INSTALLED" 479 | 480 | # Check route table 481 | if ip route show table vpn | grep -q "default dev tun0"; then 482 | checkpoint_true "$TUN2SOCKS_ROUTING_TABLE_EXISTS" 483 | else 484 | checkpoint_false "$TUN2SOCKS_ROUTING_TABLE_DOESNT_EXIST" 485 | fi 486 | 487 | IP_EXTERNAL=$(curl -s ifconfig.me) 488 | IFCONFIG=$(nslookup -type=a ifconfig.me | awk '/^Address: / {print $2}') 489 | 490 | IP_VPN=$(curl --interface tun0 -s ifconfig.me) 491 | 492 | TUN2SOCKS_WORKING=$(update_vpn_ip "$TUN2SOCKS_WORKING_TEMPLATE" "$IP_VPN") 493 | 494 | if [ "$IP_EXTERNAL" != $IP_VPN ]; then 495 | checkpoint_true "$TUN2SOCKS_WORKING" 496 | else 497 | checkpoint_false "$TUN2SOCKS_ROUTING_DOESNT_WORK" 498 | fi 499 | fi 500 | 501 | # Check sets 502 | 503 | # vpn_domains set 504 | vpn_domain_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1) 505 | vpn_domain_ipset_string=$(uci show firewall.@ipset[$vpn_domain_ipset_id] | grep -c "name='vpn_domains'\|match='dst_net'") 506 | vpn_domain_rule_id=$(uci show firewall | grep -E '@rule.*vpn_domains' | awk -F '[][{}]' '{print $2}' | head -n 1) 507 | vpn_domain_rule_string=$(uci show firewall.@rule[$vpn_domain_rule_id] | grep -c "name='mark_domains'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_domains'\|set_mark='0x1'\|target='MARK'\|family='ipv4'") 508 | 509 | if [ $((vpn_domain_ipset_string + vpn_domain_rule_string)) -eq 10 ]; then 510 | checkpoint_true "$VPN_DOMAINS_SET_EXISTS" 511 | 512 | # force resolve for vpn_domains. All list 513 | nslookup terraform.io 127.0.0.1 >/dev/null 514 | nslookup pochta.ru 127.0.0.1 >/dev/null 515 | nslookup 2gis.ru 127.0.0.1 >/dev/null 516 | 517 | 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}') 518 | if [ $VPN_DOMAINS_IP -ge 1 ]; then 519 | checkpoint_true "$IPS_IN_VPN_DOMAINS_SET_OK" 520 | else 521 | checkpoint_false "$IPS_IN_VPN_DOMAINS_SET_ERROR" 522 | printf "$VPN_DOMAINS_DETAILS\n" 523 | output_21 524 | fi 525 | else 526 | checkpoint_false "$VPN_DOMAINS_SET_DOESNT_EXIST" 527 | printf "$VPN_DOMAINS_DETAILS_2\n" 528 | fi 529 | 530 | # vpn_ip set 531 | vpn_ip_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1) 532 | vpn_ip_ipset_string=$(uci show firewall.@ipset[$vpn_ip_ipset_id] | grep -c "name='vpn_ip'\|match='dst_net'\|loadfile='/tmp/lst/ip.lst'") 533 | vpn_ip_rule_id=$(uci show firewall | grep -E '@rule.*vpn_ip' | awk -F '[][{}]' '{print $2}' | head -n 1) 534 | vpn_ip_rule_string=$(uci show firewall.@rule[$vpn_ip_rule_id] | grep -c "name='mark_ip'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_ip'\|set_mark='0x1'\|target='MARK'\|family='ipv4'") 535 | 536 | if [ $((vpn_ip_ipset_string + vpn_ip_rule_string)) -eq 11 ]; then 537 | checkpoint_true "$VPN_IP_SET_EXISTS" 538 | 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}') 539 | if [ $VPN_IP_IP -ge 1 ]; then 540 | checkpoint_true "$IPS_IN_VPN_IP_SET_OK" 541 | else 542 | checkpoint_false "$IPS_IN_VPN_IP_SET_ERROR" 543 | output_21 544 | fi 545 | elif uci show firewall | grep -q "vpn_ip"; then 546 | checkpoint_false "$VPN_IP_SET_DOESNT_EXIST" 547 | fi 548 | 549 | # vpn_subnet set 550 | vpn_subnet_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1) 551 | vpn_subnet_ipset_string=$(uci show firewall.@ipset[$vpn_subnet_ipset_id] | grep -c "name='vpn_subnets'\|match='dst_net'\|loadfile='/tmp/lst/subnet.lst'") 552 | vpn_subnet_rule_id=$(uci show firewall | grep -E '@rule.*vpn_subnet' | awk -F '[][{}]' '{print $2}' | head -n 1) 553 | vpn_subnet_rule_string=$(uci show firewall.@rule[$vpn_subnet_rule_id] | grep -c "name='mark_subnet'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_subnets'\|set_mark='0x1'\|target='MARK'\|family='ipv4'") 554 | 555 | if [ $((vpn_subnet_ipset_string + vpn_subnet_rule_string)) -eq 11 ]; then 556 | checkpoint_true "$VPN_SUBNET_SET_EXISTS" 557 | 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}') 558 | if [ $VPN_IP_SUBNET -ge 1 ]; then 559 | checkpoint_true "$IPS_IN_VPN_SUBNET_SET_OK" 560 | else 561 | checkpoint_false "$IPS_IN_VPN_SUBNET_SET_ERROR" 562 | output_21 563 | fi 564 | elif uci show firewall | grep -q "vpn_subnet"; then 565 | checkpoint_false "$VPN_SUBNET_SET_DOESNT_EXIST" 566 | fi 567 | 568 | # vpn_community set 569 | vpn_community_ipset_id=$(uci show firewall | grep -E '@ipset.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1) 570 | vpn_community_ipset_string=$(uci show firewall.@ipset[$vpn_community_ipset_id] | grep -c "name='vpn_community'\|match='dst_net'\|loadfile='/tmp/lst/community.lst'") 571 | vpn_community_rule_id=$(uci show firewall | grep -E '@rule.*vpn_community' | awk -F '[][{}]' '{print $2}' | head -n 1) 572 | vpn_community_rule_string=$(uci show firewall.@rule[$vpn_community_rule_id] | grep -c "name='mark_community'\|src='lan'\|dest='*'\|proto='all'\|ipset='vpn_community'\|set_mark='0x1'\|target='MARK'\|family='ipv4'") 573 | 574 | if [ $((vpn_community_ipset_string + vpn_community_rule_string)) -eq 11 ]; then 575 | checkpoint_true "$VPN_COMMUNITY_SET_EXISTS" 576 | 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}') 577 | if [ $VPN_COMMUNITY_IP -ge 1 ]; then 578 | checkpoint_true "$IPS_IN_VPN_COMMUNITY_SET_OK" 579 | else 580 | checkpoint_false "$IPS_IN_VPN_COMMUNITY_SET_ERROR" 581 | output_21 582 | fi 583 | elif uci show firewall | grep -q "vpn_community"; then 584 | checkpoint_false "$VPN_COMMUNITY_SET_DOESNT_EXIST" 585 | fi 586 | 587 | # getdomains script 588 | if [ -s "$GETDOMAINS_SCRIPT_PATH" ]; then 589 | checkpoint_true "$GETDOMAINS_SCRIPT_EXISTS" 590 | if crontab -l | grep -q $GETDOMAINS_SCRIPT_PATH; then 591 | checkpoint_true "$GETDOMAINS_SCRIPT_CRONTAB_OK" 592 | else 593 | checkpoint_false "$GETDOMAINS_SCRIPT_CRONTAB_ERROR" 594 | fi 595 | else 596 | checkpoint_false "$GETDOMAINS_SCRIPT_DOESNT_EXIST" 597 | fi 598 | 599 | # DNS 600 | 601 | # DNSCrypt 602 | if opkg list-installed | grep -q dnscrypt-proxy2; then 603 | checkpoint_true "$DNSCRYPT_INSTALLED" 604 | if service dnscrypt-proxy status | grep -q 'running'; then 605 | checkpoint_true "$DNSCRYPT_SERVICE_RUNNING" 606 | else 607 | checkpoint_false "$DNSCRYPT_SERVICE_NOT_RUNNING" 608 | output_21 609 | fi 610 | 611 | DNSMASQ_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c "127.0.0.53#53\|noresolv='1'") 612 | if [ $DNSMASQ_STRING -eq 2 ]; then 613 | checkpoint_true "$DNSMASQ_CONFIG_FOR_DNSCRYPT_OK" 614 | else 615 | checkpoint_false "$DNSMASQ_CONFIG_FOR_DNSCRYPT_ERROR" 616 | fi 617 | fi 618 | 619 | # Stubby 620 | if opkg list-installed | grep -q stubby; then 621 | checkpoint_true "$STUBBY_INSTALLED" 622 | if service stubby status | grep -q 'running'; then 623 | checkpoint_true "$STUBBY_SERVICE_RUNNING" 624 | else 625 | checkpoint_false "$STUBBY_SERVICE_NOT_RUNNING" 626 | output_21 627 | fi 628 | 629 | STUBBY_STRING=$(uci show dhcp.@dnsmasq[0] | grep -c "127.0.0.1#5453\|noresolv='1'") 630 | if [ $STUBBY_STRING -eq 2 ]; then 631 | checkpoint_true "$DNSMASQ_CONFIG_FOR_STUBBY_OK" 632 | else 633 | checkpoint_false "$DNSMASQ_CONFIG_FOR_STUBBY_ERROR" 634 | fi 635 | fi 636 | 637 | case $COMMAND in 638 | dump) 639 | # Create dump 640 | printf "\n$COLOR_BOLD_CYAN$DUMP_CREATION$COLOR_RESET\n" 641 | date >$DUMP_PATH 642 | $HIVPN start >>$DUMP_PATH 2>&1 643 | $GETDOMAINS_SCRIPT_PATH start >>$DUMP_PATH 2>&1 644 | uci show firewall >>$DUMP_PATH 645 | 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 646 | printf "$DUMP_DETAILS\n" 647 | ;; 648 | dns) 649 | # Check DNS 650 | printf "\n$COLOR_BOLD_CYAN$DNS_CHECK$COLOR_RESET\n" 651 | DNS_SERVERS="1.1.1.1 8.8.8.8 8.8.4.4" 652 | DOH_DNS_SERVERS="cloudflare-dns.com 1.1.1.1 mozilla.cloudflare-dns.com security.cloudflare-dns.com" 653 | DOMAINS="instagram.com facebook.com" 654 | 655 | echo "1. $IS_DNS_TRAFFIC_BLOCKED" 656 | 657 | for i in $DNS_SERVERS; do 658 | if nslookup -type=a -timeout=2 -retry=1 itdog.info $i | grep -q "timed out"; then 659 | checkpoint_false "$i" 660 | else 661 | checkpoint_true "$i" 662 | fi 663 | done 664 | 665 | echo "2. $IS_DOH_AVAILABLE" 666 | 667 | for i in $DOH_DNS_SERVERS; do 668 | 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 669 | checkpoint_true "$i" 670 | else 671 | checkpoint_false "$i" 672 | fi 673 | done 674 | 675 | echo "3. $RESPONSE_NOT_CONTAINS_127_0_0_8" 676 | 677 | for i in $DOMAINS; do 678 | if nslookup -type=a -timeout=2 -retry=1 $i | awk '/^Address: / {print $2}' | grep -q -E '127\.[0-9]{1,3}\.'; then 679 | checkpoint_false "$i" 680 | else 681 | checkpoint_true "$i" 682 | fi 683 | done 684 | 685 | echo "4. $ONE_IP_FOR_TWO_DOMAINS" 686 | 687 | FIRSTIP=$(nslookup -type=a instagram.com | awk '/^Address: / {print $2}') 688 | SECONDIP=$(nslookup -type=a facebook.com | awk '/^Address: / {print $2}') 689 | 690 | if [ "$FIRSTIP" = "$SECONDIP" ]; then 691 | checkpoint_false "$IPS_ARE_THE_SAME" 692 | else 693 | checkpoint_true "$IPS_ARE_DIFFERENT" 694 | fi 695 | 696 | echo "5. $RESPONSE_IS_NOT_BLANK" 697 | 698 | for i in $DOMAINS; do 699 | 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 700 | checkpoint_true "$i" 701 | else 702 | checkpoint_false "$i" 703 | fi 704 | done 705 | 706 | echo "6. $DNS_POISONING_CHECK" 707 | 708 | 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}') 709 | OPENIP=$(nslookup -type=a -timeout=2 facebook.com 1.1.1.1 | awk '/^Address: / {print $2}') 710 | 711 | if [ "$DOHIP" = "$OPENIP" ]; then 712 | checkpoint_true "$IPS_ARE_THE_SAME" 713 | else 714 | checkpoint_false "$IPS_ARE_DIFFERENT" 715 | fi 716 | ;; 717 | *) ;; 718 | esac 719 | 720 | # Info 721 | echo -e "\n$TELEGRAM_CHANNEL: https://t.me/itdoginfo" 722 | echo "$TELEGRAM_CHAT: https://t.me/itdogchat" 723 | -------------------------------------------------------------------------------- /getdomains-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #set -x 4 | 5 | check_repo() { 6 | printf "\033[32;1mChecking OpenWrt repo availability...\033[0m\n" 7 | 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 8 | } 9 | 10 | route_vpn () { 11 | if [ "$TUNNEL" == wg ]; then 12 | cat << EOF > /etc/hotplug.d/iface/30-vpnroute 13 | #!/bin/sh 14 | 15 | ip route add table vpn default dev wg0 16 | EOF 17 | elif [ "$TUNNEL" == awg ]; then 18 | cat << EOF > /etc/hotplug.d/iface/30-vpnroute 19 | #!/bin/sh 20 | 21 | ip route add table vpn default dev awg0 22 | EOF 23 | elif [ "$TUNNEL" == singbox ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then 24 | cat << EOF > /etc/hotplug.d/iface/30-vpnroute 25 | #!/bin/sh 26 | 27 | sleep 10 28 | ip route add table vpn default dev tun0 29 | EOF 30 | fi 31 | 32 | cp /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute 33 | } 34 | 35 | add_mark() { 36 | grep -q "99 vpn" /etc/iproute2/rt_tables || echo '99 vpn' >> /etc/iproute2/rt_tables 37 | 38 | if ! uci show network | grep -q mark0x1; then 39 | printf "\033[32;1mConfigure mark rule\033[0m\n" 40 | uci add network rule 41 | uci set network.@rule[-1].name='mark0x1' 42 | uci set network.@rule[-1].mark='0x1' 43 | uci set network.@rule[-1].priority='100' 44 | uci set network.@rule[-1].lookup='vpn' 45 | uci commit 46 | fi 47 | } 48 | 49 | add_tunnel() { 50 | 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" 51 | echo "Select a tunnel:" 52 | echo "1) WireGuard" 53 | echo "2) OpenVPN" 54 | echo "3) Sing-box" 55 | echo "4) tun2socks" 56 | echo "5) wgForYoutube" 57 | echo "6) Amnezia WireGuard" 58 | echo "7) Amnezia WireGuard For Youtube" 59 | echo "8) Skip this step" 60 | 61 | while true; do 62 | read -r -p '' TUNNEL 63 | case $TUNNEL in 64 | 65 | 1) 66 | TUNNEL=wg 67 | break 68 | ;; 69 | 70 | 2) 71 | TUNNEL=ovpn 72 | break 73 | ;; 74 | 75 | 3) 76 | TUNNEL=singbox 77 | break 78 | ;; 79 | 80 | 4) 81 | TUNNEL=tun2socks 82 | break 83 | ;; 84 | 85 | 5) 86 | TUNNEL=wgForYoutube 87 | break 88 | ;; 89 | 90 | 6) 91 | TUNNEL=awg 92 | break 93 | ;; 94 | 95 | 7) 96 | TUNNEL=awgForYoutube 97 | break 98 | ;; 99 | 100 | 8) 101 | echo "Skip" 102 | TUNNEL=0 103 | break 104 | ;; 105 | 106 | *) 107 | echo "Choose from the following options" 108 | ;; 109 | esac 110 | done 111 | 112 | if [ "$TUNNEL" == 'wg' ]; then 113 | printf "\033[32;1mConfigure WireGuard\033[0m\n" 114 | if opkg list-installed | grep -q wireguard-tools; then 115 | echo "Wireguard already installed" 116 | else 117 | echo "Installed wg..." 118 | opkg install wireguard-tools 119 | fi 120 | 121 | route_vpn 122 | 123 | read -r -p "Enter the private key (from [Interface]):"$'\n' WG_PRIVATE_KEY 124 | 125 | while true; do 126 | read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):"$'\n' WG_IP 127 | if echo "$WG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then 128 | break 129 | else 130 | echo "This IP is not valid. Please repeat" 131 | fi 132 | done 133 | 134 | read -r -p "Enter the public key (from [Peer]):"$'\n' WG_PUBLIC_KEY 135 | read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' WG_PRESHARED_KEY 136 | read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' WG_ENDPOINT 137 | 138 | read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' WG_ENDPOINT_PORT 139 | WG_ENDPOINT_PORT=${WG_ENDPOINT_PORT:-51820} 140 | if [ "$WG_ENDPOINT_PORT" = '51820' ]; then 141 | echo $WG_ENDPOINT_PORT 142 | fi 143 | 144 | uci set network.wg0=interface 145 | uci set network.wg0.proto='wireguard' 146 | uci set network.wg0.private_key=$WG_PRIVATE_KEY 147 | uci set network.wg0.listen_port='51820' 148 | uci set network.wg0.addresses=$WG_IP 149 | 150 | if ! uci show network | grep -q wireguard_wg0; then 151 | uci add network wireguard_wg0 152 | fi 153 | uci set network.@wireguard_wg0[0]=wireguard_wg0 154 | uci set network.@wireguard_wg0[0].name='wg0_client' 155 | uci set network.@wireguard_wg0[0].public_key=$WG_PUBLIC_KEY 156 | uci set network.@wireguard_wg0[0].preshared_key=$WG_PRESHARED_KEY 157 | uci set network.@wireguard_wg0[0].route_allowed_ips='0' 158 | uci set network.@wireguard_wg0[0].persistent_keepalive='25' 159 | uci set network.@wireguard_wg0[0].endpoint_host=$WG_ENDPOINT 160 | uci set network.@wireguard_wg0[0].allowed_ips='0.0.0.0/0' 161 | uci set network.@wireguard_wg0[0].endpoint_port=$WG_ENDPOINT_PORT 162 | uci commit 163 | fi 164 | 165 | if [ "$TUNNEL" == 'ovpn' ]; then 166 | if opkg list-installed | grep -q openvpn-openssl; then 167 | echo "OpenVPN already installed" 168 | else 169 | echo "Installed openvpn" 170 | opkg install openvpn-openssl 171 | fi 172 | printf "\033[32;1mConfigure route for OpenVPN\033[0m\n" 173 | route_vpn 174 | fi 175 | 176 | if [ "$TUNNEL" == 'singbox' ]; then 177 | if opkg list-installed | grep -q sing-box; then 178 | echo "Sing-box already installed" 179 | else 180 | AVAILABLE_SPACE=$(df / | awk 'NR>1 { print $4 }') 181 | if [[ "$AVAILABLE_SPACE" -gt 2000 ]]; then 182 | echo "Installed sing-box" 183 | opkg install sing-box 184 | else 185 | printf "\033[31;1mNo free space for a sing-box. Sing-box is not installed.\033[0m\n" 186 | exit 1 187 | fi 188 | fi 189 | if grep -q "option enabled '0'" /etc/config/sing-box; then 190 | sed -i "s/ option enabled \'0\'/ option enabled \'1\'/" /etc/config/sing-box 191 | fi 192 | if grep -q "option user 'sing-box'" /etc/config/sing-box; then 193 | sed -i "s/ option user \'sing-box\'/ option user \'root\'/" /etc/config/sing-box 194 | fi 195 | if grep -q "tun0" /etc/sing-box/config.json; then 196 | printf "\033[32;1mConfig /etc/sing-box/config.json already exists\033[0m\n" 197 | else 198 | cat << 'EOF' > /etc/sing-box/config.json 199 | { 200 | "log": { 201 | "level": "debug" 202 | }, 203 | "inbounds": [ 204 | { 205 | "type": "tun", 206 | "interface_name": "tun0", 207 | "domain_strategy": "ipv4_only", 208 | "address": ["172.16.250.1/30"], 209 | "auto_route": false, 210 | "strict_route": false, 211 | "sniff": true 212 | } 213 | ], 214 | "outbounds": [ 215 | { 216 | "type": "$TYPE", 217 | "server": "$HOST", 218 | "server_port": $PORT, 219 | "method": "$METHOD", 220 | "password": "$PASS" 221 | } 222 | ], 223 | "route": { 224 | "auto_detect_interface": true 225 | } 226 | } 227 | EOF 228 | 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" 229 | printf "\033[32;1mOfficial doc: https://sing-box.sagernet.org/configuration/outbound/\033[0m\n" 230 | printf "\033[32;1mManual with example SS: https://cli.co/Badmn3K \033[0m\n" 231 | 232 | fi 233 | printf "\033[32;1mConfigure route for Sing-box\033[0m\n" 234 | route_vpn 235 | fi 236 | 237 | if [ "$TUNNEL" == 'wgForYoutube' ]; then 238 | add_internal_wg Wireguard 239 | fi 240 | 241 | if [ "$TUNNEL" == 'awgForYoutube' ]; then 242 | add_internal_wg AmneziaWG 243 | fi 244 | 245 | if [ "$TUNNEL" == 'awg' ]; then 246 | printf "\033[32;1mConfigure Amnezia WireGuard\033[0m\n" 247 | 248 | install_awg_packages 249 | 250 | route_vpn 251 | 252 | read -r -p "Enter the private key (from [Interface]):"$'\n' AWG_PRIVATE_KEY 253 | 254 | while true; do 255 | read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (Address from [Interface]):"$'\n' AWG_IP 256 | if echo "$AWG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then 257 | break 258 | else 259 | echo "This IP is not valid. Please repeat" 260 | fi 261 | done 262 | 263 | read -r -p "Enter Jc value (from [Interface]):"$'\n' AWG_JC 264 | read -r -p "Enter Jmin value (from [Interface]):"$'\n' AWG_JMIN 265 | read -r -p "Enter Jmax value (from [Interface]):"$'\n' AWG_JMAX 266 | read -r -p "Enter S1 value (from [Interface]):"$'\n' AWG_S1 267 | read -r -p "Enter S2 value (from [Interface]):"$'\n' AWG_S2 268 | read -r -p "Enter H1 value (from [Interface]):"$'\n' AWG_H1 269 | read -r -p "Enter H2 value (from [Interface]):"$'\n' AWG_H2 270 | read -r -p "Enter H3 value (from [Interface]):"$'\n' AWG_H3 271 | read -r -p "Enter H4 value (from [Interface]):"$'\n' AWG_H4 272 | 273 | read -r -p "Enter the public key (from [Peer]):"$'\n' AWG_PUBLIC_KEY 274 | read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' AWG_PRESHARED_KEY 275 | read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' AWG_ENDPOINT 276 | 277 | read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' AWG_ENDPOINT_PORT 278 | AWG_ENDPOINT_PORT=${AWG_ENDPOINT_PORT:-51820} 279 | if [ "$AWG_ENDPOINT_PORT" = '51820' ]; then 280 | echo $AWG_ENDPOINT_PORT 281 | fi 282 | 283 | uci set network.awg0=interface 284 | uci set network.awg0.proto='amneziawg' 285 | uci set network.awg0.private_key=$AWG_PRIVATE_KEY 286 | uci set network.awg0.listen_port='51820' 287 | uci set network.awg0.addresses=$AWG_IP 288 | 289 | uci set network.awg0.awg_jc=$AWG_JC 290 | uci set network.awg0.awg_jmin=$AWG_JMIN 291 | uci set network.awg0.awg_jmax=$AWG_JMAX 292 | uci set network.awg0.awg_s1=$AWG_S1 293 | uci set network.awg0.awg_s2=$AWG_S2 294 | uci set network.awg0.awg_h1=$AWG_H1 295 | uci set network.awg0.awg_h2=$AWG_H2 296 | uci set network.awg0.awg_h3=$AWG_H3 297 | uci set network.awg0.awg_h4=$AWG_H4 298 | 299 | if ! uci show network | grep -q amneziawg_awg0; then 300 | uci add network amneziawg_awg0 301 | fi 302 | 303 | uci set network.@amneziawg_awg0[0]=amneziawg_awg0 304 | uci set network.@amneziawg_awg0[0].name='awg0_client' 305 | uci set network.@amneziawg_awg0[0].public_key=$AWG_PUBLIC_KEY 306 | uci set network.@amneziawg_awg0[0].preshared_key=$AWG_PRESHARED_KEY 307 | uci set network.@amneziawg_awg0[0].route_allowed_ips='0' 308 | uci set network.@amneziawg_awg0[0].persistent_keepalive='25' 309 | uci set network.@amneziawg_awg0[0].endpoint_host=$AWG_ENDPOINT 310 | uci set network.@amneziawg_awg0[0].allowed_ips='0.0.0.0/0' 311 | uci set network.@amneziawg_awg0[0].endpoint_port=$AWG_ENDPOINT_PORT 312 | uci commit 313 | fi 314 | 315 | } 316 | 317 | dnsmasqfull() { 318 | if opkg list-installed | grep -q dnsmasq-full; then 319 | printf "\033[32;1mdnsmasq-full already installed\033[0m\n" 320 | else 321 | printf "\033[32;1mInstalled dnsmasq-full\033[0m\n" 322 | cd /tmp/ && opkg download dnsmasq-full 323 | opkg remove dnsmasq && opkg install dnsmasq-full --cache /tmp/ 324 | 325 | [ -f /etc/config/dhcp-opkg ] && cp /etc/config/dhcp /etc/config/dhcp-old && mv /etc/config/dhcp-opkg /etc/config/dhcp 326 | fi 327 | } 328 | 329 | dnsmasqconfdir() { 330 | if [ $VERSION_ID -ge 24 ]; then 331 | if uci get dhcp.@dnsmasq[0].confdir | grep -q /tmp/dnsmasq.d; then 332 | printf "\033[32;1mconfdir already set\033[0m\n" 333 | else 334 | printf "\033[32;1mSetting confdir\033[0m\n" 335 | uci set dhcp.@dnsmasq[0].confdir='/tmp/dnsmasq.d' 336 | uci commit dhcp 337 | fi 338 | fi 339 | } 340 | 341 | remove_forwarding() { 342 | if [ ! -z "$forward_id" ]; then 343 | while uci -q delete firewall.@forwarding[$forward_id]; do :; done 344 | fi 345 | } 346 | 347 | add_zone() { 348 | if [ "$TUNNEL" == 0 ]; then 349 | printf "\033[32;1mZone setting skipped\033[0m\n" 350 | elif uci show firewall | grep -q "@zone.*name='$TUNNEL'"; then 351 | printf "\033[32;1mZone already exist\033[0m\n" 352 | else 353 | printf "\033[32;1mCreate zone\033[0m\n" 354 | 355 | # Delete exists zone 356 | zone_tun_id=$(uci show firewall | grep -E '@zone.*tun0' | awk -F '[][{}]' '{print $2}' | head -n 1) 357 | if [ "$zone_tun_id" == 0 ] || [ "$zone_tun_id" == 1 ]; then 358 | 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" 359 | exit 1 360 | fi 361 | if [ ! -z "$zone_tun_id" ]; then 362 | while uci -q delete firewall.@zone[$zone_tun_id]; do :; done 363 | fi 364 | 365 | zone_wg_id=$(uci show firewall | grep -E '@zone.*wg0' | awk -F '[][{}]' '{print $2}' | head -n 1) 366 | if [ "$zone_wg_id" == 0 ] || [ "$zone_wg_id" == 1 ]; then 367 | 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" 368 | exit 1 369 | fi 370 | if [ ! -z "$zone_wg_id" ]; then 371 | while uci -q delete firewall.@zone[$zone_wg_id]; do :; done 372 | fi 373 | 374 | zone_awg_id=$(uci show firewall | grep -E '@zone.*awg0' | awk -F '[][{}]' '{print $2}' | head -n 1) 375 | if [ "$zone_awg_id" == 0 ] || [ "$zone_awg_id" == 1 ]; then 376 | 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" 377 | exit 1 378 | fi 379 | if [ ! -z "$zone_awg_id" ]; then 380 | while uci -q delete firewall.@zone[$zone_awg_id]; do :; done 381 | fi 382 | 383 | uci add firewall zone 384 | uci set firewall.@zone[-1].name="$TUNNEL" 385 | if [ "$TUNNEL" == wg ]; then 386 | uci set firewall.@zone[-1].network='wg0' 387 | elif [ "$TUNNEL" == awg ]; then 388 | uci set firewall.@zone[-1].network='awg0' 389 | elif [ "$TUNNEL" == singbox ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then 390 | uci set firewall.@zone[-1].device='tun0' 391 | fi 392 | if [ "$TUNNEL" == wg ] || [ "$TUNNEL" == awg ] || [ "$TUNNEL" == ovpn ] || [ "$TUNNEL" == tun2socks ]; then 393 | uci set firewall.@zone[-1].forward='REJECT' 394 | uci set firewall.@zone[-1].output='ACCEPT' 395 | uci set firewall.@zone[-1].input='REJECT' 396 | elif [ "$TUNNEL" == singbox ]; then 397 | uci set firewall.@zone[-1].forward='ACCEPT' 398 | uci set firewall.@zone[-1].output='ACCEPT' 399 | uci set firewall.@zone[-1].input='ACCEPT' 400 | fi 401 | uci set firewall.@zone[-1].masq='1' 402 | uci set firewall.@zone[-1].mtu_fix='1' 403 | uci set firewall.@zone[-1].family='ipv4' 404 | uci commit firewall 405 | fi 406 | 407 | if [ "$TUNNEL" == 0 ]; then 408 | printf "\033[32;1mForwarding setting skipped\033[0m\n" 409 | elif uci show firewall | grep -q "@forwarding.*name='$TUNNEL-lan'"; then 410 | printf "\033[32;1mForwarding already configured\033[0m\n" 411 | else 412 | printf "\033[32;1mConfigured forwarding\033[0m\n" 413 | # Delete exists forwarding 414 | if [[ $TUNNEL != "wg" ]]; then 415 | forward_id=$(uci show firewall | grep -E "@forwarding.*dest='wg'" | awk -F '[][{}]' '{print $2}' | head -n 1) 416 | remove_forwarding 417 | fi 418 | 419 | if [[ $TUNNEL != "awg" ]]; then 420 | forward_id=$(uci show firewall | grep -E "@forwarding.*dest='awg'" | awk -F '[][{}]' '{print $2}' | head -n 1) 421 | remove_forwarding 422 | fi 423 | 424 | if [[ $TUNNEL != "ovpn" ]]; then 425 | forward_id=$(uci show firewall | grep -E "@forwarding.*dest='ovpn'" | awk -F '[][{}]' '{print $2}' | head -n 1) 426 | remove_forwarding 427 | fi 428 | 429 | if [[ $TUNNEL != "singbox" ]]; then 430 | forward_id=$(uci show firewall | grep -E "@forwarding.*dest='singbox'" | awk -F '[][{}]' '{print $2}' | head -n 1) 431 | remove_forwarding 432 | fi 433 | 434 | if [[ $TUNNEL != "tun2socks" ]]; then 435 | forward_id=$(uci show firewall | grep -E "@forwarding.*dest='tun2socks'" | awk -F '[][{}]' '{print $2}' | head -n 1) 436 | remove_forwarding 437 | fi 438 | 439 | uci add firewall forwarding 440 | uci set firewall.@forwarding[-1]=forwarding 441 | uci set firewall.@forwarding[-1].name="$TUNNEL-lan" 442 | uci set firewall.@forwarding[-1].dest="$TUNNEL" 443 | uci set firewall.@forwarding[-1].src='lan' 444 | uci set firewall.@forwarding[-1].family='ipv4' 445 | uci commit firewall 446 | fi 447 | } 448 | 449 | show_manual() { 450 | if [ "$TUNNEL" == tun2socks ]; then 451 | printf "\033[42;1mZone for tun2socks cofigured. But you need to set up the tunnel yourself.\033[0m\n" 452 | echo "Use this manual: https://cli.co/VNZISEM" 453 | elif [ "$TUNNEL" == ovpn ]; then 454 | printf "\033[42;1mZone for OpenVPN cofigured. But you need to set up the tunnel yourself.\033[0m\n" 455 | echo "Use this manual: https://itdog.info/nastrojka-klienta-openvpn-na-openwrt/" 456 | fi 457 | } 458 | 459 | add_set() { 460 | if uci show firewall | grep -q "@ipset.*name='vpn_domains'"; then 461 | printf "\033[32;1mSet already exist\033[0m\n" 462 | else 463 | printf "\033[32;1mCreate set\033[0m\n" 464 | uci add firewall ipset 465 | uci set firewall.@ipset[-1].name='vpn_domains' 466 | uci set firewall.@ipset[-1].match='dst_net' 467 | uci commit 468 | fi 469 | if uci show firewall | grep -q "@rule.*name='mark_domains'"; then 470 | printf "\033[32;1mRule for set already exist\033[0m\n" 471 | else 472 | printf "\033[32;1mCreate rule set\033[0m\n" 473 | uci add firewall rule 474 | uci set firewall.@rule[-1]=rule 475 | uci set firewall.@rule[-1].name='mark_domains' 476 | uci set firewall.@rule[-1].src='lan' 477 | uci set firewall.@rule[-1].dest='*' 478 | uci set firewall.@rule[-1].proto='all' 479 | uci set firewall.@rule[-1].ipset='vpn_domains' 480 | uci set firewall.@rule[-1].set_mark='0x1' 481 | uci set firewall.@rule[-1].target='MARK' 482 | uci set firewall.@rule[-1].family='ipv4' 483 | uci commit 484 | fi 485 | } 486 | 487 | add_dns_resolver() { 488 | echo "Configure DNSCrypt2 or Stubby? It does matter if your ISP is spoofing DNS requests" 489 | DISK=$(df -m / | awk 'NR==2{ print $2 }') 490 | if [[ "$DISK" -lt 32 ]]; then 491 | printf "\033[31;1mYour router a disk have less than 32MB. It is not recommended to install DNSCrypt, it takes 10MB\033[0m\n" 492 | fi 493 | echo "Select:" 494 | echo "1) No [Default]" 495 | echo "2) DNSCrypt2 (10.7M)" 496 | echo "3) Stubby (36K)" 497 | 498 | while true; do 499 | read -r -p '' DNS_RESOLVER 500 | case $DNS_RESOLVER in 501 | 502 | 1) 503 | echo "Skiped" 504 | break 505 | ;; 506 | 507 | 2) 508 | DNS_RESOLVER=DNSCRYPT 509 | break 510 | ;; 511 | 512 | 3) 513 | DNS_RESOLVER=STUBBY 514 | break 515 | ;; 516 | 517 | *) 518 | echo "Choose from the following options" 519 | ;; 520 | esac 521 | done 522 | 523 | if [ "$DNS_RESOLVER" == 'DNSCRYPT' ]; then 524 | if opkg list-installed | grep -q dnscrypt-proxy2; then 525 | printf "\033[32;1mDNSCrypt2 already installed\033[0m\n" 526 | else 527 | printf "\033[32;1mInstalled dnscrypt-proxy2\033[0m\n" 528 | opkg install dnscrypt-proxy2 529 | if grep -q "# server_names" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml; then 530 | sed -i "s/^# server_names =.*/server_names = [\'google\', \'cloudflare\', \'scaleway-fr\', \'yandex\']/g" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml 531 | fi 532 | 533 | printf "\033[32;1mDNSCrypt restart\033[0m\n" 534 | service dnscrypt-proxy restart 535 | printf "\033[32;1mDNSCrypt needs to load the relays list. Please wait\033[0m\n" 536 | sleep 30 537 | 538 | if [ -f /etc/dnscrypt-proxy2/relays.md ]; then 539 | uci set dhcp.@dnsmasq[0].noresolv="1" 540 | uci -q delete dhcp.@dnsmasq[0].server 541 | uci add_list dhcp.@dnsmasq[0].server="127.0.0.53#53" 542 | uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/' 543 | uci commit dhcp 544 | 545 | printf "\033[32;1mDnsmasq restart\033[0m\n" 546 | 547 | /etc/init.d/dnsmasq restart 548 | else 549 | printf "\033[31;1mDNSCrypt not download list on /etc/dnscrypt-proxy2. Repeat install DNSCrypt by script.\033[0m\n" 550 | fi 551 | fi 552 | 553 | fi 554 | 555 | if [ "$DNS_RESOLVER" == 'STUBBY' ]; then 556 | printf "\033[32;1mConfigure Stubby\033[0m\n" 557 | 558 | if opkg list-installed | grep -q stubby; then 559 | printf "\033[32;1mStubby already installed\033[0m\n" 560 | else 561 | printf "\033[32;1mInstalled stubby\033[0m\n" 562 | opkg install stubby 563 | 564 | printf "\033[32;1mConfigure Dnsmasq for Stubby\033[0m\n" 565 | uci set dhcp.@dnsmasq[0].noresolv="1" 566 | uci -q delete dhcp.@dnsmasq[0].server 567 | uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#5453" 568 | uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/' 569 | uci commit dhcp 570 | 571 | printf "\033[32;1mDnsmasq restart\033[0m\n" 572 | 573 | /etc/init.d/dnsmasq restart 574 | fi 575 | fi 576 | } 577 | 578 | add_packages() { 579 | for package in curl nano; do 580 | if opkg list-installed | grep -q "^$package "; then 581 | printf "\033[32;1m$package already installed\033[0m\n" 582 | else 583 | printf "\033[32;1mInstalling $package...\033[0m\n" 584 | opkg install "$package" 585 | 586 | if "$package" --version >/dev/null 2>&1; then 587 | printf "\033[32;1m$package was successfully installed and available\033[0m\n" 588 | else 589 | printf "\033[31;1mError: failed to install $package\033[0m\n" 590 | exit 1 591 | fi 592 | fi 593 | done 594 | } 595 | 596 | add_getdomains() { 597 | echo "Choose you country" 598 | echo "Select:" 599 | echo "1) Russia inside. You are inside Russia" 600 | echo "2) Russia outside. You are outside of Russia, but you need access to Russian resources" 601 | echo "3) Ukraine. uablacklist.net list" 602 | echo "4) Skip script creation" 603 | 604 | while true; do 605 | read -r -p '' COUNTRY 606 | case $COUNTRY in 607 | 608 | 1) 609 | COUNTRY=russia_inside 610 | break 611 | ;; 612 | 613 | 2) 614 | COUNTRY=russia_outside 615 | break 616 | ;; 617 | 618 | 3) 619 | COUNTRY=ukraine 620 | break 621 | ;; 622 | 623 | 4) 624 | echo "Skiped" 625 | COUNTRY=0 626 | break 627 | ;; 628 | 629 | *) 630 | echo "Choose from the following options" 631 | ;; 632 | esac 633 | done 634 | 635 | if [ "$COUNTRY" == 'russia_inside' ]; then 636 | EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst 637 | elif [ "$COUNTRY" == 'russia_outside' ]; then 638 | EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst 639 | elif [ "$COUNTRY" == 'ukraine' ]; then 640 | EOF_DOMAINS=DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst 641 | fi 642 | 643 | if [ "$COUNTRY" != '0' ]; then 644 | printf "\033[32;1mCreate script /etc/init.d/getdomains\033[0m\n" 645 | 646 | cat << EOF > /etc/init.d/getdomains 647 | #!/bin/sh /etc/rc.common 648 | 649 | START=99 650 | 651 | start () { 652 | $EOF_DOMAINS 653 | EOF 654 | cat << 'EOF' >> /etc/init.d/getdomains 655 | count=0 656 | while true; do 657 | if curl -m 3 github.com; then 658 | curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst 659 | break 660 | else 661 | echo "GitHub is not available. Check the internet availability [$count]" 662 | count=$((count+1)) 663 | fi 664 | done 665 | 666 | if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q "syntax check OK"; then 667 | /etc/init.d/dnsmasq restart 668 | fi 669 | } 670 | EOF 671 | 672 | chmod +x /etc/init.d/getdomains 673 | /etc/init.d/getdomains enable 674 | 675 | if crontab -l | grep -q /etc/init.d/getdomains; then 676 | printf "\033[32;1mCrontab already configured\033[0m\n" 677 | 678 | else 679 | crontab -l | { cat; echo "0 */8 * * * /etc/init.d/getdomains start"; } | crontab - 680 | printf "\033[32;1mIgnore this error. This is normal for a new installation\033[0m\n" 681 | /etc/init.d/cron restart 682 | fi 683 | 684 | printf "\033[32;1mStart script\033[0m\n" 685 | 686 | /etc/init.d/getdomains start 687 | fi 688 | } 689 | 690 | add_internal_wg() { 691 | PROTOCOL_NAME=$1 692 | printf "\033[32;1mConfigure ${PROTOCOL_NAME}\033[0m\n" 693 | if [ "$PROTOCOL_NAME" = 'Wireguard' ]; then 694 | INTERFACE_NAME="wg1" 695 | CONFIG_NAME="wireguard_wg1" 696 | PROTO="wireguard" 697 | ZONE_NAME="wg_internal" 698 | 699 | if opkg list-installed | grep -q wireguard-tools; then 700 | echo "Wireguard already installed" 701 | else 702 | echo "Installed wg..." 703 | opkg install wireguard-tools 704 | fi 705 | fi 706 | 707 | if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then 708 | INTERFACE_NAME="awg1" 709 | CONFIG_NAME="amneziawg_awg1" 710 | PROTO="amneziawg" 711 | ZONE_NAME="awg_internal" 712 | 713 | install_awg_packages 714 | fi 715 | 716 | read -r -p "Enter the private key (from [Interface]):"$'\n' WG_PRIVATE_KEY_INT 717 | 718 | while true; do 719 | read -r -p "Enter internal IP address with subnet, example 192.168.100.5/24 (from [Interface]):"$'\n' WG_IP 720 | if echo "$WG_IP" | egrep -oq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$'; then 721 | break 722 | else 723 | echo "This IP is not valid. Please repeat" 724 | fi 725 | done 726 | 727 | read -r -p "Enter the public key (from [Peer]):"$'\n' WG_PUBLIC_KEY_INT 728 | read -r -p "If use PresharedKey, Enter this (from [Peer]). If your don't use leave blank:"$'\n' WG_PRESHARED_KEY_INT 729 | read -r -p "Enter Endpoint host without port (Domain or IP) (from [Peer]):"$'\n' WG_ENDPOINT_INT 730 | 731 | read -r -p "Enter Endpoint host port (from [Peer]) [51820]:"$'\n' WG_ENDPOINT_PORT_INT 732 | WG_ENDPOINT_PORT_INT=${WG_ENDPOINT_PORT_INT:-51820} 733 | if [ "$WG_ENDPOINT_PORT_INT" = '51820' ]; then 734 | echo $WG_ENDPOINT_PORT_INT 735 | fi 736 | 737 | if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then 738 | read -r -p "Enter Jc value (from [Interface]):"$'\n' AWG_JC 739 | read -r -p "Enter Jmin value (from [Interface]):"$'\n' AWG_JMIN 740 | read -r -p "Enter Jmax value (from [Interface]):"$'\n' AWG_JMAX 741 | read -r -p "Enter S1 value (from [Interface]):"$'\n' AWG_S1 742 | read -r -p "Enter S2 value (from [Interface]):"$'\n' AWG_S2 743 | read -r -p "Enter H1 value (from [Interface]):"$'\n' AWG_H1 744 | read -r -p "Enter H2 value (from [Interface]):"$'\n' AWG_H2 745 | read -r -p "Enter H3 value (from [Interface]):"$'\n' AWG_H3 746 | read -r -p "Enter H4 value (from [Interface]):"$'\n' AWG_H4 747 | fi 748 | 749 | uci set network.${INTERFACE_NAME}=interface 750 | uci set network.${INTERFACE_NAME}.proto=$PROTO 751 | uci set network.${INTERFACE_NAME}.private_key=$WG_PRIVATE_KEY_INT 752 | uci set network.${INTERFACE_NAME}.listen_port='51821' 753 | uci set network.${INTERFACE_NAME}.addresses=$WG_IP 754 | 755 | if [ "$PROTOCOL_NAME" = 'AmneziaWG' ]; then 756 | uci set network.${INTERFACE_NAME}.awg_jc=$AWG_JC 757 | uci set network.${INTERFACE_NAME}.awg_jmin=$AWG_JMIN 758 | uci set network.${INTERFACE_NAME}.awg_jmax=$AWG_JMAX 759 | uci set network.${INTERFACE_NAME}.awg_s1=$AWG_S1 760 | uci set network.${INTERFACE_NAME}.awg_s2=$AWG_S2 761 | uci set network.${INTERFACE_NAME}.awg_h1=$AWG_H1 762 | uci set network.${INTERFACE_NAME}.awg_h2=$AWG_H2 763 | uci set network.${INTERFACE_NAME}.awg_h3=$AWG_H3 764 | uci set network.${INTERFACE_NAME}.awg_h4=$AWG_H4 765 | fi 766 | 767 | if ! uci show network | grep -q ${CONFIG_NAME}; then 768 | uci add network ${CONFIG_NAME} 769 | fi 770 | 771 | uci set network.@${CONFIG_NAME}[0]=$CONFIG_NAME 772 | uci set network.@${CONFIG_NAME}[0].name="${INTERFACE_NAME}_client" 773 | uci set network.@${CONFIG_NAME}[0].public_key=$WG_PUBLIC_KEY_INT 774 | uci set network.@${CONFIG_NAME}[0].preshared_key=$WG_PRESHARED_KEY_INT 775 | uci set network.@${CONFIG_NAME}[0].route_allowed_ips='0' 776 | uci set network.@${CONFIG_NAME}[0].persistent_keepalive='25' 777 | uci set network.@${CONFIG_NAME}[0].endpoint_host=$WG_ENDPOINT_INT 778 | uci set network.@${CONFIG_NAME}[0].allowed_ips='0.0.0.0/0' 779 | uci set network.@${CONFIG_NAME}[0].endpoint_port=$WG_ENDPOINT_PORT_INT 780 | uci commit network 781 | 782 | grep -q "110 vpninternal" /etc/iproute2/rt_tables || echo '110 vpninternal' >> /etc/iproute2/rt_tables 783 | 784 | if ! uci show network | grep -q mark0x2; then 785 | printf "\033[32;1mConfigure mark rule\033[0m\n" 786 | uci add network rule 787 | uci set network.@rule[-1].name='mark0x2' 788 | uci set network.@rule[-1].mark='0x2' 789 | uci set network.@rule[-1].priority='110' 790 | uci set network.@rule[-1].lookup='vpninternal' 791 | uci commit 792 | fi 793 | 794 | if ! uci show network | grep -q vpn_route_internal; then 795 | printf "\033[32;1mAdd route\033[0m\n" 796 | uci set network.vpn_route_internal=route 797 | uci set network.vpn_route_internal.name='vpninternal' 798 | uci set network.vpn_route_internal.interface=$INTERFACE_NAME 799 | uci set network.vpn_route_internal.table='vpninternal' 800 | uci set network.vpn_route_internal.target='0.0.0.0/0' 801 | uci commit network 802 | fi 803 | 804 | if ! uci show firewall | grep -q "@zone.*name='${ZONE_NAME}'"; then 805 | printf "\033[32;1mZone Create\033[0m\n" 806 | uci add firewall zone 807 | uci set firewall.@zone[-1].name=$ZONE_NAME 808 | uci set firewall.@zone[-1].network=$INTERFACE_NAME 809 | uci set firewall.@zone[-1].forward='REJECT' 810 | uci set firewall.@zone[-1].output='ACCEPT' 811 | uci set firewall.@zone[-1].input='REJECT' 812 | uci set firewall.@zone[-1].masq='1' 813 | uci set firewall.@zone[-1].mtu_fix='1' 814 | uci set firewall.@zone[-1].family='ipv4' 815 | uci commit firewall 816 | fi 817 | 818 | if ! uci show firewall | grep -q "@forwarding.*name='${ZONE_NAME}'"; then 819 | printf "\033[32;1mConfigured forwarding\033[0m\n" 820 | uci add firewall forwarding 821 | uci set firewall.@forwarding[-1]=forwarding 822 | uci set firewall.@forwarding[-1].name="${ZONE_NAME}-lan" 823 | uci set firewall.@forwarding[-1].dest=${ZONE_NAME} 824 | uci set firewall.@forwarding[-1].src='lan' 825 | uci set firewall.@forwarding[-1].family='ipv4' 826 | uci commit firewall 827 | fi 828 | 829 | if uci show firewall | grep -q "@ipset.*name='vpn_domains_internal'"; then 830 | printf "\033[32;1mSet already exist\033[0m\n" 831 | else 832 | printf "\033[32;1mCreate set\033[0m\n" 833 | uci add firewall ipset 834 | uci set firewall.@ipset[-1].name='vpn_domains_internal' 835 | uci set firewall.@ipset[-1].match='dst_net' 836 | uci commit firewall 837 | fi 838 | 839 | if uci show firewall | grep -q "@rule.*name='mark_domains_intenal'"; then 840 | printf "\033[32;1mRule for set already exist\033[0m\n" 841 | else 842 | printf "\033[32;1mCreate rule set\033[0m\n" 843 | uci add firewall rule 844 | uci set firewall.@rule[-1]=rule 845 | uci set firewall.@rule[-1].name='mark_domains_intenal' 846 | uci set firewall.@rule[-1].src='lan' 847 | uci set firewall.@rule[-1].dest='*' 848 | uci set firewall.@rule[-1].proto='all' 849 | uci set firewall.@rule[-1].ipset='vpn_domains_internal' 850 | uci set firewall.@rule[-1].set_mark='0x2' 851 | uci set firewall.@rule[-1].target='MARK' 852 | uci set firewall.@rule[-1].family='ipv4' 853 | uci commit firewall 854 | fi 855 | 856 | if uci show dhcp | grep -q "@ipset.*name='vpn_domains_internal'"; then 857 | printf "\033[32;1mDomain on vpn_domains_internal already exist\033[0m\n" 858 | else 859 | printf "\033[32;1mCreate domain for vpn_domains_internal\033[0m\n" 860 | uci add dhcp ipset 861 | uci add_list dhcp.@ipset[-1].name='vpn_domains_internal' 862 | uci add_list dhcp.@ipset[-1].domain='youtube.com' 863 | uci add_list dhcp.@ipset[-1].domain='googlevideo.com' 864 | uci add_list dhcp.@ipset[-1].domain='youtubekids.com' 865 | uci add_list dhcp.@ipset[-1].domain='googleapis.com' 866 | uci add_list dhcp.@ipset[-1].domain='ytimg.com' 867 | uci add_list dhcp.@ipset[-1].domain='ggpht.com' 868 | uci commit dhcp 869 | fi 870 | 871 | 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" 872 | 873 | service dnsmasq restart 874 | service network restart 875 | 876 | exit 0 877 | } 878 | 879 | install_awg_packages() { 880 | # Получение pkgarch с наибольшим приоритетом 881 | PKGARCH=$(opkg print-architecture | awk 'BEGIN {max=0} {if ($3 > max) {max = $3; arch = $2}} END {print arch}') 882 | 883 | TARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 1) 884 | SUBTARGET=$(ubus call system board | jsonfilter -e '@.release.target' | cut -d '/' -f 2) 885 | VERSION=$(ubus call system board | jsonfilter -e '@.release.version') 886 | PKGPOSTFIX="_v${VERSION}_${PKGARCH}_${TARGET}_${SUBTARGET}.ipk" 887 | BASE_URL="https://github.com/Slava-Shchipunov/awg-openwrt/releases/download/" 888 | 889 | AWG_DIR="/tmp/amneziawg" 890 | mkdir -p "$AWG_DIR" 891 | 892 | if opkg list-installed | grep -q amneziawg-tools; then 893 | echo "amneziawg-tools already installed" 894 | else 895 | AMNEZIAWG_TOOLS_FILENAME="amneziawg-tools${PKGPOSTFIX}" 896 | DOWNLOAD_URL="${BASE_URL}v${VERSION}/${AMNEZIAWG_TOOLS_FILENAME}" 897 | curl -L -o "$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME" "$DOWNLOAD_URL" 898 | 899 | if [ $? -eq 0 ]; then 900 | echo "amneziawg-tools file downloaded successfully" 901 | else 902 | echo "Error downloading amneziawg-tools. Please, install amneziawg-tools manually and run the script again" 903 | exit 1 904 | fi 905 | 906 | opkg install "$AWG_DIR/$AMNEZIAWG_TOOLS_FILENAME" 907 | 908 | if [ $? -eq 0 ]; then 909 | echo "amneziawg-tools file downloaded successfully" 910 | else 911 | echo "Error installing amneziawg-tools. Please, install amneziawg-tools manually and run the script again" 912 | exit 1 913 | fi 914 | fi 915 | 916 | if opkg list-installed | grep -q kmod-amneziawg; then 917 | echo "kmod-amneziawg already installed" 918 | else 919 | KMOD_AMNEZIAWG_FILENAME="kmod-amneziawg${PKGPOSTFIX}" 920 | DOWNLOAD_URL="${BASE_URL}v${VERSION}/${KMOD_AMNEZIAWG_FILENAME}" 921 | curl -L -o "$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME" "$DOWNLOAD_URL" 922 | 923 | if [ $? -eq 0 ]; then 924 | echo "kmod-amneziawg file downloaded successfully" 925 | else 926 | echo "Error downloading kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again" 927 | exit 1 928 | fi 929 | 930 | opkg install "$AWG_DIR/$KMOD_AMNEZIAWG_FILENAME" 931 | 932 | if [ $? -eq 0 ]; then 933 | echo "kmod-amneziawg file downloaded successfully" 934 | else 935 | echo "Error installing kmod-amneziawg. Please, install kmod-amneziawg manually and run the script again" 936 | exit 1 937 | fi 938 | fi 939 | 940 | if opkg list-installed | grep -q luci-app-amneziawg; then 941 | echo "luci-app-amneziawg already installed" 942 | else 943 | LUCI_APP_AMNEZIAWG_FILENAME="luci-app-amneziawg${PKGPOSTFIX}" 944 | DOWNLOAD_URL="${BASE_URL}v${VERSION}/${LUCI_APP_AMNEZIAWG_FILENAME}" 945 | curl -L -o "$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME" "$DOWNLOAD_URL" 946 | 947 | if [ $? -eq 0 ]; then 948 | echo "luci-app-amneziawg file downloaded successfully" 949 | else 950 | echo "Error downloading luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again" 951 | exit 1 952 | fi 953 | 954 | opkg install "$AWG_DIR/$LUCI_APP_AMNEZIAWG_FILENAME" 955 | 956 | if [ $? -eq 0 ]; then 957 | echo "luci-app-amneziawg file downloaded successfully" 958 | else 959 | echo "Error installing luci-app-amneziawg. Please, install luci-app-amneziawg manually and run the script again" 960 | exit 1 961 | fi 962 | fi 963 | 964 | rm -rf "$AWG_DIR" 965 | } 966 | 967 | # System Details 968 | MODEL=$(cat /tmp/sysinfo/model) 969 | source /etc/os-release 970 | printf "\033[34;1mModel: $MODEL\033[0m\n" 971 | printf "\033[34;1mVersion: $OPENWRT_RELEASE\033[0m\n" 972 | 973 | VERSION_ID=$(echo $VERSION | awk -F. '{print $1}') 974 | 975 | if [ "$VERSION_ID" -ne 23 ] && [ "$VERSION_ID" -ne 24 ]; then 976 | printf "\033[31;1mScript only support OpenWrt 23.05 and 24.10\033[0m\n" 977 | echo "For OpenWrt 21.02 and 22.03 you can:" 978 | echo "1) Use ansible https://github.com/itdoginfo/domain-routing-openwrt" 979 | echo "2) Configure manually. Old manual: https://itdog.info/tochechnaya-marshrutizaciya-na-routere-s-openwrt-wireguard-i-dnscrypt/" 980 | exit 1 981 | fi 982 | 983 | printf "\033[31;1mAll actions performed here cannot be rolled back automatically.\033[0m\n" 984 | 985 | check_repo 986 | 987 | add_packages 988 | 989 | add_tunnel 990 | 991 | add_mark 992 | 993 | add_zone 994 | 995 | show_manual 996 | 997 | add_set 998 | 999 | dnsmasqfull 1000 | 1001 | dnsmasqconfdir 1002 | 1003 | add_dns_resolver 1004 | 1005 | add_getdomains 1006 | 1007 | printf "\033[32;1mRestart network\033[0m\n" 1008 | /etc/init.d/network restart 1009 | 1010 | printf "\033[32;1mDone\033[0m\n" 1011 | -------------------------------------------------------------------------------- /getdomains-uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/ash 2 | 3 | echo "Выпиливаем скрипты" 4 | /etc/init.d/getdomains disable 5 | rm -rf /etc/init.d/getdomains 6 | 7 | rm -f /etc/hotplug.d/iface/30-vpnroute /etc/hotplug.d/net/30-vpnroute 8 | 9 | echo "Выпиливаем из crontab" 10 | sed -i '/getdomains start/d' /etc/crontabs/root 11 | 12 | echo "Выпиливаем домены" 13 | rm -f /tmp/dnsmasq.d/domains.lst 14 | 15 | echo "Чистим firewall, раз раз 🍴" 16 | 17 | ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1) 18 | if [ ! -z "$ipset_id" ]; then 19 | while uci -q delete firewall.@ipset[$ipset_id]; do :; done 20 | fi 21 | 22 | rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains.' | awk -F '[][{}]' '{print $2}' | head -n 1) 23 | if [ ! -z "$rule_id" ]; then 24 | while uci -q delete firewall.@rule[$rule_id]; do :; done 25 | fi 26 | 27 | ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_domains_internal.' | awk -F '[][{}]' '{print $2}' | head -n 1) 28 | if [ ! -z "$ipset_id" ]; then 29 | while uci -q delete firewall.@ipset[$ipset_id]; do :; done 30 | fi 31 | 32 | rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_domains_intenal.' | awk -F '[][{}]' '{print $2}' | head -n 1) 33 | if [ ! -z "$rule_id" ]; then 34 | while uci -q delete firewall.@rule[$rule_id]; do :; done 35 | fi 36 | 37 | ipset_id=$(uci show firewall | grep -E '@ipset.*name=.vpn_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1) 38 | if [ ! -z "$ipset_id" ]; then 39 | while uci -q delete firewall.@ipset[$ipset_id]; do :; done 40 | fi 41 | 42 | rule_id=$(uci show firewall | grep -E '@rule.*name=.mark_subnet.' | awk -F '[][{}]' '{print $2}' | head -n 1) 43 | if [ ! -z "$rule_id" ]; then 44 | while uci -q delete firewall.@rule[$rule_id]; do :; done 45 | fi 46 | 47 | uci commit firewall 48 | /etc/init.d/firewall restart 49 | 50 | echo "Чистим сеть" 51 | sed -i '/99 vpn/d' /etc/iproute2/rt_tables 52 | 53 | rule_id=$(uci show network | grep -E '@rule.*name=.mark0x1.' | awk -F '[][{}]' '{print $2}' | head -n 1) 54 | if [ ! -z "$rule_id" ]; then 55 | while uci -q delete network.@rule[$rule_id]; do :; done 56 | fi 57 | 58 | rule_id=$(uci show network | grep -E '@rule.*name=.mark0x2.' | awk -F '[][{}]' '{print $2}' | head -n 1) 59 | if [ ! -z "$rule_id" ]; then 60 | while uci -q delete network.@rule[$rule_id]; do :; done 61 | fi 62 | 63 | while uci -q delete network.vpn_route_internal; do :; done 64 | 65 | uci commit network 66 | /etc/init.d/network restart 67 | 68 | echo "Проверяем Dnsmasq" 69 | if uci show dhcp | grep -q ipset; then 70 | echo "В dnsmasq (/etc/config/dhcp) заданы домены. Нужные из них сохраните, остальные удалите вместе с ipset" 71 | fi 72 | 73 | echo "Все туннели, прокси, зоны и forwarding к ним оставляем на месте, они вам не помешают и скорее пригодятся" 74 | echo "Dnscrypt, stubby тоже не трогаем" 75 | 76 | echo " ______ _____ _____ _____ ______ _ _ _____ _____" 77 | echo " | ____ | | |_____] | | | \ |____/ | | |_____]" 78 | echo " |_____| |_____| | |_____| |_____/ | \_ |_____| | " 79 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Restart sing-box 3 | service: 4 | name: sing-box 5 | state: restarted 6 | 7 | - name: Restart network 8 | service: 9 | name: network 10 | state: restarted 11 | 12 | - name: Restart firewall 13 | service: 14 | name: firewall 15 | state: restarted 16 | 17 | - name: Run getdomains script 18 | service: 19 | name: getdomains 20 | state: restarted 21 | 22 | - name: Restart dnscrypt-proxy 23 | service: 24 | name: dnscrypt-proxy 25 | state: restarted 26 | enabled: yes 27 | 28 | - name: Restart dnsmasq 29 | service: 30 | name: dnsmasq 31 | state: restarted -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | role_name: domain_routing_openwrt 4 | namespace: itdoginfo 5 | author: itdog 6 | description: Configuring domain routing on Openwrt router 7 | issue_tracker_url: https://github.com/itdoginfo/domain-routing-openwrt/issues 8 | license: GPL-3.0 9 | min_ansible_version: 2.10.7 10 | platforms: 11 | - name: OpenWrt 12 | galaxy_tags: 13 | - openwrt 14 | - dnsmasq 15 | - ipset 16 | - wireguard 17 | - sing-box 18 | - openvpn 19 | - bypass 20 | - routing 21 | dependencies: 22 | - role: gekmihesg.openwrt -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Dnsmasq version check 4 | 5 | - name: Get dnsmasq version 6 | shell: opkg list-installed | grep dnsmasq-full | awk '{print $3}' 7 | register: dnsmasqfull_version 8 | 9 | - name: Check confdir option 10 | shell: uci get dhcp.@dnsmasq[0].confdir 11 | register: dnsmasq_confdir 12 | ignore_errors: true 13 | 14 | - name: Get openwrt major release 15 | shell: cat /etc/openwrt_release | grep -Eo [0-9]{2}[.][0-9]{2}[.][0-9]* | cut -d '.' -f 1 | tail -n 1 16 | register: openwrt_major_release 17 | 18 | - name: debug 19 | debug: 20 | var: ansible_distribution_major_version 21 | 22 | # Packages installation 23 | 24 | - name: install wg 25 | opkg: 26 | name: "{{ item }}" 27 | state: present 28 | loop: 29 | - kmod-wireguard 30 | - wireguard-tools 31 | when: tunnel == "wg" 32 | 33 | - name: install openvpn 34 | opkg: 35 | name: "{{ item }}" 36 | state: present 37 | loop: 38 | - openvpn-openssl 39 | when: tunnel == "openvpn" 40 | 41 | - name: install singbox 42 | opkg: 43 | name: "{{ item }}" 44 | state: present 45 | loop: 46 | - sing-box 47 | when: tunnel == "singbox" and ansible_distribution_major_version >= "23" 48 | 49 | - name: install curl 50 | opkg: 51 | name: "{{ item }}" 52 | state: present 53 | loop: 54 | - curl 55 | 56 | - name: install nano 57 | opkg: 58 | name: "{{ item }}" 59 | state: present 60 | loop: 61 | - nano 62 | when: nano 63 | 64 | - name: install ipset 65 | opkg: 66 | name: ipset 67 | state: present 68 | when: ansible_distribution_major_version < "22" 69 | 70 | - name: install dnsmasq-full (23) 71 | 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 72 | when: ansible_distribution_major_version >= "23" and list_domains and not dnsmasqfull_version.stdout 73 | ignore_errors: true 74 | 75 | - name: set confdir for dnsmasq 76 | uci: 77 | command: set 78 | key: dhcp.@dnsmasq[0] 79 | value: 80 | confdir: "/tmp/dnsmasq.d" 81 | when: ansible_distribution_major_version >= 24 82 | notify: 83 | - Restart dnsmasq 84 | 85 | # Getdomains script configure 86 | 87 | - name: getdomains script copy 88 | template: 89 | src: "openwrt-getdomains.j2" 90 | dest: "/etc/init.d/getdomains" 91 | mode: a+x 92 | trim_blocks: false 93 | notify: 94 | - Run getdomains script 95 | 96 | - name: create simplink in rc.d 97 | file: 98 | src: "/etc/init.d/getdomains" 99 | dest: "/etc/rc.d/S99getdomains" 100 | state: link 101 | notify: 102 | - Run getdomains script 103 | 104 | - name: check string in crontab 105 | shell: grep "getdomains" /etc/crontabs/root 106 | register: check_cron 107 | ignore_errors: true 108 | 109 | - name: add script to cron 110 | lineinfile: 111 | path: /etc/crontabs/root 112 | create: yes 113 | line: "0 4 * * * /etc/init.d/getdomains start" 114 | when: check_cron.stdout == "" 115 | 116 | - name: enable and start crontab 117 | service: 118 | name: cron 119 | state: started 120 | enabled: yes 121 | 122 | # Configure route table 123 | 124 | - name: Route for vpn table 125 | template: 126 | src: "openwrt-30-vpnroute.j2" 127 | dest: "/etc/hotplug.d/iface/30-vpnroute" 128 | mode: 0644 129 | 130 | - name: Check string in rt_tables 131 | shell: grep "99 vpn" /etc/iproute2/rt_tables 132 | register: check_rt_tables 133 | ignore_errors: true 134 | 135 | - name: add route table 136 | lineinfile: 137 | path: /etc/iproute2/rt_tables 138 | line: "99 vpn" 139 | when: check_rt_tables.stdout == "" 140 | notify: 141 | - Restart network 142 | 143 | # Configure WG 144 | 145 | - name: add wg interface 146 | uci: 147 | command: add 148 | config: network 149 | type: interface 150 | name: wg0 151 | when: tunnel == "wg" 152 | 153 | - name: configure wg interface 154 | uci: 155 | command: set 156 | key: network.wg0 157 | value: 158 | proto: wireguard 159 | private_key: "{{ wg_private_key }}" 160 | listen_port: "{{ wg_listen_port }}" 161 | addresses: 162 | - "{{ wg_client_address }}" 163 | when: tunnel == "wg" 164 | notify: 165 | - Restart network 166 | 167 | - name: set wg client without wg_preshared_key 168 | uci: 169 | command: section 170 | config: network 171 | type: wireguard_wg0 172 | find_by: 173 | name: wg0_client 174 | value: 175 | public_key: "{{ wg_public_key }}" 176 | route_allowed_ips: 0 177 | persistent_keepalive: 25 178 | endpoint_host: "{{ wg_server_address }}" 179 | allowed_ips: 0.0.0.0/0 180 | endpoint_port: "{{ wg_client_port }}" 181 | when: wg_preshared_key is undefined and tunnel == "wg" 182 | notify: 183 | - Restart network 184 | 185 | - name: set wg client with wg_preshared_key 186 | uci: 187 | command: section 188 | config: network 189 | type: wireguard_wg0 190 | find_by: 191 | name: wg0_client 192 | value: 193 | public_key: "{{ wg_public_key }}" 194 | preshared_key: "{{ wg_preshared_key }}" 195 | route_allowed_ips: 0 196 | persistent_keepalive: 25 197 | endpoint_host: "{{ wg_server_address }}" 198 | allowed_ips: 0.0.0.0/0 199 | endpoint_port: "{{ wg_client_port }}" 200 | when: wg_preshared_key is defined and tunnel == "wg" 201 | 202 | - name: set WG firewall zone 203 | uci: 204 | command: section 205 | config: firewall 206 | type: zone 207 | find_by: 208 | name: wg 209 | value: 210 | forward: REJECT 211 | output: ACCEPT 212 | name: wg 213 | input: REJECT 214 | masq: 1 215 | mtu_fix: 1 216 | network: wg0 217 | family: ipv4 218 | when: tunnel == "wg" 219 | 220 | - name: add WG forwarding 221 | uci: 222 | command: section 223 | config: firewall 224 | type: forwarding 225 | find_by: 226 | name: wg-lan 227 | value: 228 | dest: wg 229 | src: lan 230 | family: ipv4 231 | when: tunnel == "wg" 232 | 233 | # Configure Sing-box 234 | 235 | - name: set sing-box firewall zone. Only >=22 236 | uci: 237 | command: section 238 | config: firewall 239 | type: zone 240 | find_by: 241 | name: tun 242 | value: 243 | forward: ACCEPT 244 | output: ACCEPT 245 | name: tun 246 | input: ACCEPT 247 | masq: 1 248 | mtu_fix: 1 249 | device: tun0 250 | family: ipv4 251 | when: tunnel == "singbox" 252 | failed_when: ansible_distribution_major_version < "22" 253 | notify: 254 | - Restart firewall 255 | 256 | - name: template for sing-box.json 257 | template: 258 | src: "sing-box-json.j2" 259 | dest: "/etc/sing-box/config.json" 260 | mode: 0644 261 | when: tunnel == "singbox" 262 | failed_when: ansible_distribution_major_version < "22" 263 | 264 | - name: template for config/sing-box 265 | template: 266 | src: "config-sing-box.j2" 267 | dest: "/etc/config/sing-box" 268 | mode: 0600 269 | when: tunnel == "singbox" 270 | failed_when: ansible_distribution_major_version < "22" 271 | 272 | # Configure OpenVPN, tun2socks 273 | 274 | - name: set {{ tunnel }} firewall zone 275 | uci: 276 | command: section 277 | config: firewall 278 | type: zone 279 | find_by: 280 | name: tun 281 | value: 282 | forward: REJECT 283 | output: ACCEPT 284 | name: tun 285 | input: REJECT 286 | masq: 1 287 | mtu_fix: 1 288 | device: tun0 289 | family: ipv4 290 | when: tunnel == "openvpn" or tunnel == "tun2socks" 291 | notify: 292 | - Restart firewall 293 | 294 | - name: add {{ tunnel }} forwarding 295 | uci: 296 | command: section 297 | config: firewall 298 | type: forwarding 299 | find_by: 300 | name: lan-tun 301 | value: 302 | dest: tun 303 | src: lan 304 | family: ipv4 305 | when: tunnel == "openvpn" or tunnel == "tun2socks" or tunnel == "singbox" 306 | notify: 307 | - Restart firewall 308 | 309 | # Configure network 310 | 311 | - name: set rule mark0x1 312 | uci: 313 | command: section 314 | config: network 315 | type: rule 316 | find_by: 317 | name: mark0x1 318 | value: 319 | mark: "0x1" 320 | priority: 100 321 | lookup: vpn 322 | 323 | - name: set disable dns for wan 324 | uci: 325 | command: set 326 | key: network.wan 327 | value: 328 | peerdns: 0 329 | when: ansible_distribution_major_version < "22" 330 | 331 | - name: uci commit firewall 332 | uci: 333 | command: commit 334 | config: firewall 335 | notify: 336 | - Restart firewall 337 | 338 | - name: uci commit network 339 | uci: 340 | command: commit 341 | config: network 342 | notify: 343 | - Restart network 344 | 345 | # Configure firewall 346 | 347 | - name: add ipset for subnet (<22) 348 | uci: 349 | command: section 350 | config: firewall 351 | type: ipset 352 | find_by: 353 | name: vpn_subnets 354 | value: 355 | match: dst_net 356 | storage: hash 357 | loadfile: /tmp/lst/subnet.lst 358 | when: ansible_distribution_major_version < "22" and list_subnet 359 | 360 | - name: add ipset for ip (<22) 361 | uci: 362 | command: section 363 | config: firewall 364 | type: ipset 365 | find_by: 366 | name: vpn_ip 367 | value: 368 | match: dst_net 369 | storage: hash 370 | loadfile: /tmp/lst/ip.lst 371 | hashsize: 9900000 372 | maxelem: 9900000 373 | when: ansible_distribution_major_version < "22" and list_ip 374 | 375 | - name: add ipset for community (<22) 376 | uci: 377 | command: section 378 | config: firewall 379 | type: ipset 380 | find_by: 381 | name: vpn_community 382 | value: 383 | match: dst_net 384 | storage: hash 385 | loadfile: /tmp/lst/community.lst 386 | hashsize: 9900000 387 | maxelem: 9900000 388 | when: ansible_distribution_major_version < "22" and list_community 389 | 390 | - name: add nfset for subnet (22) 391 | uci: 392 | command: section 393 | config: firewall 394 | type: ipset 395 | find_by: 396 | name: vpn_subnets 397 | value: 398 | match: dst_net 399 | loadfile: /tmp/lst/subnet.lst 400 | when: ansible_distribution_major_version >= "22" and list_subnet 401 | 402 | - name: add nfset for ip (22) 403 | uci: 404 | command: section 405 | config: firewall 406 | type: ipset 407 | find_by: 408 | name: vpn_ip 409 | value: 410 | match: dst_net 411 | loadfile: /tmp/lst/ip.lst 412 | when: ansible_distribution_major_version >= "22" and list_ip 413 | 414 | - name: add nfset for community (22) 415 | uci: 416 | command: section 417 | config: firewall 418 | type: ipset 419 | find_by: 420 | name: vpn_community 421 | value: 422 | match: dst_net 423 | loadfile: /tmp/lst/community.lst 424 | when: ansible_distribution_major_version >= "22" and list_community 425 | 426 | - name: add ipset for domains (<22). If failed, repeat playbook. If failed is repeated check dnsmasq-full. 427 | uci: 428 | command: section 429 | config: firewall 430 | type: ipset 431 | find_by: 432 | name: vpn_domains 433 | value: 434 | match: dst_net 435 | storage: hash 436 | when: ansible_distribution_major_version < "22" and list_domains 437 | 438 | - name: add nfset for domains (>=22). If failed, repeat playbook. If failed is repeated check dnsmasq-full. 439 | uci: 440 | command: section 441 | config: firewall 442 | type: ipset 443 | find_by: 444 | name: vpn_domains 445 | value: 446 | match: dst_net 447 | when: ansible_distribution_major_version >= "22" and list_domains 448 | 449 | - name: add mark rule vpn_subnet 450 | uci: 451 | command: section 452 | config: firewall 453 | type: rule 454 | find_by: 455 | name: mark_subnet 456 | value: 457 | src: lan 458 | dest: "*" 459 | proto: all 460 | ipset: vpn_subnets 461 | set_mark: "0x1" 462 | target: MARK 463 | family: ipv4 464 | when: list_subnet 465 | 466 | - name: add mark rule vpn_ip 467 | uci: 468 | command: section 469 | config: firewall 470 | type: rule 471 | find_by: 472 | name: mark_ip 473 | value: 474 | src: lan 475 | dest: "*" 476 | proto: all 477 | ipset: vpn_ip 478 | set_mark: "0x1" 479 | target: MARK 480 | family: ipv4 481 | when: list_ip 482 | 483 | - name: add mark rule vpn_community 484 | uci: 485 | command: section 486 | config: firewall 487 | type: rule 488 | find_by: 489 | name: mark_community 490 | value: 491 | src: lan 492 | dest: "*" 493 | proto: all 494 | ipset: vpn_community 495 | set_mark: "0x1" 496 | target: MARK 497 | family: ipv4 498 | when: list_community 499 | 500 | - name: add mark rule vpn_domains 501 | uci: 502 | command: section 503 | config: firewall 504 | type: rule 505 | find_by: 506 | name: mark_domains 507 | value: 508 | src: lan 509 | dest: "*" 510 | proto: all 511 | ipset: vpn_domains 512 | set_mark: "0x1" 513 | target: MARK 514 | family: ipv4 515 | when: (ansible_distribution_major_version < "22" and list_domains) or (ansible_distribution_major_version >= "22" and list_domains) 516 | 517 | - name: wg access route 518 | uci: 519 | command: section 520 | config: network 521 | type: route 522 | find_by: 523 | name: wg_access_route 524 | value: 525 | interface: wg0 526 | target: "{{ wg_access_network }}" 527 | when: wg_access 528 | 529 | - name: set WG firewall zone 530 | uci: 531 | command: section 532 | config: firewall 533 | type: zone 534 | find_by: 535 | name: wg 536 | value: 537 | input: ACCEPT 538 | when: wg_access 539 | 540 | # Remove unused rules and ipset 541 | - name: Remove ipset for ip 542 | uci: 543 | command: absent 544 | config: firewall 545 | type: ipset 546 | find_by: 547 | name: vpn_ip 548 | when: not list_ip 549 | 550 | - name: Remove rule for ip 551 | uci: 552 | command: absent 553 | config: firewall 554 | type: rule 555 | find_by: 556 | name: mark_ip 557 | when: not list_ip 558 | 559 | - name: Remove ipset for subnet 560 | uci: 561 | command: absent 562 | config: firewall 563 | type: ipset 564 | find_by: 565 | name: vpn_subnets 566 | when: not list_subnet 567 | 568 | - name: Remove rule for subnet 569 | uci: 570 | command: absent 571 | config: firewall 572 | type: rule 573 | find_by: 574 | name: mark_subnet 575 | when: not list_subnet 576 | 577 | - name: Remove ipset for community 578 | uci: 579 | command: absent 580 | config: firewall 581 | type: ipset 582 | find_by: 583 | name: vpn_community 584 | when: not list_community 585 | 586 | - name: Remove rule for community 587 | uci: 588 | command: absent 589 | config: firewall 590 | type: rule 591 | find_by: 592 | name: mark_community 593 | when: not list_community 594 | 595 | - name: Remove ipset for domains 596 | uci: 597 | command: absent 598 | config: firewall 599 | type: ipset 600 | find_by: 601 | name: vpn_domains 602 | when: not list_domains 603 | 604 | - name: Remove rule for domains 605 | uci: 606 | command: absent 607 | config: firewall 608 | type: rule 609 | find_by: 610 | name: mark_domains 611 | when: not list_domains 612 | 613 | # Configure DNS resolver 614 | 615 | - name: install dnscrypt-proxy2 616 | opkg: 617 | name: dnscrypt-proxy2 618 | state: present 619 | when: dns_encrypt == "dnscrypt" 620 | 621 | - name: check string in dnscrypt-proxy.toml 622 | shell: grep "# server_names" /etc/dnscrypt-proxy2/dnscrypt-proxy.toml 623 | register: check_server_names 624 | ignore_errors: true 625 | when: dns_encrypt == "dnscrypt" 626 | 627 | - name: dnscrypt2 enable exact servers 628 | lineinfile: 629 | path: /etc/dnscrypt-proxy2/dnscrypt-proxy.toml 630 | regexp: "# server_names =" 631 | line: "server_names = ['google', 'cloudflare', 'scaleway-fr', 'yandex']" 632 | when: dns_encrypt == "dnscrypt" and check_server_names.stdout 633 | notify: 634 | - Restart dnscrypt-proxy 635 | 636 | - name: edit dhcp config. add localhost server 637 | lineinfile: 638 | path: /etc/config/dhcp 639 | firstmatch: "true" 640 | insertafter: "option leasefile '/tmp/dhcp.leases'" 641 | line: "{{ item }}" 642 | with_items: 643 | - " list server '127.0.0.53#53'" 644 | - " option noresolv '1'" 645 | notify: 646 | - Restart dnsmasq 647 | when: dns_encrypt == "dnscrypt" 648 | 649 | - name: install stubby 650 | opkg: 651 | name: stubby 652 | state: present 653 | when: dns_encrypt == "stubby" 654 | 655 | - name: edit dhcp config. add localhost server 656 | lineinfile: 657 | path: /etc/config/dhcp 658 | firstmatch: "true" 659 | insertafter: "option leasefile '/tmp/dhcp.leases'" 660 | line: "{{ item }}" 661 | with_items: 662 | - " list server '127.0.0.1#5453'" 663 | - " option noresolv '1'" 664 | notify: 665 | - Restart dnsmasq 666 | when: dns_encrypt == "stubby" 667 | 668 | # Commit 669 | 670 | - name: uci commit firewall 671 | uci: 672 | command: commit 673 | config: firewall 674 | notify: 675 | - Restart firewall 676 | 677 | - name: uci commit dhcp 678 | uci: 679 | command: commit 680 | config: dhcp 681 | notify: 682 | - Restart dnsmasq 683 | 684 | - name: uci commit network 685 | uci: 686 | command: commit 687 | config: network 688 | notify: 689 | - Restart network -------------------------------------------------------------------------------- /templates/config-sing-box.j2: -------------------------------------------------------------------------------- 1 | config sing-box 'main' 2 | option enabled '1' 3 | option user 'root' 4 | option conffile '/etc/sing-box/config.json' 5 | option workdir '/usr/share/sing-box' 6 | -------------------------------------------------------------------------------- /templates/openwrt-30-vpnroute.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | {% if tunnel == "wg" %} 4 | ip route add table vpn default dev wg0 5 | {% elif (tunnel == "openvpn") or (tunnel == "singbox") or (tunnel == "tun2socks") %} 6 | sleep 10 7 | ip route add table vpn default dev tun0 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /templates/openwrt-getdomains.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=99 4 | 5 | start () { 6 | {% if ansible_distribution_major_version >= "22" and country == "russia-inside" %} 7 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst 8 | {% endif %} 9 | {% if ansible_distribution_major_version >= "22" and country == "russia-outside" %} 10 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst 11 | {% endif %} 12 | {% if ansible_distribution_major_version >= "22" and country == "ukraine" %} 13 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst 14 | {% endif %} 15 | {% if ansible_distribution_major_version < "22" and country == "russia-inside" %} 16 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-ipset.lst 17 | {% endif %} 18 | {% if ansible_distribution_major_version < "22" and country == "russia-outside" %} 19 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-ipset.lst 20 | {% endif %} 21 | {% if ansible_distribution_major_version < "22" and country == "ukraine" %} 22 | DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-ipset.lst 23 | {% endif %} 24 | count=0 25 | while true; do 26 | if curl -m 3 github.com; then 27 | curl -f $DOMAINS --output /tmp/dnsmasq.d/domains.lst 28 | break 29 | else 30 | echo "GitHub is not available. Check the internet availability [$count]" 31 | count=$((count+1)) 32 | fi 33 | done 34 | 35 | if dnsmasq --conf-file=/tmp/dnsmasq.d/domains.lst --test 2>&1 | grep -q "syntax check OK"; then 36 | /etc/init.d/dnsmasq restart 37 | fi 38 | 39 | {% if ansible_distribution_major_version >= "22" and (list_ip or list_community) %} 40 | echo "Flush sets" 41 | nft flush ruleset 42 | {% endif %} 43 | 44 | {% if list_subnet or list_ip or list_community %} 45 | dir=/tmp/lst 46 | mkdir -p $dir 47 | 48 | count=0 49 | while true; do 50 | if curl -m 3 https://antifilter.download/; then 51 | {% if list_subnet %} 52 | curl -f -z $dir/subnet.lst https://antifilter.download/list/subnet.lst --output $dir/subnet.lst 53 | {% endif %} 54 | {% if list_ip %} 55 | curl -f -z $dir/ip.lst https://antifilter.download/list/ip.lst --output $dir/ip.lst 56 | {% endif %} 57 | {% if list_community %} 58 | curl -f -z $dir/community.lst https://community.antifilter.download/list/community.lst --output $dir/community.lst 59 | {% endif %} 60 | break 61 | else 62 | echo "antifilter.download is not available. Check the internet availability [$count]" 63 | count=$((count+1)) 64 | fi 65 | done 66 | 67 | echo "Firewall restart" 68 | /etc/init.d/firewall restart 69 | {% endif %} 70 | } -------------------------------------------------------------------------------- /templates/sing-box-json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "level": "debug" 4 | }, 5 | "inbounds": [ 6 | { 7 | "type": "tun", 8 | "interface_name": "tun0", 9 | "domain_strategy": "ipv4_only", 10 | "address": ["172.16.250.1/30"], 11 | "auto_route": false, 12 | "strict_route": false, 13 | "sniff": true 14 | } 15 | ], 16 | "outbounds": [ 17 | { 18 | "type": "$TYPE", 19 | "server": "$HOST", 20 | "server_port": $PORT, 21 | "method": "$METHOD", 22 | "password": "$PASS" 23 | } 24 | ], 25 | "route": { 26 | "auto_detect_interface": true 27 | } 28 | } -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | [openwrt] 2 | 192.168.56.23 3 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: openwrt 3 | remote_user: root 4 | 5 | roles: 6 | - domain_routing_openwrt --------------------------------------------------------------------------------