]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/sh | |
2 | ######################################################################## | |
3 | # Begin $rc_base/init.d/suricata | |
4 | # | |
5 | # Description : Suricata Initscript | |
6 | # | |
7 | # Author : Stefan Schantl <stefan.schantl@ipfire.org> | |
8 | # | |
9 | # Version : 01.02 | |
10 | # | |
11 | # Notes : | |
12 | # | |
13 | ######################################################################## | |
14 | ||
15 | . /etc/sysconfig/rc | |
16 | . ${rc_functions} | |
17 | ||
18 | PATH=/usr/local/sbin:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin; export PATH | |
19 | ||
20 | eval $(/usr/local/bin/readhash /var/ipfire/suricata/settings) | |
21 | eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) | |
22 | ||
23 | # Name of the firewall chains. | |
24 | IPS_INPUT_CHAIN="IPS_INPUT" | |
25 | IPS_FORWARD_CHAIN="IPS_FORWARD" | |
26 | IPS_OUTPUT_CHAIN="IPS_OUTPUT" | |
27 | ||
28 | # Optional options for the Netfilter queue. | |
29 | NFQ_OPTS="--queue-bypass " | |
30 | ||
31 | # Array containing the 4 possible network zones. | |
32 | network_zones=( red green blue orange ) | |
33 | ||
34 | # Array to store the network zones weather the IPS is enabled for. | |
35 | enabled_ips_zones=() | |
36 | ||
37 | # Mark and Mask options. | |
38 | MARK="0x70000000" | |
39 | MASK="0x70000000" | |
40 | ||
41 | # PID file of suricata. | |
42 | PID_FILE="/var/run/suricata.pid" | |
43 | ||
44 | # Function to get the amount of CPU cores of the system. | |
45 | function get_cpu_count { | |
46 | CPUCOUNT=0 | |
47 | ||
48 | # Loop through "/proc/cpuinfo" and count the amount of CPU cores. | |
49 | while read line; do | |
50 | [ "$line" ] && [ -z "${line%processor*}" ] && ((CPUCOUNT++)) | |
51 | done </proc/cpuinfo | |
52 | ||
53 | # Limit to a maximum of 16 cores, because suricata does not support more than | |
54 | # 16 netfilter queues at the moment. | |
55 | if [ $CPUCOUNT -gt "16" ]; then | |
56 | echo "16" | |
57 | else | |
58 | echo $CPUCOUNT | |
59 | fi | |
60 | } | |
61 | ||
62 | # Function to flush the firewall chains. | |
63 | function flush_fw_chain { | |
64 | # Call iptables and flush the chains | |
65 | iptables -F "$IPS_INPUT_CHAIN" | |
66 | iptables -F "$IPS_FORWARD_CHAIN" | |
67 | iptables -F "$IPS_OUTPUT_CHAIN" | |
68 | } | |
69 | ||
70 | # Function to create the firewall rules to pass the traffic to suricata. | |
71 | function generate_fw_rules { | |
72 | cpu_count=$(get_cpu_count) | |
73 | ||
74 | # Loop through the array of network zones. | |
75 | for zone in "${network_zones[@]}"; do | |
76 | # Convert zone into upper case. | |
77 | zone_upper=${zone^^} | |
78 | ||
79 | # Generate variable name for checking if the IDS is | |
80 | # enabled on the zone. | |
81 | enable_ids_zone="ENABLE_IDS_$zone_upper" | |
82 | ||
83 | # Check if the IDS is enabled for this network zone. | |
84 | if [ "${!enable_ids_zone}" == "on" ]; then | |
85 | # Check if the current processed zone is "red" and the configured type is PPPoE dialin. | |
86 | if [ "$zone" == "red" ] && [ "$RED_TYPE" == "PPPOE" ]; then | |
87 | # Set device name to ppp0. | |
88 | network_device="ppp0" | |
89 | else | |
90 | # Generate variable name which contains the device name. | |
91 | zone_name="$zone_upper" | |
92 | zone_name+="_DEV" | |
93 | ||
94 | # Grab device name. | |
95 | network_device=${!zone_name} | |
96 | fi | |
97 | ||
98 | # Add the network device to the array of enabled zones. | |
99 | enabled_ips_zones+=( "$network_device" ) | |
100 | fi | |
101 | done | |
102 | ||
103 | # Assign NFQ_OPTS | |
104 | NFQ_OPTIONS=$NFQ_OPTS | |
105 | ||
106 | # Check if there are multiple cpu cores available. | |
107 | if [ "$cpu_count" -gt "1" ]; then | |
108 | # Balance beetween all queues. | |
109 | NFQ_OPTIONS+="--queue-balance 0:$(($cpu_count-1))" | |
110 | NFQ_OPTIONS+=" --queue-cpu-fanout" | |
111 | else | |
112 | # Send all packets to queue 0. | |
113 | NFQ_OPTIONS+="--queue-num 0" | |
114 | fi | |
115 | ||
116 | # Flush the firewall chains. | |
117 | flush_fw_chain | |
118 | ||
119 | # Check if the array of enabled_ips_zones contains any elements. | |
120 | if [[ ${enabled_ips_zones[@]} ]]; then | |
121 | # Loop through the array and create firewall rules. | |
122 | for enabled_ips_zone in "${enabled_ips_zones[@]}"; do | |
123 | # Create rules queue input and output related traffic and pass it to the IPS. | |
124 | iptables -I "$IPS_INPUT_CHAIN" -i "$enabled_ips_zone" -m mark ! --mark "$MARK"/"$MASK" -j NFQUEUE $NFQ_OPTIONS | |
125 | iptables -I "$IPS_OUTPUT_CHAIN" -o "$enabled_ips_zone" -m mark ! --mark "$MARK"/"$MASK" -j NFQUEUE $NFQ_OPTIONS | |
126 | ||
127 | # Create rules which are required to handle forwarded traffic. | |
128 | for enabled_ips_zone_forward in "${enabled_ips_zones[@]}"; do | |
129 | iptables -I "$IPS_FORWARD_CHAIN" -i "$enabled_ips_zone" -o "$enabled_ips_zone_forward" -m mark ! --mark "$MARK"/"$MASK" -j NFQUEUE $NFQ_OPTIONS | |
130 | done | |
131 | done | |
132 | ||
133 | # Clear repeat bit, so that it does not confuse IPsec or QoS | |
134 | iptables -A "${IPS_INPUT_CHAIN}" -j MARK --set-xmark "0x0/${MASK}" | |
135 | iptables -A "${IPS_FORWARD_CHAIN}" -j MARK --set-xmark "0x0/${MASK}" | |
136 | iptables -A "${IPS_OUTPUT_CHAIN}" -j MARK --set-xmark "0x0/${MASK}" | |
137 | fi | |
138 | } | |
139 | ||
140 | case "$1" in | |
141 | start) | |
142 | # Get amount of CPU cores. | |
143 | cpu_count=$(get_cpu_count) | |
144 | ||
145 | # Numer of NFQUES. | |
146 | NFQUEUES= | |
147 | ||
148 | for i in $(seq 0 $((cpu_count-1)) ); do | |
149 | NFQUEUES+="-q $i " | |
150 | done | |
151 | ||
152 | # Check if the IDS should be started. | |
153 | if [ "$ENABLE_IDS" == "on" ]; then | |
154 | # Start the IDS. | |
155 | boot_mesg "Starting Intrusion Detection System..." | |
156 | /usr/bin/suricata -c /etc/suricata/suricata.yaml -D $NFQUEUES >/dev/null 2>/dev/null | |
157 | evaluate_retval | |
158 | ||
159 | # Allow reading the pidfile. | |
160 | chmod 644 $PID_FILE | |
161 | ||
162 | # Flush the firewall chain | |
163 | flush_fw_chain | |
164 | ||
165 | # Generate firewall rules | |
166 | generate_fw_rules | |
167 | fi | |
168 | ;; | |
169 | ||
170 | stop) | |
171 | boot_mesg "Stopping Intrusion Detection System..." | |
172 | killproc -p $PID_FILE /var/run | |
173 | ||
174 | # Flush firewall chain. | |
175 | flush_fw_chain | |
176 | ||
177 | # Remove suricata control socket. | |
178 | rm /var/run/suricata/* >/dev/null 2>/dev/null | |
179 | ||
180 | # Trash remain pid file if still exists. | |
181 | rm -f $PID_FILE >/dev/null 2>/dev/null | |
182 | ||
183 | # Don't report returncode of rm if suricata was not started | |
184 | exit 0 | |
185 | ;; | |
186 | ||
187 | status) | |
188 | statusproc /usr/bin/suricata | |
189 | ;; | |
190 | ||
191 | restart) | |
192 | $0 stop | |
193 | $0 start | |
194 | ;; | |
195 | reload) | |
196 | # Send SIGUSR2 to the suricata process to perform a reload | |
197 | # of the ruleset. | |
198 | kill -USR2 $(pidof suricata) | |
199 | ||
200 | # Flush the firewall chain. | |
201 | flush_fw_chain | |
202 | ||
203 | # Generate firewall rules. | |
204 | generate_fw_rules | |
205 | ;; | |
206 | ||
207 | *) | |
208 | echo "Usage: $0 {start|stop|restart|reload|status}" | |
209 | exit 1 | |
210 | ;; | |
211 | esac | |
212 | ||
213 | chmod 644 /var/log/suricata/* 2>/dev/null | |
214 | ||
215 | # End $rc_base/init.d/suricata |