Here’s how to do it:
firewall-cmd --zone=internal --add-service=ssh --permanent firewall-cmd --zone=internal --add-source=1.2.3.4/32 --permanent firewall-cmd --zone=internal --add-source=5.6.7.8/32 --permanent firewall-cmd --zone=public --remove-service=ssh --permanent firewall-cmd --reload
This declares an internal zone with two IPs (add as many or as few as you like) and subsequently removes the SSH service from the public zone altogether. As a result, any other IP gets a message such as “Connection refused” when trying to connect via SSH.
The “–permanent” switch saves the changes. Remove it for testing or if you don’t want this change to be permanent.
The last line reloads the current firewall rules (thanks, CertDepot).
Don’t forget to add ‘firewall-cmd –reload’ or to reboot your server, otherwise it will not work!
D’oh, I forgot that little nugget! Thanks CertDepot, I’ll add it to the instructions 😉
You can add an extra security layer by configuring tcp wrappers too 🙂
Sounds great – can you give me an example?
The basics could be read here: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/sect-Security_Guide-TCP_Wrappers_and_xinetd-TCP_Wrappers_Configuration_Files.html
Following your example:
/etc/hosts.allow:
sshd : 1.2.3.4/32, 5.6.7.8/32
/etc/hosts.deny:
sshd: ALL
—————–
You can restrict access to a wide variety of daemons. You can know whether a daemon supports or not tcp wrappers with the following command:
$ ldd /usr/sbin/sshd | grep wrap
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007fe777cbf000)
If libwrap is a dynamic dependency, tcp wrappers are supported.