update-hosts-root.sh 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #!/bin/bash
  2. # Filename: update-hosts.sh
  3. #
  4. # Author: George Lesica <george@lesica.com>
  5. # Enhanced by Eliastik ( eliastiksofts.com/contact )
  6. # Version 1.3 (22 april 2021) - Eliastik
  7. #
  8. # Description: Replaces the HOSTS file with hosts lists from Internet,
  9. # creating a backup of the old file. Can be used as an update script.
  10. #
  11. # Enhancement by Eliastik :
  12. # Added the possibility to download multiple hosts files from multiple sources,
  13. # added the possibility to use an initial hosts file to be appended at the top
  14. # of the system hosts file, added a possibility to uninstall and restore
  15. # the hosts file, added incorrect/malicious entries checking,
  16. # added the possibility to exclude hosts filtering for specific domains, others fixes.
  17. #
  18. # Can be used as a cron script.
  19. #
  20. # Launch arguments:
  21. # - Without arguments (./update-hosts.sh), the script update the hosts file
  22. # - With restore (./update-hosts.sh restore), the script restore the backup hosts file if it exists
  23. # - With uninstall (./update-hosts.sh uninstall), the script uninstall the hosts file and restore only the initial hosts file
  24. # - With check (./update-hosts.sh check), the script check the hosts file for incorrect or malicious entries (no root needed)
  25. # Configuration variables:
  26. # Add an hosts source by adding a space after the last entry of the variable HOSTS_URLS (before the ")"), then by adding your URL with quotes (ex: "http://www.example.com/hosts.txt")
  27. HOSTS_URLS=( "https://someonewhocares.org/hosts/zero/hosts" "https://pgl.yoyo.org/adservers/serverlist.php?showintro=0&mimetype=plaintext&useip=0.0.0.0" "https://winhelp2002.mvps.org/hosts.txt" )
  28. HOSTS_PATH="/etc/hosts" # The path to the hosts file
  29. INITIAL_HOSTS="/etc/hosts.initial" # The initial host file to be appended at the top of the hosts file
  30. EXCLUDE_HOSTS="/etc/hosts.exclude" # A file containing a list of domain to be excluded from the hosts file (1 domain per line)
  31. NEW_HOSTS="hosts" # New host name
  32. NB_MAX_DOWNLOAD_RETRY=10
  33. CHECK_HOSTS=0 # 1 for checking for malicious entries, 0 to disable
  34. GOOD_HOSTS=( "127."*"."*"."* "10."*"."*"."* "0.0.0.0" "255.255.255.255" "::1" "fe"*"::"* "ff0"*"::"* ) # A list of safe hosts
  35. function check_hosts() {
  36. echo "Checking hosts data..."
  37. lineNumber=0
  38. fileLines=$(cat $HOSTS_PATH | tr '\t' ' ' | tr '\r' ' ' | sed -e 's/^[[:space:]]*//' | cut -d " " -f1)
  39. while IFS= read -r line; do
  40. lineNumber=$((lineNumber + 1))
  41. found=0
  42. first_word="$(echo "$line" | head -n1)"
  43. first_letter="$(echo "$first_word" | head -c 1)"
  44. if [ -n "${first_word// }" ] && [ "$first_letter" != "#" ]; then
  45. for i in "${GOOD_HOSTS[@]}"; do
  46. if [[ "$first_word" == $i ]]; then
  47. found=1
  48. fi
  49. done
  50. if [ "$found" = "0" ]; then
  51. echo "Found incorrect or malicious entry. Exiting..."
  52. echo "Entry found: '${line}' at line $lineNumber"
  53. return 1
  54. fi
  55. fi
  56. done <<< "$fileLines"
  57. echo "No incorrect or malicious entry found."
  58. return 0
  59. }
  60. function check_root() {
  61. if [ "$(id -u)" -ne "0" ]; then
  62. echo "This script must be run as root. Exiting..." 1>&2
  63. exit 1
  64. fi
  65. }
  66. function check_curl() {
  67. if ! [ -x "$(command -v curl)" ]; then
  68. echo "Error: curl is not installed. Please install it to run this script." >&2
  69. exit 1
  70. fi
  71. }
  72. # Check for arguments - restore or uninstall the hosts file
  73. if [ $# -ge 1 ]; then
  74. if [ "$1" = "restore" ]; then
  75. check_root
  76. echo "Restoring your hosts file backup..."
  77. if [ -f "${HOSTS_PATH}.bak" ]; then
  78. cp -v ${HOSTS_PATH}.bak $HOSTS_PATH
  79. echo "Done!"
  80. exit 0
  81. else
  82. echo "The backup hosts file doesn't exist: ${HOSTS_PATH}.bak"
  83. echo "Exiting..."
  84. exit 1
  85. fi
  86. fi
  87. if [ "$1" = "uninstall" ]; then
  88. check_root
  89. echo "Uninstalling your hosts file and restoring initial hosts file..."
  90. if [ -f "$INITIAL_HOSTS" ]; then
  91. cp -v $INITIAL_HOSTS $HOSTS_PATH
  92. echo "Done!"
  93. exit 0
  94. else
  95. echo "The initial hosts file doesn't exist: $INITIAL_HOSTS"
  96. echo "Exiting..."
  97. exit 1
  98. fi
  99. fi
  100. if [ "$1" = "check" ]; then
  101. if [ -f "${HOSTS_PATH}" ]; then
  102. check_hosts $HOSTS_PATH || exit 1
  103. exit 0
  104. else
  105. echo "The hosts file doesn't exist: $HOSTS_PATH"
  106. echo "Exiting..."
  107. exit 1
  108. fi
  109. fi
  110. fi
  111. check_root # Check for root
  112. check_curl # Check for curl
  113. # Check for hosts file
  114. if [ ! -f "${HOSTS_PATH}" ]; then
  115. echo "The hosts file doesn't exist: $HOSTS_PATH"
  116. echo "Exiting..."
  117. exit 1
  118. fi
  119. # Create temporary directory
  120. echo "Creating temporary directory..."
  121. TEMP_DIR=`mktemp -d`
  122. if [[ ! "$TEMP_DIR" || ! -d "$TEMP_DIR" ]]; then
  123. echo "The temporary directory could not have been created. Exiting securely..."
  124. exit 1
  125. fi
  126. cd "$TEMP_DIR"
  127. echo "Created temporary directory at $(pwd)"
  128. # Create new temp hosts
  129. echo "">$NEW_HOSTS
  130. # Print the update time
  131. DATE=`date '+%Y-%m-%d %H:%M:%S'`
  132. echo "">>$NEW_HOSTS
  133. echo "# HOSTS last updated: $DATE">>$NEW_HOSTS
  134. echo "#">>$NEW_HOSTS
  135. # Grab hosts file
  136. for i in "${HOSTS_URLS[@]}"
  137. do
  138. :
  139. nberror=0
  140. echo "Downloading hosts list from: $i"
  141. while true; do
  142. curl -s --fail "$i">>$NEW_HOSTS && break ||
  143. nberror=$((nberror + 1))
  144. echo "Download failed ! Retrying..."
  145. if [ $nberror -ge $NB_MAX_DOWNLOAD_RETRY ]; then
  146. echo "Download failed $NB_MAX_DOWNLOAD_RETRY time(s). Check your Internet connection and the hosts source then try again. Exiting..."
  147. exit 1
  148. fi
  149. done
  150. done
  151. # Backup old hosts file
  152. echo "Backup old hosts file..."
  153. cp -v $HOSTS_PATH ${HOSTS_PATH}.bak
  154. if ! [ -f "${HOSTS_PATH}.bak" ]; then
  155. echo "HOSTS file backup not created. Exiting securely..."
  156. exit 1
  157. fi
  158. # Exclude hosts (from EXCLUDE_HOSTS file)
  159. if [ -f "$EXCLUDE_HOSTS" ]; then
  160. echo "Excluding hosts..."
  161. lineNumber=0
  162. linesHost=$(cat "$NEW_HOSTS" | tr '\t' ' ' | tr '\r' ' ')
  163. linesHostExcluded=$(cat "$EXCLUDE_HOSTS" | tr '\t' ' ' | tr '\r' ' ')
  164. while read -r lineHost; do
  165. lineNumber=$((lineNumber + 1))
  166. excludedHost=0
  167. fileHost=$(echo "$lineHost" | tr '\t' ' ' | tr '\r' ' ' | sed -e 's/^[[:space:]]*//' | cut -d " " -f2 | head -n2)
  168. while read -r lineExclude; do
  169. if [[ "$fileHost" == $lineExclude ]]; then
  170. echo "Excluded '${lineHost}' (line $lineNumber)"
  171. excludedHost=1
  172. fi
  173. done <<< $linesHostExcluded
  174. if [ "$excludedHost" = "0" ]; then
  175. echo "$lineHost">>$NEW_HOSTS".tmp"
  176. fi
  177. done <<< $linesHost
  178. echo "">$NEW_HOSTS
  179. cat $NEW_HOSTS".tmp">>$NEW_HOSTS
  180. fi
  181. # Checking new hosts
  182. if [ "$CHECK_HOSTS" = "1" ]; then
  183. check_hosts $NEW_HOSTS || ( echo "You can disable hosts checking by changing the value of the variable CHECK_HOSTS to 0 in the script." && exit 1 )
  184. fi
  185. # Install hosts
  186. echo "Installing hosts list..."
  187. # Copy initial hosts
  188. if [ -f "$INITIAL_HOSTS" ]; then
  189. cat $INITIAL_HOSTS>$HOSTS_PATH
  190. else
  191. echo "The initial hosts file doesn't exist: $INITIAL_HOSTS"
  192. echo "">$HOSTS_PATH
  193. fi
  194. cat $NEW_HOSTS >> $HOSTS_PATH
  195. # Clean up old downloads
  196. echo "Removing cache..."
  197. rm $NEW_HOSTS*
  198. echo "Done!"
  199. exit 0