HiddenSSH Config file, Cloud Firewall Single Node


This is the modern use (Firewall/Application level Firewall) in OpenSSH

Configured for running on a single node/server in cloud enviroment, with OpenSSH IP restrictions.
Note that this configuration works with public/private keys and not passowords.

Its 2026; You should be using security keys as an ssh agent, to protect your self against (key theft/unauthorized access), even using a file based public/private key is out dated in (secure environments/hardened/important servers).


sshd_cloud_firewall_single_node

Cloud-optimized SSHD config for single-node environments with IP-restricted user logins, hardened encryption, logging, and firewall integration.


#########################################################
# https://hiddenssh.com/cloud-single-node               #
#                                                       #
# sshd_cloud_firewall_single_node                       #
# version 1.43                                          #
# Minor text edit fixes, and tweaks.			#
#                                                       #
# Standard practice: keep a known-good recovery backup  #   
# https://hiddenssh.com/backup-sshd-config              #
#########################################################
# Notes: if issues; run following commands.
# mkdir -p /run/sshd
# chmod 0755 /run/sshd
# chown root:root /run/sshd

# Network
# -------
# If you want to change the port on SELinux(enforcing mode); 
# You need to change SELinux booleans, to allow this. 
# semanage port -a -t ssh_port_t -p tcp 2222
# Port tcp/22, is priority traffic but depends usually on networks.
Port 22
Protocol 2
# Define inet; If you want to only listen on IPv4, 
# keep in mind you need to firewall twice; rules for IPv4 & IPv6, if you use both IPv4 & IPv6 at the same time.
# This is NOT recommended!
# AddressFamily any = IPv4 & IPv6
# AddressFamily inet = IPv4
# AddressFamily inet6 = IPv6
AddressFamily inet
# Use dedicated IP for sshd; From a Different Network block, 
# Trick from the 90s, credits "(Big Blue/IBM) worker".
# Seeing the IPv4 shortage today, this only works with IPv6 today.
# NOTE: Not recommended using (*/wildcard). 
# *Change me*
ListenAddress 192.168.0.1
# (VPN) You need to listen to the IPv4 address inside the tunnel.
# Not recommended; adds chain of failure risk.
# *Change me*
#ListenAddress 10.0.0.1
TCPKeepAlive yes
# WARNING
AllowAgentForwarding no
# https://hiddenssh.com/ssh-socks5-proxy
AllowTcpForwarding no
# https://hiddenssh.com/ssh-tunnel
PermitTunnel yes
GatewayPorts no

# Firewall
# ---------
# https://hiddenssh.com/cloud-single-node see; OpenSSH Application Level Firewall.
# *Change me*
AllowUsers user1@192.168.0.10 user2@10.0.0.10

# Deamon
# -------
PidFile /var/run/sshd.pid

# Info
# ----
# Greating for brutforces, Shows up as.  
# debug1: Remote protocol version 2.0, remote software version OpenSSH_8.7 HiddenSSH-cloud
# debug1: compat_banner: match: OpenSSH_8.7 HiddenSSH-cloud pat OpenSSH* compat 
# *Change me*
VersionAddendum hiddenssh-cloud
# Print before login
#Banner /etc/ssh/login.txt
# Print /etc/motd at succesful login
PrintMotd yes
# Show last login IPs
PrintLastLog yes

# Encryption
# ----------
# Syntax: ssh -Q cipher check what Encryption Ciphers your sshd has been (compiled with/supports).
# aes256-cbc uses AES in cipher-block chaining (CBC) mode, which can be vulnerable to certain attacks if not used correctly.
# aes256-gcm@openssh.com uses AES in Galois/Counter Mode (GCM), which provides both encryption and authentication, 
# making it resistant to certain types of attacks. However, it may not be as widely supported; use aes256-ctr if aes256-gcm@openssh.com breaks.
# twofish256-ctr is a good option but not supported by all systems
# chacha20-poly1305@openssh.com The ChaCha20 stream cipher is generally faster than AES, when without support for AES hardware acceleration.
# Run: cat /proc/cpuinfo to check the accelerators.
# Profile(Large data traffic): 
#Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com
# Profile(Best balance): 
Ciphers aes256-gcm@openssh.com

# If you want to choose one MAC algorithm for the best security, hmac-sha2-512-etm@openssh.com would be the best choice.
MACs hmac-sha2-512-etm@openssh.com
# Profile(Hardware Security Key)
#KexAlgorithms curve25519-sha256@libssh.org
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
# Public key types accepted
# NIST P-curves are possibly back-doored by the U.S. National Security Agency.
# ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521
# You should prerable ONLY use; ed25519 if possible.
# Profile(Hardware Security Key)      
#PubkeyAcceptedKeyTypes ssh-ed25519-cert-v01@openssh.com
PubkeyAcceptedKeyTypes ssh-rsa,rsa-sha2-512,ssh-ed25519-cert-v01@openssh.com 
# Profile(Hardware Security Key)
#PubkeyAcceptedKeyTypes ssh-ed25519-cert-v01@openssh.com

# Profile(Large data traffic): 
#RekeyLimit 100G 1h
# Profile(Hardware Security Key) 
#RekeyLimit 10G 8h
RekeyLimit 4G 1h
# SSH compression can leak secrets via side-channel attacks: if attacker-controlled text is compressed with secrets, 
# output size changes reveal matching bytes, enabling gradual secret recovery. 
# Profile(hardened): Disable compression.
Compression no
# Profile(Large data traffic): 
#Compression delayed

# Hardening login
# ---------------
LoginGraceTime 2m
StrictModes yes
MaxAuthTries 5
MaxSessions 5
MaxStartups 10:30:100
ChallengeResponseAuthentication no
UseDNS yes
# Warning Will break some systems (Disables /etc/shadow file)
UsePAM no
PermitRootLogin no
DenyGroups root guest nobody ubuntu
# Never put this to yes! 
PermitEmptyPasswords no
DenyUsers root admin administrator user test guest nobody ubuntu webmaster backup ftp ssh postgres mysql oracle tomcat apache www-data git docker mail pi
# Checks dead/unresponsive sessions, (0 = every X second).
ClientAliveInterval 0
ClientAliveCountMax 3
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitTTY yes
# Needed for: (SCP/sshfs) (Disable if you dont use scp). 
# Recommended: rsync -azvP -e "ssh" file.txt user1@host:/tmp/file.txt (No sftp needed)
Subsystem sftp  /usr/libexec/openssh/sftp-server

# Logging
# -------
SyslogFacility AUTH
SyslogFacility AUTHPRIV
LogLevel info

# User Settings
# -------------
# With this option set to "yes", users can set arbitrary environment variables that can potentially 
# override system settings/perform unauthorized actions. 
# This can be especially dangerous if the user connecting via SSH has administrative privileges on the system.
# *Change me*
PermitUserEnvironment yes
     Match user user1,user2
Match all
     PermitUserEnvironment no
     # Passwords are legacy and increasingly deprecated.
     PasswordAuthentication no
     PubkeyAuthentication yes
#PermitUserEnvironment yes
     #Match user chroot-user
     #ChrootDirectory /home/restricteduser
     #ForceCommand internal-sftp
     #AllowTcpForwarding no
     #X11Forwarding no
     #PermitTunnel no
     # Passwords are legacy and increasingly deprecated.
     #PasswordAuthentication no
     #PubkeyAuthentication yes
     # Chroot Jail
     # https://members.hiddenssh.com/restricted-ssh
     # A chroot jail restrict (user/service account/proces)s to a specific directory tree.
     #ChrootDirectory /home/chroot-user/chroot/
     # Allows SSH sessions to allocate a (terminal/normal interactive shell)
     # With (process/service account) turn this off, for inviduall users with (Match User $USERNAME)
     #PermitTTY no

# Environment variables
# --------------------- 
# https://hiddenssh.com/sshd-env
# echo $hiddenssh
# env
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
AcceptEnv hiddenssh oraclesecretkey oracleauthtoken cloudflaretoken openaikey

# Keys Settings
# -------------
# Root controlled Authorized Key files.
# AuthorizedKeysFile /etc/ssh/%u tells sshd to look for each user’s allowed SSH public keys in /etc/ssh/ 
# (e.g., /etc/ssh/user1) instead of ~/.ssh/authorized_keys.
# touch /etc/ssh/user1
# chmod 0644 /etc/ssh/user1
# chown root:root /etc/ssh/user1
# Profile(SELinux): chcon -v system_u:object_r:sshd_key_t:s0 /etc/ssh/user1 && restorecon -v /etc/ssh/user1
# Profile(OpenRC): /etc/init.d/sshd reload 
# Profile(Systemd): systemctl reload sshd
#AuthorizedKeysFile /etc/ssh/%u
#
# Classic ~/.ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_backup
#
# Certificate File
#TrustedUserCAKeys /etc/ssh/certificate-auth/user1-hiddenssh-cert.pub
# AuthorizedPrincipalsFile is mainly relevant when you use an SSH CA.
#AuthorizedPrincipalsFile none

# Centralized Authentication
# --------------------------
KerberosAuthentication no
#KerberosOrLocalPasswd no
#KerberosTicketCleanup no
#KerberosUseKuserok no
#GSSAPIAuthentication no
#GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck no
#GSSAPIStrictAcceptorCheck no
#GSSAPIKeyExchange no
#GSSAPIEnablek5users no
# Disables external key lookup helpers, such as scripts that fetch keys from LDAP, HTTP APIs, databases, etc. This reduces attack surface.
AuthorizedKeysCommandUser nobody

Iptables

Iptables and firewall integration.


iptables -N ssh-ingress
iptables -A INPUT -j ssh-ingress
iptables -P INPUT DROP
iptables -A ssh-ingress -s 192.168.0.0/32 -d 192.168.0.1/32 -i Interface -p tcp -m tcp --dport 22 \
  -m state --state NEW,RELATED,ESTABLISHED \
  -m comment --comment "SSH client User1" -j ACCEPT

Example of how your Iptables should look:

You need to match IPs in sshd_config and iptables, because they work on different levels.
Iptables operates at the network/kernel level — it controls which source IPs can reach OpenSSH socket.
OpenSSH filters connections at the application level — it restricts which (IP/IPs) each user is allowed to login from.

Example: OpenSSH IP Firewall

Pay close attention to user1@ this part defines the user, rest defines the IP, this is specific for each user.


# Firewall
# ---------        Invidually matched IPs to specific user
                      |
AllowUsers user1@192.168.0.10 user2@10.0.0.10 user3@1.1.1.*
            |                                             |
          user1 must exist in /etc/passwords     Wildcard allowing any IP in the .255 block
					         Note: Wildcards only work in the last block.

Example: Iptables Ip filtering

Pay close attention to ssh-ingress chain, and Policy of the CHAIN: DROP


Chain INPUT (policy DROP)
target             prot opt source               destination
ACCEPT             0    --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ssh-ingress        2    --  0.0.0.0/0            144.24.33.7          tcp dpt:22

Chain OUTPUT (policy DROP)
target      	   prot opt source               destination
ACCEPT     	   0    --  0.0.0.0/0            0.0.0.0/0            ctstate ESTABLISHED /* NEEDED for 2 way communication */

Chain ssh-ingress (1 references)
target     	   prot opt source               destination
ACCEPT     	   all  --  144.24.46.145/32	 144.24.33.7/32       ctstate NEW,ESTABLISHED /* SSH Client User1 */
ACCEPT     	   all  --  144.24.46.145/32     144.24.33.7/32       ctstate NEW,ESTABLISHED /* SSH Client User2 */