#!/bin/sh ################################################################################################################### # █████╗ ███████╗██╗ ██╗███████╗██╗ ██╗██████╗ ████████╗ ███╗ ███╗███████╗██████╗ ██╗ ██╗███╗ ██╗# #██╔══██╗██╔════╝██║ ██║██╔════╝██║ ██║██╔══██╗╚══██╔══╝ ████╗ ████║██╔════╝██╔══██╗██║ ██║████╗ ██║# #███████║███████╗██║ ██║███████╗██║ █╗ ██║██████╔╝ ██║ █████╗ ██╔████╔██║█████╗ ██████╔╝██║ ██║██╔██╗ ██║# #██╔══██║╚════██║██║ ██║╚════██║██║███╗██║██╔══██╗ ██║ ╚════╝ ██║╚██╔╝██║██╔══╝ ██╔══██╗██║ ██║██║╚██╗██║# #██║ ██║███████║╚██████╔╝███████║╚███╔███╔╝██║ ██║ ██║ ██║ ╚═╝ ██║███████╗██║ ██║███████╗██║██║ ╚████║# #╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═══╝# #██████╗ ███╗ ██╗███████╗ ██████╗██████╗ ██╗ ██╗██████╗ ████████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗ ██╗# #██╔══██╗████╗ ██║██╔════╝██╔════╝██╔══██╗╚██╗ ██╔╝██╔══██╗╚══██╔══╝ ██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝# #██║ ██║██╔██╗ ██║███████╗██║ ██████╔╝ ╚████╔╝ ██████╔╝ ██║█████╗██████╔╝██████╔╝██║ ██║ ╚███╔╝ ╚████╔╝ # #██║ ██║██║╚██╗██║╚════██║██║ ██╔══██╗ ╚██╔╝ ██╔═══╝ ██║╚════╝██╔═══╝ ██╔══██╗██║ ██║ ██╔██╗ ╚██╔╝ # #██████╔╝██║ ╚████║███████║╚██████╗██║ ██║ ██║ ██║ ██║ ██║ ██║ ██║╚██████╔╝██╔╝ ██╗ ██║ # #╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ # #██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ███████╗██████╗ Original Author: # #██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ██╔════╝██╔══██╗ bigeyes0x0 # #██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ █████╗ ██████╔╝ Current Maintainer: # #██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ██╔══╝ ██╔══██╗ SomeWhereOverTheRainBow # #██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗███████╗██║ ██║ v2.5.3 # #╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ # ################################################################################################################### # shellcheck disable=SC2016 # shellcheck disable=SC2124 # shellcheck disable=SC3043 # shellcheck disable=SC3045 # shellcheck disable=SC3057 # shellcheck disable=SC3060 export LC_ALL=C export PATH="/sbin:/bin:/usr/sbin:/usr/bin:${PATH}" DI_VERSION="v2.5.3" export DI_VERSION readonly LATEST_URL="https://api.github.com/repos/jedisct1/dnscrypt-proxy/releases/latest" varcnt=0 until [ -n "${DNSCRYPT_VER}" ]; do [ -z "${DNSCRYPT_VER}" ] && DNSCRYPT_VER="$(curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -sL "${LATEST_URL}" | grep "tag_name" | head -1 | cut -d \" -f 4 &)" || true varcnt="$((varcnt + 1))" if [ "${varcnt}" -le 84 ]; then wait else printf "%s/n" "One or more critical variables could not be set in a timely mannor." "Please check your internet connection, or try again later." "The installer script will now exit." sleep 3s exit 1 fi done wait unset varcnt readonly DNSCRYPT_VER readonly BASE_DIR="/jffs" readonly TARG_DIR="${BASE_DIR}/dnscrypt" readonly CONF_FILE="${TARG_DIR}/.config" readonly TOML_FILE="${TARG_DIR}/dnscrypt-proxy.toml" readonly TOML_BAK="${TARG_DIR}/dnscrypt-proxy.toml.bak" readonly TOML_ERR="${TARG_DIR}/dnscrypt-proxy.toml.err" readonly TOML_ORI="${TARG_DIR}/example-dnscrypt-proxy.toml" SCRIPT_LOC="$(readlink -f "$0")" || true readonly SCRIPT_LOC BOLD="$(printf "\033[1m")" || true readonly BOLD NORM="$(printf "\033[0m")" || true readonly NORM INFO="$(printf "%s" "${BOLD} Info: ${NORM}")" || true readonly INFO ERROR="$(printf "%s" "${BOLD} *** Error: ${NORM}")" || true readonly ERROR WARNING="$(printf "%s" "${BOLD} * Warning: ${NORM}")" || true readonly WARNING INPUT="$(printf "%s" "${BOLD} => ${NORM}")" || true readonly INPUT _quote() { printf "%s\n" "$1" | sed 's/[]\/()$*.^|[]/\\&/g' } PTXT() { case "$1" in -n) shift while [ $# -gt 0 ]; do printf "%s" "$1" shift done ;; *) while [ $# -gt 0 ]; do printf "%s\n" "$1" shift done ;; esac } backup_restore() { if [ "$1" = "BACKUP" ] && [ -d "${TARG_DIR}" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ]; then if [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then PTXT "${INFO} There is an old backup detected." local USE_OLD if read_yesno "Do you want to continue?(this will remove the old backup)"; then USE_OLD="NO"; else USE_OLD="YES"; fi if [ "${USE_OLD}" = "YES" ]; then PTXT "${INFO} Leaving Old Backup." end_op_message 1 elif [ "${USE_OLD}" = "NO" ]; then PTXT "${INFO} Removing Old Backup." rm -rf "${BASE_DIR}/backup_dnscrypt.tar.gz" fi fi PTXT "${INFO} This operation will backup dnscrypt-proxy(<4MB)to jffs partition." \ "${INFO} Please wait a moment." tar -czvf "${BASE_DIR}/backup_dnscrypt.tar.gz" -C "${TARG_DIR}" ../dnscrypt/ >/dev/null 2>&1 PTXT "${INFO} Backup complete" [ -z "$2" ] && end_op_message 0 elif [ "$1" = "BACKUP" ] && [ ! -d "${TARG_DIR}" ] && [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; then PTXT "${ERROR} No ${TARG_DIR}/dnscrypt-proxy to Backup!" end_op_message 1 fi if [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ] && [ "$1" = "RESTORE" ]; then PTXT "${INFO} Please wait a moment." tar -xzvf "${BASE_DIR}/backup_dnscrypt.tar.gz" -C "${BASE_DIR}" >/dev/null 2>&1 chown "$(nvram get http_username)":root ${TARG_DIR}/* chmod 755 "${TARG_DIR}/dnscrypt-proxy" inst_dnscrypt "${1:-RESTORE}" elif [ ! -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ] && [ "$1" = "RESTORE" ]; then PTXT "${ERROR} No Backup found!" \ "${ERROR} Please make sure Backup Resides in $BASE_DIR" end_op_message 1 return fi } ########################Modified Version of @Adamm Check_Connection#################################################### check_connection() { local livecheck="0" i while [ "${livecheck}" != "4" ]; do for i in google.com github.com snbforums.com; do if { ! nslookup "${i}" 127.0.0.1 >/dev/null 2>&1; } && { ping -q -w3 -c1 "${i}" >/dev/null 2>&1; }; then if { ! curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -Is "http://${i}" | head -n 1 >/dev/null 2>&1; } || { ! wget --no-cache --no-cookies --tries=3 --timeout=3 --waitretry=1 --retry-connrefused -q --spider "http://${i}" >/dev/null 2>&1; }; then sleep 1s continue fi fi return 0 done livecheck="$((livecheck + 1))" if [ "${livecheck}" != "4" ]; then sleep 10s continue fi return 1 done } ######################################################################################################################## check_dnscrypt_toml() { [ ! -f "${TOML_FILE}" ] && return PTXT "${INFO} Checking dnscrypt-proxy configuration..." if ! ${TARG_DIR}/dnscrypt-proxy -check -config "${TOML_FILE}"; then PTXT "${INFO} Move invalid configuration file to ${TOML_ERR}" \ "${INFO} Operation will continue with clean config file." mv "${TOML_FILE}" "${TOML_ERR}" return 1 fi } check_dns_environment() { if [ -f "/opt/etc/init.d/S61stubby" ] || [ -f "/opt/sbin/stubby" ] || [ -f "/opt/bin/install_stubby" ] || [ -f "/jffs/scripts/install_stubby.sh" ] || [ -d "/jffs/addons/AdGuardHome.d" ]; then PTXT "${ERROR} Potential stubby or adguardhome installation detected." \ "${ERROR} Please remove before attempting to continue." \ "${ERROR} Exiting..." exit 1 fi local NVCHECK NVCHECK="0" if [ "$(nvram get dnspriv_enable)" != "0" ]; then { nvram set dnspriv_enable="0"; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(pidof stubby)" ]; then { killall -q -9 stubby 2>/dev/null; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcp_dns1_x)" ] && [ "${NVCHECK}" != "0" ]; then { nvram set dhcp_dns1_x=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcp_dns2_x)" ] && [ "${NVCHECK}" != "0" ]; then { nvram set dhcp_dns2_x=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcpd_dns_router)" != "1" ] && [ "${NVCHECK}" != "0" ]; then { nvram set dhcpd_dns_router="1"; } NVCHECK="$((NVCHECK + 1))" fi if [ "${NVCHECK}" != "0" ]; then { nvram commit; } { service restart_dnsmasq >/dev/null 2>&1; } (while { ! check_connection; }; do sleep 1s; done) & local PID="$!" wait "${PID}" 2>/dev/null fi PTXT "${INFO} DNS Environment is Ready." } check_dns_filter() { local NVCHECK USE_SOME NVCHECK="0" if [ "$1" -eq 0 ]; then if [ "$(nvram get dnsfilter_enable_x)" -ne 0 ]; then { nvram set dnsfilter_enable_x="0"; } NVCHECK="$((NVCHECK + 1))" fi PTXT "${INFO} DNS will not be forced through to Dnscrypt-Proxy." fi if [ "$1" -eq 1 ]; then if [ "$(nvram get dnsfilter_enable_x)" -ne 1 ]; then { nvram set dnsfilter_enable_x="1"; } NVCHECK="$((NVCHECK + 1))" fi PTXT "${INFO} You can choose to keep any custom dnsfilter values by only redirect non-custom traffic or send all traffic through to Dnscrypt-Proxy." if read_yesno "Do you want to redirect only NON-CUSTOM DNS resolutions on your network through to Dnscrypt-Proxy?"; then USE_SOME="0"; else USE_SOME="1"; fi if [ "${USE_SOME}" -eq 0 ]; then if [ "$(nvram get dnsfilter_mode)" != "11" ]; then { nvram set dnsfilter_mode="11"; } NVCHECK="$((NVCHECK + 1))" fi PTXT "${INFO} DNSFilter is set to control DNS through to Dnscrypt-Proxy, while leaving any Custom Rules and Values." fi if [ "$USE_SOME" -eq 1 ]; then if [ "$(nvram get dnsfilter_custom1)" ]; then { nvram set dnsfilter_custom1=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_custom2)" ]; then { nvram set dnsfilter_custom2=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_custom3)" ]; then { nvram set dnsfilter_custom3=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_mode)" != "11" ]; then { nvram set dnsfilter_mode="11"; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist)" ]; then { nvram set dnsfilter_rulelist=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist1)" ]; then { nvram set dnsfilter_rulelist1=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist2)" ]; then { nvram set dnsfilter_rulelist2=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist3)" ]; then { nvram set dnsfilter_rulelist3=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist4)" ]; then { nvram set dnsfilter_rulelist4=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dnsfilter_rulelist5)" ]; then { nvram set dnsfilter_rulelist5=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcp_dns1_x)" ]; then { nvram set dhcp_dns1_x=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcp_dns2_x)" ]; then { nvram set dhcp_dns2_x=""; } NVCHECK="$((NVCHECK + 1))" fi if [ "$(nvram get dhcpd_dns_router)" != "1" ]; then { nvram set dhcpd_dns_router="1"; } NVCHECK="$((NVCHECK + 1))" fi PTXT "${INFO} DNS is set to redirect All DNS resolutions through to Dnscrypt-Proxy." fi fi if [ "${NVCHECK}" != "0" ]; then { nvram commit; } { service "restart_firewall;restart_dnsmasq" >/dev/null 2>&1; } (while { ! check_connection; }; do sleep 1s; done) & local PID="$!" wait "${PID}" 2>/dev/null fi } check_dns_local() { local LOCAL_CACHE case "$1" in 0) LOCAL_CACHE="NO" write_conf DNSCRYPT_LOCAL "\"${LOCAL_CACHE}\"" ;; 1) LOCAL_CACHE="YES" write_conf DNSCRYPT_LOCAL "\"${LOCAL_CACHE}\"" ;; esac } check_jffs_enabled() { if [ "$(nvram get jffs2_format)" = "1" ]; then PTXT "${ERROR} JFFS partition is scheduled to be reformatted." \ "${ERROR} Please reboot to format or disable that setting and try again." \ "${ERROR} Exiting..." exit 1 fi local JFFS2_SCRIPTS JFFS2_ENABLED jffs2_on JFFS2_SCRIPTS="$(nvram get jffs2_scripts)" [ -z "$(nvram get jffs2_enable)" ] && JFFS2_ENABLED="$(nvram get jffs2_on)" || JFFS2_ENABLED="$(nvram get jffs2_enable)" [ -z "$(nvram get jffs2_enable)" ] && jffs2_on="jffs2_on" || jffs2_on="jffs2_enable" if [ "${JFFS2_ENABLED}" -ne 1 ] || [ "${JFFS2_SCRIPTS}" -ne 1 ]; then PTXT "${INFO} JFFS custom scripts and configs are not enabled." \ "${INFO} Enabling them now!" nvram set "${jffs2_on}"=1 nvram set jffs2_scripts=1 nvram commit else PTXT "${INFO} JFFS custom scripts and configs are already enabled." fi } check_anonymized_automatic() { if [ "$1" -eq 0 ] && grep -q '^server_names = .*Static.*' "${TOML_FILE}"; then PTXT "${INFO} Custom servers that are potentially not compatible with relays are detected!" \ "${WARNING} These servers might not work with relays." \ "${WARNING} Use at your own risk." fi local USE_BROKEN USE_WILDCARD PTXT "${INFO} This allows for the use of server_name='*' as wildcard option for all servers compatible with relays." \ "${INFO} This will be the default route for all compatible servers." \ "${INFO} Additionally routes can be distinctly selected by using via=['*'] as relay wildcard." if read_yesno "Do you want to use wildcard relay (via=['*']) option?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_automatic_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_automatic fi if read_yesno "Do you want to skip using resolvers that are incompatible with anonymization instead of using them directly?"; then USE_BROKEN="true"; else USE_BROKEN="false"; fi toml_avars_prep skip_incompatible "${USE_BROKEN}" } check_anonymized_disabled() { toml_avar_disable routes toml_avars_prep skip_incompatible false PTXT "${INFO} Continue without Relays Support" } check_opendns() { if grep -q '^server_names = .*cisco.*' "${TOML_FILE}"; then if [ -f "${CONF_FILE}" ]; then local OPENDNS_USER OPENDNS_PASSWORD OPENDNS_USER="$(awk -F'=' '/OPENDNS_USER/ {print $2}' "${CONF_FILE}")" OPENDNS_PASSWORD="$(awk -F'=' '/OPENDNS_PASSWORD/ {print $2}' "${CONF_FILE}")" if [ "${OPENDNS_USER}" ] && [ "${OPENDNS_PASSWORD}" ]; then PTXT "${INFO} Found OpenDNS account ${BOLD}${OPENDNS_USER}" \ "${INFO} What do you want to do:" \ " 1) Use this account" \ " 2) Setup new account" \ " 3) Disable OpenDNS account authen" read_input_num "Your choice" 1 3 case "${CHOSEN}" in 1) PTXT "${INFO} Use previous account ${BOLD}${OPENDNS_USER}${NORM}" ;; 2) opendns_authen 1 ;; 3) opendns_authen 0 ;; esac else if read_yesno "Do you want to set up OpenDNS account ip update?"; then opendns_authen 1; else opendns_authen 0; fi fi else if read_yesno "Do you want to set up OpenDNS account ip update?"; then opendns_authen 1; else opendns_authen 0; fi fi else opendns_authen 0 fi } check_relays() { local DNSCRYPT_ARGS DNSCRYPT ODOH_ARGS ODOH FRAGSBLOCKED_ARGS FRAGSBLOCKED VARSARGS SERVER COUNT NUMFRAG NUMCRYPT CRYPT FRAGSBLOCKED_ARGS="$(grep '^fragments_blocked =' "${TOML_ORI}" | cut -d'[' -f2- | sed "s/['\"\,]//g;s/]//g;s/^ [ t]*//;s/[ \t]*$//;s/ /|/g")" NUMCRYPT="0" while read -r CRYPT; do CRYPT="$(PTXT "${CRYPT}" | cut -d',' -f1)" if [ "${NUMCRYPT}" -eq 0 ]; then NUMCRYPT="1" continue fi if [ "${NUMCRYPT}" -eq 1 ]; then if ! PTXT "${FRAGSBLOCKED_ARGS}" | grep -qoF "${CRYPT}"; then DNSCRYPT_ARGS="${CRYPT}"; fi elif [ "${NUMCRYPT}" -gt 1 ]; then if ! PTXT "${FRAGSBLOCKED_ARGS}" | grep -qoF "${CRYPT}"; then DNSCRYPT_ARGS="${DNSCRYPT_ARGS}|${CRYPT}"; fi fi NUMCRYPT="$((NUMCRYPT + 1))" done <${TARG_DIR}/dnscrypt-resolvers.csv ODOH_ARGS="$(awk -v PATT="odohrelay" '/^## / && ($0 !~ PATT) {printf "";printf ""$2"";getline;print}' "${TARG_DIR}/odoh-servers.md" | tr '\n' ' ' | sed 's/[ \t]*$//' | sed 's/ /|/g')" if [ -n "${STAT_CRYPT}" ]; then DNSCRYPT_ARGS="${DNSCRYPT_ARGS}|${STAT_CRYPT}" fi if [ -n "${STAT_ODOH}" ]; then ODOH_ARGS="${ODOH_ARGS}|${STAT_ODOH}" fi VARSARGS="${DNSCRYPT_ARGS}|${ODOH_ARGS}|${FRAGSBLOCKED_ARGS}" COUNT="0" NUMFRAG="0" [ "${NUMFRAG}" -eq 0 ] && toml_avars_prep skip_incompatible false for SERVER in ${VARSARGS//|/ }; do if [ "$(grep '^server_names = .*'"${SERVER}"'.*' "${TOML_FILE}" | grep -cF "'${SERVER}'")" -ne 0 ]; then if PTXT "${DNSCRYPT_ARGS}" | grep -qoF "${SERVER}"; then DNSCRYPT="${SERVER}"; fi if PTXT "${ODOH_ARGS}" | grep -qoF "${SERVER}"; then ODOH="${SERVER}"; fi if PTXT "${FRAGSBLOCKED_ARGS}" | grep -qoF "${SERVER}"; then FRAGSBLOCKED="${SERVER}"; fi case "${SERVER}" in "${DNSCRYPT}") if read_yesno "Do you want to add relays for ${SERVER}?"; then ADD_RELAYS="YES"; else ADD_RELAYS="NO"; fi if [ "${ADD_RELAYS}" = "YES" ]; then PTXT "${INFO} You may manually choose relays for ${SERVER} or you may specify wildcard relay (via=['*'])."; fi if [ "${COUNT}" -eq 0 ] && [ "${ADD_RELAYS}" = "YES" ]; then toml_avar_enable routes if read_yesno "Do you want to use wildcard relay (via=['*']) option for ${SERVER}?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_manual_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_manual fi COUNT="$((COUNT + 1))" elif [ "${COUNT}" -gt 0 ] && [ "${ADD_RELAYS}" = "YES" ]; then if read_yesno "Do you want to use wildcard relay (via=['*']) option for ${SERVER}?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_manual_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_manual fi elif [ "${ADD_RELAYS}" = "NO" ]; then PTXT "${INFO} Skipping relays for ${SERVER}." fi ;; "${ODOH}") PTXT "${INFO} Found ${SERVER}, Oblivious DNS-over-HTTPS relays are required for Oblivious DNS-over-HTTPS servers." \ "${INFO} You may manually choose relays for ${SERVER} server or you may specify wildcard relay (via=['*'])." if [ "${COUNT}" -eq 0 ]; then if read_yesno "Do you want to use wildcard relay (via=['*']) option for ${SERVER}?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_manual_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_manual_odoh fi COUNT="$((COUNT + 1))" elif [ "${COUNT}" -gt 0 ]; then if read_yesno "Do you want to use wildcard relay (via=['*']) option for ${SERVER}?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_manual_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_manual_odoh fi fi ;; "${FRAGSBLOCKED}") if [ "${NUMFRAG}" -eq 0 ] && [ "${COUNT}" -gt 0 ]; then local USE_BROKEN if read_yesno "Do you want to skip using resolvers that are incompatible with anonymization instead of using them directly?"; then USE_BROKEN="true"; else USE_BROKEN="false"; fi toml_avars_prep skip_incompatible "${USE_BROKEN}" NUMFRAG="$((NUMFRAG + 1))" fi ;; esac fi done if [ "${COUNT}" -eq 0 ] && grep -q '^odoh_servers = .*false.*' "${TOML_FILE}" && grep -q '^dnscrypt_servers = .*true.*' "${TOML_FILE}"; then if [ -n "${DNSCRYPT}" ] || { grep -q '^dnscrypt_servers = .*true.*' "${TOML_FILE}" && ! grep -q '^server_names' "${TOML_FILE}"; }; then PTXT "${INFO} To continue, you may still define a default route for all compatible DNSCrypt servers and relays by selecting wildcard option for servers and relays." if read_yesno "Do you still want to setup wildcard options for servers (server_name "*") and relays (via=['*']) for all compatible DNSCrypt servers and relays?"; then check_anonymized_automatic 0; else check_anonymized_disabled; fi else check_anonymized_disabled fi elif [ "${COUNT}" -eq 0 ] && grep -q '^odoh_servers = .*true.*' "${TOML_FILE}" && grep -q '^dnscrypt_servers = .*true.*' "${TOML_FILE}"; then PTXT "${INFO} This option allows you to setup wildcard options for servers (server_name "*") and relays (via=['*']) for all compatible servers and relays." if read_yesno "Do you only want to skip this option for Dnscrypt Servers (still required for ODOH)?"; then choose_relays_automatic_odoh; else COUNT="$((COUNT + 1))"; fi if [ "${COUNT}" -gt 0 ]; then check_anonymized_automatic 0; fi elif [ "${COUNT}" -eq 0 ] && grep -q '^odoh_servers = .*true.*' "${TOML_FILE}" && grep -q '^dnscrypt_servers = .*false.*' "${TOML_FILE}"; then PTXT "${INFO} This option allows you to setup wildcard options for both servers (server_name "*") and relays (via=['*']) required for Oblivious DNS-over-HTTPS servers." if read_yesno "Do you want to use wildcard relay (via=['*']) option for (server_name "*")?"; then USE_WILDCARD="YES"; else USE_WILDCARD="NO"; fi if [ "${USE_WILDCARD}" = "YES" ]; then choose_relays_automatic_wildcard; elif [ "${USE_WILDCARD}" = "NO" ]; then PTXT "${INFO} You chose not to use wildcard for relay selection." "${INFO} Instead you will manually choose relays from a list." choose_relays_automatic_odoh fi elif [ "${COUNT}" -eq 0 ] && grep -q '^odoh_servers = .*false.*' "${TOML_FILE}" && grep -q '^dnscrypt_servers = .*false.*' "${TOML_FILE}"; then check_anonymized_disabled fi } check_swap() { local SWAP_SIZE SWAP_SIZE="$(awk '/SwapTotal/ {print $2}' /proc/meminfo)" if [ "${SWAP_SIZE}" -gt 0 ]; then PTXT "${INFO} Swap file is already setup" end_op_message 0 return fi inst_swap } check_version() { local RMNSTALL LINSTALL MD5SUM_L MD5SUM_R if [ -f "${TARG_DIR}/installer" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ] && [ -z "$2" ]; then if [ -n "$1" ] || { check_connection; }; then local varcnt=0 until [ -n "${LINSTALL}" ] && [ -n "${RMNSTALL}" ] && [ -n "${MD5SUM_L}" ] && [ -n "${MD5SUM_R}" ]; do [ -z "${LINSTALL}" ] && LINSTALL="$(awk '{ print }' "${TARG_DIR}/installer" | grep -m1 "^DI_VERSION=" | grep -oE '[0-9]{1,2}([.][0-9]{1,2})([.][0-9]{1,2})' &)" || true [ -z "${RMNSTALL}" ] && RMNSTALL="$(curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -sL "${RURL}/installer" | grep -m1 "^DI_VERSION=" | grep -oE '[0-9]{1,2}([.][0-9]{1,2})([.][0-9]{1,2})' &)" || true [ -z "${MD5SUM_L}" ] && MD5SUM_L="$(md5sum "${TARG_DIR}/installer" | cut -d' ' -f1 &)" || true [ -z "${MD5SUM_R}" ] && MD5SUM_R="$(curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -fsL "${RURL}/installer" | md5sum | awk '{print $1}' &)" || true varcnt="$((varcnt + 1))" if [ "${varcnt}" -le 84 ]; then wait else printf "%s/n" "One or more critical variables could not be set in a timely mannor." "Please check your internet connection, or try again later." "The installer script will now exit." sleep 3s exit 1 fi done wait if { [ -n "${LINSTALL}" ] && [ -n "${RMNSTALL}" ]; }; then [ -z "${LINSTALL}" ] && exit 1 [ -z "${RMNSTALL}" ] && exit 1 if [ "${RMNSTALL}" != "${LINSTALL}" ]; then PTXT "${INFO} New DI_VERSION=v${RMNSTALL} Available!" \ "${INFO} Run Option 1 of the Installer to upgrade DNScrypt Asuswrt Installer." AUTO_UPDATE="update" elif [ "${MD5SUM_R}" = "${MD5SUM_L}" ]; then PTXT "${INFO} DI_VERSION=v${LINSTALL}" else PTXT "${INFO} DI_VERSION=v${LINSTALL}, but a New Minor Update is Available!" \ "${INFO} Run Option 1 of the Installer to upgrade DNScrypt Asuswrt Installer." AUTO_UPDATE="update" fi local LVERSION LVERSION="$("${TARG_DIR}/dnscrypt-proxy" -version)" [ -z "${LVERSION}" ] && exit 1 [ -z "${DNSCRYPT_VER}" ] && exit 1 if [ "${DNSCRYPT_VER}" != "${LVERSION}" ]; then PTXT "${INFO} New DNSCRYPT_VER=${DNSCRYPT_VER} Available!" \ "${INFO} Run Option 1 of the Installer to upgrade DNScrypt Proxy." AUTO_UPDATE="update" else PTXT "${INFO} DNSCRYPT_VER=${LVERSION}" fi if [ -f "${TARG_DIR}/manager" ]; then local MD5SUM_LM MD5SUM_M MURL varcnt=0 MURL="${URL_GEN}/manager" until [ -n "${MD5SUM_LM}" ] && [ -n "${MD5SUM_M}" ]; do [ -z "${MD5SUM_LM}" ] && MD5SUM_LM="$(md5sum "${TARG_DIR}/manager" | cut -d' ' -f1 &)" || true [ -z "${MD5SUM_M}" ] && MD5SUM_M="$(curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -fsL "${MURL}" | md5sum | awk '{print $1}' &)" || true varcnt="$((varcnt + 1))" if [ "${varcnt}" -le 84 ]; then wait else printf "%s/n" "One or more critical variables could not be set in a timely mannor." "Please check your internet connection, or try again later." "The installer script will now exit." sleep 3s exit 1 fi done wait if [ "${MD5SUM_M}" = "${MD5SUM_LM}" ]; then PTXT "${INFO} Manager file is Up-To-Date!" else PTXT "${INFO} New Manager file is Available!" \ "${INFO} Run Option 1 of the Installer to upgrade the Manager File." AUTO_UPDATE="update" fi fi fi elif { [ -z "$LINSTALL" ] && [ -z "$RMNSTALL" ]; } && [ -z "$1" ]; then while { ! check_connection; }; do sleep 1s; done && check_version x else check_version x x fi fi } choose_dnscrypt_server() { local USE_IPV6 if [ "$(nvram get ipv6_service)" != "disabled" ]; then { if read_yesno "Do you want to use DNS server over IPv6 (yes only if your connection has IPv6)?"; then USE_IPV6="true"; else USE_IPV6="false"; fi; }; else USE_IPV6="false"; fi toml_avars_prep ipv6_servers "${USE_IPV6}" PTXT "${INFO} Choose DNS resolving load balancing strategy:" \ " 1) p2 (default)" \ " 2) ph" \ " 3) first" \ " 4) random" read_input_num "Select your strategy" 1 4 case "${CHOSEN}" in 1) toml_avars_prep lb_strategy "\'p2\'" ;; 2) toml_avars_prep lb_strategy "\'ph\'" ;; 3) toml_avars_prep lb_strategy "\'first\'" ;; 4) toml_avars_prep lb_strategy "\'random\'" ;; esac if read_yesno "Do you want to use load balance estimator to adjust resolvers based on latency calculations?"; then USE_LBE="true"; else USE_LBE="false"; fi toml_avars_prep lb_estimator "${USE_LBE}" PTXT "${INFO} Choose how your DNS servers are selected:" \ " 1) Automatically (default)" \ " 2) Manually" \ " 3) Static" read_input_num "Select your mode" 1 3 case "${CHOSEN}" in 1) choose_dnscrypt_server_auto if grep -q '^dnscrypt_servers = .*true.*' "${TOML_FILE}" && [ -z "${CRYPT_COUNT}" ]; then CRYPT_COUNT="1"; fi if read_yesno "Do you want to choose which servers to disable (this can be a long process)?"; then CHOOSE_DISABLED="true"; else CHOOSE_DISABLED="false"; fi if [ "${CHOOSE_DISABLED}" = "true" ]; then choose_dnscrypt_server_disabled; elif [ "${CHOOSE_DISABLED}" = "false" ]; then toml_avar_disable disabled_server_names; fi ;; 2) toml_avar_disable disabled_server_names if read_yesno "Do you only want to use the Oblivious DNS-over-HTTPS protocol?"; then ODOH_ONLY="true"; else ODOH_ONLY="false"; fi if [ "${ODOH_ONLY}" = "true" ]; then choose_dnscrypt_server_odoh; elif [ "${ODOH_ONLY}" = "false" ]; then choose_dnscrypt_server_manual; fi ;; 3) toml_avar_disable disabled_server_names static_chosen 0 ;; esac } choose_dnscrypt_server_auto() { toml_avar_disable server_names if read_yesno "Use servers that support the DNSCrypt protocol"; then toml_avars_prep dnscrypt_servers true; else toml_avars_prep dnscrypt_servers false; fi if read_yesno "Use servers that support the DNS-over-HTTPS protocol"; then toml_avars_prep doh_servers true; else toml_avars_prep doh_servers false; fi if read_yesno "Use servers that support the Oblivious DNS-over-HTTPS protocol"; then toml_avars_prep odoh_servers true; else toml_avars_prep odoh_servers false; fi if read_yesno "Use only servers that support DNSSEC"; then toml_avars_prep require_dnssec true; else toml_avars_prep require_dnssec false; fi if read_yesno "Use only servers that do not log user's queries"; then toml_avars_prep require_nolog true; else toml_avars_prep require_nolog false; fi if read_yesno "Use only servers that do not filter result"; then toml_avars_prep require_nofilter true; else toml_avars_prep require_nofilter false; fi } choose_dnscrypt_server_disabled() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then if [ "${USE_IPV6}" = "true" ]; then USE_IPV6="NOMATCH"; else USE_IPV6="6"; fi local RESOLVERS PTXT "${INFO} Available DNS servers to disable: " INDEX="$(awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/public-resolvers.md" | wc -l)" awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/public-resolvers.md" read_input_num "Please choose DNS server to disable" 1 "${INDEX}" else if ! read_input_num "Please choose next DNS server to disable or press n to stop" 1 "${INDEX}" n; then if grep -q '^odoh_servers = .*true.*' "${TOML_FILE}"; then if read_yesno "Do you want to choose which Oblivious DNS-over-HTTPS DNS servers to disable?"; then ODOH_DISABLED="true"; else ODOH_DISABLED="false"; fi if [ "${ODOH_DISABLED}" = "true" ]; then choose_dnscrypt_server_disabled_odoh; fi fi toml_avars_prep disabled_server_names "\"[${RESOLVERS}]\"" return fi fi local ITEM ITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/public-resolvers.md")" if PTXT "${RESOLVERS}" | grep -qoF "'${ITEM}'"; then PTXT "${INFO} ${ITEM} is already set." else if [ "${RESOLVERS}" ]; then RESOLVERS="${RESOLVERS%?}', '${ITEM}'" else RESOLVERS="'${ITEM}'" fi fi choose_dnscrypt_server_disabled "${INDEX}" } choose_dnscrypt_server_disabled_odoh() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then local ORESOLVERS PTXT "${INFO} Available DNS servers to disable: " INDEX="$(awk -v PATT="odohrelay" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/odoh-servers.md" | wc -l)" awk -v PATT="odohrelay" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/odoh-servers.md" read_input_num "Please choose DNS server to disable" 1 "${INDEX}" else if ! read_input_num "Please choose next DNS server to disable or press n to stop" 1 "${INDEX}" n; then RESOLVERS="${ORESOLVERS}, ${RESOLVERS}" return fi fi local OITEM OITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="odohrelay" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/odoh-servers.md")" if PTXT "${ORESOLVERS}" | grep -qoF "'${OITEM}'"; then PTXT "${INFO} ${OITEM} is already set." else if [ "${ORESOLVERS}" ]; then ORESOLVERS="${ORESOLVERS%?}', '${OITEM}'" else ORESOLVERS="'${OITEM}'" fi fi choose_dnscrypt_server_disabled_odoh "${INDEX}" } choose_dnscrypt_server_manual() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then [ "${USE_IPV6}" = "true" ] && USE_IPV6="NOMATCH" || USE_IPV6="6" local RESOLVERS toml_avars_prep dnscrypt_servers true doh_servers true require_dnssec false require_nolog false require_nofilter false PTXT "${INFO} Available DNS servers: " INDEX="$(awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/public-resolvers.md" | wc -l)" awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/public-resolvers.md" read_input_num "Please choose DNS server." 1 "${INDEX}" else if ! read_input_num "Please choose next DNS server or press n to stop." 1 "${INDEX}" n; then if read_yesno "Do you want to choose which Oblivious DNS-over-HTTPS DNS servers to enable?"; then ODOH_ENABLE="true"; else ODOH_ENABLE="false"; fi if [ "${ODOH_ENABLE}" = "true" ]; then choose_dnscrypt_server_odoh; elif [ "${ODOH_ENABLE}" = "false" ]; then toml_avars_prep odoh_servers "${ODOH_ENABLE}"; fi if read_yesno "Do you want to add any static servers?"; then ADD_STATIC="YES"; else ADD_STATIC="NO"; fi if [ "${ADD_STATIC}" = "YES" ]; then static_chosen 0; fi toml_avars_prep server_names "\"[${RESOLVERS}]\"" return fi fi local ITEM ITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/public-resolvers.md")" if PTXT "${RESOLVERS}" | grep -qoF "'${ITEM}'"; then PTXT "${INFO} ${ITEM} is already set" else if [ "${RESOLVERS}" ]; then RESOLVERS="${RESOLVERS%?}', '${ITEM}'" else RESOLVERS="'${ITEM}'" fi fi choose_dnscrypt_server_manual "${INDEX}" } choose_dnscrypt_server_odoh() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then local ORESOLVERS toml_avars_prep odoh_servers true PTXT "${INFO} Available DNS servers: " INDEX="$(awk -v PATT="odohrelay" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/odoh-servers.md" | wc -l)" awk -v PATT="odohrelay" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/odoh-servers.md" read_input_num "Please choose DNS server." 1 "${INDEX}" else if ! read_input_num "Please choose next DNS server or press n to stop." 1 "${INDEX}" n; then if [ "${ODOH_ONLY}" = "true" ]; then toml_avars_prep server_names "\"[${ORESOLVERS}]\"" dnscrypt_servers false doh_servers false require_dnssec false require_nolog false require_nofilter false; elif [ "${ODOH_ONLY}" = "false" ]; then RESOLVERS="${ORESOLVERS}, ${RESOLVERS}"; fi return fi fi local OITEM OITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="odohrelay" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/odoh-servers.md")" if PTXT "${ORESOLVERS}" | grep -qoF "'${OITEM}'"; then PTXT "${INFO} ${OITEM} is already set" else if [ "${ORESOLVERS}" ]; then ORESOLVERS="${ORESOLVERS%?}', '${OITEM}'" else ORESOLVERS="'${OITEM}'" fi fi choose_dnscrypt_server_odoh "${INDEX}" } choose_relays_automatic() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then if [ "${USE_IPV6}" = "true" ]; then USE_IPV6="NOMATCH"; else USE_IPV6="6"; fi local RELAYS PTXT "${INFO} Available Relay servers: " INDEX="$(awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/relays.md" | wc -l)" awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/relays.md" read_input_num "Please choose RELAY server" 1 "${INDEX}" else if ! read_input_num "Please choose next RELAY server or press n to stop" 1 "${INDEX}" n; then if grep -q '^odoh_servers = .*true.*' "${TOML_FILE}"; then PTXT "${INFO} Now to pick relays for Oblivious DNS-over-HTTPS DNS servers." choose_relays_automatic_odoh fi if read_yesno "Do you want to add any static relays?"; then ADD_STATIC="YES"; else ADD_STATIC="NO"; fi if [ "${ADD_STATIC}" = "YES" ]; then static_chosen_relays 0; fi toml_avars_prep routes "\"[ { server_name='*', via=[${RELAYS}] } ]\"" return fi fi local ITEM ITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/relays.md")" if PTXT "${RELAYS}" | grep -qoF "'${ITEM}'"; then PTXT "${INFO} ${ITEM} is already set." else if [ "${RELAYS}" ]; then RELAYS="${RELAYS%?}', '${ITEM}'" else RELAYS="'${ITEM}'" fi fi choose_relays_automatic "${INDEX}" } choose_relays_automatic_odoh() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then local ORELAYS PTXT "${INFO} Available Relay servers: " INDEX="$(awk -v PATT="odoh-" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/odoh-relays.md" | wc -l)" awk -v PATT="odoh-" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/odoh-relays.md" read_input_num "Please choose RELAY server" 1 "${INDEX}" else if ! read_input_num "Please choose next RELAY server or press n to stop" 1 "${INDEX}" n; then if grep -q '^dnscrypt_servers = .*false.*' "${TOML_FILE}" || [ "${COUNT}" -eq 0 ]; then toml_avars_prep routes "\"[ { server_name='*', via=[${ORELAYS}] } ]\""; else RELAYS="${ORELAYS}, ${RELAYS}"; fi return fi fi local OITEM OITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="odoh-" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/odoh-relays.md")" if PTXT "${ORELAYS}" | grep -qoF "'${OITEM}'"; then PTXT "${INFO} ${OITEM} is already set." else if [ "${ORELAYS}" ]; then ORELAYS="${ORELAYS%?}', '${OITEM}'" else ORELAYS="'${OITEM}'" fi fi choose_relays_automatic_odoh "${INDEX}" } choose_relays_automatic_wildcard() { toml_avars_prep routes "\"[ { server_name='*', via=['*'] } ]\"" } choose_relays_manual() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then if [ "${USE_IPV6}" = "true" ]; then USE_IPV6="NOMATCH"; else USE_IPV6="6"; fi local RELAYS PTXT "${INFO} Available Relay servers: " INDEX="$(awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/relays.md" | wc -l)" awk -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/relays.md" read_input_num "Please choose RELAY server" 1 "${INDEX}" else if ! read_input_num "Please choose next RELAY server or press n to stop" 1 "${INDEX}" n; then if read_yesno "Do you want to add any static relays?"; then ADD_STATIC="YES"; else ADD_STATIC="NO"; fi if [ "${ADD_STATIC}" = "YES" ]; then static_chosen_relays 0; fi if [ "${COUNT}" -eq 0 ]; then toml_avars_prep routes "\"[ { server_name='${SERVER}', via=[${RELAYS}] } ]\"" else toml_nvars_replace "} ]" "}, { server_name='${SERVER}', via=[${RELAYS}] } ]" "${TOML_FILE}" fi return fi fi local ITEM ITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="${USE_IPV6}" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/relays.md")" if PTXT "${RELAYS}" | grep -qoF "'${ITEM}'"; then PTXT "${INFO} ${ITEM} is already set." else if [ "${RELAYS}" ]; then RELAYS="${RELAYS%?}', '${ITEM}'" else RELAYS="'${ITEM}'" fi fi choose_relays_manual "${INDEX}" } choose_relays_manual_odoh() { local INDEX INDEX="$1" if [ -z "${INDEX}" ]; then local RELAYS PTXT "${INFO} Available Relay servers: " INDEX="$(awk -v PATT="odoh-" '/^## / && ($0 !~ PATT)' "${TARG_DIR}/odoh-relays.md" | wc -l)" awk -v PATT="odoh-" '/^## / && ($0 !~ PATT) {printf " "; printf ++i") "$2": "; getline; getline; print}' "${TARG_DIR}/odoh-relays.md" read_input_num "Please choose RELAY server" 1 "${INDEX}" else if ! read_input_num "Please choose next RELAY server or press n to stop" 1 "${INDEX}" n; then if read_yesno "Do you want to add any static relays?"; then ADD_STATIC="YES"; else ADD_STATIC="NO"; fi if [ "${ADD_STATIC}" = "YES" ]; then static_chosen_relays 0; fi if [ "${COUNT}" -eq 0 ]; then toml_avars_prep routes "\"[ { server_name='${SERVER}', via=[${RELAYS}] } ]\"" else toml_nvars_replace "} ]" "}, { server_name='${SERVER}', via=[${RELAYS}] } ]" "${TOML_FILE}" fi return fi fi local ITEM ITEM="$(awk -v INDEX="${CHOSEN}" -v PATT="odoh-" '/^## / && ($0 !~ PATT) {i++} i==INDEX {print $2;exit}' "${TARG_DIR}/odoh-relays.md")" if PTXT "${RELAYS}" | grep -qoF "'${ITEM}'"; then PTXT "${INFO} ${ITEM} is already set." else if [ "${RELAYS}" ]; then RELAYS="${RELAYS%?}', '${ITEM}'" else RELAYS="'${ITEM}'" fi fi choose_relays_manual_odoh "${INDEX}" } choose_relays_manual_wildcard() { if [ "${COUNT}" -eq 0 ]; then toml_avars_prep routes "\"[ { server_name='${SERVER}', via=['*'] } ]\"" else toml_nvars_replace "} ]" "}, { server_name='${SERVER}', via=['*'] } ]" "${TOML_FILE}" fi } cleanup() { rm -rf "${TARG_DIR}/dnscrypt-fw-rules" "${TARG_DIR}/dnscrypt-start" "${TARG_DIR}/dnsmasq-dnscrypt-reconfig" "${TARG_DIR}/fake-hwclock*" "${TARG_DIR}/init-start" "${TARG_DIR}/services-stop" del_jffs_script /jffs/scripts/wan-start dnscrypt-start del_jffs_script /jffs/scripts/openvpn-event del_jffs_script /jffs/scripts/firewall-start del_jffs_script /jffs/scripts/wan-start } create_dir() { if ! mkdir -p "${1}"; then PTXT "${ERROR} Unable to create ${1}!" return 1 fi } del_between_magic() { local TARG MAGIC BOUNDS TARG="$1" MAGIC="$2" [ -f "${TARG}" ] || return BOUNDS="$(awk -v PATT="${MAGIC}" '($0 ~ PATT) {printf NR","}' "${TARG}")" if [ "${BOUNDS}" ]; then sed -i "${BOUNDS%,}d" "${TARG}" fi } del_conf() { [ ! -f "${CONF_FILE}" ] && return local KEY for KEY in "$@"; do sed -i "/^${KEY}=.*$/d" "${CONF_FILE}" done } del_jffs_script() { local TARG LINE_NUM LINE_ABOVE OP TARG="$1" [ -f "${TARG}" ] || return if [ "$2" ]; then OP="${2:0:1}" if [ "${OP}" = "!" ]; then LINE_NUM="$(grep -n -F "[ -x ${TARG_DIR}/" "${TARG}" | grep -v "$(_quote "$2")" | cut -d':' -f1)" else LINE_NUM="$(grep -n -F "[ -x ${TARG_DIR}/" "${TARG}" | grep "$(_quote "$2")" | cut -d':' -f1)" fi else LINE_NUM="$(grep -n -F "[ -x ${TARG_DIR}/" "${TARG}" | cut -d':' -f1)" fi [ -z "${LINE_NUM}" ] && return sed -i "${LINE_NUM}d" "${TARG}" if [ "${LINE_NUM}" -gt 1 ]; then LINE_NUM="$((LINE_NUM - 1))" LINE_ABOVE="$(sed "${LINE_NUM}q;d" "${TARG}")" [ -z "${LINE_ABOVE}" ] && sed -i "${LINE_NUM}d" "${TARG}" fi [ "$(awk '{ print }' "${TARG}")" = "#!/bin/sh" ] && rm -f "${TARG}" } download_file() { local TARG PERM URL RET FILENAME MD5SUM_OLD MD5SUM_CURR TARG="$1" shift PERM="$1" shift for URL in "$@"; do FILENAME="$(basename "${URL}")" local varcnt="0" until [ -n "${MD5SUM_CURR}" ]; do if [ -f "${TARG}/${FILENAME}" ]; then [ -z "${MD5SUM_OLD}" ] && MD5SUM_OLD="$(md5sum "${TARG}/${FILENAME}" | cut -d' ' -f1 &)" || true fi [ -z "${MD5SUM_CURR}" ] && MD5SUM_CURR="$(curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -fsL "${URL}" | md5sum | awk '{print $1}' &)" || true varcnt="$((varcnt + 1))" if [ "${varcnt}" -eq 1 ]; then wait else break fi done wait if [ "$(PTXT -n "${MD5SUM_CURR}" | wc -c)" -eq 32 ] && [ "${MD5SUM_CURR}" = "${MD5SUM_OLD}" ]; then PTXT "${INFO} ${FILENAME} is up to date. Skipping..." else local COUNT COUNT="0" while [ "${COUNT}" -lt 3 ]; do PTXT "${INFO} Downloading ${FILENAME}" if curl --retry 3 --connect-timeout 3 --retry-delay 1 --max-time $((3 * 5)) --retry-connrefused -L -k -s "${URL}" -o "${TARG}/${FILENAME}"; then chmod "${PERM}" "${TARG}/${FILENAME}" break fi COUNT="$((COUNT + 1))" done if [ "${COUNT}" -eq 3 ]; then PTXT "${ERROR} Unable to download ${BOLD}${URL}${NORM}" if [ -z "${RET}" ]; then RET="1"; else RET="$((RET + 1))"; fi fi fi done if [ -z "${RET}" ]; then RET="0"; else PTXT "${ERROR} One or more download failures has occured." "${ERROR} It is recommended to rerun the installer, or restore from a backup!"; fi return "${RET}" } end_op_message() { case "${1:-0}" in 0) PTXT "${INFO} Operation completed, returning to Main Menu. You can quit or continue." ;; 1) PTXT "${INFO} Operation aborted, returning to Main Menu. You can quit or continue." ;; 2) PTXT "${INFO} Abnormal operations, returning to Main Menu. You can quit or continue." ;; esac PTXT "=====================================================" PTXT " " PTXT " " sleep 3s && clear if [ -f "${TARG_DIR}/installer" ]; then chmod 755 "${TARG_DIR}/installer" >/dev/null 2>&1 exec "${TARG_DIR}/installer" "${BRANCH}" && exit elif [ ! -f "${TARG_DIR}/installer" ] && [ -f "${SCRIPT_LOC}" ]; then chmod 755 "${SCRIPT_LOC}" >/dev/null 2>&1 exec "${SCRIPT_LOC}" "${BRANCH}" && exit elif [ -f "${HOME}/installer" ]; then chmod 755 "${HOME}/installer" exec "${HOME}/installer" "${BRANCH}" && exit else clear && { end_op_header 2>/dev/null; } && exit fi } end_op_header() { sed -n -e "1,$(($(grep -wn 'esac' "$0" | cut -d':' -f1 | tail -n1) + 1))p" "$0" >"${0}.tmp" chmod 755 "${0}.tmp" exec "${0}.tmp" "${BRANCH}" && rm -rf "${0}.tmp" } inst_dnscrypt() { local DNSCRYPT_TAR RESOLVERS_URL_PREFIX CRYPT_RESOLVERS DNSCRYPT_TAR=dnscrypt-proxy-${DNSCRYPT_ARCH}-${DNSCRYPT_VER}.tar.gz RESOLVERS_URL_PREFIX="https://download.dnscrypt.info/resolvers-list/v3/" CRYPT_RESOLVERS="https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v1/" if [ -z "$2" ]; then if [ "${1:-RESTORE}" != "RESTORE" ]; then if [ ! -d "$TARG_DIR" ] && [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then PTXT "${INFO} Backup is detected." local USE_OLD if read_yesno "Do you want Restore instead?"; then USE_OLD="YES"; else USE_OLD="NO"; fi if [ "${USE_OLD}" = "YES" ]; then PTXT "${INFO} Installing from an old backup!" backup_restore RESTORE elif [ "${USE_OLD}" = "NO" ]; then PTXT "${INFO} Continuing without restoring from backup!" fi elif [ -d "${TARG_DIR}" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ] && [ ! -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then if read_yesno "Do you want create a backup before updating?"; then backup_restore BACKUP 0; else PTXT "${INFO} continuing without making a backup."; fi fi fi if [ -z "${DNSCRYPT_VER}" ] || { ! check_connection; }; then PTXT "${ERROR} Unable to detect the Internet!" end_op_message 1 return fi if ! create_dir "${TARG_DIR}"; then end_op_message 1 return fi if ! download_file "${TARG_DIR}" 755 "${RURL}/installer" || ! awk '{ print }' "${TARG_DIR}/installer" | grep -m1 "^DI_VERSION=" | grep -qoE '[0-9]{1,2}([.][0-9]{1,2})([.][0-9]{1,2})'; then PTXT "${ERROR} Failed to download installer." end_op_message 1 return fi download_file "${TARG_DIR}" 755 "${URL_GEN}/manager" if [ "${1:-RESTORE}" != "RESTORE" ]; then if [ -f "${TARG_DIR}/dnscrypt-proxy" ]; then local LVERSION LVERSION="$("${TARG_DIR}/dnscrypt-proxy" -version)" [ -z "${LVERSION}" ] && exit 1 [ -z "${DNSCRYPT_VER}" ] && exit 1 if [ "${DNSCRYPT_VER}" != "${LVERSION}" ]; then PTXT "${INFO} New DNSCRYPT_VER=${DNSCRYPT_VER} Available!" \ "${INFO} Updating DNSCRYPT_VER=${LVERSION} to ${DNSCRYPT_VER}." inst_dnscrypt "${1:-update}" "${DNSCRYPT_VER}" else PTXT "${INFO} DNSCRYPT_VER=${LVERSION}" fi else inst_dnscrypt "${1:-install}" "${DNSCRYPT_VER}" fi fi else if ! download_file "${TARG_DIR}" 644 "https://github.com/jedisct1/dnscrypt-proxy/releases/download/${2}/${DNSCRYPT_TAR}"; then PTXT "${ERROR} Unable to download dnscrypt-proxy package for your router" end_op_message 1 return fi tar xzv -C "${TARG_DIR}" -f "${TARG_DIR}/${DNSCRYPT_TAR}" chown "$(nvram get http_username)":root ${TARG_DIR}/"${DNSCRYPT_ARCH_TAR}"/* mv ${TARG_DIR}/"${DNSCRYPT_ARCH_TAR}"/* "${TARG_DIR}" rm -r "${TARG_DIR:?}/${DNSCRYPT_ARCH_TAR}" "${TARG_DIR:?}/${DNSCRYPT_TAR}" if ! chmod 755 "${TARG_DIR}/dnscrypt-proxy" && [ -z "$("${TARG_DIR}/dnscrypt-proxy" -version)" ]; then PTXT "${ERROR} Failed to download dnscrypt-proxy package for your router" end_op_message 1 return fi fi download_file "${TARG_DIR}" 644 "${RESOLVERS_URL_PREFIX}/public-resolvers.md" \ "${RESOLVERS_URL_PREFIX}/public-resolvers.md.minisig" \ "${RESOLVERS_URL_PREFIX}/relays.md" \ "${RESOLVERS_URL_PREFIX}/relays.md.minisig" \ "${RESOLVERS_URL_PREFIX}/odoh-servers.md" \ "${RESOLVERS_URL_PREFIX}/odoh-servers.md.minisig" \ "${RESOLVERS_URL_PREFIX}/odoh-relays.md" \ "${RESOLVERS_URL_PREFIX}/odoh-relays.md.minisig" download_file "${TARG_DIR}" 644 "${CRYPT_RESOLVERS}/dnscrypt-resolvers.csv" \ "${CRYPT_RESOLVERS}/dnscrypt-resolvers.csv.minisig" chown nobody:nobody "${TARG_DIR}/public-resolvers.md" \ "${TARG_DIR}/public-resolvers.md.minisig" \ "${TARG_DIR}/relays.md" \ "${TARG_DIR}/relays.md.minisig" \ "${TARG_DIR}/odoh-servers.md" \ "${TARG_DIR}/odoh-servers.md.minisig" \ "${TARG_DIR}/odoh-relays.md" \ "${TARG_DIR}/odoh-relays.md.minisig" \ "${TARG_DIR}/dnscrypt-resolvers.csv" \ "${TARG_DIR}/dnscrypt-resolvers.csv.minisig" for i in init-start services-stop; do if { ! grep -q "${TARG_DIR}/manager ${i} &" "/jffs/scripts/${i}" && grep -q "${TARG_DIR}/manager ${i}" "/jffs/scripts/${i}"; }; then del_jffs_script "/jffs/scripts/${i}"; fi; done write_manager_script /jffs/scripts/init-start "init-start &" write_manager_script /jffs/scripts/services-stop "services-stop &" write_manager_script /jffs/scripts/dnsmasq.postconf dnsmasq del_between_magic /jffs/scripts/service-event-end '# Asuswrt-Merlin-Dnscrypt-Proxy-Installer' write_command_script /jffs/scripts/service-event-end 'if printf "%s" "$@" | /bin/grep -qE "^(((((dnscrypt-)?(start|stop)|restart|kill))_?.*dnscrypt-proxy)$)"; then { sh /jffs/dnscrypt/manager "$(printf "%s" "$@" | /bin/grep -oE "^(((dnscrypt-)?(start|stop)|restart|kill))")" x & }; fi # Asuswrt-Merlin-Dnscrypt-Proxy-Installer' if ! setup_dnscrypt "" "${1:-install}"; then end_op_message 1 return fi PTXT "${INFO} Starting dnscrypt-proxy..." service start_dnscrypt-proxy >/dev/null 2>&1 sleep 1s if [ -z "$(pidof dnscrypt-proxy)" ]; then PTXT "${ERROR} Couldn't start dnscrypt-proxy" \ "${ERROR} Please send WebUI System Log to dev" end_op_message 1 return fi service restart_dnscrypt-proxy >/dev/null 2>&1 PTXT "${INFO} For dnscrypt-proxy version 2 to work reliably, you might also want to:" \ "${INFO} - Add swap" \ "${INFO} - Add a RNG" \ "${INFO} - Set your timezone" end_op_message 0 } manager_monitor_restart() { local MAN_PID PID MAN_PID="$(pidof manager)" if [ "${MAN_PID}" ]; then for PID in ${MAN_PID}; do if awk '{ print }' "/proc/${PID}/cmdline" | grep -q dnscrypt; then { kill -s 10 "${PID}" 2>/dev/null || kill -s 9 "${PID}" 2>/dev/null; } break fi done fi ${TARG_DIR}/manager monitor-start } opendns_authen() { if [ "$1" -eq 0 ]; then del_conf OPENDNS_USER OPENDNS_PASSWORD return fi if [ -z "${PW1}" ] || [ -z "${PW2}" ]; then local USERNAME PTXT -n "${INPUT} Please enter OpenDNS username${NORM}: " read -r USERNAME fi local PW1 PW2 PTXT -n "${INPUT} Please enter OpenDNS password${NORM}: " read -rs PW1 PTXT " " PTXT -n "${INPUT} Please reenter OpenDNS password${NORM}: " read -rs PW2 PTXT " " if [ -z "${PW1}" ] || [ -z "${PW2}" ] || [ "${PW1}" != "${PW2}" ]; then PTXT "${ERROR} Password entered incorrectly!" opendns_authen "$1" fi write_conf OPENDNS_USER "\"${USERNAME}\"" write_conf OPENDNS_PASSWORD "\"${PW1}\"" } inst_random() { create_dir "${TARG_DIR}" PTXT "${INFO} Install a (P)RNG for better cryptographic operations" \ "${INFO} Available random number generator providers:" \ " 1) HAVEGED (Preferred if you do not have a HW RNG)" \ " 2) RNGD (Preferred if you have a HW RNG)" \ "${INFO} If you choose a HW RNG, please have it plugged in now before" \ "${INFO} proceeding with your selection." read_input_num "Please enter the number designates your selection" 1 2 case "${CHOSEN}" in 1) rm -f "${TARG_DIR}/rngd" "${TARG_DIR}/stty" { kill -s 9 "$(pidof haveged jitterentropy-rngd rngd stty)" 2>/dev/null || killall -q -9 haveged jitterentropy-rngd rngd stty 2>/dev/null; } download_file "${TARG_DIR}" 755 "${URL_ARCH}/haveged" "${URL_GEN}/manager" write_conf RAN_PRV haveged ${TARG_DIR}/haveged -w 1024 -d 32 -i 32 -v 1 ;; 2) local RNG_DEV { kill -s 9 "$(pidof haveged jitterentropy-rngd rngd stty)" 2>/dev/null || killall -q -9 haveged jitterentropy-rngd rngd stty 2>/dev/null; } download_file "$TARG_DIR" 755 "${URL_ARCH}/haveged" "${URL_ARCH}/rngd" "${URL_ARCH}/stty" "${URL_GEN}/manager" inst_ran_dev || return write_conf RAN_PRV rngd ${TARG_DIR}/stty raw -echo -ixoff -F "/dev/${RNG_DEV}" speed 115200 ${TARG_DIR}/rngd -r "/dev/${RNG_DEV}" ;; esac write_manager_script /jffs/scripts/init-start init-start end_op_message 0 } inst_ran_dev() { if [ -c "/dev/ttyACM0" ]; then local PRODSTR VID PID PRODSTR="$(awk '{ print }' "/sys/class/tty/ttyACM0/device/uevent" | grep "^PRODUCT\=")" VID="$(PTXT "${PRODSTR}" | cut -d '=' -f 2 | cut -d '/' -f 1)" PID="$(PTXT "${PRODSTR}" | cut -d '=' -f 2 | cut -d '/' -f 2)" if [ "${VID}" = "4d8" ] && [ "${PID}" = "f5fe" ]; then PTXT "${INFO} Found TrueRNG USB HW RNG" RNG_DEV="ttyACM0" fi if [ "${VID}" = "16d0" ] && [ "${PID}" = "aa0" ]; then PTXT "${INFO} Found TrueRNGpro USB HW RNG" RNG_DEV="ttyACM0" fi if [ "${VID}" = "1d50" ] && [ "${PID}" = "6086" ]; then PTXT "${INFO} Found OneRNG USB HW RNG" RNG_DEV="ttyACM0" fi if [ "${VID}" = "20df" ] && [ "${PID}" = "1" ]; then PTXT "${INFO} Found EntropyKey USB HW RNG" RNG_DEV="ttyACM0" fi fi if [ -z "${RNG_DEV}" ]; then PTXT "${ERROR} Unable to find any HW RNG device! Retrying..." inst_random return 1 fi write_conf RNG_DEV "/dev/${RNG_DEV}" } inst_swap() { local SWAP_SIZE USB_COUNT SWAP_SIZE="524288" USB_COUNT="$(df | awk -v SWS="$((SWAP_SIZE * 2))" '/\/tmp\/mnt\// {if ($4 > SWS){print $6}}' | wc -l)" if [ "${USB_COUNT}" -lt 1 ]; then PTXT "${ERROR} Unable to find any external USB storage" \ "${ERROR} Or no suitable external USB storage found" \ "${ERROR} Please connect a USB storage with at least" \ "${ERROR} $((SWAP_SIZE * 2 / 1024))MB of free space." end_op_message 1 return fi PTXT "${INFO} Available partition to install swap file:${NORM}" df | awk -v SWS="$((SWAP_SIZE * 2))" '/\/tmp\/mnt\// {if ($4 > SWS){++i; print " " i ") " $6 " (" $4/1024 "MB free)"}}' read_input_num "Please select the partition to install swap file" 1 "${USB_COUNT}" local MOUNT MOUNT="$(df | awk -v IDX="${CHOSEN}" -v SWS="$((SWAP_SIZE * 2))" '/\/tmp\/mnt\// {if ($4 > SWS){++i; if (i==IDX){print $6}}}')" PTXT "${INFO} Please wait..." dd if=/dev/zero of="${MOUNT}/swap" bs=1024 count="${SWAP_SIZE}" local MOUNT_FS MOUNT_FS="$(df -T "${MOUNT}" | awk 'FNR==2 {print $2}')" [ "${MOUNT_FS%?}" = "ext" ] && chmod 600 "${MOUNT}/swap" mkswap "${MOUNT}/swap" if ! swapon "${MOUNT}/swap"; then sed -i "/^$(_quote '[ -f $1/swap ] && swapon $1/swap')$/d" /jffs/scripts/post-mount sed -i "/^$(_quote '[ -f $1/swap ] && swapoff $1/swap')$/d" /jffs/scripts/unmount write_command_script /jffs/scripts/post-mount '[ -f "$1/swap" ] && swapon "$1/swap"' write_command_script /jffs/scripts/unmount '[ -f "$1/swap" ] && swapoff "$1/swap"' end_op_message 0 else PTXT "${ERROR} Unable to create swap. Get the command log to dev" end_op_message 1 fi } read_input_dns() { PTXT -n "${INPUT} $1 ${BOLD}${2}: ${NORM}" local DNS_SERVER read -r DNS_SERVER [ -z "${DNS_SERVER}" ] && DNS_SERVER="$2" if ! PTXT "${DNS_SERVER}" | grep -qoE "\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"; then PTXT "${ERROR} Invalid DNS server address entered" read_input_dns "$@" fi if [ "${DNS_SERVER1}" = "${DNS_SERVER}" ]; then PTXT "${ERROR} ${DNS_SERVER} DNS server address already entered, please try again!" read_input_dns "$@" fi case "$1" in "Default is") BOOTSTRAP="'${DNS_SERVER}:53'" PROBE="${DNS_SERVER}:53" DNS_SERVER1="${DNS_SERVER}" ;; "2nd Default is") BOOTSTRAP2="${BOOTSTRAP}, '${DNS_SERVER}:53'" ;; esac } read_input_num() { local RANGE [ -z "$4" ] && [ -z "$5" ] && [ -z "$6" ] && RANGE="[${2}-${3}]" [ -n "$4" ] && [ -z "$5" ] && [ -z "$6" ] && RANGE="[${2}-${3}/${4}]" [ -n "$4" ] && [ -n "$5" ] && [ -z "$6" ] && RANGE="[${2}-${3}/${4}/${5}]" [ -n "$4" ] && [ -n "$5" ] && [ -n "$6" ] && RANGE="[${2}-${3}/${4}/${5}/${6}]" PTXT -n "${INPUT} $1, ${BOLD}${RANGE}${NORM}: " read -r CHOSEN case "$1" in "Set log level, default is 2, 0 is the most verbose") if [ -z "${CHOSEN}" ]; then CHOSEN="2"; fi ;; "Select your strategy" | "Select your mode") if [ -z "${CHOSEN}" ]; then CHOSEN="1"; fi ;; *) if [ -z "${CHOSEN}" ]; then PTXT "${ERROR} Invalid character(s) entered! Retrying..." read_input_num "$@" return fi ;; esac case "${CHOSEN}" in "$4" | "$5" | "$6") return 1 ;; "$2" | "$3" | *) if ! PTXT "${CHOSEN}" | grep -qE '^[0-9]+$'; then PTXT "${ERROR} Invalid character(s) entered! Retrying..." read_input_num "$@" return fi if [ "${CHOSEN}" -lt "$2" ] || [ "${CHOSEN}" -gt "$3" ]; then PTXT "${ERROR} Chosen number is not in range! Retrying..." read_input_num "$@" return fi ;; esac } read_yesno() { PTXT -n "${INPUT} $1 ${BOLD}[y/n]${NORM}: " local YESNO read -r YESNO case "${YESNO}" in y | Y) return 0 ;; n | N) return 1 ;; *) PTXT "${ERROR} Invalid input!" read_yesno "$@" ;; esac } static_chosen() { local SDNSSTAMP STATICNAME if [ "$1" -eq 0 ]; then local STATICRESOLVERS [ -z "${ADD_STATIC}" ] && toml_avars_prep dnscrypt_servers true doh_servers true odoh_servers false require_dnssec false require_nolog false require_nofilter false PTXT -n "${INPUT} Please choose Static Server Name${NORM}: " read -r STATICNAME PTXT -n "${INPUT} Please enter Static Server SDNS stamp${NORM}: " read -r SDNSSTAMP else if read_yesno "Do you want to set up another Static Server?"; then ANOTHER="YES"; else ANOTHER="NO"; fi if [ "${ANOTHER}" = "YES" ]; then PTXT -n "${INPUT} Please choose Static Server Name${NORM}: " read -r STATICNAME PTXT -n "${INPUT} Please enter Static Server SDNS stamp${NORM}: " read -r SDNSSTAMP elif [ "${ANOTHER}" = "NO" ]; then PTXT "${INFO} finished static setup." [ "${ADD_STATIC}" = "YES" ] && RESOLVERS="${STATICRESOLVERS}, ${RESOLVERS}" [ -z "${ADD_STATIC}" ] && toml_avars_prep server_names "\"[${STATICRESOLVERS}]\"" return fi fi local STATIC STATIC="${STATICNAME}-Static" if PTXT "${STATICRESOLVERS}" | grep -qoF "${STATIC}"; then PTXT "${INFO} ${STATIC} is already set" else toml_nvars_insert "[static]" "[static.'${STATICNAME}-Static']" "${TOML_FILE}" toml_nvars_insert "[static.'${STATICNAME}-Static']" "stamp = '${SDNSSTAMP}'" "${TOML_FILE}" if [ "${STATICRESOLVERS}" ]; then STATICRESOLVERS="${STATICRESOLVERS%?}', '${STATIC}'" else STATICRESOLVERS="'${STATIC}'" fi fi if read_yesno "Is ${STATIC} a DNSCrypt Server?"; then DNSCRYPT_STATIC="true"; else DNSCRYPT_STATIC="false"; fi if [ "${DNSCRYPT_STATIC}" = "true" ]; then if [ -z "${STAT_CRYPT}" ]; then STAT_CRYPT="${STATIC}" else STAT_CRYPT="${STAT_CRYPT}|${STATIC}" fi else if read_yesno "Is ${STATIC} an Oblivious DNS-over-HTTPS Server?"; then ODOH_ENABLE="true"; else ODOH_ENABLE="false"; fi if [ "${ODOH_ENABLE}" = "true" ]; then if [ -z "${STAT_ODOH}" ]; then if grep -q '^odoh_servers = .*false.*' "${TOML_FILE}"; then toml_avars_prep odoh_servers true; fi STAT_ODOH="${STATIC}" else STAT_ODOH="${STAT_ODOH}|${STATIC}" fi fi fi static_chosen 1 } static_chosen_relays() { local SDNSSTAMP STATICNAME if [ "$1" -eq 0 ]; then local STATICRELAYS PTXT -n "${INPUT} Please choose Static Relay Name${NORM}: " read -r STATICNAME PTXT -n "${INPUT} Please enter Static Relay SDNS stamp${NORM}: " read -r SDNSSTAMP else if read_yesno "Do you want to set up another Static Relay?"; then ANOTHER="YES"; else ANOTHER="NO"; fi if [ "${ANOTHER}" = "YES" ]; then PTXT -n "${INPUT} Please choose Static Relay Name${NORM}: " read -r STATICNAME PTXT -n "${INPUT} Please enter Static Relay SDNS stamp${NORM}: " read -r SDNSSTAMP elif [ "${ANOTHER}" = "NO" ]; then PTXT "${INFO} finished static setup." RELAYS="${STATICRELAYS}, ${RELAYS}" return fi fi local STATIC STATIC="${STATICNAME}-Static" if PTXT "${STATICRELAYS}" | grep -qoF "${STATIC}"; then PTXT "${INFO} ${STATIC} is already set" else toml_nvars_insert "[static]" "[static.'${STATICNAME}-Static']" "${TOML_FILE}" toml_nvars_insert "[static.'${STATICNAME}-Static']" "stamp = '${SDNSSTAMP}'" "${TOML_FILE}" if [ "${STATICRELAYS}" ]; then STATICRELAYS="${STATICRELAYS%?}', '${STATIC}'" else STATICRELAYS="'${STATIC}'" fi fi static_chosen_relays 1 } setup_dnscrypt() { if [ ! -f "${TOML_ORI}" ] || [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; then PTXT "${ERROR} dnscrypt-proxy is not installed. Aborting..." end_op_message 1 return fi PTXT "${INFO} Configuring dnscrypt-proxy..." setup_dnscrypt_impl "$@" local RET="$?" check_opendns if [ "$1" = "reconfig" ]; then if [ "${RET}" -eq 0 ]; then PTXT "${INFO} Restarting dnscrypt-proxy with new config..." service restart_dnscrypt-proxy >/dev/null 2>&1 end_op_message 0 else end_op_message 0 fi fi return "${RET}" } setup_dnscrypt_impl() { if [ -z "$1" ] && [ -f "${TOML_FILE}" ]; then if ! check_dnscrypt_toml; then setup_dnscrypt_impl x return fi PTXT "${INFO} Found previous dnscrypt-proxy config file" if read_yesno "Do you want to use this file without reconfiguring?"; then PTXT "${INFO} Use previous settings file"; else setup_dnscrypt_impl x; fi else if [ -f "${TOML_FILE}" ]; then if [ "$1" = "reconfig" ]; then if ! check_dnscrypt_toml; then setup_dnscrypt_impl x return fi PTXT "${INFO} Found previous dnscrypt-proxy config file" fi PTXT "${INFO} How do you want to reconfigure:" \ "${INFO} 1) Start from previous settings file" \ "${INFO} 2) Start from default config" read_input_num "Your selection" 1 2 case "${CHOSEN}" in 1) PTXT "${INFO} Use previous settings file" ;; 2) PTXT "${INFO} Backing up previous settings file..." mv "${TOML_FILE}" "${TOML_BAK}" cp -f "${TOML_ORI}" "${TOML_FILE}" ;; esac else cp -f "${TOML_ORI}" "${TOML_FILE}" fi case "${2:-reconfig}" in "install" | "reconfig") if read_yesno "Do you want to redirect all DNS resolutions on your network through to Dnscrypt-Proxy?"; then check_dns_filter 1; else check_dns_filter 0; fi if [ "$(nvram get dns_local_cache)" != "1" ]; then { if read_yesno "Do you want to run Dnsmasq as a local caching DNS service which includes sending the routers traffic to Dnscrypt-Proxy?"; then check_dns_local 1; else check_dns_local 0; fi; }; else { check_dns_local 0; }; fi toml_avar_enable disabled_server_names local PHX NXT PHX="$(grep -wn "sources.odoh-servers" "${TOML_FILE}" | cut -f1 -d:)" NXT="$((PHX + 11))" sed -i "${PHX},${NXT} s/#//g" "${TOML_FILE}" choose_dnscrypt_server PTXT "${INFO} Evaluating the possibilities for other dnscrypt-proxy configurations such as relay support..." check_relays PTXT "${INFO} Set the DNS server(s) for initializing dnscrypt-proxy" \ "${INFO} and router services (e.g. ntp) at boot" read_input_dns "Default is" 9.9.9.9 read_input_dns "2nd Default is" 8.8.8.8 read_input_num "Set log level, default is 2, 0 is the most verbose" 0 6 toml_nvars_replace "fallback_resolvers =" "bootstrap_resolvers = [$BOOTSTRAP2]" "$TOML_FILE" if read_yesno "Do you want to use TLSv1.3 (http3)?"; then toml_avar_disable tls_cipher_suite toml_avars_prep http3 true else toml_avar_enable tls_cipher_suite toml_avars_prep http3 false tls_cipher_suite "\"[52393, 52392, 49199, 49195, 4867, 4865]\"" fi toml_avars_prep bootstrap_resolvers "\"[${BOOTSTRAP2}]\"" log_level "${CHOSEN}" ignore_system_dns true listen_addresses "[\'127.0.1.1:53\']" cache false cert_ignore_timestamp true max_clients 25000 keepalive 120 netprobe_timeout 120 netprobe_address "\'${PROBE}\'" tls_disable_session_tickets true dnscrypt_ephemeral_keys true case "${ROUTER_MODEL}" in RT-AX56U | RT-AX58U | RT-AX3000) toml_avar_disable user_name ;; *) toml_avars_prep user_name "\'nobody\'" ;; esac PTXT "${INFO} Writing dnscrypt-proxy configuration..." if ! check_dnscrypt_toml; then PTXT "${INFO} Writing dnscrypt-proxy configuration failed " \ "${INFO} Please send ${TOML_ERR} file and screen log of " \ "${INFO} all operations you have made to this script dev" return 1 fi ;; esac fi } set_timezone() { local TMP TZ_DATA INDEX TZ_ARCH TMP="/root" TZ_ARCH="$(uname -m)" case "${TZ_ARCH}" in "aarch64" | "arm64") TZ_ARCH="aarch64" ;; "armv7l") TZ_ARCH="arm" ;; esac TZ_DATA="tzdata-2021e-1-${TZ_ARCH}.pkg.tar.bz2" download_file "${TARG_DIR}" 755 "${URL_GEN}/manager" download_file "${TMP}" 644 "${URL_GEN}/${TZ_DATA}" local INDEX INDEX="$(tar tjf "${TMP}/${TZ_DATA}" | awk -F'/' '!/\/$/ && /\/posix\//' | wc -l)" PTXT "${INFO} Available timezones/locations:" tar tjf "${TMP}/${TZ_DATA}" | awk -F'/' '!/\/$/ && /\/posix\//' | sort | cut -d'/' -f2- | awk -v INDEX=0 -F'/' '!/\/$/ {++INDEX;printf " " INDEX") ";for (i=5; i/dev/null 2>&1; } rm -r "${TMP:?}/${TZ_DATA}" "${TMP:?}/usr" end_op_message 0 } toml_avar_disable() { local VAR IDX_NX_AVAR VAR="$1" IDX_NX_AVAR="$(awk 'END {print NR}' "${TOML_FILE}")" sed -i "1,${IDX_NX_AVAR}{s/\(^${VAR} = .*\)/# \1/}" "${TOML_FILE}" } toml_avar_enable() { local VAR IDX_NX_AVAR VAR="$1" IDX_NX_AVAR="$(awk 'END {print NR}' "${TOML_FILE}")" sed -i "1,${IDX_NX_AVAR}{/^#.*${VAR} = .*$/s/^#\ //}" "${TOML_FILE}" } toml_avars_prep() { local AVARS_ARGS AVARS_ARGS="" AVARS_ARGS="${AVARS_ARGS} $@" eval toml_avars_write "${AVARS_ARGS}" } toml_avars_write() { local IDX_NX_AVAR IDX_GLB_INS VAR VALUE TO INDEX HAS_GLB_INS SED_CMD IDX_NX_AVAR="$(awk 'END {print NR}' "${TOML_FILE}")" IDX_GLB_INS="$(awk -v VAR="#.*Global settings.*" '($0 ~ VAR) {while (getline) {if ($0 ~ "^$") break} print NR;exit}' "${TOML_FILE}")" while [ "$#" -gt 0 ]; do VAR="$1" shift VALUE="$1" shift TO="$(_quote "${VAR} = ${VALUE}")" INDEX="$(awk -v IDX="${IDX_NX_AVAR}" -v VAR="^${VAR} = " '($0 ~ VAR) && (NR < IDX) {print NR; exit}' "${TOML_FILE}")" if [ "${INDEX}" ]; then SED_CMD="${INDEX}{s/.*/${TO}/};${SED_CMD}" continue fi INDEX="$(awk -v IDX="${IDX_NX_AVAR}" -v VAR="#.*${VAR} = " '($0 ~ VAR) && (NR < IDX) {print NR; exit}' "${TOML_FILE}")" if [ "${INDEX}" ]; then SED_CMD="${INDEX}{s/.*/${TO}/};${SED_CMD}" continue fi [ -z "${HAS_GLB_INS}" ] && SED_CMD="${SED_CMD}${IDX_GLB_INS}{s/^/\n${TO}\n" || SED_CMD="${SED_CMD}${TO}\n" HAS_GLB_INS="1" done [ "${HAS_GLB_INS}" ] && SED_CMD="${SED_CMD}/}" sed -i "${SED_CMD%;}" "${TOML_FILE}" } toml_nvars_insert() { PATTERN="$(_quote "$1")" CONTENT="$(_quote "$2")" sed -i "/${PATTERN}/a${CONTENT}" "$3" } toml_nvars_replace() { PATTERN="$(_quote "$1")" CONTENT="$(_quote "$2")" sed -i "s/${PATTERN}/${CONTENT}/" "$3" } toml_nvars_append() { echo "$1" >>"$2" } toml_nvars_delete() { PATTERN="$(_quote "$1")" sed -i "/${PATTERN}/d" "$2" } toml_static_removal() { PTXT "${INFO} Removing any static server configuration." toml_nvars_delete "[static.'" "${TOML_FILE}" toml_nvars_delete "stamp =" "${TOML_FILE}" } uninst_all() { if [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then PTXT "${INFO} Old Backup Detected!" if read_yesno "Do you want to remove backup?(this will prevent restoring from backups later)"; then rm -rf "${BASE_DIR}/backup_dnscrypt.tar.gz"; else PTXT "${INFO} Keeping backup instead."; fi fi service stop_dnscrypt-proxy >/dev/null 2>&1 mv "${TARG_DIR}/installer" "${HOME}/installer" rm -rf "${TARG_DIR}" del_jffs_script /jffs/scripts/dnsmasq.postconf del_jffs_script /jffs/scripts/init-start del_jffs_script /jffs/scripts/services-stop { kill -s 9 "$(pidof haveged rngd stty dnscrypt-proxy)" 2>/dev/null || killall -q -9 haveged rngd stty dnscrypt-proxy 2>/dev/null; } del_between_magic /jffs/scripts/service-event-end '# Asuswrt-Merlin-Dnscrypt-Proxy-Installer' local MAN_PID PID MAN_PID="$(pidof manager)" if [ "${MAN_PID}" ]; then for PID in ${MAN_PID}; do if awk '{ print }' "/proc/${PID}/cmdline" | grep -q dnscrypt; then { kill -s 10 "${PID}" 2>/dev/null || kill -s 9 "${PID}" 2>/dev/null; } break fi done fi service restart_dnsmasq >/dev/null 2>&1 end_op_message 0 } uninst_dnscrypt() { service stop_dnscrypt-proxy >/dev/null 2>&1 PTXT "${INFO} Uninstalling dnscrypt-proxy..." rm -f "${TARG_DIR}/dnscrypt-proxy" "${TARG_DIR}/nonroot" del_jffs_script /jffs/scripts/dnsmasq.postconf { kill -s 9 "$(pidof dnscrypt-proxy)" 2>/dev/null || killall -q -9 dnscrypt-proxy 2>/dev/null; } service restart_dnsmasq >/dev/null 2>&1 PTXT "${INFO} Some configuration files are not removed in case you want to reinstall" end_op_message 0 } uninst_random() { PTXT "${INFO} Uninstalling (P)RNG..." rm -f "${TARG_DIR}/haveged" "${TARG_DIR}/rngd" "${TARG_DIR}/stty" { kill -s 9 "$(pidof haveged rngd stty)" 2>/dev/null || killall -q -9 haveged rngd stty 2>/dev/null; } del_conf RAN_PRV RNG_DEV if [ ! -f "${TARG_DIR}/localtime" ] && [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; then del_jffs_script /jffs/scripts/init-start del_jffs_script /jffs/scripts/services-stop fi end_op_message 0 } unset_timezone() { rm -f "${TARG_DIR}/localtime" if ! grep -q "^RAN_PRV=.*$" "${TARG_DIR}/.config" && [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; then del_jffs_script /jffs/scripts/init-start del_jffs_script /jffs/scripts/services-stop fi end_op_message 0 } write_conf() { local VAR VALUE VAR="$1" VALUE="$2" if [ -f "${TARG_DIR}/.opendns-auth" ]; then mv "${TARG_DIR}/.opendns-auth" "${CONF_FILE}" chmod 644 "${CONF_FILE}" fi if [ ! -f "${CONF_FILE}" ]; then touch "${CONF_FILE}" && chmod 644 "${CONF_FILE}" fi if grep -q "${VAR}" "${CONF_FILE}"; then VALUE=$(_quote "${VALUE}") sed -i "/^${VAR}=/s/=.*/=${VALUE}/" "${CONF_FILE}" else PTXT "${VAR}=${VALUE}" >>"${CONF_FILE}" fi } write_command_script() { local TARG COMMAND FILENAME TARG="$1" COMMAND="$2" FILENAME="$(basename "${TARG}")" if [ ! -f "${TARG}" ]; then PTXT "${INFO} Creating ${FILENAME} file" PTXT "#!/bin/sh" >"${TARG}" fi chmod 755 "${TARG}" if [ "$(grep -c -F "${COMMAND}" "${TARG}")" -gt 0 ]; then PTXT "${INFO} ${FILENAME} file already configured" else PTXT "${INFO} Configure ${FILENAME} file" PTXT "${COMMAND}" >>"${TARG}" fi } write_manager_script() { local TARG OP FILENAME COMMAND TARG="$1" OP="$2" FILENAME="$(basename "${TARG}")" COMMAND="${TARG_DIR}/manager" if [ ! -f "${TARG}" ]; then PTXT "${INFO} Creating ${FILENAME} file" PTXT "#!/bin/sh" >"${TARG}" fi chmod 755 "${TARG}" "${COMMAND}" del_between_magic "${TARG}" dnscrypt-asuswrt-installer if [ "$(grep -c -F "[ -x ${COMMAND} ] && ${COMMAND} ${OP}" "${TARG}")" -gt 0 ]; then PTXT "${INFO} ${FILENAME} file already configured" else PTXT "${INFO} Configure ${FILENAME} file" if grep -q "^${COMMAND}" "${TARG}"; then sed -i "s~^${COMMAND}~[ -x ${COMMAND} ] \&\& ${COMMAND} ${OP}~" "${TARG}" else del_jffs_script "${TARG}" !manager [ "$(tail -1 "${TARG}" | grep -c '^$')" -eq 0 ] && PTXT "" >>"${TARG}" PTXT "[ -x ${COMMAND} ] && ${COMMAND} ${OP}" >>"${TARG}" fi fi } [ "$1" ] && BRANCH="$1" || BRANCH="master" [ -z "$(nvram get odmpid)" ] && ROUTER_MODEL="$(nvram get productid)" || ROUTER_MODEL="$(nvram get odmpid)" RURL="https://raw.githubusercontent.com/thuantran/dnscrypt-asuswrt-installer/${BRANCH}" URL_GEN="${RURL}/gen" ROUTER_OS="$(uname)" ROUTER_ARCH="$(uname -m)" [ -z "${ROUTER_MODEL}" ] && PTXT "${ERROR} This is an unsupported router, sorry." && sleep 3s && exit 1 [ "$(nvram get sw_mode)" != "1" ] && PTXT "${ERROR} You are not running in router mode, sorry." && sleep 3s && exit 1 if [ -z "$2" ]; then printf '\e[8;50;125t' printf '\033[?7l' clear sed -n '2,21p' "$0" printf '\033[?7h' fi case "${ROUTER_MODEL}" in #RT-AX56U|RT-AX58U|RT-AX3000) # PTXT "${ERROR} This is an unsupported router, sorry." # exit 1 # ;; *) [ -z "$2" ] && PTXT "${INFO} Detected ${ROUTER_MODEL} router." ;; esac case "${ROUTER_OS}" in "Linux") [ -z "$2" ] && PTXT "${INFO} Detected ${ROUTER_OS} platform." ROUTER_OS="linux" ;; *) PTXT "${ERROR} This is an unsupported platform, sorry." exit 1 ;; esac case "${ROUTER_ARCH}" in "aarch64" | "arm64") ROUTER_ARCH="arm64" URL_ARCH="${RURL}/armv8" DNSCRYPT_ARCH="${ROUTER_OS}_${ROUTER_ARCH}" DNSCRYPT_ARCH_TAR="${ROUTER_OS}-${ROUTER_ARCH}" [ -z "$2" ] && PTXT "${INFO} Detected ARMv8 architecture." ;; "armv7l") ROUTER_ARCH="arm" URL_ARCH="${RURL}/armv7" DNSCRYPT_ARCH="${ROUTER_OS}_${ROUTER_ARCH}" DNSCRYPT_ARCH_TAR="${ROUTER_OS}-${ROUTER_ARCH}" [ -z "$2" ] && PTXT "${INFO} Detected ARMv7 architecture." ;; *) PTXT "${ERROR} This is an unsupported architecture, sorry." exit 1 ;; esac menu() { trap - HUP INT QUIT ABRT TERM case "$1" in "") PTXT "${INFO} Choose what you want to do:" \ " 1) Install/Update dnscrypt-proxy" \ " 2) Uninstall dnscrypt-proxy" \ " 3) Configure dnscrypt-proxy" \ " 4) Set timezone" \ " 5) Unset timezone" \ " 6) Install (P)RNG" \ " 7) Uninstall (P)RNG" \ " 8) Install swap file" \ " 9) Uninstall ALL" if { [ -d "${TARG_DIR}" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ]; }; then { PTXT " b) Backup"; }; fi if { [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; }; then { PTXT " r) Restore"; }; fi PTXT " q) Quit" if { [ ! -d "${TARG_DIR}" ] || [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; } && [ ! -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then { read_input_num "Please enter the number that designates your selection:" 1 9 q; }; fi if { [ ! -d "${TARG_DIR}" ] || [ ! -f "${TARG_DIR}/dnscrypt-proxy" ]; } && [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; then { read_input_num "Please enter the number that designates your selection:" 1 9 r q; }; fi if { [ -d "${TARG_DIR}" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ] && [ ! -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; }; then { read_input_num "Please enter the number that designates your selection:" 1 9 b q; }; fi if { [ -d "${TARG_DIR}" ] && [ -f "${TARG_DIR}/dnscrypt-proxy" ] && [ -f "${BASE_DIR}/backup_dnscrypt.tar.gz" ]; }; then { read_input_num "Please enter the number that designates your selection:" 1 9 b r q; }; fi ;; *) CHOSEN="$1" ;; esac [ -n "${CHOSEN}" ] && trap 'clear; end_op_message 2' HUP INT QUIT ABRT TERM case "${CHOSEN}" in "1" | "install" | "update") [ "${CHOSEN}" = "update" ] && AUTO_UPDATE="update" PTXT "${INFO} This operation will install dnscrypt-proxy and related files (<6MB)" \ "${INFO} to jffs, no other data will be changed." \ "${INFO} Also some start scripts will be installed/modified as required." if read_yesno "Do you want to install dnscrypt-proxy to /jffs?"; then inst_dnscrypt "${AUTO_UPDATE:-install}"; else end_op_message 1; fi ;; "2" | "uninstall") PTXT "${INFO} This operation will uninstall dnscrypt-proxy and related files" \ "${INFO} from jffs, no other data will be changed." \ "${INFO} Also some start scripts will be modified as required." if read_yesno "Do you want to uninstall dnscrypt-proxy from /jffs?"; then uninst_dnscrypt; else end_op_message 1; fi ;; "3" | "configure") PTXT "${INFO} This operation allows you to configure dnscrypt-proxy" if read_yesno "Do you want to proceed?"; then setup_dnscrypt reconfig; else end_op_message 1; fi ;; "4" | "setTZ") PTXT "${INFO} This operation allows you to set your router timezone for background services and processes." if read_yesno "Do you want to proceed?"; then set_timezone; else end_op_message 1; fi ;; "5" | "unsetTZ") PTXT "${INFO} This operation allows you to unset your router timezone for background services and processes." if read_yesno "Do you want to proceed?"; then unset_timezone; else end_op_message 1; fi ;; "6" | "instRNG") PTXT "${INFO} This operation will install a (P)RNG (<0.5MB) to jffs, no other data will be changed." \ "${INFO} Also some start scripts will be installed/modified as required." if read_yesno "Do you want to install (P)RNG to /jffs?"; then inst_random; else end_op_message 1; fi ;; "7" | "unstRNG") PTXT "${INFO} This operation will uninstall (P)RNG" \ "${INFO} from jffs, no other data will be changed." \ "${INFO} Also some start scripts will be installed/modified as required." if read_yesno "Do you want to uninstall (P)RNG from /jffs?"; then uninst_random; else end_op_message 1; fi ;; "8" | "instSWAP") PTXT "${INFO} This operation will install a swap file for your device." \ "${INFO} You need an external USB storage to host this file." if read_yesno "Do you want to install a swap file (512MB on ext filesystem partition)?"; then check_swap; else end_op_message 1; fi ;; "9" | "unstALL") PTXT "${INFO} This operation will cleanup everything installed by this script (except swap)." if read_yesno "Do you want to continue?"; then uninst_all; else end_op_message 1; fi ;; "b" | "B" | "backup") PTXT "${INFO} This operation will backup everything!" if read_yesno "Do you want to continue?"; then backup_restore BACKUP; else end_op_message 1; fi ;; "r" | "R" | "restore") PTXT "${INFO} This operation will restore everything!" if read_yesno "Do you want to continue?"; then backup_restore RESTORE; else end_op_message 1; fi ;; "q" | "Q") PTXT "${INFO} Operations have been applied if any has been made" \ "${INFO} In case of anomaly, please reboot your router!" if [ -f "${HOME}/installer" ]; then rm -rf "${HOME}/installer"; fi sleep 3s clear ;; esac } case "$2" in "") cleanup check_jffs_enabled check_dns_environment check_version menu ;; [1-9] | "install" | "update" | "uninstall" | "configure" | "setTZ" | "unsetTZ" | "instRNG" | "unstRNG" | "instSWAP" | "unstALL" | [bB] | "backup" | [rR] | "restore") menu "$2" ;; *) PTXT "${INFO} Usage: sh installer {master|dev?|""} (1 - {install/update} | 2 - uninstall | 3 - configure | 4 - setTZ | 5 - unsetTZ | 6 - instRNG | 7 - unstRNG | 8 - instSWAP | 9 - unstALL | {b/B} - backup | {r/R} - restore)" \ "${INFO} Branch or Tag must be represented by a value or empty quotes in place of string e.g. \"\" in the \$1 string position." \ "${INFO} Action must be represented by a usage value in the \$2 string position." \ "${INFO} An update example: sh installer master update, or just use the regular menu by not specifying an action e.g: sh installer master." ;; esac