|
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" |
31 | 48 | done |
32 | | -shift $((OPTIND - 1)) |
| 49 | +echo -e "➕ ${GREEN}Adding to Postfix:${RESET} $LIST_FILE OK" |
33 | 50 |
|
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" |
35 | 54 |
|
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 |
39 | 59 |
|
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 |
157 | 62 |
|
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