Server ssh security

Posted May 27, 20205 min read

There is no preface. . . Start directly. . .
There are some ssh related comparisons in my github repo itnotes linux/network/ssh, welcome to visit and correct me.

Login record view

Current Linux distributions mostly store history records in binary files, so text files with history records may not be found in /var/log.

  • Login history

    • The user's recent login status:lastlog
    • Record of successful login:last
    • Record of failed login:lastb
      lastb needs to be focused on, the output content is sorted by time, and the last output content is the oldest record. If there are too many entries, you can use tac to arrange it in reverse order:lastb | tac.
      From this file, you can see which usernames the script kid likes to use to try to log in to your server. Use lastb | wc -l to count failed records(note:too many records will clear the old records according to the settings). My cloud server has more than 200,000 lastb records in a week ...
  • Currently logged in user

    • Currently logged in user list(and what operation the logged in user is performing):w
    • Currently logged in user information:who

Defense tools

  • fail2ban
    Please refer to the documentation for specific use, and use it with firewalld or iptables. At the end of the article, I attached a fail2ban script that I wrote while using it to easily configure fail2ban(of course, fail2ban configuration is also quite simple).
  • sshguard is a bit old and unused.

Root user login restrictions

The root user is prohibited from logging in or only allowed to log in using the key. It is recommended to turn off root login if it is not necessary.(Looking at the thousands of root login records in my lastb, don't panic, I turned off root login).

Modify the value of PermitRootLogin in the server's/etc/ssh/sshd_config file, the value can be:

  • no or yes prohibit or allow root user to log in
  • prohibit-password or without-password does not allow password login(other authentication methods can be used, such as ssh key)
  • forced-commands-only can only use the key to log in and only allow authorized commands

Disallow certain users from using the shell

Prohibiting him from using the shell of course prohibits his login.
Some users may only be used to automatically start a daemon without logging in, and can modify their shell to nologin.
The scanning tool generally scans the default users of well-known software, such as the postgres user of postgresql and the zabbix user of zabbix. Of course, by default, no password is set for the user, and the user cannot log in via ssh. After setting up postgresql, you can easily set After the password postgresql, it was finally broiled and the mining program was installed.

Modification method:

  • chsh -s/sbin/nologin username username is the name of the user
  • Edit the /etc/passwd file, find the line where the user is, and change the word/bin/bash to /sbin/nologin.
  • Change the default port 22

There is no technical content but a very effective method. It can keep up with the modification of the default weak password. The two simple and effective defense methods can reduce the chance of being scanned by the tool in batches. Do n t look at most hackers. After all, weak passwords and default There are so many machines on the port. Isn't it good to scan simple machines? You may skip your server.

Modify the Port value in the server's/etc/ssh/sshd_config file to other available ports.

If you want to listen to multiple ports, add multiple lines of Port, if you want to specify the listening address, add the ListenAddress line:

Port 1234
Port 4567

Sign in with a key instead of a password

Safe but inconvenient.

ssh-keygen #or ssh-keygen -t rsa 4096 client generates key
ssh-copy-id -p 23579 user @ host #upload the public key to the server

Note that the dsa key has been proven to be insecure, and if the number of rsa keys is too low, it is also insecure. It is recommended to have at least 4096 bits.

IP whitelist and blacklist

  • Add ban list to blacklist /etc/hosts.deny.
  • Add allow list to whitelist /etc/hosts.allow.

User whitelist and blacklist

  • sshd control, add configuration line in /etc/sshd_config

    • whitelist

      • User:AllowUsers username1 username2
      • User group:AllowGroups groupname1 groupname2
    • Blacklist

      • User:DenyUsers username1 username2
      • User group:DenyGroups groupname1 groupname2
  • PAM control

    1. Add in /etc/pam.d/sshd file:

       auth required item = user sense = deny file =/etc/ssh/deny onerr = succeed

      The value of sense:the blacklist value is deny and the whitelist value is allow.

    2. Add blacklist/whitelist users in /etc/ssh/denyhosts, one username per line.

After installing fail2ban, execute the script and follow the prompts to configure the rules of sshd. The configuration rule:an ip fails to log in 5 times in a row and pulls it into the blacklist for 8640000 seconds(100 days).
After execution, the following available commands will be generated:

  • ban_ip:black out specified ip ban_ip

  • unban_ip:Unblock a certain ip unban_ip, unban_ip all clears the blacklist.

  • blacklist:view the blacklist

    if [[$USER! = root]]; then

    echo "need root or sudo."



    jail_file =/etc/fail2ban/jail.d/jail.local

    jails =(sshd mongodb-auth mysqld-auth vsftpd)

    #log path

    bandtime = 8640000 #default seconds s m h d w
    findtime = 6000
    maxretry = 5


    #install fail2ban
    which pacman 2>/dev/null || pacman -Syy fail2ban --no-confirm

    if [[! $(which fail2ban-server)]]; then

    echo "please install fail2ban"


    function services_logs() {

    case $1 in
      echo "/var/log/mongodb/mongod.log"
      echo ''


    function add_jails() {

    echo "$(tput bold) Select filter service:$(tput sgr0)"
    local i = 0
    for jail in ${jails [*]}; do
      echo "$i) $jail $([[$i -eq 0]]&& echo [default])"
      i = $((i + 1))
    echo "-------------"
    read select_jails
    [["$select_jails"]]|| select_jails = '0'
    for select_jail in $select_jails; do
      local this_jail = ${jails [$select_jail]}
      [[$this_jail]]|| continue
      log = $(services_logs $this_jail)
      [[$log]]&& logpath = "logpath = $log"
      echo "[$this_jail]

    enabled = true
    ">> $jail_file

      unset log
      unset logpath
    systemctl restart fail2ban
    systemctl enable fail2ban


    function gen_scripts() {

    ## ban_ip
    echo '#!/bin/sh

    fail2ban-client set sshd banip "$*"

    ## unban_ip
    echo '#!/bin/sh

    case "$*" in

      fail2ban-client unban --all
      fail2ban-client set sshd unbanip "$*"


    #ignore ip
    echo '#!/bin/sh

    fail2ban-client set sshd addignoreip "$*"

    ## delete ignore ip
    echo '#!/bin/sh

    fail2ban-client set sshd delignoreip "$*"

    ## sshd blacklist
    echo '#!/bin/sh

    fail2ban-client status sshd
    echo "===== for sshd jail ====="
    echo "see all banned IP:blacklist"
    echo "ban IP example:ban_ip"
    echo "unban IP example:unban_ip"
    echo "unban all IP example:unban_ip all"
    echo "ignore IP example:ignore_ip"
    echo "delete ignore IP example:delignore_ip"


    chmod + x/usr/local/bin/{ban_ip, unban_ip, delignore_ip, ignore_ip, blacklist}


    function gen_jail_file() {

    [[-f $jail_file]]&& mv $jail_file $jail_file.bak
    echo "[DEFAULT]

    bantime = $bandtime
    findtime = $findtime
    maxretry = $maxretry
    "> $jail_file


    echo "----- fail2ban jail list -----"
    fail2ban-client status