Join the discussion

Write your take first — we'll ask for email only when you're ready to publish.

  • Hacker News
  • > and why it is not enough on its own

    Nothing is good enough on its own.

    Geoblocking, fail2ban, port obscurity, SSH keys, limiting logins to specific usernames, not using your public internet nickname, putting things behind CloudFlare tunnels or WireGuard, wildcard DNS obscurity, 2FA... There are many options.

    Defense in depth is the only way to put services on the internet.

  • > Geoblocking, fail2ban

    I use both on one port 22 host. Not much actually touches the server: maybe 5 hosts a day get banned. Meanwhile, China and the Netherlands are forever getting blocked and logged by geoblocking.

    I check the 24h log window by country most business days. Some days China leads, other days the Netherlands pulls ahead. Almost never are any other countries close to those two.

  • I certainly agree with your general point, but it is very much my experience that just forcing public key authentication on ssh is good enough on its own. (Yes, I understand that by writing this on the internet, I have doomed us all to dealing with a sev zero openssh sshd RCE on the weekend. Sorry in advance.)
  • I would go with something like:

      seed=`date +%s%N`; ( echo "secretknock-20260811|$seed"|sha512sum  ; echo $seed ) | xargs nc -u 192.168.1.1
    
    It is not secure as hmac and it can be 'trivially' brute forced, but don't require extra tools (probably nc not always readily available).

    On other hand if threat vector includes network monitor with ability to replay i would use wireguard to wrap ssh traffic.

  • The enlightened trick is to run ssh on port 443.
  • And https on 22? Why didn't I think of that?
  • Jokes aside, this would be trivial to detect with nmap, right? The SSH banner prints anyways.
  • I had to do this once. SSH server needed to run on port 443 because the clients had a locked down network firewall and could only make connections to particular port numbers.
  • Just wrap it in wireguard. WG won't respond to any incoming handshake without a valid and authorized client key, it's essentially invisible.
  • > If a zero-day drops in OpenSSH...

    Realistically, fwknop is more likely to have a vuln than OpenSHH. Last release was two years ago and the readme dates back twelve :/ Time will tell.

  • fwknop is a bit lower risk though. If all an attacker can do is open a port, they’ll still have to exploit OpenSSH.
  • Seriously. If a zero-day drops in OpenSSH, it's quite literally the end of the world.
  • The real solution is using something like Pangolin or Tailscale (or Headscale) for this. You can control access way better and you never have to expose ssh ever. Not even temporarily.
  • I agree with you.

    I’m reading this thread and wondering if I’m missing something, why people are still talking about port knocking, port obfuscation, and fail2ban.

    I use a cloud VPS. I ssh in via Tailscale. The cloud provider firewall blocks all incoming connections except traffic originating from Cloudflare IP ranges on port 443. My host plays dead to portscans. I check with nmap periodically. I have a break-glass backup terminal login option via my cloud provider dashboard (secured with MFA) in case Tailscale failed and needed investigation and repair.

    This has worked well for me on AWS and Oracle Cloud. It’s quick and easy to set up. You need a timed service to refresh the ingress IP ranges, but any LLM could spit that out in a second.

  • I made my ssh server to listen ipv6-only, and it has been super silent in the logs ever since.

    In the first iteration the IPv6 got polled by a handful of attackers as soon as the letsencrypt certificate was published. In the second iteration I just picked another IPv6 address from the /64 and made ssh.example.com to point to it. This should work until the attackers start guessing subdomain s...

  • This is an interesting piece that is often overlooked by folks in the "but NAT is security" camp; Having a sparse address space that is 64-bits makes it impossible to iteratively scan over a range. If you don't reverse resolve or you disallow zone transfers then you also have no real discoverability for that /64.
  • I don’t know why this wasn’t mentioned before but why not use a Firewall. If you’re using a virtual box like Hetzner or Scaleway you can specify an ip or range at the router level. For all intents and purposes this removes public exposure. Scaleway also has a cheap VPN bridge. So you never need to connect via the public internet if you don’t want to… hardly gets more secure than that
  • They could be hosting on their own homelab network (without tailscale etc magic)
  • If you are connecting from a residence or a mobile device (like a laptop), your ip address isn't fixed, so a firewall won't help.
  • Is this actually practically reducing the attack surface? We're replacing a battle hardened service with a random one that has the ability to manipulate the firewall rules.
  • If you mean fail2ban by “battle hardened service”, it manipulates the firewall rules as well. And OpenSSH has the same functionality built-in, without any additional service (PerSourcePenalties).
  • A sensible observation. In theory, the entire codebase for a simple HMAC knock knock ought to be tiny and easy to harden with multiple rounds of human and LLM review.

    The goal should be to have your complex layers sitting in front of simpler, easier-to-review lines of defence. Once you get to something like an open connection to ssh, the potential attack surface would be orders of magnitude larger, even though it’s more mature and closely scrutinised.

  • I think the answer is yes. A response from a remote system (or lack of) is a signal. The conventional ssh protocol method when connecting to a server is to instantly send over the identification string. RFC 4253 requires "both sides MUST send an identification string". It doesn't necessarily decide an order, but most ssh implementations I've seen send their protocol string before any other data has been received.

    The broadcasting of the versioning information does constitute a potential leakage of information that could be useful to an attacker. Even if we contrast this to something like mTLS, the client certificate doesn't come until fairly late in the handshake, so there is still information that can be cleaned from the ServerHello from an unauthenticated inspector. This is also the case with QUIC since it piggybacks off the general TLS handshake.

    I think the issue is, for a known set of systems, can you create communications between them that are oblivious/non-discoverable to non-authorized systems. I think the answer is yes, but it requires an out-of-band key agreement protocol. Wireguard is an example. However, the problem of out-of-band key agreement can't really be ignored.

    I think the article's method is somewhat valid. I also think it is non-ideal for only doing source IP based rulesets, especially in the world of IPv4 and NAT being prevalent.

    by mvkg
  • No, it's not. The article itself is somewhat incoherent; for instance, if you're using key-only authentication (which: of course you are) fail2ban has literally no function (unless you think attackers are brute-forcing ECDH keys).

    The reality is that there are basically two ways to operate SSH:

    (1) You can, because OpenSSH is the significant remote service with the literal best track record of any remote service, just disable passwords and let SSH run in 22/tcp exposed to the Internet. Probably stop logging people scanning you; there's nothing you're going to do about it, so it's not real information.

    (2) You can keep SSH behind WireGuard, an even simpler security protocol with an even better security story (though: OpenSSH is quite solid), which is designed to not to chat with counterparties that don't have keys, even to do negotiation.

    Everything else is performative.

    I'd incline towards option (2).

  • A scheme like this is in the process of being standardised by Peter Gutmann who knows what he is doing. To give that statement more context he's an NZ cryptographer and has also worked in standardisation before. So, he is promoting this model with knowledge of cryptography, risks and the standards process.

    https://datatracker.ietf.org/doc/draft-gutmann-ssh-preauth/

    by ggm
  • What I do is laughably simple.

    1. Disable all logging about break-in attempts.

    2. Do not have any common user names like "root".

    Say you want to be able to log in as root from anywhere, just with a password. This is a wise idea; what if you need access, but are in a situation where you are not able to use a certificate?

    Make up an alternative name like roto-rooter or whatever pops into your head. Install it into the password file as an alternative name for UID 0. (Make sure it appears later than the "root" entry!). Also edit the shadow file, making sure that the entry is duplicated for the alternative name.

    Then in the sshd config file, use AllowUsers to allow only a whitelisted set of users. Here if you say "AllowUsers rotorooter", then the only user id that can authenticate is exactly that one, and it's mapped to UID 0 via passwd/shadow. Add any other accounts you would like to remotely access, giving them similar aliases if they happen to land into a commonly probed space, or are something that a targeted attacker could infer from knowing something about you.

    Attackers do not probe the user ID space at all. They concentrate exclusively on probing the password spaces of common user IDs like root, admin, database, www-data, etc. If your system does not support any of those IDs, they are not on a trajectory to crack anything. Your rotorooter password could be "g0d" and they will not get in, if all they ever try is root.

  • This is a bad idea™. You should never have more than one UID 0 on a Unix system. This will violate most corporate security guidelines (STIG and CIS) *. And for good reason.

    A much better idea is to set up a non-root user and configure sudo correctly.

    * https://www.stigviewer.com/stigs/red_hat_enterprise_linux_9/...

  • Port knocking, and other bespoke middle layers in front of internet services, is stupid. It violates Kerckhoffs’s principle¹. If you want more secret bits which users need to know in order to access your system, increase your password lengths, or cryptographic key sizes. If you want to keep log sizes (or “noise”) manageable, adjust your logging levels.

    Anything added in front of your normal service also complicates access, since it’s non-standard. If you want a standard solution to solve all your needs for secure access of IP-based services, use IPsec and be done with it once and for all.

    1. <https://en.wikipedia.org/w/index.php?title=Kerckhoffs%27s_pr...>

    (Adapted from this old post: <https://news.ycombinator.com/item?id=39898061>)

  • I think you are missing the point. It isn't about increasing the bits of security, it's about avoiding the flood of port scanners and the logs that produces.

    IPsec is way more complicated to set up than this (or other VPN solutions like Wireguard or OpenVPN for that matter), and doesn't even completely solve that problem, because your ipsec port is open. Although, admittedly, there are probably less bots looking for ipsec than ssh.

  • It is not stupid. Your stated principle assumes the exposed OpenSSH server does not have pre-auth 0-days. Having open 22 exposes a lot of information about the machine already, not to mention possible banners. The mentioned method is an elegant solution to both risks.