forked from adrelanos/vpn-firewall
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vpnfirewall
executable file
·290 lines (219 loc) · 7.18 KB
/
vpnfirewall
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
287
288
289
290
#!/bin/bash
###########################
## debugging
###########################
#set -x
###########################
## error_handler
###########################
error_handler() {
echo "##################################################"
echo "VPN firewall script failed!"
echo "##################################################"
exit 1
}
trap "error_handler" ERR INT TERM
###########################
## configuration
###########################
## IP address of the VPN server.
## Get the IP using: nslookup vpn-example-server.org
## Example: seattle.vpn.riseup.net
#VPN_SERVER=46.246.32.2
help() {
cat << EOF
Simple VPN Firewall
-------------------------------
by Felix Bauer
very much based on adrelanos vpn-firewall https://github.com/adrelanos/VPN-Firewall
$0 [-in {ACCEPT|DROP}] (IP|DNS)
-in defines iptables INPUT policy
IP|DNS OUTPUT is allowed to those hosts only
alternatively outgoing connections can be allowed with
$0 ALLOW (IP|DNS) # NOTE: it has to be in upper case
comes with absolutely NO WARRANTY
EOF
exit 1
}
addAllowOut() {
for i in $@; do
if [[ "$i" =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then
iptables -I OUTPUT 2 -d "$i" -j ACCEPT
echo "out to $i allowed"
else
echo "resolve $i"
dig $i A +noauthority +noadditional +nocomments +noquestion | sed -n "s/.*IN[[:space:]]A[[:space:]]\([0-9\.]*\)/\1/p" | while read j; do
iptables -I OUTPUT 2 -d "$j" -j ACCEPT
echo "out to $j allowed"
done
fi
done
}
if [ $# -eq 0 ] || [ $1 == "-h" ] || [ $1 == "--help" ]; then
help
fi
polINPUT="DROP"
if [ $# -gt 0 ]; then
if [ $1 == "-in" ]; then
polINPUT=$2
shift 2
fi
if [ $1 == "ALLOW" ]; then
shift 1
addAllowOut $@
exit 0
fi
fi
echo "INPUT policy "$polINPUT
if [ $# -gt 0 ]; then
VPN_SERVER=$@
else
VPN_SERVER=1.1.1.1
fi
## For OpenVPN.
VPN_INTERFACE=tun0
## Destinations you don not want routed through the VPN.
LOCAL_NET="192.168.0.0/16 172.0.0.0/8 10.0.0.0/8"
######################################################################
## DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING! #
## DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING! #
## DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING! #
## DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING! #
## DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING! #
######################################################################
###########################
## root check
###########################
if [ "$(id -u)" != "0" ]; then
echo "FATAL ERROR: This script must be run as root (sudo)!"
exit 1
fi
###########################
## comments
###########################
## --reject-with
## http://ubuntuforums.org/showthread.php?p=12011099
## Set to icmp-admin-prohibited because icmp-port-unreachable caused
## confusion. icmp-port-unreachable looks like a bug while
## icmp-admin-prohibited hopefully makes clear it is by design.
###########################
## /usr/local/bin/vpnfirewall
###########################
echo "OK: Loading VPN firewall..."
###########################
## IPv4 DEFAULTS
###########################
## Set secure defaults.
iptables -P INPUT $polINPUT
## FORWARD rules does not actually do anything if forwarding is disabled. Better be safe just in case.
iptables -P FORWARD DROP
## Only the VPN process is allowed to establish outgoing connections.
iptables -P OUTPUT DROP
###########################
## IPv4 PREPARATIONS
###########################
## Flush old rules.
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
############################
## IPv4 DROP INVALID PACKAGES
############################
## DROP INVALID
iptables -A INPUT -m state --state INVALID -j DROP
## DROP INVALID SYN PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
iptables -A INPUT -f -j DROP
## DROP INCOMING MALFORMED XMAS PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
## DROP INCOMING MALFORMED NULL PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
###########################
## IPv4 INPUT
###########################
## Traffic on the loopback interface is accepted.
iptables -A INPUT -i lo -j ACCEPT
## Established incoming connections are accepted.
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
## Allow all incoming connections on the virtual VPN network interface.
iptables -A INPUT -i "$VPN_INTERFACE" -j ACCEPT
## Log.
if [ $polINPUT == "DROP" ]; then
echo "LOG INPUT RUBBISH"
iptables -A INPUT -j LOG --log-prefix "VPN firewall blocked input4: "
fi
## Reject anything not explicitly allowed above.
## Drop is better than reject here, because ...
iptables -A INPUT -j $polINPUT
###########################
## IPv4 FORWARD
###########################
## Log.
iptables -A FORWARD -j LOG --log-prefix "VPN firewall blocked forward4: "
## Reject everything.
iptables -A FORWARD -j REJECT --reject-with icmp-admin-prohibited
###########################
## IPv4 OUTPUT
###########################
## XXX
iptables -A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
## XXX
iptables -P OUTPUT ACCEPT
addAllowOut $VPN_SERVER
set +x
iptables -P OUTPUT DROP
## Existing connections are accepted.
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
## Accept outgoing connections to local network.
for NET in $LOCAL_NET; do
iptables -A OUTPUT -d "$NET" -j ACCEPT
done
## Log.
iptables -A OUTPUT -j LOG --log-prefix "VPN firewall blocked output4: "
## Reject all other outgoing traffic.
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
###########################
## IPv6
###########################
## Policy DROP for all traffic as fallback.
ip6tables -P INPUT $polINPUT
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP
## Flush old rules.
ip6tables -F
ip6tables -X
ip6tables -t mangle -F
ip6tables -t mangle -X
## Allow unlimited access on loopback.
## Not activated, since we do not need it.
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
## Log.
#ip6tables -A INPUT -j LOG --log-prefix "VPN firewall blocked input6: "
#ip6tables -A OUTPUT -j LOG --log-prefix "VPN firewall blocked output6: "
#ip6tables -A FORWARD -j LOG --log-prefix "VPN firewall blocked forward6: "
## Allow on VPN interface only.
ip6tables -A INPUT -i "$VPN_INTERFACE" -j ACCEPT
ip6tables -A INPUT -j $polINPUT
## --reject-with icmp-admin-prohibited not supported by ip6tables
ip6tables -A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT
ip6tables -A OUTPUT -j REJECT
## --reject-with icmp-admin-prohibited not supported by ip6tables
ip6tables -A FORWARD -j REJECT
## Established incoming connections are accepted.
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
## Allow all incoming connections on the virtual VPN network interface.
###########################
## End
###########################
echo "OK: The firewall should not show any messages,"
echo "OK: besides output beginning with prefix OK:..."
echo "OK: VPN firewall loaded."
exit 0