SlackwareThis Forum is for the discussion of Slackware Linux.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
View Poll Results: I reviewed this proposal, and I think:
I suspect there would be others like myself who have scripted their own rc.firewall without checking for a start/stop argument, and the introduction of such a change would really wreak havoc.
Yes -- and I've been mulling this problem over since Henrik brought it up earlier. I had one thought. Let me ask you, since your system represents an actual case in point. When you change runlevel to single-user, and then change runlevel to multi-user, don't you run into the same problem? Doesn't your rc.firewall run a second time without checking for a start/stop argument and bollocks things up? And wouldn't the presence of a shutdown hook for rc.firewall actually give you the right tool to fix that?
Quote:
Originally Posted by avian
if the change did occur, the only thing I'd ask for is a bunch of notice
Just make symlink of rc.firewall in rc0.d, rc1.d and rc6.d
Yes, it's better than requiring a manual edit, and it works. That's my current workaround, as I noted in the original post.
The virtue I see in a shutdown hook in rc.6, is that Slackware is very BSD initscript-centric. System V initscript support, according to what I've read, is just there for a few commercial packages that expect it. So intentionally using a System V initscript in a Slackware package for shutdown, but using a BSD initscript for startup, seems like it will cause the greatest possible confusion. Using a BSD initscript at both ends would be easier to understand.
If I understand your question right, the answer depends on what the installed rc.firewall does. If rc.firewall start does more than just load static rules, if for example it starts a process that updates rules in real time based on intrusion detection, then the call to rc.firewall stop would stop that process.
Thank you, metaed. Auto updating rules would indeed be like the problems that can exist with the old "lazy write" condition. I've never bothered to automate rules updating and the subject is intriguing. I will be looking into this.
I've never bothered to automate rules updating and the subject is intriguing. I will be looking into this
The package I'm developing has:
1. A daemon that detects intrusion attempts in real time and adds the attacking IPs to an NFT firewall blocklist.
2. A monthly cron job that updates a second NFT firewall blocklist of IP ranges that serve as a geofilter.
So it becomes important to snapshot the ruleset at shutdown time, and also periodically during multiuser to prevent the updates from being lost to a power fail or panic.
Slackware does not ship a rc.firewall script, but it does ship two basic firewall scripts from Roaring Penguin Software (firewall-masq and firewall-standalone in /etc/ppp/).
It might be worth noting that none of those scripts cares about any start or stop parameter. If called during shutdown the will simply rerun the stuff intended to run at start. On the other hand, running that again during shutdown might not make much harm in this example.
The package I'm developing has:
1. A daemon that detects intrusion attempts in real time and adds the attacking IPs to an NFT firewall blocklist.
2. A monthly cron job that updates a second NFT firewall blocklist of IP ranges that serve as a geofilter.
So it becomes important to snapshot the ruleset at shutdown time, and also periodically during multiuser to prevent the updates from being lost to a power fail or panic.
The running daemon could possibly write the ruleset to file before it gets killed (just after its main loop or maybe trap SIGTERM?)
The package I'm developing has:
1. A daemon that detects intrusion attempts in real time and adds the attacking IPs to an NFT firewall blocklist.
2. A monthly cron job that updates a second NFT firewall blocklist of IP ranges that serve as a geofilter.
So it becomes important to snapshot the ruleset at shutdown time, and also periodically during multiuser to prevent the updates from being lost to a power fail or panic.
I think I am getting a better picture of what you are trying to architect.
/etc/rc.d/rc.firewall is just a bash script. Although it is usually reserved for implementing firewalls it can also be used to do other tasks.
To protect a running daemon, you could check for a PID in /run and take action accordingly.
Same with /etc/rc.d/rc.local_shutdown. You could check for the running daemon and save the rulesets.
The monthly cron job does not seem to be affected by the dynamics. It could be installed as part of package installation.
Interesting thread! I haven't voted yet because I wanted to see the arguments for/against.
Another angle: It could be argued that the firewall-modifying daemon shouldn't be started by rc.firewall, but by it's own startup script. Then of course it would be stopped like usual.
What I've done to keep rc.local (and rc.local_shutdown) from getting unwieldly is add a directory /etc/rc.d/rc.local.d and the following snippets to rc.local and rc.local_shutdown:
Code:
# Process all startup scripts in /etc/rc.d/rc.local.d/
for rc_script in /etc/rc.d/rc.local.d/rc.* ; do
if [ -x "$rc_script" ]; then
$rc_script start
fi
done
unset rc_script
Code:
# Process all shutdown scripts in /etc/rc.d/rc.local.d/
for rc_script in /etc/rc.d/rc.local.d/rc.* ; do
if [ -x "$rc_script" ]; then
$rc_script stop
fi
done
unset rc_script
For OP's use case, rc.firewall would do nothing but load the firewall (either by restoring a previously-saved state or creating one from scratch like alien bob's easy firewall generator script output). That is, restrict rc.firewall's functionality to ONLY loading a firewall.
Then the firewall daemon would be started/stopped by custom startup/shutdown scripts called by rc.local (or with my above snippets just placed in /etc/rc.d/rc.local.d/). Because the daemon only modifies the existing firewall, it is not sensitive to when it is started/stopped. Stopping the daemon doesn't nuke the firewall - it only stops the on-the-fly modifications to the running firewall.
But now the firewall daemon has a dependency on rc.firewall already being started - it doesn't make much sense to run a firewall daemon if the firewall isn't up. So in this sense this solution adds complexity.
After seeing what you plan to do, I would point you toward the example of fail2ban. Which although not identical, is in the same ballpark of target audience and potential implementation. It runs a daemon to monitor abusive clients connecting to your system, and then implements firewall rules to ban them.
I have fail2ban running here (with a custom rc.firewall), and it doesn't need to touch rc.firewall in the slightest. It starts from a reference in rc.local and shuts down via rc.local_shutdown. In the case of fail2ban, it is very well behaved, i can start and stop it at will, and it wont touch any of my custom rules as set by rc.firewall. It doesn't need to save the state of the nft tables at any point, instead it keeps track of banned IPs separately in a database. The advantages here are that you can set time limits on bans, and go back and analyse IPs, IP blocks, number of attacks or unauthorized logins etc.
I have heavily customised so much of my slackware install. Including the way it brings up networking, the way it handles ethernet disconnects and reconnects (through ifplugd), the way it handles new dhcp requests (through dhclient hook scripts - which modify firewall rules dynamically) etc. I would not have installed fail2ban if I thought it would hinder my customisations in any way, or if it had proven difficult in any way.
I would suggest that since you are starting your own daemon, it would be best started outside of rc.firewall. And considering there are packages similar what you are trying to achieve, that have been implemented in very end-user friendly, and sysadmin friendly manner, that you could do similar also. I would also suggest that saving the state of the nft tables and restoring them later perhaps isn't ideal either.
I think the underlying question here is whether rc.firewall is intended to be considered a subsystem script that supports start/stop, such as rc.elogind, or more like rc.M, that doesn't. As Slackware currently stands, it seems the latter is the case.
In CRUX, /etc/rc.d/ is reserved for subsystem scripts, and the main rc scripts, such as the rc.M equivalent rc.multi, are actually directly in /etc outside of the rc.d directory: making the distinction clearer.
Don't hate me for this, but IMO the CRUX approach¹ — using a rc.conf and a SERVICES=( ) array to decide what in rc.d gets started/stopped and in what order — is a much cleaner approach. A lot of lessons have been learnt over the ~30 years since the Slackware scripts were devised and it'd be nice to see them modernised. However, the change would be a disruptive one and for that reason I don't see it ever happening.
____
1. If I remember rightly, prior to systemd adoption, Arch also did something like this.
Same with /etc/rc.d/rc.local_shutdown. You could check for the running daemon and save the rulesets.
If this were only a local customization, yes, that's what I would do. On the other hand, a package should avoid, if possible, giving post-installation instructions such as "create or edit your rc.local_shutdown". That's sometimes a necessary evil. But it's much cleaner to have the package register itself using stock Slackware 15.0 hooks.
The package is able to fully install itself without post-installation manual edits. It drops config files in /etc, /etc/rc.d, and /etc/syslog.d. All the operator has to do post installation is reboot, or if they prefer not to reboot:
This all works. The issue is just that the package has to use a BSD initscript to start and a System V initscript to stop. That's going to be confusing, and I want to find something better. This is why I proposed that /etc/rc.d/rc.firewall stop should be called when stopping multiuser.
Another angle: It could be argued that the firewall-modifying daemon shouldn't be started by rc.firewall, but by it's own startup script.
That would be fine also. But if there is another way that a package can automatically arrange for that to happen, and happen early enough, I just don't know about it.
[fail2ban] doesn't need to save the state of the nft tables at any point, instead it keeps track of banned IPs separately in a database. The advantages here are that you can set time limits on bans, and go back and analyse IPs, IP blocks, number of attacks or unauthorized logins etc.
How best to implement IP bans is a separate question, and there's no simple answer. The question I'm raising is just how a package can automatically arrange to be stopped when stopping multiuser, without having to use a System V initscript.
I can tell you how I'm doing IP bans. I use the NFT firewall, and it supports (and so my package supports) time limits on bans, and attack counters. From your summary of fail2ban, I take it that it doesn't ban IP addresses in the firewall, but does it downstream using hooks in protected applications. This approach has plusses and minuses.
On the plus side, you can probably prevent the "patient 0" intrusion attempt, where a syslog-based approach has to detect the attack in the log and then block the IP address so the attempt cannot be repeated.
On the minus side, the attacker is not blocked from trying other types of attack once one route has been closed. When my package detects an attack on the SMTP port, the NFT-firewall-based ban means that from the attacker's point of view, my entire server just went dark. They can't try SSH, HTTPS, etc., next.
I think the underlying question here is whether rc.firewall is intended to be considered a subsystem script that supports start/stop, such as rc.elogind, or more like rc.M, that doesn't. As Slackware currently stands, it seems the latter is the case.
The former, actually. The stock rc.inet2 does:
Code:
if [ -x /etc/rc.d/rc.firewall ]; then
/etc/rc.d/rc.firewall start
fi
I consider it a mistake of my past to use scripted networking.
(note in the early 1990's when I used slackware off walnut creek ELFO, everyone was doing it and saying it was fine)
A good thing would be a C program which listens to FD (not polling) and configures upon activation and has an interface, and that it run in a sandbox like Apple would do.
I would not "get too deep in scripting it all". It won't be portable or take easily to eventual upgrades.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.