Recently, I discovered that SSH of my VPS server is constantly battered as follows.

Apr 06 11:15:14 abastro-personal-arm sshd[102702]: Unable to negotiate with 218.92.0.201 port 53768: no matching key exchange method found. Their offer: diffie>
Apr 06 11:30:29 abastro-personal-arm sshd[102786]: Unable to negotiate with 218.92.0.207 port 18464: no matching key exchange method found. Their offer: diffie>
Apr 06 11:45:36 abastro-personal-arm sshd[102881]: Unable to negotiate with 218.92.0.209 port 59634: no matching key exchange method found. Their offer: diffie>
Apr 06 12:01:02 abastro-personal-arm sshd[103019]: Unable to negotiate with 218.92.0.203 port 16976: no matching key exchange method found. Their offer: diffie>
Apr 06 12:05:49 abastro-personal-arm sshd[103066]: Unable to negotiate with 218.92.0.212 port 49130: no matching key exchange method found. Their offer: diffie>
Apr 06 12:07:09 abastro-personal-arm sshd[103077]: Connection closed by 162.142.125.122 port 56110 [preauth]
Apr 06 12:12:18 abastro-personal-arm sshd[103154]: Connection closed by 45.79.181.223 port 22064 [preauth]
Apr 06 12:12:19 abastro-personal-arm sshd[103156]: Connection closed by 45.79.181.223 port 22078 [preauth]
Apr 06 12:12:20 abastro-personal-arm sshd[103158]: Connection closed by 45.79.181.223 port 22112 [preauth]
Apr 06 12:21:26 abastro-personal-arm sshd[103253]: Connection closed by 118.25.174.89 port 36334 [preauth]
Apr 06 12:23:39 abastro-personal-arm sshd[103282]: Unable to negotiate with 218.92.0.252 port 59622: no matching key exchange method found. Their offer: diffie>
Apr 06 12:26:38 abastro-personal-arm sshd[103312]: Connection closed by 92.118.39.73 port 44400
Apr 06 12:32:22 abastro-personal-arm sshd[103373]: Unable to negotiate with 218.92.0.203 port 57092: no matching key exchange method found. Their offer: diffie>
Apr 06 12:49:48 abastro-personal-arm sshd[103556]: error: maximum authentication attempts exceeded for root from 98.22.89.155 port 53675 ssh2 [preauth]
Apr 06 12:49:48 abastro-personal-arm sshd[103556]: Disconnecting authenticating user root 98.22.89.155 port 53675: Too many authentication failures [preauth]
Apr 06 12:49:51 abastro-personal-arm sshd[103558]: error: maximum authentication attempts exceeded for root from 98.22.89.155 port 53775 ssh2 [preauth]
Apr 06 12:49:51 abastro-personal-arm sshd[103558]: Disconnecting authenticating user root 98.22.89.155 port 53775: Too many authentication failures [preauth]
Apr 06 12:49:53 abastro-personal-arm sshd[103561]: error: maximum authentication attempts exceeded for root from 98.22.89.155 port 53829 ssh2 [preauth]
Apr 06 12:49:53 abastro-personal-arm sshd[103561]: Disconnecting authenticating user root 98.22.89.155 port 53829: Too many authentication failures [preauth]
Apr 06 12:49:54 abastro-personal-arm sshd[103563]: Connection closed by 98.22.89.155 port 53862 [preauth]
Apr 06 12:50:41 abastro-personal-arm sshd[103576]: Invalid user  from 75.12.134.50 port 36312
Apr 06 12:54:26 abastro-personal-arm sshd[103621]: Connection closed by 165.140.237.71 port 54236
Apr 06 13:01:26 abastro-personal-arm sshd[103702]: Connection closed by 193.32.162.132 port 33380
Apr 06 13:03:40 abastro-personal-arm sshd[103724]: Unable to negotiate with 218.92.0.204 port 60446: no matching key exchange method found. Their offer: diffie>
Apr 06 13:11:49 abastro-personal-arm sshd[103815]: Received disconnect from 165.140.237.71 port 50952:11:  [preauth]
Apr 06 13:11:49 abastro-personal-arm sshd[103815]: Disconnected from authenticating user root 165.140.237.71 port 50952 [preauth]
Apr 06 13:19:08 abastro-personal-arm sshd[103897]: Unable to negotiate with 218.92.0.208 port 59274: no matching key exchange method found. Their offer: diffie>
Apr 06 13:33:36 abastro-personal-arm sshd[104066]: Received disconnect from 165.140.237.71 port 50738:11:  [preauth]
Apr 06 13:33:36 abastro-personal-arm sshd[104066]: Disconnected from authenticating user ubuntu 165.140.237.71 port 50738 [preauth]
Apr 06 13:34:50 abastro-personal-arm sshd[104079]: Unable to negotiate with 218.92.0.204 port 44816: no matching key exchange method found. Their offer: diffie>
Apr 06 13:50:32 abastro-personal-arm sshd[104249]: Unable to negotiate with 218.92.0.206 port 27286: no matching key exchange method found. Their offer: diffie>
Apr 06 13:51:58 abastro-personal-arm sshd[104261]: Received disconnect from 165.140.237.71 port 50528:11:  [preauth]
Apr 06 13:51:58 abastro-personal-arm sshd[104261]: Disconnected from authenticating user root 165.140.237.71 port 50528 [preauth]
Apr 06 14:01:25 abastro-personal-arm sshd[104351]: Invalid user  from 65.49.1.29 port 18519
Apr 06 14:01:28 abastro-personal-arm sshd[104351]: Connection closed by invalid user  65.49.1.29 port 18519 [preauth]

As you can see, it is happening quite frequently, and I am worried one might break in at some point. Since SSH access guards users with root-access, it can be quite serious once penetrated. How do I harden against these kind of attacks? Because this is VPS, disabling SSH is a no-go (SSH is my only entry of access). Are there ways to stop some of these attackers?

As always, thanks in advance!

  • bizdelnick@lemmy.ml
    link
    fedilink
    English
    arrow-up
    13
    ·
    6 days ago

    The best way is to disable password login and use SSH keys only. Any further steps are not required, but you may additionally install fail2ban or sshguard.

  • Gerowen@lemmy.world
    link
    fedilink
    English
    arrow-up
    11
    ·
    edit-2
    6 days ago

    I generally do a few things to protect SSH:

    1. Disable password login and use keys only
    2. Install and configure Fail2Ban
    3. Disable root login via ssh altogether. Just change “permit root login” from “no password” to just “no”. You can still become root via sudo or su after you’re connected, but that would trigger an additional password request. I always connect as a normal user and then use sudo if/when I need it. I don’t include NOPASSWD in my sudoers to make certain sudo prompts for a password. Doesn’t do any good to force normal user login if sudo doesn’t require a password.
    4. If connecting via the same network or IPs, restrict the SSH open port to only the IPs you trust.
    5. I don’t have SSH internet visible. I have my own Wireguard server running on a separate raspberry pi and use that to access SSH when I’m away, but SSH itself is not open to the internet or forwarded in the router.
  • tomsh@lemmy.world
    link
    fedilink
    English
    arrow-up
    9
    arrow-down
    1
    ·
    6 days ago

    In addition to what others say, I also have ntfy notifications on successful login.

  • Treczoks@lemmy.world
    link
    fedilink
    English
    arrow-up
    2
    ·
    5 days ago

    Move away from port 22, and 90% vanishes. Move it up to a port in the five digit range, and you will rarely see them.

  • irmadlad@lemmy.world
    link
    fedilink
    English
    arrow-up
    11
    ·
    edit-2
    7 days ago

    OP, here is what I do. It might seem overboard, and my way doesn’t make it the best, or the most right, but it seems to work for me:

    • Fail2ban
    • UFW
    • Reverse Proxy
    • IPtraf (monitor)
    • Lynis (Audit)
    • OpenVas (Audit)
    • Nessus (Audit)
    • Non standard SSH port
    • CrowdSec + Appsec
    • No root logins
    • SSH keys
    • Tailscale
    • RKHunter

    The auditing packages, like Lynis, will scour your server, and make suggestions as to how to further harden your server. Crowdsec is very handy in that it covers a lot of ‘stuff’. It’s not the only WAF around. There is Wazuh, Bunkerweb, etc. Lots of other great comments here with great suggestions. I tend to go overboard on security because I do not like mopping up the mess after a breach.

    ETA: just looked up one of your attackers:

    218.92.0.201 was found in our database! This IP was reported 64,044 times. Confidence of Abuse is 100%: ISP CHINANET jiangsu province network Usage Type Fixed Line ISP ASN AS4134 Domain Name chinatelecom.cn Country China City Shanghai, Shanghai

    busy little cunts.

    • sugar_in_your_tea@sh.itjust.works
      link
      fedilink
      English
      arrow-up
      1
      ·
      6 days ago

      It’s absolutely overboard, and you can get 99% of the way there with this:

      1. WireGuard config (Tailscale in your case)
      2. Bind SSH to WireGuard IP only (so no public SSH port)
      3. SSH keys only, and disable root login over SSH

      That will require breaking WireGuard and openSSH’s key-based authentication, which just isn’t happening. The rest looks like mostly auditing. Even a firewall isn’t necessary if no ports are accessible anyway (i.e. everything only accessible over Tailscale), and you can just configure iptables to block everything on the WAN IP and call it a day.

      • irmadlad@lemmy.world
        link
        fedilink
        English
        arrow-up
        2
        ·
        6 days ago

        sugar_in_your_tea @sh.itjust.works

        It’s nice to be commented by someone famous.

        Open up the window, let some air into this room I think I’m almost chokin’ from the smell of stale perfume And that cigarette you’re smokin’ 'bout scare me half to death Open up the window, sucker, let me catch my breath

        • sugar_in_your_tea@sh.itjust.works
          link
          fedilink
          English
          arrow-up
          1
          ·
          edit-2
          6 days ago

          Mama told me not to come.

          Fun fact, my usernames on Reddit (I would cycle them every couple of years) were all Three Dog Night lyrics, so I continued the theme on Lemmy.

          Thanks for noticing. 😀

  • plz1@lemmy.world
    link
    fedilink
    English
    arrow-up
    4
    ·
    6 days ago

    Does SSH have to be your only way? Could you deploy something like Tailscale? Can you restrict the allowed IP ranges on SSH with a firewall rule?

  • BrianTheeBiscuiteer@lemmy.world
    link
    fedilink
    English
    arrow-up
    15
    ·
    7 days ago

    In addition to other advice you could also use SSH over Wireguard. Wireguard basically makes the open port invisible. If you don’t provide the proper key upfront you get no response. To an attacker the port might as well be closed.

    Here’s at least one article on the subject: https://rair.dev/wireguard-ssh/

  • hemmes@lemmy.world
    link
    fedilink
    English
    arrow-up
    5
    arrow-down
    1
    ·
    7 days ago

    What VPS are you using?

    You should be able to setup a firewall, blocking all access to the SSH port. Then setup a VPN so that only you can access via SSH after making your VPN connection.

    If you connect via a static IP, you can also create an ACL for the VPN connection just in case. You can set an ACL for the SSH port forward rule directly as well, but I don’t like that personally. I prefer keeping things behind the VPN.

    • Voroxpete@sh.itjust.works
      link
      fedilink
      English
      arrow-up
      3
      arrow-down
      2
      ·
      7 days ago

      This is the correct answer. Never expose your SSH port on the public web, always use a VPN. Tailscale, Netmaker or Netbird make it piss easy to connect to your VPS securely, and because they all use NAT traversal you don’t have to open any ports in your firewall.

      Combine this with configuring UFW on the server (in addition to the firewall from the VPS provider - layered defence is king) and Fail2Ban. SSH keys are also a good idea. And of course disable root SSH just in case.

      With a multi-layered defence like this you will be functionally impervious to brute force attacks. And while each layer of protection may have an undiscovered exploit, it will be unlikely that there are exploits to bypass every layer simultaneously (Note for the pendants; I said “unlikely”, not “impossible”. No defence is perfect).

  • Encrypt-Keeper@lemmy.world
    link
    fedilink
    English
    arrow-up
    3
    arrow-down
    1
    ·
    7 days ago

    https://www.crowdsec.net/

    Take the concept of Fail2Ban and add in a community blocklist of thousands of IPs so that you’re blocking not only IPs that have attacked you, but others as well.

    It’s neat because they have a number of collections you can download from the community that include readymade parsers for other kinds of logs, and other attack scenarios you can guard against. For example, if you run Nginx or Caddy as webservers on that machine, you can download associated collections for each that can parse your web access log files and ban IPs based on IPs probing your web server for unprotected admin panels, or abusive AI crawlers.

    You can even write your own scenarios. I wrote one that immediately blocks you after just one attempt to log in using an account like root, admin,adm,administrator, etc.

  • sugar_in_your_tea@sh.itjust.works
    link
    fedilink
    English
    arrow-up
    3
    arrow-down
    1
    ·
    edit-2
    7 days ago

    One of the simplest is geoip blocks. Here’s an article using iptables, and there may be a nicer way w/ whatever firewall you’re using.

    For reference, here are the areas I see in your logs (using this service):

    • 218.92.0.201 - China
    • 162.142.125.122 - US (Michigan)
    • 45.79.181.223 - US (New Jersey)
    • 118.25.174.89 - China
    • 92.118.39.73 - Romania
    • 98.22.89.155 - US (Nebraska)
    • 75.12.134.50 - US (Tennessee)
    • 165.140.237.71 - US (Washington)
    • 65.49.1.29 - US (California)

    If you don’t expect valid users to come from those areas, block them. A lot of those in the US are probably from VPN users, so be careful if people are using a VPN to connect to your services.

    If you can do it w/ iptables, it’ll be a lot more efficient than doing it at the application layer. I also recommend using something like fail2ban to block individual IPs within regions you care about to get any stragglers that make it through the first tier of blocks. Since this is a VPS, you can also check what firewall settings your provider has and see if you can configure it there so it doesn’t make it to your instance in the first place.

      • sugar_in_your_tea@sh.itjust.works
        link
        fedilink
        English
        arrow-up
        2
        ·
        7 days ago

        I highly recommend using key-based SSH authentication exclusively for all users on your server, and disallow root login as well.

        Geoblocking mostly cuts down on the spam, but also constrains where an actual attack can come from. If there’s some kind of zero-day attack on SSH, this will dramatically reduce the risk you’re hit.

        • someacnt@sh.itjust.worksOP
          link
          fedilink
          English
          arrow-up
          2
          ·
          7 days ago

          Fortunately my VPS (oracle) has set SSH authentication to be default. Disallowing root login sounds good, gotta try that as well.

  • ShortN0te@lemmy.ml
    link
    fedilink
    English
    arrow-up
    1
    ·
    7 days ago

    Do you want to prevent brute forcing or do you want to prevent the attack getting in?

    If you want to prevent brute forcing then software like fail2ban helps a little, but this is only a IP based block, so with IPv6 this is not really helpfull against a real attack, since rotating IP addresses is trivial. But still can slow down the attacker. Also limiting the amount of sessions and auth tries does significantly slow down the attacker.

    If you just want to not worry about it set strong passwords, and when it is a multi user system where other ppl might access it, configure Public Key Auth so you can be sure the other users have strong passwords (or keys in this case) to authenticate.

    With strong passwords or keys it is basically impossible to brute force your way in with ssh.