# ssh brute force attacks



## VampirD (Jan 22, 2013)

Hello, I'm trying to figure how I can block ssh brute force attacks to my server (FreeBSD 9.0 amd64), so I try two methods, the first was to adapt my Linux script and block it using cron


```
#!/usr/bin/env bash

# Este script monitorea los intentos fallidos de ingreso al sistema con ssh, al 3ro agrega la ip al archivo /etc/hosts.allow con opcion deny

LOGFILE="/var/log/auth.log"
HOSTSDENY="/etc/hosts.allow"
BADCOUNT="3"

# busco los intentos fallidos en el log
grep sshd $LOGFILE |grep "Invalid user"| awk '{print $NF}'|sort|uniq -c|sort -n|sed "s/[[:space:]]*//" | while read i
do
   # los cuento
   count=`echo $i | cut -d" " -f1`
   # leo la IP
   ip=`echo $i | cut -d" " -f2`
   # verifico que no exista en hosts.allow
   already=`grep $ip $HOSTSDENY | grep ALL`  
   # si la IP no existe la agrego
   if [ -z "$already"  ]
      then
         if [ "$count" -ge "$BADCOUNT" ]
            then
               echo "ALL : "$ip" : deny" >> $HOSTSDENY
               echo "$ip agregada a $HOSTSDENY" | mail -s "sshlock report" root 
         fi
   fi
done
```

but it only works if I run it manually, even running it every minute with cron it does'nt nothing :S

The second I try is sshguard-pf, but again it doesn't work.
I uncomment the line:

```
auth.info;authpriv.info     |exec /usr/local/sbin/sshguard -a 3 -p 9200 -s 12000
```
from /etc/syslog.conf, but still I have logs from brute force attacks


----------



## SirDice (Jan 22, 2013)

VampirD said:
			
		

> The second I try is sshguard-pf, but again it doesn't work.
> I uncomment the line:
> 
> ```
> ...


Did you restart syslog?

`# service syslogd restart`

And did you add the table in your /etc/pf.conf?


```
table <sshguard> persist

block in log on $ext_if proto tcp from <sshguard> to any port ssh label "ssh bruteforce"
```


----------



## fonz (Jan 22, 2013)

VampirD said:
			
		

> Hello, I'm trying to figure how I can block ssh brute force attacks to my server (FreeBSD 9.0 amd64)


If a machine is connected to the Internet using a public IP address (i.e. not in 192.168.0.0/16 or another private range) and running sshd(8) on the standard port 22, it *will* be ssh-brute-forced. Period. The easiest way to stop this is by running sshd(8) on a high-numbered non-standard port (this can be set in /etc/ssh/sshd_config, don't forget to restart sshd(8)) and if at all possible placing the machine behind a NAT and/or firewall that blocks all incoming traffic to the standard SSH port (or in fact any port not used on that machine).


----------



## kpa (Jan 22, 2013)

Disable password authentication and keyboard interactive authentication, the brute force attacks will be in vain. It of course requires you to set up public keys for authentication.


----------



## fonz (Jan 22, 2013)

kpa said:
			
		

> Disable password authentication and keyboard interactive authentication, the brute force attacks will be in vain.


Indeed. However, it does not stop the attacks from happening in the first place.


----------



## wblock@ (Jan 22, 2013)

Running SSH on a different port does not really stop the attacks, either.  And Michael Lucas points out that it does not really increase security, it mostly just quiets the logs.  security/sshguard is fairly forgiving, and the defaults can be tightened up a bit.  If possible, use the firewall to limit SSH connections to known external networks, not just anyone.


----------



## fonz (Jan 22, 2013)

wblock@ said:
			
		

> Running SSH on a different port does not really stop the attacks, either.


Correct. But my experience is that _in combination with_ a NAT/firewall it does help.


----------



## chatwizrd (Jan 22, 2013)

wblock@ said:
			
		

> Running SSH on a different port does not really stop the attacks, either.  And Michael Lucas points out that it does not really increase security, it mostly just quiets the logs.



Yeah it quiets the logs because you arent getting scanned as much. Its very helpful.


----------



## fonz (Jan 22, 2013)

chatwizrd said:
			
		

> Yeah it quiets the logs because you arent[sic] getting scanned as much. Its[sic] very helpful.


Actually, Warren does have a point. Merely running sshd(8) on a non-standard port doesn't get you scanned a whole lot less, it just makes such scans fail (which in turn increases security). It's combining that with a NAT/firewall that actually decreases the amount of scanning, unless someone is determined to attack you specifically.


----------



## wblock@ (Jan 22, 2013)

fonz said:
			
		

> Actually, Warren does have a point.



Try not to sound surprised. 



> Merely running sshd(8) on a non-standard port doesn't get you scanned a whole lot less, it just makes such scans fail (which in turn increases security). It's combining that with a NAT/firewall that actually decreases the amount of scanning, unless someone is determined to attack you specifically.



Not quite what I meant.  Even using a nonstandard port, there is still an SSH port open.  Attackers can still connect to that port, and a thorough attacker will.  (Don't be the guy who says "Oh, but nobody will do that!"  Those are the guys who admit they've been hacked.)  

Changing ports obscures it a bit.  Does it make you more secure?  It would delay the first scan, but after that...  Not like limiting where SSH connections originate in the firewall, for example.


----------



## fonz (Jan 22, 2013)

wblock@ said:
			
		

> Even using a nonstandard port, there is still an SSH port open.  Attackers can still connect to that port, and a thorough attacker will.


Correct. But in my experience most attackers aren't that thorough. And the ones that are, are usually after you specifically, in which case you have bigger problems I'd imagine.


----------



## VampirD (Jan 22, 2013)

SirDice said:
			
		

> Did you restart syslog?
> 
> `# service syslogd restart`
> 
> ...



I don't add this, adding it now


----------



## wblock@ (Jan 22, 2013)

fonz said:
			
		

> Correct. But in my experience most attackers aren't that thorough. And the ones that are, are usually after you specifically, in which case you have bigger problems I'd imagine.



The safest way to play it is to assume that they are *all* after you specifically.


----------



## SirDice (Jan 23, 2013)

fonz said:
			
		

> Correct. But in my experience most attackers aren't that thorough.


Most attacks you'll see are actually automated bots scanning for easy targets.



> And the ones that are, are usually after you specifically, in which case you have bigger problems I'd imagine.


They can try all they want on my systems. I don't even bother running it on a different port. Yes, it's noisy in the logs but who cares about that? I'd be a whole lot more worried if my logs remained empty....


----------



## VampirD (Jan 23, 2013)

T_T I still have entries from IP 200.107.28.190


----------



## SirDice (Jan 23, 2013)

You could add your own table and add notorious "bangers" to it and block them permanently. Although my logs are getting large I do review them and add those to my own "blacklist".


----------



## VampirD (Jan 23, 2013)

Now I have added the IP with the command "pfctl -t sshguard -T add 200.107.28.190", but I don't know if my pf.conf is correct


```
### Scrub
# From the PF user's guide (http://www.openbsd.org/faq/pf/index.html):
# "Scrubbing" is the normalization of packets so there are no ambiguities in
# interpretation by the ultimate destination of the packet. The scrub directive
# also reassembles fragmented packets, protecting some operating systems from
# some forms of attack, and # drops TCP packets that have invalid flag
# combinations.
scrub in all

bittorrent_port = "6881:6999"
tcp_pass = "{ 22 53 80 }"

#pass in proto tcp to port $tcp_pass

pass in quick on vr0 proto tcp to port 22
pass in quick on vr0 proto tcp to port 80
pass in quick on vr0 proto udp to port 53

pass quick on lo0 all

pass out quick on vr0 proto tcp to port 20 # Usado por FTP en modo PASV  
pass out quick on vr0 proto tcp to port 21
pass out quick on vr0 proto tcp to port 22 
pass out quick on vr0 proto tcp to port 25
pass out quick on vr0 proto udp to port 53
pass out quick on vr0 proto tcp to port 80
pass out quick on vr0 proto tcp to port 443
pass out quick inet proto icmp all icmp-type echoreq 

pass out quick on vr0 proto { udp, tcp } to port $bittorrent_port
pass out quick on vr0 proto tcp to port 587
pass out quick on vr0 proto tcp to port 80
pass out quick on vr0 proto { udp, tcp } to port 6881

# SSHGuard Config
table <sshguard> persist
block in log on vr0 proto tcp from <sshguard> to any port ssh label "ssh bruteforce"

block in all
block out all
```


----------



## fonz (Jan 23, 2013)

SirDice said:
			
		

> Most attacks you'll see are actually automated bots scanning for easy targets.


Exactly.


----------



## SirDice (Jan 23, 2013)

VampirD said:
			
		

> Now I have added the IP with the command "pfctl -t sshguard -T add 200.107.28.190", but I don't know if my pf.conf is correct
> 
> 
> ```
> ...


Try not to use the quick keyword. As it stands now your ruleset will _never_ block anything from sshguard. Your pass rule 'short-circuits' because of the quick and it will not process any more rules if it gets hit.

This is a much better way:

```
# short circuit with quick, we don't want this traffic so there's no point in processing the rest of the rules
block in log quick on vr0 proto tcp from <sshguard> to any port ssh label "ssh bruteforce"

# Allow ssh access
pass in on vr0 proto tcp to port 22
```
Order is really important.


----------



## kpa (Jan 23, 2013)

It usually helps to order the rules in this way:


 Default deny rule(s).

 Block rules for unwanted traffic with logging on, use quick keyword to stop evaluation. The security/sshguard-pf rule goes here.

 Pass rules for outgoing traffic.

 Pass rules for incoming traffic.


----------



## VampirD (Jan 23, 2013)

-_- fixed the rules order, but now I have to wait to return to my home to fix the pf, and also I have learned why I must use */sbin/pfctl -f /etc/pf.conf && sleep 120 && /sbin/pfctl -d* instead of *service pf restart*.


----------



## kpa (Jan 23, 2013)

When you do service pf restart the state table gets reset and you'll lose your current ssh(1) connection. You can do this instead to reload the rules without resetting the state table:

`# service pf reload`


----------



## SirDice (Jan 23, 2013)

I think VampirD ran into the age old problem of locking oneself out after changing firewall rules.

Don't worry, after years of experience, it still happens to me too if I'm not paying enough attention


----------



## VampirD (Jan 23, 2013)

Yes, completely locked, fortunately is a personal server and not an essential service


----------



## xtaz (Jan 23, 2013)

If you have an iPhone or Android phone I would also recommend running security/pam_google_authenticator from the ports along with the Google Authenticator app on the phone. That way if you ssh with a certificate then it will log you straight in, if there is no certificate it will ask you for the password and a 6 digit code that appears in the phone app and changes every 30 seconds. Instantly massively increases your security. For people that are not aware of this, it's not actually anything to do with google. It's just that they use an open source algorithm for time-based one-time-passwords and thus their app can be used for other things.

It needs a bit of configuration to get it to work. These are my changes to /etc/pam.d/sshd:


```
# diff /usr/src/etc/pam.d/sshd /etc/pam.d/sshd
12c12,13
< auth          required        pam_unix.so             no_warn try_first_pass
---
> auth          required        /usr/local/lib/pam_google_authenticator.so forward_pass
> auth          required        pam_unix.so             no_warn use_first_pass
root@tao[~]#
```

And then you run google-authenticator and answer the questions. It generates a QR code which you scan into the phone app. The next time you ssh the box it will ask for a validation code, you just type in the password and the code on the same line. The QR code is generated using a Google Charts API URL, however you can also install graphics/libqrcode and if you use a UTF8 locale and terminal it will generate them in your terminal instead.

Personally I use this, along with running sshd on a different port to stop scans getting logged too often. Works a treat.

One thing to note is that the config file for this is kept in the users home directory. That's fine if it's just your own personal box. If it was used by others it would be better to move the config files into a different directory only accessible by the root user. The readme file has instructions for doing this. I didn't include them as it just makes it more complicated for the purposes of this post.


----------



## throAU (Jan 23, 2013)

Is there any reason you need to allow SSH from any IP address?

First thing I would do is set up hosts.deny and/or appropriate firewall rules to block port 22 for all remote hosts except for the machines you will be logging in from to administer the machine from.

Also, require SSH keys, and generate the key pair on a different box, only your public key should ever be stored on the machine.


Security is layered.  If you don't need to listen for ANY ip address, don't.


Personally, I do not listen on port 22 for connections from the internet (or expose SSH via any other port).  Management network connections only, if I'm not on the LAN that means VPN session first.

Unless you're running a public access shell server, listening for SSH from anywhere is just an un-necessary risk.


----------



## VampirD (Jan 23, 2013)

I'm home now, so I "fix" my /etc/pf.conf, it now looks like:


```
# macros

ext_if = "vr0"
tcp_pass = "{ 22 53 80 }"
tcp_out = "{ 20 21 22 25 53 80 443 587 }"
bittorrent_port = "6881:6999"
icmp_types = "echoreq"

# options

set block-policy drop
set skip on lo0
scrub in all

# tables

table <sshguard> persist

# rules

block in all
block out all

antispoof log quick for $ext_if
block in log quick on $ext_if proto tcp from <sshguard> to any port ssh label "ssh bruteforce"

pass out on $ext_if proto tcp to port $tcp_out
pass out on $ext_if proto { udp, tcp } to port $bittorrent_port
pass out inet proto icmp all icmp-type $icmp_types

pass in on $ext_if proto tcp to port $tcp_pass
```

following Kpa post I ordered the rules this way, but the block in/out all lock me completely


----------



## kpa (Jan 24, 2013)

You should allow outgoing UDP DNS traffic as well.


```
pass out on $ext_if proto udp from $ext_if to any port domain
```


----------



## johnblue (Jan 28, 2013)

VampirD said:
			
		

> Hello, I'm trying to figure how I can block ssh brute force attacks to my server (FreeBSD 9.0 amd64), so I try two methods, the first was to adapt my Linux script and block it using cron


What you need is already built into PF: max-src-conn-rate  It is extremely easy to implement and it works as advertised:

http://johan.fredin.info/openbsd/block_ssh_bruteforce.html


----------



## VampirD (Jan 29, 2013)

trying it in the test VM


----------



## Lorem-Ipsum (Jan 29, 2013)

I tend to use fail2ban to block IP addresses after 5 or so incorrect attempts. You could also increase the time between password attempts, won't stop them but will show them down a lot.


----------

