summaryrefslogtreecommitdiffstats
path: root/sbin/init.d/firewall
blob: a136c10704267d26eb23725c0f4c2c031bee1f4c (plain) (blame)
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
#!/bin/bash 

. `dirname $0`/functions

option	confdir		standard_option /etc/firewall
option	current		standard_option	current
option	backup		standard_option	backup
option	hashsize	standard_option 65535
option	forward		boolean_option	1
option	filter		boolean_option	1
option	stateful	boolean_option	1
option	nat		boolean_option

IPTABLES=/sbin/iptables
IPRESTORE=/sbin/iptables-restore

function do_help {
    echo "Usage: ${0##*/} <status|start|revert|reload|stop|route|block|help>"
    echo "List of config.rc options (name, type, default value, current value) :"
    echo
    echo "   - confdir  : dir     ; def='/etc/firewall' ; cur=$opt_confdir"
    echo "   - current  : subdir  ; def='current'       ; cur=$opt_current"
    echo "   - backup   : subdir  ; def='backup'        ; cur=$opt_backup"
    echo "   - hashsize : integer ; def=65535           ; cur=$opt_hashsize"
    echo "   - forward  : boolean ; def=1               ; cur=$opt_forward"
    echo "   - filter   : boolean ; def=1               ; cur=$opt_filter"
    echo "   - stateful : boolean ; def=1               ; cur=$opt_stateful"
    echo "   - nat      : boolean ; def=                ; cur=$opt_nat"
    echo
    echo "The configuration file is $opt_confdir/$opt_current/conf-$(uname -n).ipt"
    echo
    exit 1 
}

# starts the firewall with the specified config.
# if none is specified, no configuration is loaded.
# - disables ip_forwarding. It's up to the caller to
#   enable it after initialization.
# - sets INPUT/OUTPUT/FORWARD policies to DROP
# returns 1 if the config could not be loaded.
function start_with_config {
    local table chain chains

    echo 0 > /proc/sys/net/ipv4/ip_forward

    echo "Firewall: loading modules..."
    /sbin/modprobe ip_tables
    /sbin/modprobe iptable_filter
    if [ -n "$opt_stateful" ]; then
    	/sbin/modprobe ip_conntrack hashsize=$opt_hashsize
    	[ -n "$opt_nat" ] && /sbin/modprobe iptable_nat
    fi

    # filter chain has a default policy set to DROP
    echo "Firewall: setting default policy to DROP..."
    for chain in INPUT OUTPUT FORWARD; do
	$IPTABLES -t filter -P $chain DROP
    done

    # flush all rules in all tables
    echo "Firewall: Flushing all rules..."
    for table in mangle filter ${opt_stateful:+${opt_nat:+nat}}; do
	$IPTABLES -t $table -F
	$IPTABLES -t $table -X
    done

    # other chains have a default policy set to ACCEPT
    for table in mangle ${opt_stateful:+${opt_nat:+nat}}; do
	chains=$($IPTABLES -t $table -L | grep "^Chain " | cut -f2 -d' ')
	for chain in $chains; do
	    $IPTABLES -t $table -P $chain ACCEPT
	done
    done

    if [ -n "$1" ]; then
        echo "Firewall: loading configuration file $opt_confdir/$1..."
	if ! [ -r "$opt_confdir/$1" ] || ! $IPRESTORE < $opt_confdir/$1; then
	    echo "Firewall: Error! cannot load configuration file !"
	    # we'll block external traffic and enable internal one in this case
	    do_block
	    return 1
	fi
    fi
    return 0
}

# reloads the firewall with the specified config, without
# unloading any module nor flushing existing sessions. If
# the configuration cannot be loaded, only existing sessions
# can continue, and all external traffic is blocked.
# if the firewall wasn't loaded, branch to do_start
# returns 1 if the config could not be loaded.
function do_reload {
    local table chain chains conf

    if [ ! -e /proc/net/ip_tables_names ]; then
	do_start $*
	return $?
    fi

    echo "Firewall: disabling IP forwarding..."
    echo 0 > /proc/sys/net/ipv4/ip_forward
    # filter chain has a default policy set to DROP
    echo "Firewall: setting default policy to DROP..."
    for chain in INPUT OUTPUT FORWARD; do
	$IPTABLES -t filter -P $chain DROP
    done

    # flush all rules in all tables
    echo "Firewall: Flushing all rules..."
    for table in mangle filter ${opt_stateful:+${opt_nat:+nat}}; do
	$IPTABLES -t $table -F
	$IPTABLES -t $table -X
    done

    # other chains have a default policy set to ACCEPT
    for table in mangle ${opt_stateful:+${opt_nat:+nat}}; do
	chains=$($IPTABLES -t $table -L | grep "^Chain " | cut -f2 -d' ')
	for chain in $chains; do
	    $IPTABLES -t $table -P $chain ACCEPT
	done
    done

    conf=${opt_filter:+$opt_current/conf-$(uname -n).ipt}

    echo "Firewall: loading configuration file $opt_confdir/$conf..."
    if ! [ -r "$opt_confdir/$conf" ] || ! $IPRESTORE < $opt_confdir/$conf; then
	echo "Firewall: Error! cannot load configuration file !"
	# we'll block external traffic and enable internal one in this case
        echo "Firewall: Changing policy to block external traffic..."
	$IPTABLES -t filter -A INPUT -m state --state ESTABLISHED -j ACCEPT
        $IPTABLES -t filter -A INPUT -i lo -j ACCEPT
	$IPTABLES -t filter -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
        $IPTABLES -t filter -A OUTPUT -o lo -j ACCEPT
        $IPTABLES -t mangle -P PREROUTING DROP
        $IPTABLES -t mangle -P INPUT DROP
        $IPTABLES -t mangle -P FORWARD DROP
        $IPTABLES -t mangle -P POSTROUTING DROP
        $IPTABLES -t mangle -P OUTPUT DROP
        $IPTABLES -t mangle -A PREROUTING -i lo -j ACCEPT
        $IPTABLES -t mangle -A INPUT -i lo -j ACCEPT
        $IPTABLES -t mangle -A POSTROUTING -o lo -j ACCEPT
        $IPTABLES -t mangle -A OUTPUT -o lo -j ACCEPT
	echo
	echo "################################################################"
        echo "Firewall: There was a critical error. Only established sessions"
	echo "from and to the firewall will still work. Everything else has"
	echo "been blocked, and forwarding has been disabled."
	echo "################################################################"
	echo
 	return 1
    fi
    if [ -n "$opt_forward" ]; then
        echo "Firewall: enabling IP forwarding..."
        echo 1 > /proc/sys/net/ipv4/ip_forward
    fi
    echo "Firewall: done."
    return 0
}

# checks wether the firewall modules are loaded
function do_status {
    if [ -e /proc/net/ip_tables_names ]; then
	if [ -n "$(cat /proc/net/ip_tables_names)" ]; then
	    echo "Firewall modules are loaded."
	    return 0
	fi
    fi
    echo "Firewall modules are not loaded."
    return 1
}

# stops the firewall and unloads the modules
function do_stop {
    # stop forwarding
    echo "Firewall: disabling IP forwarding..."
    echo 0 > /proc/sys/net/ipv4/ip_forward

    if [ -e /proc/net/ip_tables_names ] ; then
        echo "Firewall: flushing all rules..."
        # flush all rules in all tables
        for table in $(cat /proc/net/ip_tables_names); do
	    $IPTABLES -t $table -F
	    $IPTABLES -t $table -X
	    # all chains have a default policy set to ACCEPT
	    chains=$($IPTABLES -t $table -L | grep "^Chain " | cut -f2 -d' ')
	    for chain in $chains; do
	        $IPTABLES -t $table -P $chain ACCEPT
	    done
        done
    fi 

    # then unload the firewall modules
    echo "Firewall: unloading modules..."
    recursive_rmmod iptable_nat
    recursive_rmmod ip_conntrack
    recursive_rmmod iptable_filter
    recursive_rmmod ip_tables
    echo "Firewall: unloaded successfully."
}

# block all incoming/outgoing traffic, but allows local
# communications
function do_block {
    do_stop

    # we force some options to ensure proper blocking
    unset opt_stateful
    unset opt_forward
    opt_filter=1

    start_with_config
    echo "Firewall: Changing policy to block external traffic..."
    $IPTABLES -t filter -A INPUT -i lo -j ACCEPT
    $IPTABLES -t filter -A OUTPUT -o lo -j ACCEPT
    $IPTABLES -t mangle -P PREROUTING DROP
    $IPTABLES -t mangle -P INPUT DROP
    $IPTABLES -t mangle -P FORWARD DROP
    $IPTABLES -t mangle -P POSTROUTING DROP
    $IPTABLES -t mangle -P OUTPUT DROP
    $IPTABLES -t mangle -A PREROUTING -i lo -j ACCEPT
    $IPTABLES -t mangle -A INPUT -i lo -j ACCEPT
    $IPTABLES -t mangle -A POSTROUTING -o lo -j ACCEPT
    $IPTABLES -t mangle -A OUTPUT -o lo -j ACCEPT
    echo "Firewall: done."
}

# load current configuration
function do_start {
    do_stop
    if start_with_config ${opt_filter:+$opt_current/conf-$(uname -n).ipt}; then
	if [ -n "$opt_forward" ]; then
            echo "Firewall: enabling IP forwarding..."
	    echo 1 > /proc/sys/net/ipv4/ip_forward
	fi
    fi
    echo "Firewall: done."
}

# load backup configuration
function do_revert {
    do_stop
    if start_with_config ${opt_filter:+$opt_backup/conf-$(uname -n).ipt}; then
	if [ -n "$opt_forward" ]; then
            echo "Firewall: enabling IP forwarding..."
	    echo 1 > /proc/sys/net/ipv4/ip_forward
	fi
    fi
    echo "Firewall: done."
}

# unload the firewall and enable ip forwarding
function do_route {
    do_stop
    # enable ip forwarding
    if [ -n "$opt_forward" ]; then
        echo "Firewall: enabling IP forwarding..."
        echo 1 > /proc/sys/net/ipv4/ip_forward
    fi
    echo "Firewall: done."
}

load_config