Just to describe the scenario in more detail, why i even have this request:
- Server with dynamic IP (ppp0 for example)
- UI that allows to activate/deactivate .rules files
- ifup-post script for the dynamic interface
Following scenario might happen:
- UI changes the .yaml config to include foobar.rules and thus sends a SIGUSR2 to suricata so the new rules get activated.
- While the reload is in progress (takes some seconds) the dynamic interface comes up and receives a new dynamic IP. The ifup script changes HOME_NET in .yaml so the new dynamic IP is included and thus sends also a SIGUSR2 to suricata so the new HOME_NET value gets activated.
- Since the second SIGUSR2 is ignored, suricata ends up with a valid but old config that is active for the recent running suricata process. So in this example HOME_NET still has the old value it has when the rule was changed.
The script could check in /var/log/suricata.log if the last line is "rule reload complete" but that's far from perfect to make sure the recent reload is done.
Andreas Herz wrote:
I would suggest that the second USR2 signal is stored and after the first reload is completed the second one should reload to make sure the proper IP is in HOME_NET.
After digging into the code one possible way is to extend "SignalHandlerSigusr2Idle" like:
void SignalHandlerSigusr2Idle(int sig)
{
if (run_mode == RUNMODE_UNKNOWN || run_mode == RUNMODE_UNITTEST) {
SCLogInfo("Ruleset load signal USR2 triggered for wrong runmode");
return;
}
SCLogInfo("Ruleset load in progress. New ruleset load "
"allowed after current is done");
// wait until the reload is done
while (UtilSignalIsHandler(SIGUSR2, SignalHandlerSigusr2Idle)) {
usleep(500000);
}
// start a new reload
SignalHandlerSigusr2();
return;
}
(just an example, needs more logic like when a third SIGUSR2 comes etc.)
This could result in the following behaviour:
- Receiving SIGUSR2 -> start reload
- Receiving SIGUSR2 #2 while reload in progress -> wait for reload to finish, to reload again
This results in a sane active suricata config with the most recent values.
An alternative would be some way to detect if the rule-reload is still in progress, so a script could wait. Having a logwatch is one possibility, but kinda messy.
Since there is no way (at least i know none) to check if the rule-reload is done (besides reading logfiles which could result in other errors) i could also think about some other ways:
- create a lockfile that could be checked from external scripts, although this would result in the scripts to wait
- send some answer/return value that could be checked
A workaround is to restart suricata everytime, but since the rule-reload feature is included, makes more sense and is just nice, i would like to improve this part.
So i would appreciate any opinion about this issue and what could be the most preferable way to deal with it. I will play around with the codebase to see if i can find some other (better) way of dealing with that besides patching the SignalHandlerSigusr2Idle.