summaryrefslogtreecommitdiff
blob: b276f4901bb14d1e79d486732fed4042e38505e3 (plain)
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
#!/sbin/openrc-run
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

SURICATA_BIN=/usr/bin/suricata
SURICATA_DIR=${SURICATA_DIR:-/etc/suricata}
SURICATA=${SVCNAME#*.}
SURICATAID=$(shell_var "${SURICATA}")
if [ -n "${SURICATA}" ] && [ ${SVCNAME} != "suricata" ]; then
    eval SURICATACONF=\$SURICATA_CONF_${SURICATAID}
    [ ${#SURICATACONF} -eq 0 ] && SURICATACONF="${SURICATA_DIR}/suricata-${SURICATA}.yaml" || SURICATACONF="${SURICATA_DIR}/${SURICATACONF}"
    SURICATAPID="/var/run/suricata/suricata.${SURICATA}.pid"
    eval SURICATAOPTS=\$SURICATA_OPTS_${SURICATAID}
    eval SURICATALOGPATH=\$SURICATA_LOG_FILE_${SURICATAID}
    eval SURICATAUSER=\$SURICATA_USER_${SURICATAID}
    eval SURICATAGROUP=\$SURICATA_GROUP_${SURICATAID}
else
    SURICATACONF=${SURICATA_CONF}
    [ ${#SURICATACONF} -eq 0 ] && SURICATACONF="${SURICATA_DIR}/suricata.yaml" || SURICATACONF="${SURICATA_DIR}/${SURICATACONF}"
    SURICATAPID="/var/run/suricata/suricata.pid"
    SURICATAOPTS=${SURICATA_OPTS}
    SURICATALOGPATH=${SURICATA_LOG_FILE}
    SURICATAUSER=${SURICATA_USER}
    SURICATAGROUP=${SURICATA_GROUP}
fi
SURICATAUSER=${SURICATAUSER:-${SURICATA_USER}}
SURICATAGROUP=${SURICATAGROUP:-${SURICATA_GROUP}}
[ -e ${SURICATACONF} ] && SURICATAOPTS="${SURICATAOPTS} -c ${SURICATACONF}"

description="Suricata IDS/IPS"
extra_commands="checkconfig dump"
description_checkconfig="Check config for ${SVCNAME}"
description_dump="List all config values that can be used with --set"
extra_started_commands="reload relog"
description_reload="Live rule and config reload"
description_relog="Close and re-open all log files"

depend() {
	need net
	after mysql
	after postgresql
}

checkconfig() {
	if [ ! -d "/var/run/suricata" ] ; then
		checkpath -d /var/run/suricata
	fi
	if [ ${#SURICATALOGPATH} -gt 0 ]; then
		SURICATALOGFILE=$( basename ${SURICATA_LOG_FILE} )
		SURICATALOGFILE=${SURICATALOGFILE:-suricata.log}
		SURICATALOGPATH=$( dirname ${SURICATALOGPATH} )
		if [ ! -d "${SURICATALOGPATH}" ] ; then
			checkpath -d "${SURICATALOGPATH}"
		fi
		if [ ${#SURICATAUSER} -gt 0 ] && [ ${#SURICATAGROUP} -gt 0 ] && [ -e "${SURICATALOGPATH}" ]; then
			chown ${SURICATAUSER}:${SURICATAGROUP} "${SURICATALOGPATH}" || return 1
			chown ${SURICATAUSER}:${SURICATAGROUP} "${SURICATALOGPATH}"/* >/dev/null 2>&1 3>&1
		fi
		SURICATAOPTS="${SURICATAOPTS} --set logging.outputs.1.file.filename=${SURICATALOGPATH}/${SURICATALOGFILE}"
		SURICATALOGPATH="-l ${SURICATALOGPATH}"
	fi
	if [ ! -e ${SURICATACONF} ] ; then
		einfo "The configuration file ${SURICATACONF} was not found."
		einfo "If this is OK then make sure you set enough options for ${SVCNAME} in /etc/conf.d/suricata."
		einfo "Take a look at the suricata arguments --set and --dump-config."
	fi
	if [ ${#SURICATAUSER} -gt 0 ] && [ ${#SURICATAGROUP} -gt 0 ]; then
		einfo "${SVCNAME} will run as user ${SURICATAUSER}:${SURICATAGROUP}."
		SURICATAOPTS="${SURICATAOPTS} --user=${SURICATAUSER} --group=${SURICATAGROUP}"
	fi
}

initpidinfo() {
	[ -e ${SURICATAPID} ] && SUR_PID="$(cat ${SURICATAPID})"
	if [ ${#SUR_PID} -gt 0 ]; then
	    SUR_PID_CHECK="$(ps -eo pid | grep -c ${SUR_PID})"
	    SUR_USER="$(ps -p ${SUR_PID} --no-headers -o user)"
	fi
}

checkpidinfo() {
	initpidinfo
        if [ ! -e ${SURICATAPID} ]; then
        	eerror "${SVCNAME} isn't running"
                return 1
	elif [ ${#SUR_PID} -eq 0 ] || [ $((SUR_PID_CHECK)) -ne 1 ]; then
		eerror "Could not determine PID of ${SVCNAME}! Did the service crash?"
		return 1
	elif [ ${#SUR_USER} -eq 0 ]; then
		eerror "Unable to determine user running ${SVCNAME}!"
		return 1
	elif [ "x${SUR_USER}" != "xroot" ]; then
		ewarn "${SVCNAME} may need to be running as root or as a priviledged user for the extra commands reload and relog to work."
        fi
}

start() {
	checkconfig || return 1
	ebegin "Starting ${SVCNAME}"
	start-stop-daemon --start --quiet --exec ${SURICATA_BIN} \
		-- --pidfile ${SURICATAPID} -D ${SURICATAOPTS} ${SURICATALOGPATH} >/dev/null 2>&1
	local SUR_EXIT=$?
	if [ $((SUR_EXIT)) -ne 0 ]; then
	    einfo "Could not start ${SURICATA_BIN} with:"
	    einfo "--pidfile ${SURICATAPID} -D ${SURICATAOPTS} ${SURICATALOGPATH}"
	    einfo "Exit code ${SUR_EXIT}"
	fi
	eend ${SUR_EXIT}
}

stop() {
	ebegin "Stopping ${SVCNAME}"
	initpidinfo
	start-stop-daemon --stop --quiet --pidfile ${SURICATAPID} >/dev/null 2>&1
	einfo "Waiting for ${SVCNAME} to shut down. This can take a while..."
	# max wait: 5 minutes as it can take quite a while on some systems with heavy traffic
	local cnt=300
	while [ -e ${SURICATAPID} ] && [ $cnt -gt 0 ]; do
	    cnt=$(expr $cnt - 1)
	    sleep 1
	    echo -ne "$cnt seconds left before we give up checking the PID file...\r"
	done
	# under certain conditions suricata can be pretty slow and the PID can persist long after the pidfile has been removed
	# max wait for process to terminate: 1 minute
	if [ ${#SUR_PID} -gt 0 ]; then
	    cnt=60
	    SUR_PID_CHECK="$(ps -eo pid | grep -c ${SUR_PID})"
	    if [ $((SUR_PID_CHECK)) -ne 0 ]; then
		einfo "The PID file ${SURICATAPID} is gone but the ${SVCNAME} PID ${SUR_PID} is still running."
		einfo "Waiting for process to shut down on its own. This can take a while..."
	    fi
	    while [ $((SUR_PID_CHECK)) -ne 0 ]; do
		cnt=$(expr $cnt - 1)
		if [ $cnt -lt 1 ] ; then
		    eend 1 "Failed. You might need to kill PID ${SUR_PID} or find out why it can't be stopped."
		    break
		fi
		sleep 1
		echo -ne "$cnt seconds left before we give up checking PID ${SUR_PID}...\r"
		SUR_PID_CHECK="$(ps -eo pid | grep -c ${SUR_PID})"
	    done
	fi
	eend 0
}

reload() {
	checkpidinfo || return 1
	checkconfig || return 1
	ebegin "Sending USR2 signal to ${SVCNAME} to perform a live rule and config reload."
	if [ ${#SURICATAUSER} -gt 0 ] && [ ${#SURICATAGROUP} -gt 0 ]; then
		start-stop-daemon --user ${SURICATAUSER} --group ${SURICATAGROUP} --signal USR2 --pidfile ${SURICATAPID}
	else
		start-stop-daemon --signal USR2 --pidfile ${SURICATAPID}
	fi
	eend $?
}

relog() {
	checkpidinfo || return 1
	checkconfig || return 1
	ebegin "Sending HUP signal to ${SVCNAME} to close and re-open all log files."
	if [ ${#SURICATAUSER} -gt 0 ] && [ ${#SURICATAGROUP} -gt 0 ]; then
		start-stop-daemon --user ${SURICATAUSER} --group ${SURICATAGROUP} --signal HUP --pidfile ${SURICATAPID}
	else
		start-stop-daemon --signal HUP --pidfile ${SURICATAPID}
	fi
	eend $?
}

dump() {
	checkconfig || return 1
	ebegin "Dumping ${SVCNAME} config values and quitting."
	${SURICATA_BIN} --dump-config --pidfile ${SURICATAPID} ${SURICATAOPTS} ${SURICATALOGPATH}
	eend $?
}