Linux - SecurityThis forum is for all security related questions.
Questions, tips, system compromises, firewalls, etc. are all included here.
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.
I'm trying to secure my ssh port with iptables. So far I successfully limit one ip to connect once a minute:
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 -j DROP
How would I add a rule that limits the total number of connections to 10, on port 22?
I know you could use the connlimit match to restrict the number of concurrent connections, but I think it can only be made to work on a per subnet basis (not in total). I'm not sure about that, though, so maybe you should still look into it and see. If you have a really modern version of OpenSSH (I don't), the MaxSessions parameter might satisfy your needs AFAICT.
BTW, what you posted isn't limiting to 1/minute, it's limiting to 2/minute:
Code:
[!] --hitcount hits
This option must be used in conjunction with one of --rcheck or
--update. When used, this will narrow the match to only happen
when the address is in the list and packets had been received
greater than or equal to the given value. This option may be
used along with --seconds to create an even narrower match
requiring a certain number of hits within a specific time frame.
1) A connection to port 22 can only be made once every 60 seconds per IP.
Edit* 2) There can only be 10 new connections to port 22 every 5 minutes, regardless of IP.
I haven't read the article you've linked, but I did some TCP SYN scan tests with nmap and they confirm that you're absolutely right. My bad.
Quote:
I'm trying to build rule 2). I don't want rule 2) to be based on IP, I just want to allow 10 connections from any number of IPs at once to port 22.
Thanks for the suggestion but it's actually another way of building rule 1).
Actually, I understand that part. That's why I mentioned that even though I know connlimit would let you do this per subnet, I wasn't sure if it had the option to do it "in total" (or for all subnets/IPs). I honestly wouldn't be surprised if it did have a way to say "any IP" - but I don't know if it does. I look forward to seeing how you end up achieving this with iptables, though, because I'd like to learn how to do it too. Good luck.
I looked around and people were saying the --limit and --limit-burst would limit concurrent connections, no matter the IP. I only have two comps so I haven't tested it out on multiple machines yet- it works against one.
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 -j DROP
iptables -A INPUT -p tcp --dport 22 -i eth1 -m limit --limit 1/minute --limit-burst 10 -j ACCEPT
I would rather have the --limit rule first, but I haven't found a way for it to say, "continue to the next rule if true, drop if false". Then if someone does a DDOS attack with a big botnet the packets will get dropped before going through two rules.
Ideally:
iptables -A INPUT -p tcp --dport 22 -i eth1 -m limit --limit 1/minute --limit-burst 10 -j "continue to the next rule if true, drop if false"
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 -j DROP
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW -j ACCEPT
I looked around and people were saying the --limit and --limit-burst would limit concurrent connections, no matter the IP
Well, they can stop the connections from being started within the timeframe, yes.
Quote:
I would rather have the --limit rule first, but I haven't found a way for it to say, "continue to the next rule if true, drop if false".
You could put the recent rules in a separate chain, and have the limit rule jump to it when TRUE.
Using the example you posted as a base, it might look something like this:
Code:
iptables -N SSH_PROTECT
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW \
-m limit --limit 1/minute --limit-burst 10 -j SSH_PROTECT
iptables -A SSH_PROTECT -m recent --set
iptables -A SSH_PROTECT -m recent --update --seconds 60 --hitcount 2 -j DROP
iptables -A SSH_PROTECT -j ACCEPT
Notice that you don't need any protocol, interface, port, or state matches in the SSH_PROTECT rules, as they would be redundant. Also, packets which don't match the limit rule wouldn't get sent to SSH_PROTECT, so they would be dealt with either by some matching rule further down the INPUT chain, or by whatever the INPUT chain's policy is set to (if there were no other matching rules).
You're very welcome. BTW, remember to enable TCP SYN cookies when doing stuff like this otherwise even a caveman could have you under denial-of-service attack if they know the IP you (or any other client) will be connecting from. And when you do so, make sure you filter any TCP packets in state NEW which aren't proper SYNs, like:
Code:
iptables -N SSH_PROTECT
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW \
-m limit --limit 1/minute --limit-burst 10 -j SSH_PROTECT
iptables -A SSH_PROTECT -m recent --set
iptables -A SSH_PROTECT -m recent --update --seconds 60 --hitcount 2 -j DROP
iptables -A SSH_PROTECT -j ACCEPT
Or if you only want it to apply to this SSH stuff then:
Code:
iptables -N SSH_PROTECT
iptables -A INPUT -p tcp --dport 22 -i eth1 ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --dport 22 -i eth1 -m state --state NEW \
-m limit --limit 1/minute --limit-burst 10 -j SSH_PROTECT
iptables -A SSH_PROTECT -m recent --set
iptables -A SSH_PROTECT -m recent --update --seconds 60 --hitcount 2 -j DROP
iptables -A SSH_PROTECT -j ACCEPT
Now that I think a bit more about your configuration, the cookies only stop the caveman from exploiting your recent match rules in order to DoS attack you. With the way the rules are currently laid-out, the caveman would still be able to exploit your limit match rule and have you under DoS in the blink of an eye (and he wouldn't need to spoof any IPs to do it).
Yeah that's right, cause syn attacks can be issued on any port and that rule is limited to port 22. I now added input and forward rules for it.
No, that's not the reason. This isn't about a SYN flood. It's about exploiting your limit rule to get you under DoS. You see, the SYN cookies prevent the bad guy from sending SYN packets with spoofed source IPs (your IP or your other clients') to activate the recent match and lock you out of your box. But the cookies have zero effect for the limit rule, as those matches will be triggered regardless. So the bad guy simply sends SYN packets to you at a rate higher than the limit, and neither you or any of your clients will be able to connect.
Theoretically speaking, this DoS vulnerability can be eliminated by inversing the order in which the checks are being applied in the above rules. In other words, you instead use recent first to check that the IP isn't sending more SYNs than you allow per individual IP, and if that check is passed, then limit is used to check that the ceiling you've set for IPs in total hasn't been broken. If both checks are passed (in that order) then the packet gets sent to ACCEPT. This way if the bad guy tries to trigger the limit rule to put you under DoS, he won't even be able to get that far, as he'll get smacked down by the recent rule.
Ok, the packets would trigger the limit rule because they wouldn't get blocked by the IP block rule, which is in the SSH_PROTECT chain.
Your idea of reording the rules makes sense to me.
I think I'd rather keep those two ! --syn DROP rules at the beginning of the input and forward tables though. That way it will apply to all subsequent rules and I won't have to worry about --syn being in the wrong place in a rule.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.