Monday 11 August 2014

FirewallD: Adding Services and Direct Rules

This post will expand somewhat upon the firewall rules in my RHEL7-install blogpost. I'm trying to make an IPsec connection between two machines (CentOS6 & CentOS7) - I'll detail the IPsec in another post, but this covers adding the FirewallD rules on the CentOS7 box.

I did have quite a few of these commands in my RHEL7 post, but Blogger somehow ate them between Edits on my post.

Anyway, here we go:

Enable IPsec via Standard FirewallD Services

# Is IPsec enabled?
firewall-cmd --zone=public --query-service=ipsec
# No? Then enable it:
firewall-cmd --zone=public --add-service=ipsec
# and next reboot too:
firewall-cmd --permanent --zone=public --add-service=ipsec


Manipulate Direct iptables Rules

Ok, that was easy. Now the hard-bit: rate-limiting inbound new SSH connections, via FirewallD's Direct rules.

There are lots of ways to protect an SSH server on the public internet - move SSH port (PS if you do this in RHEL7, you need to tell SELinux that the port has moved; This appears in the sshd config file) but that is no panacea (I have a high-port-listening SSH server on an IP with no DNS and no internet-advertised services... and it gets hit quite a bit), key-only login (a great idea - password brute force attacks are utterly useless), IPv6 only (good luck connecting to it from everywhere!) and even port-knocking (if that still exists). However, for a bog-standard SSH connection on port 22, another good way is rate-limiting for NEW connections via iptables.


So, now we need to use the Direct interface to iptables. As we can see from the output below, the Direct table rules are interpreted by iptables before the Zone-based stuff.

[21:16][root@host:~]# iptables -nv -L INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
14535 8172K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
1 240 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
57138 34M INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
57138 34M INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
57138 34M INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
52 4547 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
56602 34M REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited


So, we add the following direct rules:
firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp -m tcp --dport 22 -m recent --update --seconds 180 --hitcount 3 --rttl --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j LOG --log-prefix "SSH_brute_force "
firewall-cmd --direct --add-rule ipv4 filter INPUT 1 -p tcp -m tcp --dport 22 -m recent --update --seconds 180 --hitcount 3 --rttl --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j DROP
firewall-cmd --direct --add-rule ipv4 filter INPUT 2 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j ACCEPT

And now we remove SSH from the public Zone:
firewall-cmd --zone=public --remove-service=ssh

I seriously suggest that you log back into this server with a new, secondary SSH connection to make sure that you haven't just locked yourself out!
And now feel free to try SSHing into the host 4 times - you will see that your 4th connect is blocked.
Please note that each connection can try multiple passwords, so this doesn't stop password brute-forcing for the first ~12 passwords - combining this with preshared-key-only entry is still the most effective method.

If this is all working for you, remember to run the above commands with a --permanent flag:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp -m tcp --dport 22 -m recent --update --seconds 180 --hitcount 3 --rttl --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j LOG --log-prefix "SSH_brute_force "
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp -m tcp --dport 22 -m recent --update --seconds 180 --hitcount 3 --rttl --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j DROP
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 2 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource -m comment --comment "SSH Brute-force protection" -j ACCEPT
firewall-cmd --permanent --zone=public --remove-service=ssh



Useful links I found on my travails:

Very good start to FirewallD:
http://ktaraghi.blogspot.com.au/2013/10/what-is-firewalld-and-how-it-works.html

Not actually FirewallD, but Linux kernel rate-limiting - this might be a useful link in the future!:
http://blog.oddbit.com/2011/12/26/simple-rate-limiting/

1 comments:

  1. Key only login for ssh / scp highly recomended, and essentially makes a non-directly targeted attack useless.

    ReplyDelete