-
Notifications
You must be signed in to change notification settings - Fork 258
/
functions
253 lines (222 loc) · 7.1 KB
/
functions
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
. /lib/functions/network.sh
[ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret
. "$ZAPRET_BASE/config"
QNUM=200
TPPORT_HTTP=1188
TPPORT_HTTPS=1189
TPWS_USER=daemon
# max wait time for the link local ipv6 on the LAN interface
LINKLOCAL_WAIT_SEC=5
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
CUSTOM_SCRIPT="$ZAPRET_BASE/init.d/openwrt/custom"
[ -f "$CUSTOM_SCRIPT" ] && . "$CUSTOM_SCRIPT"
exists()
{
which "$1" >/dev/null 2>/dev/null
}
existf()
{
type "$1" >/dev/null 2>/dev/null
}
# can be multiple ipv6 outgoing interfaces
# uplink from isp, tunnelbroker, vpn, ...
# want them all. who knows what's the real one that blocks sites
# dont want any manual configuration - want to do it automatically
# standard network_find_wan[6] return only the first
# we use low level function from network.sh to avoid this limitation
# it can change theoretically and stop working
network_find_wan_all()
{
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return
network_find_wan $1
}
network_find_wan6_all()
{
__network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return
network_find_wan6 $1
}
ipt()
{
iptables -C "$@" 2>/dev/null || iptables -I "$@"
}
ipt6()
{
ip6tables -C "$@" 2>/dev/null || ip6tables -I "$@"
}
# there's no route_localnet for ipv6
# the best we can is to route to link local of the incoming interface
# OUTPUT - can DNAT to ::1
# PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr
# not a good idea to expose tpws to the world (bind to ::)
get_ipv6_linklocal()
{
# $1 - interface name. if empty - any interface
if exists ip ; then
local dev
[ -n "$1" ] && dev="dev $1"
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1
else
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Link.*$/\1/;t;d' | head -n 1
fi
}
get_ipv6_global()
{
# $1 - interface name. if empty - any interface
if exists ip ; then
local dev
[ -n "$1" ] && dev="dev $1"
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1
else
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Global.*$/\1/;t;d' | head -n 1
fi
}
dnat6_target()
{
# get target ip address for DNAT. prefer link locals
# tpws should be as inaccessible from outside as possible
# link local address can appear not immediately after ifup
# DNAT6_TARGET=- means attempt was made but address was not found (to avoid multiple re-attempts)
[ -n "$DNAT6_TARGET" ] || {
# no reason to query if its down
network_is_up lan || return
local DEVICE
network_get_device DEVICE lan
local ct=0
while
DNAT6_TARGET=$(get_ipv6_linklocal $DEVICE)
[ -n "$DNAT6_TARGET" ] && break
[ "$ct" -ge "$LINKLOCAL_WAIT_SEC" ] && break
echo waiting for the link local for another $(($LINKLOCAL_WAIT_SEC - $ct)) seconds ...
ct=$(($ct+1))
sleep 1
do :; done
[ -n "$DNAT6_TARGET" ] || {
echo no link local. getting global
DNAT6_TARGET=$(get_ipv6_global $DEVICE)
[ -n "$DNAT6_TARGET" ] || {
echo could not get any address
DNAT6_TARGET=-
}
}
}
}
fw_nfqws_pre()
{
# $1 - filter ipv4
# $2 - filter ipv6
# $3 - queue number
local DEVICE wan_iface
[ "$DISABLE_IPV4" = "1" ] || {
network_find_wan_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt PREROUTING -t mangle -i $DEVICE -p tcp --tcp-flags SYN,ACK SYN,ACK $1 -j NFQUEUE --queue-num $3 --queue-bypass
done
}
[ "$DISABLE_IPV6" = "1" ] || {
network_find_wan6_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt6 PREROUTING -t mangle -i $DEVICE -p tcp --tcp-flags SYN,ACK SYN,ACK $2 -j NFQUEUE --queue-num $3 --queue-bypass
done
}
}
fw_nfqws_post()
{
# $1 - filter ipv4
# $2 - filter ipv6
# $3 - queue number
local DEVICE wan_iface
[ "$DISABLE_IPV4" = "1" ] || {
network_find_wan_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt POSTROUTING -t mangle -o $DEVICE -p tcp $1 -j NFQUEUE --queue-num $3 --queue-bypass
done
}
[ "$DISABLE_IPV6" = "1" ] || {
network_find_wan6_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt6 POSTROUTING -t mangle -o $DEVICE -p tcp $2 -j NFQUEUE --queue-num $3 --queue-bypass
done
}
}
IPT_OWNER="-m owner ! --uid-owner $TPWS_USER"
fw_tpws()
{
# $1 - filter ipv4
# $2 - filter ipv6
# $3 - tpws port
local DEVICE wan_iface
[ "$DISABLE_IPV4" = "1" ] || {
network_find_wan_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $1 -j DNAT --to 127.0.0.1:$3
done
ipt prerouting_lan_rule -t nat -p tcp $1 -j DNAT --to 127.0.0.1:$3
network_get_device DEVICE lan
sysctl -qw net.ipv4.conf.$DEVICE.route_localnet=1
}
[ "$DISABLE_IPV6" = "1" ] || {
network_find_wan6_all wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
ipt6 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $2 -j DNAT --to [::1]:$3
done
network_get_device DEVICE lan
dnat6_target
[ "$DNAT6_TARGET" != "-" ] && ipt6 PREROUTING -t nat -i $DEVICE -p tcp $2 -j DNAT --to [$DNAT6_TARGET]:$3
}
}
create_ipset()
{
echo "Creating ipset"
"$IPSET_CR" "$@"
}
zapret_apply_firewall()
{
case "${MODE}" in
tpws_hostlist|tpws_all)
fw_tpws "--dport 80" "--dport 80" $TPPORT_HTTP
;;
tpws_ipset)
create_ipset no-update
fw_tpws "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $TPPORT_HTTP
;;
tpws_ipset_https)
create_ipset no-update
fw_tpws "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $TPPORT_HTTP
fw_tpws "--dport 443 -m set --match-set zapret dst" "--dport 443 -m set --match-set zapret6 dst" $TPPORT_HTTPS
;;
tpws_all_https)
fw_tpws "--dport 80" "--dport 80" $TPPORT_HTTP
fw_tpws "--dport 443" "--dport 443" $TPPORT_HTTPS
;;
nfqws_ipset)
create_ipset no-update
fw_nfqws_pre "--sport 80 -m set --match-set zapret src" "--sport 80 -m set --match-set zapret6 src" $QNUM
fw_nfqws_post "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $QNUM
;;
nfqws_ipset_https)
create_ipset no-update
fw_nfqws_pre "-m multiport --sports 80,443 -m set --match-set zapret src" "-m multiport --sports 80,443 -m set --match-set zapret6 src" $QNUM
fw_nfqws_post "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $QNUM
;;
nfqws_all)
fw_nfqws_pre "--sport 80" "--sport 80" $QNUM
fw_nfqws_post "--dport 80" "--dport 80" $QNUM
;;
nfqws_all_https)
fw_nfqws_pre "-m multiport --sports 80,443" "-m multiport --sports 80,443" $QNUM
fw_nfqws_post "--dport 80" "--dport 80" $QNUM
;;
ipset)
create_ipset no-update
;;
custom)
existf zapret_custom_firewall && zapret_custom_firewall $1
;;
esac
}