/
setup_iptables
executable file
·258 lines (208 loc) · 7.03 KB
/
setup_iptables
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
#!/bin/bash
usage () {
cat <<-EOF
Usage:
$0 [-d] <client_port> <overall_connlimit> [per_ip_connlimit] [conn_rate_limit] [conn_rate_period] [logging_level]
Options:
-d - Delete the corresponding rules.
Removes the rules corresponding to the supplied input parameters.
-t - Test mode. Prints out the list of input settings and exits.
Input Parameters:
client_port - Required. The node's client port.
overall_connlimit - Required. The overall connection limit for all clients.
per_ip_connlimit - Optional. The connection limit per IP address; defaults to 10.
conn_rate_limit - Optional. The connection limit for connection rate limiting; default to -1, off.
conn_rate_period - Optional. The period for connection rate limiting; defaults to 60 seconds.
logging_level - Optional. If used, this should be set to a level such as 'debug' so they can
easily be filtered from the logs and included only as needed.
Default is no logging.
Example:
$0 9702 15000
EOF
exit 1
}
check_setup () {
cat <<-EOF
Warning: iptables and/or iptables-persistent is not installed, or permission denied. Client connections limit is not set.
Please ensure iptables and iptables-persistent are both installed and iptables-persistent is enabled, and try running with sudo.
# To install iptables-persistent:
sudo apt-get install -y iptables-persistent
# Make sure services are enabled on Debian or Ubuntu using the systemctl command:
sudo systemctl is-enabled netfilter-persistent.service
# If not enable it:
sudo systemctl enable netfilter-persistent.service
# Get status:
sudo systemctl status netfilter-persistent.service
EOF
exit 1
}
print_settings() {
if (( ${CONN_RATE_LIMIT_LIMIT} <= 0 || ${CONN_RATE_LIMIT_PERIOD} <= 0 )); then
RATE_LIMIT_MESSAGE=" - Connection rate limiting is turned off."
fi
cat <<-EOF
client_port: ${DPORT}
overall_connlimit: ${OVER_ALL_CONN_LIMIT}
per_ip_connlimit: ${CONN_LIMIT_PER_IP}
conn_rate_limit: ${CONN_RATE_LIMIT_LIMIT} ${RATE_LIMIT_MESSAGE}
conn_rate_period: ${CONN_RATE_LIMIT_PERIOD} ${RATE_LIMIT_MESSAGE}
logging_level: ${CONN_LOGGING_LEVEL:-Not set, (off) default}
OPERATION: ${OPERATION}
DELETE: ${DELETE}
TEST_MODE: ${TEST_MODE}
EOF
}
LOG_CHAIN=LOG_CONN_REJECT
OPERATION="add_rule"
while getopts dth FLAG; do
case $FLAG in
d)
OPERATION="delete_rule"
DELETE=1
;;
t)
TEST_MODE=1
;;
h)
usage
;;
\?)
usage
;;
esac
done
shift $((OPTIND-1))
DPORT=${1}
OVER_ALL_CONN_LIMIT=${2}
# Default to 10 connections per IP.
CONN_LIMIT_PER_IP=${3:-10}
# Default: Rate limiting disabled; -1.
CONN_RATE_LIMIT_LIMIT=${4:--1}
# Default to a per minute rate limit.
CONN_RATE_LIMIT_PERIOD=${5:-60}
CONN_LOGGING_LEVEL=${6}
add() {
if [ -z ${DELETE} ]; then
return 0
else
return 1
fi
}
delete() {
if [ ! -z ${DELETE} ]; then
return 0
else
return 1
fi
}
rule_exists() {
RULE="${1}"
cmd="iptables -C ${RULE} 2>/dev/null 1>&2"
# echo $cmd
eval $cmd
rtnCd=$?
if (( ${rtnCd} == 0 )); then
return 0
else
return 1
fi
}
add_rule() {
RULE="${1}"
if ! rule_exists "${RULE}"; then
cmd="iptables -A ${RULE}"
# echo $cmd
eval $cmd
fi
}
delete_rule() {
RULE="${1}"
if rule_exists "${RULE}"; then
cmd="iptables -D ${RULE}"
# echo $cmd
eval $cmd
fi
}
save_rules() {
su -c "iptables-save > /etc/iptables/rules.v4 && ip6tables-save > /etc/iptables/rules.v6"
}
disable_ipv6() {
echo "Disabling IPv6 ..."
ip6_conf_file="/etc/sysctl.d/60-custom-disable-ipv6.conf"
mkdir -p ${ip6_conf_file%/*}
cat <<-EOF > ${ip6_conf_file}
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
sysctl -p
systemctl restart procps
}
enable_ipv6() {
echo "Enabling IPv6 ..."
ip6_conf_file="/etc/sysctl.d/60-custom-disable-ipv6.conf"
if [ -f ${ip6_conf_file} ]; then
rm ${ip6_conf_file}
fi
sysctl -p
systemctl restart procps
}
if [ $# -lt 2 ]; then
usage
fi
if [ ! -z ${TEST_MODE} ]; then
print_settings
exit 0
fi
# Check whether iptables installed and works
dpkg -s iptables 2>/dev/null 1>&2 && iptables -nL 2>/dev/null 1>&2 && dpkg -s iptables-persistent 2>/dev/null 1>&2
if [ $? -eq 0 ]; then
if add; then
echo "Adding iptable rules ..."
# Create logging chain for rejected connections
iptables -N ${LOG_CHAIN} 2>/dev/null 1>&2
else
echo "Removing iptable rules ..."
fi
# Make sure the previous default logging rule is removed. It causes too much CPU overhead under load.
RULE="${LOG_CHAIN} -j LOG --log-level warning --log-prefix \"connlimit: \""
delete_rule "${RULE}"
# Append a rule that sets log level and log prefix
# Default to no logging unless a logging level is explicitly supplied.
if [ ! -z ${CONN_LOGGING_LEVEL} ]; then
RULE="${LOG_CHAIN} -j LOG --log-level ${CONN_LOGGING_LEVEL} --log-prefix \"connlimit: \""
${OPERATION} "${RULE}"
fi
# Append a rule that finally rejects connection
RULE="${LOG_CHAIN} -p tcp -j REJECT --reject-with tcp-reset"
${OPERATION} "${RULE}"
# Append a rule to limit the total number of simultaneous client connections
RULE="INPUT -p tcp --syn --dport ${DPORT} -m connlimit --connlimit-above ${OVER_ALL_CONN_LIMIT} --connlimit-mask 0 -j ${LOG_CHAIN}"
${OPERATION} "${RULE}"
# Append a rule to limit the number connections per IP address
RULE="INPUT -p tcp -m tcp --dport ${DPORT} --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above ${CONN_LIMIT_PER_IP} --connlimit-mask 32 --connlimit-saddr -j ${LOG_CHAIN}"
${OPERATION} "${RULE}"
# Append rules to rate limit connections
if (( ${CONN_RATE_LIMIT_LIMIT} > 0 && ${CONN_RATE_LIMIT_PERIOD} > 0 )); then
echo "Including settings for rate limiting ..."
RULE="INPUT -p tcp -m tcp --dport ${DPORT} -m conntrack --ctstate NEW -m recent --set --name DEFAULT --mask 255.255.255.255 --rsource"
${OPERATION} "${RULE}"
RULE="INPUT -p tcp -m tcp --dport ${DPORT} -m conntrack --ctstate NEW -m recent --update --seconds ${CONN_RATE_LIMIT_PERIOD} --hitcount ${CONN_RATE_LIMIT_LIMIT} --name DEFAULT --mask 255.255.255.255 --rsource -j ${LOG_CHAIN}"
${OPERATION} "${RULE}"
else
echo "Rate limiting is disabled, skipping settings for rate limiting ..."
fi
if delete; then
# Remove logging chain for rejected connections
iptables -X ${LOG_CHAIN} 2>/dev/null 1>&2
fi
# Save the rules
save_rules
if add; then
disable_ipv6
else
enable_ipv6
fi
else
check_setup
fi