-
Notifications
You must be signed in to change notification settings - Fork 3
/
allow_whitelist.sh
executable file
·286 lines (250 loc) · 7.23 KB
/
allow_whitelist.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#!/bin/sh
# 用户定义的变量
username="用户名"
password="密码"
host="127.0.0.1"
port=9091
chain="OUTPUT"
custom_chain_ipv4="CUSTOM_CHAIN_IPV4"
custom_chain_ipv6="CUSTOM_CHAIN_IPV6"
whitelist_pattern="Transmission|qBittorrent|µTorrent|aria2|BitComet" # 白名单
special_pattern="qbittorrent/3\.3\.15|Transmission\ 2\.9|BitComet\ 2\.04" # 白名单例外
log_path="/tmp/allow_whitelist.log"
interval_hour=12 # 12: 12:00/24:00 重置防火墙规则, 0:禁用
DEBUG=0 # 调试模式,默认禁用,不会加入防火墙和修改日志
# ANSI 转义码定义
RED='\033[0;31m'
GREEN='\033[0;32m'
ORANGE='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Colo
# 包装 echo 的函数
echo_default() {
echo -e "$@"
}
echo_info() {
echo -e "${BLUE}$1${NC}"
}
echo_warn() {
echo -e "${ORANGE}$1${NC}"
}
echo_err() {
echo -e "${RED}$1${NC}"
}
echo_pass() {
echo -e "${GREEN}$1${NC}"
}
debug_echo_default() {
if [ "$DEBUG" -eq 1 ]; then
echo -e "$@"
fi
}
debug_echo_info() {
if [ "$DEBUG" -eq 1 ]; then
echo_info "$1"
fi
}
debug_echo_warn() {
if [ "$DEBUG" -eq 1 ]; then
echo_warn "$1"
fi
}
debug_echo_err() {
if [ "$DEBUG" -eq 1 ]; then
echo_err "$1"
fi
}
debug_echo_pass() {
if [ "$DEBUG" -eq 1 ]; then
echo_pass "$1"
fi
}
# 打印自定义链规则
print_chain_rules() {
echo_info "当前IPv4自定义链规则:"
iptables -nL $custom_chain_ipv4 --line-numbers
echo_info "当前IPv6自定义链规则:"
ip6tables -nL $custom_chain_ipv6 --line-numbers
}
print_log() {
cat $log_path
}
# 清空自定义链函数和日志
reset_chains() {
echo_info "清空自定义链 $custom_chain_ipv4 和 $custom_chain_ipv6"
iptables -F $custom_chain_ipv4 # 清空IPv4自定义链
ip6tables -F $custom_chain_ipv6 # 清空IPv6自定义链
}
clean_log() {
echo_info "清空日志"
echo "" >$log_path
}
# 处理参数函数
process_args() {
while [ $# -gt 0 ]; do
case "$1" in
--debug)
DEBUG=1
echo_info "调试模式已启用"
;;
--chain)
print_chain_rules
exit 0
;;
--resetchain)
reset_chains
exit 0
;;
--log)
print_log
exit 0
;;
--cleanlog)
clean_log
exit 0
;;
--help)
echo " --debug Enable debug mode"
echo " --chain Print chain rules"
echo " --resetchain Reset chain rules"
echo " --log Print log"
echo " --cleanlog Clean log"
echo " --help Show this help message"
exit 0
;;
*)
echo "Invalid option: $1" >&2
process_args --help
exit 1
;;
esac
shift
done
}
# 处理传入的参数
process_args "$@"
# 主脚本逻辑部分
# 检查时间是否为 interval_hour 的整数倍
check_interval() {
if [ "$interval_hour" -eq 0 ]; then
return
fi
local minute=$(date "+%M")
local hour=$(date "+%H")
if [ "$minute" -eq 00 ] && [ $(($hour % $interval_hour)) -eq 0 ] && [ "$DEBUG" -eq 0 ]; then
debug_echo_info "当前时间是 $interval_hour 的整数倍"
flush_chains
fi
}
# 检查并创建自定义链并获取规则
create_chains_and_get_rules() {
debug_echo_info "检查并创建自定义链(如果不存在)并获取当前规则..."
ipv4_rules=$(iptables -nL $custom_chain_ipv4 2>/dev/null)
if [ -z "$ipv4_rules" ]; then
debug_echo_info "创建IPv4自定义链 $custom_chain_ipv4"
iptables -N $custom_chain_ipv4
else
debug_echo_info "当前IPv4自定义链规则:"
debug_echo_default "$ipv4_rules"
fi
ipv6_rules=$(ip6tables -nL $custom_chain_ipv6 2>/dev/null)
if [ -z "$ipv6_rules" ]; then
debug_echo_info "创建IPv6自定义链 $custom_chain_ipv6"
ip6tables -N $custom_chain_ipv6
else
debug_echo_info "当前IPv6自定义链规则:"
debug_echo_default "$ipv6_rules"
fi
}
# 确保自定义链在主链中被调用函数
ensure_chain_calls() {
debug_echo_info "确保自定义链在主链中被调用..."
iptables -C $chain -j $custom_chain_ipv4 > /dev/null 2>&1 || (
debug_echo_info "添加 $custom_chain_ipv4 到 $chain"
iptables -A $chain -j $custom_chain_ipv4
)
ip6tables -C $chain -j $custom_chain_ipv6 > /dev/null 2>&1 || (
debug_echo_info "添加 $custom_chain_ipv6 到 $chain"
ip6tables -A $chain -j $custom_chain_ipv6
)
}
# 检查是否为私有地址函数
is_private_ip() {
local ip=$1
if echo "$ip" | grep -q ":"; then
echo $ip | grep -qE '^fc00:|^fd00:|^fe80:'
else
echo $ip | grep -qE '^10\.|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-1]\.|^192\.168\.|^127\.0\.0\.1'
fi
}
# 获取所有传输任务的对等节点IP地址
debug_echo_info "获取传输任务对等节点的IP地址..."
ips=$(transmission-remote $host:$port --auth $username:$password -t all --info-peers | grep -v "^Address" | grep -v "^$" | awk '!seen[$1]++')
debug_echo_default "$ips"
# 执行函数
check_interval
create_chains_and_get_rules
ensure_chain_calls
# 初始化一个变量来记录已经处理过的IP地址,使用换行符分隔
processed_ips=""
# 遍历所有IP地址
echo "$ips" | while IFS= read -r line; do
ip=$(echo "$line" | cut -d " " -f 1)
client=$(echo "$line" | awk '{for(i=6;i<=NF;++i)printf "%s ",$i;print ""}' | xargs)
# 转化成/64,/24掩码
if echo "$ip" | grep -q ":"; then
ip=$(echo "$ip" | awk -F: '{
# 如果第四组为:,用"0000"替代
if ($4 == ":") $4="0000";
printf "%s:%s:%s:%s::/64", $1, $2, $3, $4
}')
else
ip=$(echo "$ip" | cut -d '.' -f 1-3).0/24
fi
# 检查IP是否已在本地缓存中
if echo "$processed_ips" | grep -q "^$ip$"; then
echo_pass "$ip 已在本地缓存中,跳过处理"
continue
fi
# 初始化标志
in_special_cases=0
in_whitelist=0
# 检查是否在特殊情况中
if echo "$client" | grep -qiE "$special_pattern"; then
in_special_cases=1
echo_err "例外\t\t$client\t\t$ip"
fi
# 检查是否在白名单中
if echo "$client" | grep -qiE "$whitelist_pattern"; then
in_whitelist=1
debug_echo_default "白名单\t\t$client\t\t$ip"
else
echo_err "黑名单\t\t$client\t\t$ip"
fi
# 如果在特殊情况或不在白名单中,检查并加入屏蔽规则
if [ "$in_special_cases" -eq 1 ] || [ "$in_whitelist" -eq 0 ]; then
# 检查当前IP是否已经在规则中
if (echo "$ip" | grep -q "::" && echo "$ipv6_rules" | grep -q "$ip") || (echo "$ip" | grep -q "." && echo "$ipv4_rules" | grep -q "$ip"); then
echo_pass "$ip 已在规则中"
else
echo_err "$ip 不在规则中"
# 检查是否为私有地址
if is_private_ip "$ip"; then
echo_pass "$ip 是私有地址, 忽略."
else
# 添加规则
[ "$DEBUG" -eq 0 ] && echo -e "$(date '+%Y-%m-%d %H:%M:%S')\t$client\t$ip" >>$log_path
# 将已处理的IP加入本地缓存,使用换行符分隔
processed_ips="${processed_ips}${ip}\n"
if echo "$ip" | grep -q "::"; then
echo_err "添加IPv6地址 $ip 到自定义链 $custom_chain_ipv6"
[ "$DEBUG" -eq 0 ] && ip6tables -I $custom_chain_ipv6 -d $ip -j DROP
else
echo_err "添加IPv4地址 $ip 到自定义链 $custom_chain_ipv4"
[ "$DEBUG" -eq 0 ] && iptables -I $custom_chain_ipv4 -d $ip -j DROP
fi
fi
fi
fi
done
echo_info "脚本执行完毕."