惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
WordPress大学
WordPress大学
小众软件
小众软件
Cloudbric
Cloudbric
AWS News Blog
AWS News Blog
腾讯CDC
量子位
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
Scott Helme
Scott Helme
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
Jina AI
Jina AI
Attack and Defense Labs
Attack and Defense Labs
S
SegmentFault 最新的问题
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
Google Online Security Blog
Google Online Security Blog
美团技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
罗磊的独立博客
L
LINUX DO - 最新话题
博客园 - Franky
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
AI
AI
C
Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
I
Intezer
S
Securelist

Ittavern.com

Wimage - Hosting Open-Source Image Uploader with Podman and external S3 Storage Switching from Hugo to picopaper Encryption using SSH Keys with age in Linux ETag in nginx - Simple Resource Caching Sending nginx Logs to Loki with Grafana Alloy How to: Cisco ISE backup to SFTP repository with public key authentication Dummy IP & MAC Addresses for Documentation & Sanitization Deploying ISSO Commenting System for Static Content using Docker Generate a Vanity v3 Hidden Service Onion Address with mkp224o ssh-audit Primer - Audit your SSH Server mtr - More Detailed Traceroute - Network Troubleshooting My Personal Backup Strategy - August 2024 iperf3 - User Authentication with Password and RSA Public Keypair Adding a trash can to Linux with trash-cli Bandwidth Measurement using netcat on Linux Getting started with rsync - Comprehensive Guide Cron Jobs on Linux - Comprehensive Guide with Examples Port Knocking with knockd and Linux - Server Hardening Getting started with rclone - Data transmission Getting started with dig - DNS troubleshooting Getting started with Fail2Ban on Linux Getting started with netcat on Linux with examples URL explained - The Fundamentals Troubleshooting Asking The Right Questions Create tmux layouts using bash scripts Getting started with tcpdump - Ittavern.com Curl on Linux - Reference Guide Getting started with nmap scripts My Offsite Backup - March 2023 Getting started with iperf3 - Network Troubleshooting ICMP echo requests on Linux and Windows - Reference Guide Simulate an unreliable network connection with tc and netem on Linux Detecting Rogue DHCP Server - Ittavern.com Basics of the Linux Bash Command History with Examples Getting started with GNU screen - Beginners Guide Basics of Power over Ethernet (PoE) Difference between RSS and Atom SSH Troubleshooting Guide - Ittavern.com Backup Guide - how to secure crucial data SSH - run script or command at login Linux - unmount a busy target safely Visual guide to SSH tunneling and port forwarding Guide to Wireshark display filters Online Security Guide - Ittavern.com My IT EDC tool kit v2212 10 prompts - 1000 AI generated images - openAI Dall-E SSH - How to use public key authentication on Linux Ways to support open-source projects Getting started with nmap - Ittavern.com nginx - simple and native authentication function Linux - How to work with complex commands EICAR test file - riskless method to test your antivirus and firewall solution Linux - connect to a serial port with screen Podman / Docker - expose port only to the localhost of the host machine Tmux - reload .tmux.conf configuration file My use cases for CyberChef Nginx - simple permanent or temporary redirects Getting started with tmux - Ittavern.com Tmux - synchronize the input of all panes within a window Nginx - check your public IP CyberChef - How to remove empty lines
SSH Server Hardening Guide v2
2023-11-22 · via Ittavern.com

This is an updated version from last year. Thank you for the great feedback!


This article covers mainly the configuration of the SSH service and only references ways to protect the service on the host machine or via policies.

I'll use Linux with an SSH server as a reference (OpenBSD Secure Shell server according to systemd).


Important: Please test the configuration changes in a test environment or a single user or group to limit the lockout risk!

Additionally, DO NOT copy any configuration mindlessly! - Some configuration changes are just recommendations and work in most cases, but make sure those work for your system, too.

SSH Server Configuration

The following configurations can be changed in the /etc/ssh/sshd_config file or in a separate configuration file that can be created in a subdirectory /etc/ssh/sshd_config.d/*.conf.

Side note: It is recommended to create a separate configuration file as the default file is at risk of getting overwritten with a future software update. Just make sure that the default configuration file references the subdirectory with Include /etc/ssh/sshd_config.d/*.conf.

That said, you can check the configuration file with sudo sshd -t; no output means that it is okay, and errors will be displayed if someone is not working out, like in the following example:

$ sudo sshd -t
/etc/ssh/sshd_config: line 49: Bad configuration option: DebianBanner
/etc/ssh/sshd_config: terminating, 1 bad configuration options

Use sudo sshd -T for a more verbose output, which additionally displays all the options that are used.

Almost every config file change requires a restart of the SSH server service.

Public key authentication #

You can find a guide on how to use public key authentication in this linked article. I highly recommend securing your server with public key authentication instead of password authentication.

After enabling it, make sure to turn off password authentification:

PasswordAuthentication no

It requires some configuration on the server and client, but it is worth it as it is one of the best ways to protect your server.

Changing the ssh port #

Port 2222

Change the default SSH port 22 of your host to something else. Some people think it is a must; some think it is useless. There is no perfect answer, but I hope the following list of pros and cons will help you to decide:

Pros:

  • Reduce exposure to automated attacks and bots
  • Reduce noises in the logs
  • Attackers need to port scan to find the correct port, which makes it easier to detect targeted attacks with IPS and firewalls. Great for internal servers as port scans are uncommon; for internet-facing servers, rather useless as port scans are inevitable and common

Cons:

  • It does not protect against targeted attacks, as a simple port scan can detect the correct port
  • Compatibility issues, since some clients or applications might not work with a non-default port
  • Adds complexity, as clients and scripts must be configured differently, must be documented, users must be informed, etc

Side note: choosing a port below 1024 (system or well-known port) is recommended to make it more difficult for an unprivileged user to highjack the service, as by default, non-root processes can only open ports above 1023. Just make sure to avoid conflicts with already used ports.

Disable root login #

PermitRootLogin no

Prohibits connecting as root as it is recommended to work with a separate user with optional sudo permissions.

I've got some feedback that it is unnecessary to disable this since users with sudo permissions could do the same damage, but I disagree. Most - if not all - systems have a root user, and this is known, which makes it easy to run brute-force or dictionary attacks against the system. Most attackers don't know the available users on a system, which makes the username a kind of password.

Disable login attempts with empty passwords #

PermitEmptyPasswords no

It is fairly self-explanatory, but to make sure, allowing any account without a password to log into the system is a big no-no and should be turned off immediately.

Disable SSHv1 and use SSHv2 #

Protocol 2

SSHv2 is usually the default, but it is worth ensuring SSHv1 is disabled.

There are multiple ways to check if SSHv1 is still enabled, and I show you some. The following commands can be done remotely or on the server with localhost as destination:

ssh -1 remoteuser@remoteserver
SSH protocol v.1 is no longer supported

or with a verbose output like this:

ssh -v remoteuser@remoteserver
[...]
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.9p1 Ubuntu-3ubuntu0.3 
[...]

or netcat:

echo ~ | nc remoteserver 22
SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3

Important: If you see SSH-1.99 as version, it means that SSHv1 is enabled and it should be disabled!

Restrict access to specific users or/and groups #

AllowUsers a_this a_that

AllowGroups ssh_login

This option is pretty straightforward and limits the users or groups that can access the server via SSH.

Restrict access to specific IP or network #

AllowUsers *@10.10.10.10 # affects all users

AllowUsers provider-a@111.111.111.111 provider-b@222.222.222.222

AllowUsers internal-user@10.10.0.0/16

You can further limit the access to specific IPs or networks.

Restrict access to specific interfaces #

ListenAddress 10.10.10.10

Most servers have multiple interfaces. If the server has one interface for the internal network and one for the internet, and you don't need to reach the server over the internet, it is recommended to make the SSH server listen only to the internal IP. The default is 0.0.0.0, which allows the service to listen to all interfaces.

Set an authentication timer #

LoginGraceTime 20

The authentication must happen in 20 seconds before the connection gets closed. The default is 2 minutes. It helps to prevent specific denial-of-service attacks where authentication sessions are kept open for a period of time and prevent valid authentications.

Side note: make sure that this limit works for you. This limit won't be a problem for Public Key Authentication, but if you have to wait for mail to arrive with the MFA token, 20 seconds might be too short.

Limit maximum number of attempted authentications #

MaxAuthTries 3

The default is 6, and lowering it makes it a little bit more difficult to brute-force a password since the server drops the unauthenticated connection after 3 failed attempts.

Side note: Every SSH key loaded into the ssh-agent counts as one attempt each. Keep this in mind if you have a bunch of keys loaded! Additionally, if the Kerberos/GSSAPI authentication method is enabled, the look-up of whether the client is authenticated counts as one attempt.

Limit the number of concurrent unauthenticated connections #

MaxStartups 10:30:100

This is the default and good enough, but I thought explaining this option makes sense.

Explanation MaxStartups start:rate:full:
10 - number of allowed concurrent unauthenticated connections
30 - percentage chance of randomly dropping connections attempts after reaching start (10) and the chance increases linearly until the full (100) connections are reached
100 - maximum number of unauthenticated connections after every new attempt is getting dropped

The randomized connection dropping makes it more difficult to DOS the service with unauthenticated connections.

Side note: Please remember that this option can cause problems with automation and configuration tools or transferring tools that might authenticate slowly and require separate connections.

This option only affects pre-authentication connection and does not limit anything else. Additionally, it has nothing to do with the following option.

Restrict Multiplexing #

MaxSessions 10

This is the default, limits the 'sessions' for one SSH session to 10, and is fine for most cases. Nevertheless, I thought I'd write about some options.

This option simply limits the 'sessions' - as in shell, login, or subsystems like sftp - of a single network connection (TCP)/ SSH authentication. If this limit is reached, a user could simply open another connection.


You can disable multiplexing by setting this option to 1. Every shell, sftp connection, and so on, will then each require a TCP connection, which adds overhead, but can be helpful to limit the damage a highjacked session can do, increases visibility of the connections as they are separate, and therefore troubleshoot certain issues.

But please keep in mind that disabling multiplexing can cause problems and limits some functions! Automation and configuration tools like Chef, parallel transfers via scp, and other tools that need multiplexing could stop working.


Setting MaxSessions to 0 disables all shell, login, and subsystem sessions but still allows tunneling, port forwarding, or SOCKS proxying.

This option can be used to limit the permissions of a bastion/jump host user or group to a single task.

Set up a session timeout #

ClientAliveCountMax 3

ClientAliveInterval 120

The configuration above means that the session is terminated after 6 minutes of client inactivity. After 120 seconds without receiving any data from the client, the server will ask if the client is still there. If the client does not respond, the server will try it again in 120 seconds. If the client fails to answer 3 times, the session is getting terminated.

Hide Linux Version in identification string #

DebianBanner no

The Linux version is being added as a comment on the identification string. Debian and Debian derivates add it by default, RHEL distros do not (from my experience, CentOS+RockyOS).

It changes the identification string pre-authentication from SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3 to SSH-2.0-OpenSSH_8.9p1.

Please note that the rest of the identification string must remain unchanged according to RFC 4253:

4.2.  Protocol Version Exchange

   When the connection has been established, both sides MUST send an
   identification string.  This identification string MUST be

      SSH-protoversion-software version SP comments CR LF

Disable tunneling and port forwarding #

AllowAgentForwarding no

AllowTcpForwarding no

PermitTunnel no

Disabling those functions makes it more difficult to use the server as a jump host to gain access to the connected networks, malicious or not. Most servers do not need those functions enabled, but to learn more, feel free to check my article about SSH tunneling and port forwarding.

Disable unused authentification methods #

KerberosAuthentication no

GSSAPIAuthentication no

ChallengeResponseAuthentication

It highly depends on your needs, but if an authentification method is unused, it should be disabled as it increases the attack surface to exploits and vulnerabilities.

Side note: Please ensure you don't disable the only method you can log in to prevent a lockout.

Disable X11 Forwarding #

X11Forwarding no

The security concern here is that X11 forwarding opens a channel from the server to the client. In an X11 session, the server can send specific X11 commands to the client, which can be dangerous if the server is compromised. Source

Disable SFTP subsystem #

If you do not need SFTP, disable it. It decreases the attack surfaces and makes the system less vulnerable to security flaws.

Just comment out the Subsystem sftp [...] out of the config by placing a # at the beginning of the lines.

Disable insecure ciphers and MACs #

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

KexAlgorithms curve25519-sha256@libssh.org

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256

There are even some more restrictive options, but I have not tested them myself.

Side note: Please note that some clients could encounter problems connecting to the server if they don't support the same ciphers. Either update the software on the client or add ciphers that are supported by the client to the server.

Auditing tools like ssh-audit can tell you what is secure and what is not.

Host Server configurations

I won't go into detail in this section as it is not in the scope. I just reference methods that I have already covered and name others that can help you secure your server even further.


Methods:

  • use Fail2Ban or similar software to monitor the access logs to ban IPs that failed too many login attempts. This helps to prevent brute forcing and DOS attacks > Getting started with Fail2Ban on Linux
  • use Port Knocking to hide the service and decrease the attack surface > Port Knocking with knockd and Linux - Server Hardening
  • get notified as soon someone logs into the machine - practical for critical infrastructure > SSH - run script or command at login
  • Enable MFA with TOTP-modules like libpam-google-authenticator for your SSH access
  • use host and/or network firewalls to limit the hosts or networks that can access the server. Feel free to add this in additionally to the whitelisting of the SSH server configuration
  • use host and/or network firewalls to add a rate limit of network connection to help prevent brute-forcing and DOS attacks.

General policies:

  • keep your OS and software up-to-date
  • use a remote logging instance to keep the logs safe in case of an incident
  • audit those logs with a threat/anomaly detection of your choice
  • don't expose your services to the internet. Use VPNs instead
  • use hardened bastion/jump hosts in front of hosts that can't be properly secured
  • do scheduled and regular audits of your hardening procedure. Use tools like ssh-audit and make sure that your systems are still secure
  • check regularly if services, user accounts, permissions, etc are required and remove them, if not
  • if you use password authentication, force secure password or passphrases

Special thanks to ruffy for recommending disabling X11 forwarding and the SFTP subsystem.