I'm running a CentOS server (7.0) and I'd like to login via sshd as a user, not root. So I set PermitRootLogin no in the config file and su - after login. I've received lots of hacking activities and I decided to allow only one user to login via sshd. Since the username is not my real name or any common name, I think it would be good enough. Let's say it's 'hkbjhsqj'.

I've tried both ways introduced on nixCraft: AllowUsers in sshd_config or pam_listfile.so in PAM. The only problem to me is that anyone else still has chances to type in passwords and that leaves records in /var/log/secure. I assume these actions consumes my server's resources to run password checking and other stuff.

Let's say I try to login with the username 'admin':

www$ ssh admin@0.0.0.0
admin@0.0.0.0's password:
Permission denied, please try again.
admin@0.0.0.0's password:
Permission denied, please try again.
admin@0.0.0.0's password:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

and in the secure log:

Aug  8 08:28:40 www sshd[30497]: pam_unix(sshd:auth): check pass; user unknown
Aug  8 08:28:40 www sshd[30497]: pam_listfile(sshd:auth): Refused user admin for service sshd
Aug  8 08:28:43 www sshd[30497]: Failed password for invalid user admin from 192.168.0.1 port 52382 ssh2
Aug  8 08:28:47 www sshd[30497]: pam_unix(sshd:auth): check pass; user unknown
Aug  8 08:28:47 www sshd[30497]: pam_listfile(sshd:auth): Refused user admin for service sshd
Aug  8 08:28:50 www sshd[30497]: Failed password for invalid user admin from 192.168.0.1 port 52382 ssh2
Aug  8 08:28:52 www sshd[30497]: pam_unix(sshd:auth): check pass; user unknown
Aug  8 08:28:52 www sshd[30497]: pam_listfile(sshd:auth): Refused user admin for service sshd
Aug  8 08:28:55 www sshd[30497]: Failed password for invalid user admin from 192.168.0.1 port 52382 ssh2
Aug  8 08:28:55 www sshd[30497]: Connection closed by 192.168.0.1 [preauth]
Aug  8 08:28:55 www sshd[30497]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.0.1

While all this will not happen if I add the IP in /etc/hosts.deny:

www$ ssh admin@0.0.0.0
ssh_exchange_identification: Connection closed by remote host

and in the secure log:

Aug  8 08:35:11 www sshd[30629]: refused connect from 192.168.0.1 (192.168.0.1)
Aug  8 08:35:30 www sshd[30638]: refused connect from 192.168.0.1 (192.168.0.1)

So my question would be, is there a way I can refuse all irrelevant users' ssh requests from anywhere without password checking, like I put them in the hosts.deny list? But at the same time I do need allow all ssh requests with the username 'hkbjhsqj' from anywhere and check the password then.

up vote 5 down vote accepted

I don't think it is possible to do what you are asking. If you could, someone could "brute force" to find valid usernames on your server. I am also pretty sure that the username and the password are sent simultaneously by the client, you could verify this by capturing packets using Wireshark on an unencrypted SSH connection.

By "hacking activities" I assume you are talking about brute force attempts at passwords. There are many ways to protect yourself from this, I will explain the most common ways.

Disable root login By denying root login with SSH the attacker has to know or guess a valid username. Most automated brute force attacks only try logging in as root.

Blocking IPs on authentication failure Daemons like fail2ban and sshguard monitor your log files to detect login failures. You can configure these to block the IP address trying to log in after a number of failed login attempts. In your case this is what I would recommend. This reduces log spam and strain on your server, as all packets from this IP would be blocked before they reach the sshd daemon. Your could, for example, set fail2ban to block IPs with 3 login failures in the last 5 minutes for 60 minutes. You will in the worst cases see three failed logins in your log every 60 minutes, assuming the attacker does not give up and move on.

Public key authentication You can disable password authentication entirely and only allow clients with specific keys. This is often considered to be the most secure solution (assuming the client keeps his key safe and encrypted). To disable password authentication, add your public key to ~/.ssh/authorized_keys on the server and set PasswordAuthentication to no in sshd_config. There are numerous tutorials and tools to assist with this.

I hope this helps you!

  • I don't have enough reputation, but I would +1 for fail2ban. It's relatively easy to setup, you can ban IPs after any number of failed login attempts and it writes the addresses to iptables so they stay banned. Of course, you can ban yourself if you mis-type your p/w once too many times. – LHWizard Aug 8 '14 at 14:56
  • thanks for your detailed reply! I've set PermitRootLogin no and I'm using fail2ban too. The third way seems the most desirable while a little problem remains---I can only login with my own computers. I can't use any client with no key file. That seems a tiny flaw and limitation. Certainly in practice I login mostly with my computer. I'm just curious if there's an ultimate solution which meets my question. Thanks!~ – leoce Aug 8 '14 at 15:07
  • @leoce Sorry, I have never heard if any of any authentecation method that meets all your requirements. Its either portability or security. All authentication methods I know of are password, key or host based. Personally I keep my private key encrypted and stored in my Lastpass vault. I can then download it if I need to use another computer. An alternative would be to keep a memory stick containing the key on person, perhaps attached to your keys or something. Some of those are barely any larger than the USB connector! – arnefm Aug 8 '14 at 20:04
  • @arnefm Thanks! Your explanation is convincing and the Lastpass idea is good. I can also compress my key files with a password and put the zip file in Dropbox. And I just verified another way. I write "sshd: ALL" in the hosts.deny and I install Webmin. I also deploy the Google 2-factor authentication module in Webmin. So it can build a block list and it requires the code on my phone. If I'm somewhere with a new computer, I can login webmin and run echo sshd: 0.0.0.0 >> /etc/hosts.allow. I think this also works for me. – leoce Aug 11 '14 at 14:27

If your only concern is the amount of logging, you could reduce this with the LogLevel setting in sshd_config.

If you would rather avoid excessive tampering with your SSH server, you could use something like fail2ban to block IP addresses after a certain amount of failed attempts.

  • thanks for your suggestion, I'm also using fail2ban and I know the 3-time thing is just the default setting of sshd. Fail2ban adds IPs which exceeds the maxretry within findtime into iptables block list. The reason I'm asking this question is that I want to know if there's a way of combination of the mechanics of PAM and hosts.deny. I tried to add 'sshd: hkbjhsqj@*' in my hosts.allow and 'sshd: ALL' in my hosts.deny but failed. – leoce Aug 8 '14 at 14:57

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.