|
A Cure for the Common SSH Login Attack Updated: 2006-03-20 Introduction I did find a lot of information, but only a few script-based solutions. Most of the cures included: 1) Moving the ssh port to another number -- not much better; 2) Allowing only specific IP addresses -- not workable for a road-warrior; 3) Systematically blocking each offending IP address (imagine the eventual buildup). None of these solutions seemed... well... elegant. What I wanted was a way to stop the attacks altogether, yet allow ssh access from anywhere. In addition, I wanted to avoid using an approach that was so complicated it could lead to more pain than I was experiencing from the original problem.
The solution should support simple port knocking, for example, using the following shell prompt activity: $ ssh username@hostname # No response (Ctrl-C to exit) ^C $ nmap -P0 --host_timeout 201 -p <port1> hostname &> /dev/null $ nmap -P0 --host_timeout 201 -p <port2> hostname &> /dev/null $ history -r # Clear knocking history $ ssh username@hostname # Now logins are allowed username@hostname's password: NOTE: The ports used to open port 22 (<port1> and <port2>) should also appear closed, say, to a port scanner. Proposed Solution The following represents the contents of an iptables.rules file. The highlighted text outlines the changes needed to support our style of port knocking. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :TRAFFIC - [0:0] :SSH-INPUT - [0:0] -A INPUT -j TRAFFIC -A FORWARD -j TRAFFIC # Accepted -A TRAFFIC -i lo -j ACCEPT -A TRAFFIC -s 192.168.0.0/24 -j ACCEPT -A TRAFFIC -p icmp --icmp-type any -j ACCEPT -A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT # Port Knocking -- use either port 1234 or port 5678 out of sequence to close port 22 -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH1 -j ACCEPT -A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 5678 -m recent --rcheck --name SSH0 -j SSH-INPUT -A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP -A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 1234 -m recent --name SSH0 --set -j DROP -A SSH-INPUT -m recent --name SSH1 --set -j DROP # Others -A TRAFFIC -j DROP COMMIT NOTE: The <port1> and <port2> ports used in the above example are ports 1234 and 5678, respectively. For security purposes, please use a unique set of ports. Knock Yourself... In
#!/bin/bash # $1 host name or IP address nmap -P0 --host_timeout 201 -p $2 $1 &> /dev/null nmap -P0 --host_timeout 201 -p $3 $1 &> /dev/null Here's how the script would work: $ ssh username@hostname # No response (Ctrl-C to exit) ^C $ sh knock.sh 1234 5678 hostname; history -r $ ssh username@hostname # Now logins are allowed username@hostname's password: Conclusion Also, if you feel the need for more security, you can close port 22 -- sort of like closing the door behind you -- by knocking out of sequence (say, from another shell) and you won't lose your established ssh connection. What I find most elegant about this approach is that you don't have to fill up your iptables with dozens of DROP entries, in order to block the world of would-be attackers. In addition, it wouldn't be too difficult to add a third knock, just to keep attackers guessing. Sample Log
Jan 7 09:58:47 hostname sshd[24729]: Illegal user test from [IP_ADDRESS_A] Jan 7 09:58:50 hostname sshd[24729]: Failed password for illegal user test from [IP_ADDRESS_A] port 51250 ssh2 Jan 7 09:58:52 hostname sshd[24731]: Illegal user guest from [IP_ADDRESS_A] Jan 7 09:58:54 hostname sshd[24731]: Failed password for illegal user guest from [IP_ADDRESS_A] port 51396 ssh2 Jan 7 09:58:56 hostname sshd[24733]: Illegal user admin from [IP_ADDRESS_A] Jan 7 09:58:58 hostname sshd[24733]: Failed password for illegal user admin from [IP_ADDRESS_A] port 51546 ssh2 Jan 7 09:59:00 hostname sshd[24735]: Illegal user admin from [IP_ADDRESS_A] Jan 7 09:59:03 hostname sshd[24735]: Failed password for illegal user admin from [IP_ADDRESS_A] port 51688 ssh2 Jan 7 09:59:04 hostname sshd[24737]: Illegal user user from [IP_ADDRESS_A] Jan 7 09:59:07 hostname sshd[24737]: Failed password for illegal user user from [IP_ADDRESS_A] port 51828 ssh2 Jan 7 09:59:11 hostname sshd[24739]: Failed password for root from [IP_ADDRESS_A] port 51963 ssh2 Jan 7 09:59:15 hostname sshd[24741]: Failed password for root from [IP_ADDRESS_A] port 52114 ssh2 Jan 7 09:59:20 hostname sshd[24743]: Failed password for root from [IP_ADDRESS_A] port 52288 ssh2 Jan 7 09:59:22 hostname sshd[24745]: Illegal user test from [IP_ADDRESS_A] Jan 7 09:59:24 hostname sshd[24745]: Failed password for illegal user test from [IP_ADDRESS_A] port 52419 ssh2 Jan 7 16:35:22 hostname sshd[25103]: Failed password for nobody from [IP_ADDRESS_B] port 53721 ssh2 Jan 7 16:35:25 hostname sshd[25105]: Illegal user patrick from [IP_ADDRESS_B] Jan 7 16:35:28 hostname sshd[25105]: Failed password for illegal user patrick from [IP_ADDRESS_B] port 53832 ssh2 Jan 7 16:35:31 hostname sshd[25107]: Illegal user patrick from [IP_ADDRESS_B] Jan 7 16:35:33 hostname sshd[25107]: Failed password for illegal user patrick from [IP_ADDRESS_B] port 53907 ssh2 Jan 7 16:35:39 hostname sshd[25109]: Failed password for root from [IP_ADDRESS_B] port 54003 ssh2 Jan 7 16:35:45 hostname sshd[25111]: Failed password for root from [IP_ADDRESS_B] port 54093 ssh2 Jan 7 16:35:50 hostname sshd[25113]: Failed password for root from [IP_ADDRESS_B] port 54181 ssh2 Jan 7 16:35:58 hostname sshd[25115]: Failed password for root from [IP_ADDRESS_B] port 54312 ssh2 Jan 7 16:36:04 hostname sshd[25117]: Failed password for root from [IP_ADDRESS_B] port 54395 ssh2 Jan 7 16:36:07 hostname sshd[25119]: Illegal user rolo from [IP_ADDRESS_B] Jan 7 16:36:10 hostname sshd[25119]: Failed password for illegal user rolo from [IP_ADDRESS_B] port 54488 ssh2 Jan 7 16:36:14 hostname sshd[25121]: Illegal user iceuser from [IP_ADDRESS_B] Jan 7 16:36:16 hostname sshd[25121]: Failed password for illegal user iceuser from [IP_ADDRESS_B] port 54577 ssh2 Jan 7 16:36:21 hostname sshd[25123]: Illegal user horde from [IP_ADDRESS_B] Jan 7 16:36:23 hostname sshd[25123]: Failed password for illegal user horde from [IP_ADDRESS_B] port 54681 ssh2 Jan 7 16:36:26 hostname sshd[25125]: Illegal user cyrus from [IP_ADDRESS_B] Jan 7 16:36:28 hostname sshd[25125]: Failed password for illegal user cyrus from [IP_ADDRESS_B] port 54786 ssh2 Jan 7 16:36:32 hostname sshd[25127]: Illegal user www from [IP_ADDRESS_B] Jan 7 16:36:34 hostname sshd[25127]: Failed password for illegal user www from [IP_ADDRESS_B] port 54878 ssh2 Jan 7 16:36:37 hostname sshd[25129]: Illegal user wwwrun from [IP_ADDRESS_B] Jan 7 16:36:40 hostname sshd[25129]: Failed password for illegal user wwwrun from [IP_ADDRESS_B] port 54966 ssh2 Jan 7 16:36:43 hostname sshd[25131]: Illegal user matt from [IP_ADDRESS_B] Jan 7 16:36:46 hostname sshd[25131]: Failed password for illegal user matt from [IP_ADDRESS_B] port 55050 ssh2 Jan 7 16:36:50 hostname sshd[25133]: Illegal user test from [IP_ADDRESS_B] Jan 7 16:36:53 hostname sshd[25133]: Failed password for illegal user test from [IP_ADDRESS_B] port 55152 ssh2 Jan 7 16:36:57 hostname sshd[25135]: Illegal user test from [IP_ADDRESS_B] Jan 7 16:36:59 hostname sshd[25135]: Failed password for illegal user test from [IP_ADDRESS_B] port 55263 ssh2 Jan 7 16:37:02 hostname sshd[25137]: Illegal user test from [IP_ADDRESS_B] Jan 7 16:37:04 hostname sshd[25137]: Failed password for illegal user test from [IP_ADDRESS_B] port 55366 ssh2 Jan 7 16:37:08 hostname sshd[25139]: Illegal user test from [IP_ADDRESS_B] Jan 7 16:37:10 hostname sshd[25139]: Failed password for illegal user test from [IP_ADDRESS_B] port 55457 ssh2 Jan 7 16:37:13 hostname sshd[25141]: Illegal user www-data from [IP_ADDRESS_B] Jan 7 16:37:16 hostname sshd[25141]: Failed password for illegal user www-data from [IP_ADDRESS_B] port 55548 ssh2 Jan 7 16:37:21 hostname sshd[25143]: Failed password for mysql from [IP_ADDRESS_B] port 55637 ssh2 Jan 7 16:37:26 hostname sshd[25145]: Failed password for operator from [IP_ADDRESS_B] port 55724 ssh2 Jan 7 16:37:33 hostname sshd[25147]: Failed password for adm from [IP_ADDRESS_B] port 55799 ssh2 Jan 7 16:37:42 hostname sshd[25149]: Failed password for apache from [IP_ADDRESS_B] port 55912 ssh2 Jan 7 16:37:52 hostname sshd[25151]: Illegal user irc from [IP_ADDRESS_B] Jan 7 16:37:54 hostname sshd[25151]: Failed password for illegal user irc from [IP_ADDRESS_B] port 56036 ssh2 Disclaimer |