Summary: | iptables init.d script should be 'before net' not 'need net' | ||
---|---|---|---|
Product: | Gentoo Linux | Reporter: | Michael C. Ferguson <michael.christopher.ferguson> |
Component: | [OLD] Core system | Assignee: | Gentoo's Team for Core System packages <base-system> |
Status: | RESOLVED FIXED | ||
Severity: | major | CC: | aalmenar, aurelus, chutz+bugs.gentoo.org, dopey, john.robinson+bug.gentoo.org, mholzer, michael.christopher.ferguson |
Priority: | High | ||
Version: | 2004.0 | ||
Hardware: | All | ||
OS: | Linux | ||
Whiteboard: | |||
Package list: | Runtime testing required: | --- | |
Bug Depends on: | |||
Bug Blocks: | 14761 | ||
Attachments: |
New iptables initscript
Simple before-net iptables script |
Description
Michael C. Ferguson
2003-08-21 18:23:35 UTC
umm and how do you propose resolving hostnames if you dont have net ? or do you tell users that they have to use ip addresses for all their rules ? Rules can still use names, as long as they are entered after the network (and, presumably, DNS or whatever) is brought up. /sbin/iptables-save saves rules as IP addresses anyway, even if you entered them as names, so I think you are exaggerating the issue. you're picking over less than 60 seconds of no iptables rules and you're telling me i'm exageratting ? after all, who knows when a box comes up ? the chances of 'exploiting' anything is quite small I Im sorry I wrote you were exaggerating actually, hostname resolution is a non-issue, since it is only used once (during the initial rule creation with /sbin/iptables) and then never again. iptables L will use reverse-lookup to try to give you a readable idea about what your rules do, but the reverse-lookup it does may or may not resolve to the same hostname you originally used in your rule. If I didn't believe this was a security issue, I would not have posted a bug report. I know of cases where internet-connected Windows machines have been compromised during installation, before they even had a chance to be patched. Although it is improbable that a machine would be compromised during this short time period, it is still possible, and therefore we should attempt to eliminate the possibility. If you have any *constructive* comments, please post them. -- mcf Created attachment 18131 [details] New iptables initscript The new script removes the ENABLE_FORWARDING_IPv4 option (see bug 14761 for why) and changes the init order slightly to put iptables 'before net'. This also incorporates changes suggested by Max Kalika in bug 21801 (reload support). It's more a matter of security/simplicity but setting up a firewall after the net could help automatize some stuff (like denying packets that don't belong to your network/IP) What about having iptables setup to DENY/REJECT everything before setting up the network and doing the real firewall setup only after? Nahor - That idea sounds good also. The question is... where to put it? iptables is not installed in the system by default, so maybe we need a test in one of the initialization scripts to see if it exists, and to enable it if it is ? I admit this is not my area of expertice. I like the idea of having iptables as part of the default system, but I'm not sure if this goes with the overall minimalist Gentoo architecture. Also, while testing the modified script, I noticed that portage will still turn off iptables before turning off the network, even though iptables is Nahor - That idea sounds good also. The question is... where to put it? iptables is not installed in the system by default, so maybe we need a test in one of the initialization scripts to see if it exists, and to enable it if it is ? I admit this is not my area of expertice. I like the idea of having iptables as part of the default system, but I'm not sure if this goes with the overall minimalist Gentoo architecture. Also, while testing the modified script, I noticed that portage will still turn off iptables before turning off the network, even though iptables is before net (maybe this is a bug in the initscripts ?) it sounds like your idea might also help that situation, if we block everything whenever iptables is stopped. I would still like to get rid of ENABLE_FORWARDING_IPv4 in the iptables initscript, since I think this is misplaced no matter what. Forwarding, static routes, and other settings that sit under /proc/sys/net/ipv4/conf/* and net.ipv?.conf.* kernel parameters really belong in the net.* scripts, not in iptables. > where to put it?
Two possibilities:
- Have an iptables-before and an iptables-after scripts which has the advantage
of being "firewall-idependant" (one can then easily replace iptables with
ipchains)
- Or put it in the net script.
I'm in favor of the net script. It would not be the first generic script having
some code for a specific package (like halt.sh assume that nut is handling the
UPS) and iptables is quite the default firewall now.
Then, one can:
- check if the iptables executable is there or not and ignore any error
messages if it's not in the kernel (maybe not ideal if the error is because of a
failures of some sort in the program/kernel).
- or have yet another variable in the /etc/conf.d/net to specify if the script
should call iptables or not.
As for Gentoo being minimalist, a firewall can be consider mandatory, can't it?
Afterall, a firewall is more important than Python (which has to be install for
portage) :p. Anyway, a variable in /etc/conf.d/net should solve that problem.
I was going to post something along these lines here myself, but you guys have saved me bothering. Still I'd like to add my 2p to the discussion. I agree that iptables should be up and running before the net starts, and that it shouldn't be stopped until after net. I agree that the ENABLE_FOWARDING stuff shouldn't be in iptables, really it should be in net or even in a separate routing item. People do use Linux boxes as non-filtering routers from time to time. Worse, some people use iptables as a firewall to protect a non-routing box, so why the heck would they want IP forwarding enabled? For my current application - home firewall/router - I do want IP forwarding, and as we're most likely to have IP at boot time (because that's when the loopback interface is brought up, at least with the current Gentoo structure), moving the ENABLE_FORWARDING stuff is no big deal for me right now. So, I've merged the distribution /etc/init.d/iptables with MCF's version - keeping the ENABLE_FORWARDING in - but what's currently bugging me is that even though it says 'before net' it isn't running before net at all. I've run /sbin/depscan.sh by hand just to try to persuade it to do the right thing, and actually it does because the contents of /var/init.d/deptree look fine: depinfo_net() { export rc_name="net" export rc_ineed= export rc_needsme="dhcp exim named netmount sshd" export rc_iuse= export rc_usesme="rsyncd" export rc_ibefore= export rc_iafter="iptables" export rc_broken= export rc_parallel= } This sounds like it may be related to MCF's report of things not being done in the right reverse order at shutdown. However this in itself is not a bug report for iptables so I'll take it elsewhere :-) I have had A Thought[tm]. New virtual service called firewall. Default configuration, it's an empty stub except for a note saying, "If you have a network interface, you ought to have a firewall.". Then net can depend() { need firewall } or whatever. And those of us who like doing things properly can install iptables or whatever our firewall software of choice is. when running before net, iptables doesn't resolve domains MH, MCF has covered this above; `/sbin/iptables` resolves names as a service to the user on the command line, but `/etc/init.d/iptables save` saves the filter rules as IP numbers so that `/etc/init.d/iptables start` doesn't need to resolve names, and because of this, it is safe to run the service before net. It is also useful to do so to make sure your filters are in place as soon as the interfaces are up. That's suppose that the script just reload a previous firewall state. People using DHCP may want a script that will dynamically update the firewall to there current IP. But as I suggested before, a solution is to block everything from the network (except DHCP if so configured) before bringing up the network and once the network is up, to finish setting up the network. That way, the firewall scrip can still access any network data it needs without leaving gaping holes in the firewall. That's a good point, and it's made me think again: what are we protecting by using iptables (or whatever)? I mean, if we think iptables (or whatever) is good enough that it is not itself vulnerable to nasty hackers, can we suppose that the kernel's IP handling is reasonably solid and unlikely to be cracked? I ask this as a lead-in to the suggestion that, if we can contrive that iptables (or whatever firewall configuration) is run immediately after after the network interfaces are brought up, and before any userland software binds to them, it might even be safe enough not to load any firewall configuration at all before bringing up the network interfaces; only the kernel's regular IP handling code is at risk. At the moment I'm not sure the initscripts' "after" feature could, even in theory, guarantee such immediate running, however; what happens if two things both want to be "after" something? Also, if the interfaces have previously been set to drop almost all traffic, I can envisage scenarios when something that "need"s net cannot start if the firewall configuration proper has not yet been run despite net having been run. Perhaps the answer is actually that this really does need to be done within net, but in a configurable way; for example if conf.d/net says "FIREWALL=iptables" then net can run a separate script (or two or more e.g. pre-if and post-if) called iptables. Similarly, there might be configuration for what kind of routing and forwarding a box does, so we run something else if we've a bunch of complex routing to do, or just set default route if specified, and then don't turn on IP forwarding if we don't want it. Already net is a multi-module service (eth, ppp, vlan etc), let's just add some more modules? Hope that's of interest. I might have done it myself by now if I hadn't totally hosed my box. (Dunno how I did it, but I'd been playing with compiler options so maybe I overdid it with the optimisation.) I think Comment 14 is a good idea. However, I think the ability to load multiple scripts is a bit redundant (e.g having a pre-if and post-if). This would simply add to the complexity of the iptables setup and kill unnecassary CPU cycles. The ability to load the firewall script, though, from /etc/conf.d/net /after/ the interfaces are loaded should resolve this issue since the system is really under no threat until network-aware services are loaded. Loading the iptables rules after the network interfaces has the added benefit of being able to configure dynamic network devices--such as those using DHCP. It may also be of interest (for those of you not watching the mailing list) that there's a rather lengthly thread regarding this topic. The Subject is: What is the best way to start iptables on boot time? No, the solution is still just to make iptables 'before net'. I haven't seen a rational reason yet why this wouldn't work (and in fact, this is exactly what all of my machines are using, via the initscript I attached above). There's no reason to add more needless complexity to what is really a simple fix. iptables should be loaded before any other network service, including bringing up interfaces and using dhcp. -- mcf Michael, please define "rational reason" if you don't see DHCP as being a problem. Or explain how you would handle dynamic IPs. Your attached initscipt didn't enlightened me Let me see if I understand you correctly... You're stating that one should load their iptables script before the network interfaces. Then, after the interfaces load, you're saying that the iptables script (or possibly a second script) would be run to gather the requisite IP data from dynamically configured interfaces. Yes? I think I understand your perspective. Truth is...it would work. But so would what I (and some other posters) suggested--I stand by my previous posts. I don't know, though, that using /etc/conf.d/net is the best solution--it's simply one of many possibles. Another options would be to load the iptables script after net.eth* but before any userland programs load. This would eliminate the need to add modules to conf.d/net. In either case, I think the load time between net.eth* and iptables (as it currently stands) is inconsequential. The fact of the matter is that someone would have to know the exact moment that the system begins to boot to launch a successful attack on the system--and even then, we're only talking a few seconds of opportunity. I don't know of anyone who can successfully exploit a system in that amount of time. Hi Nahor, If you're using DHCP, you should filter on the interface (-i ethX) instead of on the interface's address (-d ...). This is regardless of whether or not you're using any initscript, since you may be assigned a new address at any time, at which point your iptables rules would probably become invalid. Best regards, -- mcf Hi Thomas, I'm suggesting that iptables be started (and the saved rules from /var/lib/iptables/rules-save) be loaded 'before net' is started. There is no need to do any 'post-initialization' of any kind. I wrote a small explanation of the perceived issues in bug 14761, which might help clarify things. Please let me know if you have any other questions, and feel free to contact me via e-mail or IRC (also nickname 'mcf' on FreeNode). Best regards, -- mcf Usually, when renewing an IP with DHCP, you keep the same one. And in any case, there is always the possibility to restart the firewall then. As for filtering on the interface only, I'm not sure it would be enough. For instance one could forge a network packet to use your MAC address with a bogus IP. It's probably not a good example but the idea is there. And the same way it is advised to use TCP Wrapper even if one has a firewall, it is best to filter on both the interface and the IP. I give you that your solution is still better than what we have now. But I do think that the better solution is to block everything (except DHCP if needed), bringing the network up then setup the firewall. The before-net script is very simple and secures the machine. The after-net script can then be run any time, even after the network services (well maybe not completly, some service may need the network to start (like ntpd which tries to sync the clock first)) Okay, let me backup a little ;-)... The "before-net" idea sounds interesting for "simple" setups--say, for example, for systems with single or multiple NICs and the script justs binds to those devices. But what about situations where servers have entire subnets aliased on one interface? One of my servers has around 200 IPs on a single interface. To take it one further, not all of those IPs require the same services to be available--thus, only the necassary ports are opened (on a per-IP basis) and the rest are blocked. This situation would certainly require filtering by IP and not by device--thus an "after-net" script would be required. Given this situation, and Nahor's comments, perhaps a "before-net" and "after-net" /option/ would be beneficial. Going back a couple of comments, adding a conf.d/net option may be the right way to go. People who don't want to use it can leave out the options; those who'd like to use it can add the option(s). I personally don't think that a "before-net" option is unnecassary--but that's just my opinion. The arguments made for it are valid and compelling but loading iptables immediately after the net.eth* devices will acheive the same effect. In the spirit of Gentoo, users should have the option to use before-net/after-net, just before-net, or just after-net--as opposed to being locked into a single method. For example, one could add to conf.d/net a BEFORE_NET= and an AFTER_NET= variable pointing to a script that does what they want. Simple. Flexible. Every body's happy (at least in an ideal world ;-). >I think the load time between net.eth* and iptables (as it currently stands) is inconsequential. Not so. A real world example: I'm one of those who needs to switch between administrative net and "work" net from time to time. Both nets have dhcp service for ipv4 and one of them has stateless ipv6. When switching from one net to other using "/etc/init.d/net.eth0 restart" there is about 15 second delay before the dhcpcd decides that it can't contanct the latest dhcp server and looks for a new one. During that time anyone can use global ipv6 connections to my host as the firewall rules are disabled. >One of my servers has around 200 IPs on a single interface... >This situation would certainly require filtering by IP and not by device--thus an "after-net" script would be required. For such a list it is propably fixed ip-numbers. The rules by ip-number can be loaded as well even before you have initialized any of your network interfaces. It's just dynamic numbers (like dhcp) that you should newer trust to be constant. Doing similar things with dynamic numbers... Well, there are interesting things you can do to shoot your own legs. To sum it up. The current iptables doesn't contain anything that uses net at service start-up. Changing it from "need net" to "before net" is therefore the correct solution. Created attachment 21506 [details]
Simple before-net iptables script
Hi there,
I think it's a good idea to put iptables before the net services. What I would
suggest is a script such as the changed (stateful) iptables script I attached.
It blocks all TCP and UDP traffic by default, and makes a chain in which rules
can be added to allow certain traffic. These rules could be added by the
services that need a specific "hole" and/or by an after-net iptables script
that loads user-specific settings. (A machine with no external services
wouldn't need the last script.) Such as rule would e.g. be "/sbin/iptables -I
INPUT_ACCEPT -p tcp -m tcp --dport 80 -j ACCEPT".
I'm aware that this script would not yet suit more complex situations. Probably
a FORWARD_ACCEPT chain or so would be needed for example.
With regards,
Aurelus
*** Bug 39112 has been marked as a duplicate of this bug. *** I'd like to join the discussion in favor of "before net". My argument: Since all that these scripts do in start() is to run ip{,6}tables-restore on the data that has been saved by ip{,6}tables-save, this is all pretty static stuff, isn't it? ip{,6}tables-save does not save dynamic configuration if I am not mistaken. And I really need to do this "before net", because there is a broken router somewhere in school that I want to block. It is broadcasting useless ipv6 data, which assigns a useless ipv6 address to my interface (there is no routing to this address). It's been a month since my comment, and three months since the comment before that. Progress on this one? I'd really like to see it addressed. I finaly got a chance to see for my self that iptables can be loaded without incident "before net". Thus, my previous arguments hold much less weight than I originally thought. The only remaining issue, as I now see it, is catering to those who use DHCP. I agree with a previous post that everything in /var/lib/iptables/rules-save will remain static. This being the case, how would one plug DHCP-obtained values into it if iptables is loaded "before net"? (I suppose, too, that it would be much easier to simply edit /etc/init.d/iptables and change depend() { need logger net } to depend() { need logger before net } for those who don't need DHCP or who prefer to load iptable "before net" rather than inventing a new way to load iptables.) Re: Comment #29 How exactly do DHCP users benefit from the current setup? The stuff in /var/lib/ip{,6}tables/rules-save *is* static. There is no way around it, unless the dhcp client adjusts stuff in those files, which I haven't checked but highly doubt. If you want to have dynamic information in you iptables rules, you'd need to load a custom script, and the current default /etc/init.d/ip{,6}tables do not mention any custom scripts. Those scripts only read the *static* /var/lib/ip*/rules-save. Neither DHCP users (need net), nor those like me (before net) benefit from the current setup. Could you give an exact example of a situation where one would actually need the ip{,6}tables init script to be "need net"? Before submitting this example, could you test in your environment and confirm that this is *really* what the person would want? Agreed, the DHCP problem is separate from this. If you use DHCP, you need to keep some things open enough so you can renew your lease(s). So if your filters can work at all, they can work before your IP is assigned. If you use DHCP, you probably ought to be filtering on interface, not IP address, or doing something else otherwise beyond the scope of the iptables package (because you need to hook in to whatever dhcpcd is doing so you can update your filters). Please can we have this fixed up. To make myself clearer: Quote from comment #29: ``The only remaining issue, as I now see it, is catering to those who use DHCP. I agree with a previous post that everything in /var/lib/iptables/rules-save will remain static. This being the case, how would one plug DHCP-obtained values into it if iptables is loaded "before net"?'' Question: How would one plug DHCP-obtained values into it if iptables is loaded "after net"? My point: There is no way to do anything about DHCP-obtained values with the current setup. "need net" does not help *anyone*. Precisely. You can have a /var/lib/iptables/rules-save file produced by iptables-save which works with DHCP, and it'll work just fine "before net". (It just won't refer to your DHCP-allocated variable IP address, but to your network interface, and perhaps the IP range(s) issued by your DHCP server.) If you want to do funky stuff which takes note of an IP address assigned by DHCP, you have to do something extra, and if you decided then you wanted iptables to "need net" you could make the change yourself. This is very much beyond what most users want. But the default shipped version should be "before net". In fact it's not all that funky at all; `man dhcpcd` shows that dhcpcd calls a script (/var/lib/dhcpc/dhcpcd.exe, stupid name I know) when it gets an IP, gets a new IP, or loses its IP, and `man pppd` shows pppd does something similar with /etc/ppp/ip-up and /etc/ppp/ip-down. iptables fiddling for variable IPs should be done by those scripts, and iptables fiddling for default and fixed rules should be done by /etc/init.d/iptables "before net". Any progress on this? the "before net" idea seems really kludgy to me. I don't know why. however, i can't think of a simpler solution. I really think a better solution overall is add the ability to do immediately after/immediately before which will let the admin decide, but this will result in cluttering the dependency tree more. Back into the pool with you. Someone fix this please... it's a no brainer. If you want, e-mail me and I will call you from work and explain what the issue is and why it should be fixed. Or just read bug 14761 or below if you have time... Added to 1.2.9-r1 Either I'm doing something wrong, or something is just wonky. my iptables script now has before net in the depend() section. However, iptables is still being loaded in alphabetical order with the rest of the initscripts. Anyone else still seeing this behavior? Yes, I had that problem when I made the change myself (see comment 9) but I think it's an init-system bug, not an iptables bug. I've kludged round this by adding iptables to the boot runlevel. I meant, yes I had that problem, and yes it is still present. I have reported the init problem in bug #31950. Worth noting that the new baselayout allows us to solve this problem easily: $ tail -n3 /etc/conf.d/net depend_eth0() { need ip6tables iptables } |