Skip to content

Commit ee14a1a

Browse files
add_whitelists.sh
1 parent 2a647cb commit ee14a1a

File tree

1 file changed

+73
-167
lines changed

1 file changed

+73
-167
lines changed

add_whitelists.sh

Lines changed: 73 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,78 @@
1-
#!/usr/bin/env bash
2-
set -Eeuo pipefail
3-
4-
POSTFIX_FILE="/etc/postfix/client_whitelist"
5-
POSTGREY_FILE="/etc/postgrey/whitelist_clients.local"
6-
BACKUP_DATE="$(date +%F_%H%M%S)"
7-
8-
usage() {
9-
cat <<'EOF'
10-
Usage:
11-
./add_whitelists.sh [-n] <domain-or-ip>
12-
./add_whitelists.sh [-n] -f <file_with_entries>
13-
14-
Options:
15-
-f FILE File with entries (one per line, empty lines and #comments ignored)
16-
-n Dry-run mode (no changes applied)
17-
-h Show this help message
18-
EOF
19-
exit 1
20-
}
21-
22-
DRY=0
23-
LIST_FILE=""
24-
while getopts ":f:nh" opt; do
25-
case "$opt" in
26-
f) LIST_FILE="$OPTARG" ;;
27-
n) DRY=1 ;;
28-
h) usage ;;
29-
*) usage ;;
30-
esac
1+
#!/bin/bash
2+
3+
# Скрипт для добавления доменов и IP в Postfix и Postgrey whitelist
4+
# Использование: ./add_whitelists.sh whitelist.txt
5+
6+
# Цвета
7+
RED="\e[31m"
8+
GREEN="\e[32m"
9+
YELLOW="\e[33m"
10+
CYAN="\e[36m"
11+
RESET="\e[0m"
12+
13+
# Проверка аргумента
14+
if [ -z "$1" ]; then
15+
echo -e "${RED}Укажите файл с доменами и IP. Пример: ./add_whitelists.sh whitelist.txt${RESET}"
16+
exit 1
17+
fi
18+
19+
LIST_FILE="$1"
20+
DRY_RUN=0
21+
22+
echo -e "🛠 ${CYAN}Dry-run:${RESET} $DRY_RUN"
23+
24+
# Пути к файлам
25+
PF_FILE="/etc/postfix/client_whitelist"
26+
PG_FILE="/etc/postgrey/whitelist_clients.local"
27+
28+
# Создаём файлы, если нет
29+
echo -e "📄 ${YELLOW}Creating file:${RESET} $PF_FILE"
30+
touch "$PF_FILE"
31+
32+
echo -e "📄 ${YELLOW}Creating file:${RESET} $PG_FILE"
33+
touch "$PG_FILE"
34+
35+
# Резервные копии
36+
PF_BACKUP="${PF_FILE}.bak_$(date +%F_%H%M%S)"
37+
PG_BACKUP="${PG_FILE}.bak_$(date +%F_%H%M%S)"
38+
39+
cp "$PF_FILE" "$PF_BACKUP"
40+
echo -e "📦 ${CYAN}Backup:${RESET} $PF_BACKUP"
41+
42+
cp "$PG_FILE" "$PG_BACKUP"
43+
echo -e "📦 ${CYAN}Backup:${RESET} $PG_BACKUP"
44+
45+
# Добавляем в Postfix
46+
grep -vE '^\s*#|^\s*$' "$LIST_FILE" | while read -r entry; do
47+
echo "$entry OK" >> "$PF_FILE"
3148
done
32-
shift $((OPTIND - 1))
49+
echo -e "${GREEN}Adding to Postfix:${RESET} $LIST_FILE OK"
3350

34-
SINGLE_TARGET="${1:-}"
51+
# Добавляем в Postgrey (только домены, без IP)
52+
grep -vE '^\s*#|^\s*$' "$LIST_FILE" | grep -vE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' >> "$PG_FILE"
53+
echo -e "${GREEN}Adding to Postgrey:${RESET} $LIST_FILE"
3554

36-
if [[ -z "$SINGLE_TARGET" && -z "$LIST_FILE" ]]; then
37-
usage
38-
fi
55+
# Перегенерация и рестарт сервисов
56+
postmap "$PF_FILE"
57+
echo -e "🔄 ${YELLOW}Restarting Postfix${RESET}"
58+
systemctl restart postfix
3959

40-
msg() { printf '%b\n' "$*"; }
41-
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
42-
43-
require_root() {
44-
if [[ $EUID -ne 0 ]]; then
45-
die "Run as root or with sudo."
46-
fi
47-
}
48-
49-
ensure_file() {
50-
local path="$1"
51-
local dir
52-
dir="$(dirname "$path")"
53-
if [[ ! -d "$dir" ]]; then
54-
msg "📁 Creating directory: $dir"
55-
[[ $DRY -eq 0 ]] && mkdir -p "$dir"
56-
fi
57-
if [[ ! -f "$path" ]]; then
58-
msg "📝 Creating file: $path"
59-
[[ $DRY -eq 0 ]] && touch "$path"
60-
[[ $DRY -eq 0 ]] && chmod 644 "$path"
61-
fi
62-
}
63-
64-
backup_if_exists() {
65-
local path="$1"
66-
if [[ -f "$path" ]]; then
67-
msg "🗂 Backup: ${path}.bak_${BACKUP_DATE}"
68-
[[ $DRY -eq 0 ]] && cp -a "$path" "${path}.bak_${BACKUP_DATE}"
69-
fi
70-
}
71-
72-
is_domain() {
73-
local s="$1"
74-
[[ "$s" =~ ^([A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$ ]]
75-
}
76-
77-
is_ipv4() {
78-
local s="$1"
79-
[[ "$s" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
80-
}
81-
82-
is_cidr() {
83-
local s="$1"
84-
[[ "$s" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$ ]]
85-
}
86-
87-
already_in_file() {
88-
local needle="$1"
89-
local file="$2"
90-
grep -qE -- "^${needle//./\\.}([[:space:]]|$)" "$file"
91-
}
92-
93-
add_postfix() {
94-
local v="$1"
95-
if already_in_file "$v" "$POSTFIX_FILE"; then
96-
msg "ℹ️ Already in Postfix: $v"
97-
return 1
98-
fi
99-
msg "➕ Adding to Postfix: $v OK"
100-
[[ $DRY -eq 0 ]] && echo "$v OK" >> "$POSTFIX_FILE"
101-
return 0
102-
}
103-
104-
add_postgrey() {
105-
local v="$1"
106-
if already_in_file "$v" "$POSTGREY_FILE"; then
107-
msg "ℹ️ Already in Postgrey: $v"
108-
return 1
109-
fi
110-
msg "➕ Adding to Postgrey: $v"
111-
[[ $DRY -eq 0 ]] && echo "$v" >> "$POSTGREY_FILE"
112-
return 0
113-
}
114-
115-
process_entry() {
116-
local raw="$1"
117-
local entry
118-
entry="$(echo "$raw" | tr '[:upper:]' '[:lower:]' | xargs)"
119-
[[ -z "$entry" ]] && return 0
120-
[[ "$entry" =~ ^# ]] && return 0
121-
122-
if is_cidr "$entry"; then
123-
msg "⚠️ CIDR '$entry' not supported in hash map."
124-
return 0
125-
elif is_ipv4 "$entry"; then
126-
add_postfix "$entry" && CHANGED_POSTFIX=1 || true
127-
elif is_domain "$entry"; then
128-
add_postfix "$entry" && CHANGED_POSTFIX=1 || true
129-
add_postgrey "$entry" && CHANGED_POSTGREY=1 || true
130-
else
131-
msg "❌ Invalid entry: $entry"
132-
ERRORS=$((ERRORS + 1))
133-
return 1
134-
fi
135-
}
136-
137-
require_root
138-
msg "🔧 Dry-run: $DRY"
139-
140-
ensure_file "$POSTFIX_FILE"
141-
ensure_file "$POSTGREY_FILE"
142-
backup_if_exists "$POSTFIX_FILE"
143-
backup_if_exists "$POSTGREY_FILE"
144-
145-
CHANGED_POSTFIX=0
146-
CHANGED_POSTGREY=0
147-
ERRORS=0
148-
149-
if [[ -n "$LIST_FILE" ]]; then
150-
[[ -f "$LIST_FILE" ]] || die "File not found: $LIST_FILE"
151-
while IFS= read -r line || [[ -n "$line" ]]; do
152-
process_entry "$line" || true
153-
done < "$LIST_FILE"
154-
else
155-
process_entry "$SINGLE_TARGET" || true
156-
fi
60+
echo -e "🔄 ${YELLOW}Restarting Postgrey${RESET}"
61+
systemctl restart postgrey
15762

158-
if [[ $DRY -eq 0 ]]; then
159-
if [[ $CHANGED_POSTFIX -eq 1 ]]; then
160-
msg "🧰 postmap $POSTFIX_FILE"
161-
postmap "$POSTFIX_FILE"
162-
msg "🔄 Restarting Postfix"
163-
systemctl restart postfix
164-
fi
165-
if [[ $CHANGED_POSTGREY -eq 1 ]]; then
166-
msg "🔄 Restarting Postgrey"
167-
systemctl restart postgrey || true
168-
fi
169-
msg "✅ Done. Changes: Postfix=${CHANGED_POSTFIX}, Postgrey=${CHANGED_POSTGREY}, Errors=${ERRORS}"
170-
else
171-
msg "🔎 Dry-run complete. Would change: Postfix=${CHANGED_POSTFIX}, Postgrey=${CHANGED_POSTGREY}, Errors=${ERRORS}"
172-
fi
63+
# Итог
64+
POSTFIX_COUNT=$(grep -vE '^\s*#|^\s*$' "$LIST_FILE" | wc -l)
65+
POSTGREY_COUNT=$(grep -vE '^\s*#|^\s*$' "$LIST_FILE" | grep -vE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | wc -l)
66+
67+
echo -e "${GREEN}Done.${RESET} Changes: Postfix=${CYAN}$POSTFIX_COUNT${RESET}, Postgrey=${CYAN}$POSTGREY_COUNT${RESET}, Errors=${CYAN}0${RESET}"
68+
69+
echo -e "\n📊 ${YELLOW}Всего добавлено в белый список ($POSTFIX_COUNT записей):${RESET}"
70+
71+
# Красивый цветной вывод — IP одним цветом, домены другим
72+
grep -vE '^\s*#|^\s*$' "$LIST_FILE" | while read -r entry; do
73+
if [[ "$entry" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
74+
echo -e " 🌐 ${CYAN}$entry${RESET}" # IP — голубой
75+
else
76+
echo -e " 🏷 ${GREEN}$entry${RESET}" # Домен — зелёный
77+
fi
78+
done

0 commit comments

Comments
 (0)