128 lines
3.5 KiB
Bash
Executable File
128 lines
3.5 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# Must run as root
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo "🚨 This script must be run as root."
|
||
echo "👉 Please run it using: sudo $0"
|
||
exit 1
|
||
fi
|
||
|
||
DOMAINS_FILE="domains.txt"
|
||
HOSTS_FILE="/etc/hosts"
|
||
TMP_HOSTS=$(mktemp)
|
||
|
||
cp "$HOSTS_FILE" "$TMP_HOSTS"
|
||
|
||
CURRENT_CATEGORY=""
|
||
declare -a CATEGORY_DOMAINS=()
|
||
|
||
log() {
|
||
echo "🔧 $1"
|
||
}
|
||
|
||
add_ipv4_block() {
|
||
local ip="127.0.0.1"
|
||
local comment="$1"
|
||
|
||
log "Adding IPv4 entries under category: $comment"
|
||
|
||
if grep -Fxq "$comment" "$TMP_HOSTS"; then
|
||
END_LINE=$(awk -v cat="$comment" '
|
||
$0 == cat { found=1; next }
|
||
found && $0 ~ /^#/ { exit }
|
||
found { line=NR }
|
||
END { print (line ? line : 0) }
|
||
' "$TMP_HOSTS")
|
||
INSERT_LINE=$((END_LINE + 1))
|
||
|
||
for domain in "${CATEGORY_DOMAINS[@]}"; do
|
||
if ! grep -qE "^[[:space:]]*$ip[[:space:]]+$domain\$" "$TMP_HOSTS"; then
|
||
log " ➕ Inserting $ip $domain at line $INSERT_LINE"
|
||
sed -i "${INSERT_LINE}i$ip $domain" "$TMP_HOSTS"
|
||
((INSERT_LINE++))
|
||
else
|
||
log " ⚠️ Skipping duplicate: $ip $domain"
|
||
fi
|
||
done
|
||
else
|
||
log " 🔹 Category not found, appending new category: $comment"
|
||
echo "" >> "$TMP_HOSTS"
|
||
echo "$comment" >> "$TMP_HOSTS"
|
||
for domain in "${CATEGORY_DOMAINS[@]}"; do
|
||
echo "$ip $domain" >> "$TMP_HOSTS"
|
||
log " ➕ Appended $ip $domain"
|
||
done
|
||
fi
|
||
}
|
||
|
||
add_ipv6_block() {
|
||
local ip="::1"
|
||
local comment="$1 ipv6"
|
||
|
||
log "Adding IPv6 entries under category: $comment"
|
||
|
||
if grep -Fxq "$comment" "$TMP_HOSTS"; then
|
||
END_LINE=$(awk -v cat="$comment" '
|
||
$0 == cat { found=1; next }
|
||
found && $0 ~ /^#/ { exit }
|
||
found { line=NR }
|
||
END { print (line ? line : 0) }
|
||
' "$TMP_HOSTS")
|
||
INSERT_LINE=$((END_LINE + 1))
|
||
|
||
for domain in "${CATEGORY_DOMAINS[@]}"; do
|
||
if ! grep -qE "^[[:space:]]*$ip[[:space:]]+$domain\$" "$TMP_HOSTS"; then
|
||
log " ➕ Inserting $ip $domain at line $INSERT_LINE"
|
||
sed -i "${INSERT_LINE}i$ip $domain" "$TMP_HOSTS"
|
||
((INSERT_LINE++))
|
||
else
|
||
log " ⚠️ Skipping duplicate: $ip $domain"
|
||
fi
|
||
done
|
||
else
|
||
log " 🔹 IPv6 category not found, appending: $comment"
|
||
echo "" >> "$TMP_HOSTS"
|
||
echo "$comment" >> "$TMP_HOSTS"
|
||
for domain in "${CATEGORY_DOMAINS[@]}"; do
|
||
echo "$ip $domain" >> "$TMP_HOSTS"
|
||
log " ➕ Appended $ip $domain"
|
||
done
|
||
fi
|
||
}
|
||
|
||
flush_category() {
|
||
[[ -z "$CURRENT_CATEGORY" ]] && return
|
||
|
||
log "📦 Flushing category: $CURRENT_CATEGORY"
|
||
add_ipv4_block "$CURRENT_CATEGORY"
|
||
add_ipv6_block "$CURRENT_CATEGORY"
|
||
|
||
CURRENT_CATEGORY=""
|
||
CATEGORY_DOMAINS=()
|
||
}
|
||
|
||
# Read and process domains.txt
|
||
while IFS= read -r line || [ -n "$line" ]; do
|
||
line=$(echo "$line" | sed 's/^[ \t]*//;s/[ \t]*$//') # Trim spaces
|
||
[[ -z "$line" ]] && continue
|
||
|
||
if [[ "$line" == \#* ]]; then
|
||
flush_category
|
||
CURRENT_CATEGORY="$line"
|
||
else
|
||
CATEGORY_DOMAINS+=("$line")
|
||
fi
|
||
done < "$DOMAINS_FILE"
|
||
|
||
flush_category
|
||
|
||
# Backup and replace /etc/hosts
|
||
cp "$HOSTS_FILE" "${HOSTS_FILE}.bak"
|
||
cp "$TMP_HOSTS" "$HOSTS_FILE"
|
||
|
||
log "✅ Hosts file updated with IPv4 and IPv6 domain blocks under categories."
|
||
log "🗂️ Backup created at ${HOSTS_FILE}.bak"
|
||
|
||
rm "$TMP_HOSTS"
|
||
|