Within minutes of receiving dedicated IPv4/IPv6 addresses and starting up, an internet-facing VPS is exposed to frequent probes from global Botnets. Thousands of distributed scanners continuously sweep common ports and use weak-password dictionaries for intensive Brute-Force Attacks. Once credentials are compromised, the host is often quickly infected with mining malware, given backdoor accounts, or recruited as a source for the next DDoS attack.
Building a rigorous Linux operations baseline requires eliminating password exposure, standardizing asymmetric cryptography, revising port exposure policies, and introducing dynamic defenses. This article systematically covers modern local key-pair generation and server-side daemons (sshd) security hardening and least-privilege account management through Fail2ban dynamic blocking and emergency recovery when access is lost.
One. Public-Internet Threat Models and Initial Policies of Major Providers#
Before detailed configuration, understand the differences in providers' initial networking and authentication architectures:
- DMIT's “Keys by Default” Model: When provisioning cloud server instances, DMIT favors a strict passwordless security model. System images disable remote root password login by default during initialization and strongly require users to associate an SSH public key when activating an instance. This prevents the risks of initial default-password leaks and password dictionary attacks at their source.
- BandwagonHost's “Random High-Numbered Port” Model:
When BandwagonHost initializes an operating system under KiwiVM, it generates a random initial root password but also assigns a nonstandard five-digit SSH port by default, such as
2xxxx~3xxxx),而非开放默认的 22 端口。这种策略能够在第一时间过滤掉全网绝大多数盲扫 22 端口的低级扫描脚本。
Regardless of the provider's initial settings, reconfigure SSH access to a consistent production-grade security standard before putting the server into production.
二、 现代加密基准:为什么弃用 RSA,全面转向 ED25519?#
长期以来,基于大数分解难题的 RSA 算法被广泛用于 SSH 鉴权。然而在当前的算力与安全架构下,RSA 逐渐显露劣势:
- Imbalance Between Security and Key Size: to provide sufficient security, RSA must use 3072-bit or 4096-bit keys, increasing handshake overhead and producing extremely long strings.
- Risk of Side-Channel Attacks: Traditional RSA software implementations can be vulnerable to microarchitectural Timing Attacks and cache side-channel attacks.
ED25519 is based on the high-performance EdDSA (Edwards-curve Digital Signature Algorithm) elliptic-curve signature scheme, Curve25519:
- Equivalent High Security: Only 256 bits long (about 68 characters for the public key), while offering security equivalent to a traditional RSA key of roughly 3000 bits or more.
- Resistance to Side-Channel Attacks:算法设计在底层运算中完全保持常数时间执行(Constant-Time Execution),天然免疫计时侧信道攻击。
- Ultra-Fast Performance: Signatures are generated and verified much faster with very low memory usage, improving handshake performance on poor connections or during sudden bursts of concurrent connections.
1. Generate an ED25519 Key Pair on Your Local Workstation#
Key generation should always take place on受信任的本地 Workstation (Linux, macOS, or Windows Terminal with OpenSSH configured). Never generate the key pair on a public VPS and then download the private key.
Run the following command in your local terminal:
ssh-keygen -t ed25519 -a 100 -C "admin-ops-2026@vpsmap"参数技术剖析:
-t ed25519:指定生成 ED25519 签名算法密钥。-a 100: specifies 100 rounds of strengthened bcrypt hashing for the Key Derivation Function (KDF). This significantly increases the time needed for GPU/ASIC-based offline brute-force attacks against the private key passphrase.-C "...": appends an identifying comment to the end of the public key, making it easier to identify its purpose and host when managing multiple devices.
Enter file in which to save the key (/home/username/.ssh/id_ed25519): [直接回车使用默认路径,或指定独立名称]
Enter passphrase (empty for no passphrase): [务必设置强私钥密码短语]
Enter same passphrase again: [再次输入确认][!IMPORTANT] A Private Key Passphrase Is the Last Line of Defense Against Theft of Local Assets. Even if your local workstation is physically stolen or someone copies
id_ed25519private key file, an attacker without the passphrase cannot decrypt it or establish a remote connection.
After the command finishes, the local ~/.ssh/ Two key files will be created in the directory:
id_ed25519:私钥文件. Permissions must be600,绝不可上传、复制或共享。id_ed25519.pub:Public Key File. A public string distributed to the target cloud server.
Three. Public Key Deployment and Strict Linux Filesystem Permission Requirements#
方案 A:使用 ssh-copy-id Automated Delivery (For Hosts That Currently Allow Password Login)#
If a newly purchased instance initially supports password login, such as BandwagonHost's default installation environment, run locally:
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p [当前实际SSH端口] root@[服务器公网IP]方案 B:手动配置与控制台接入(适用于 DMIT 等纯密钥环境)#
If the provider's initial image disables password authentication, or if you need to update an existing key:
- Inject Through the Console or Provider Panel:
On the instance details page in the DMIT control panel, navigate to Access (Access Control) page, you can directly open SSH Keys Repository. In the console, add the locally generated
id_ed25519.pubpublic key content.[!WARNING] According to DMIT's official technical documentation, after replacing or adding an SSH Key through Access in the panel,You Must Restart the Instance Through the Control Panel (Restart), allowing the underlying metadata service (Cloud-Init) to correctly write the new public key into the system's
authorized_keysin it. - Log In to the System and Add It Manually: If you log in with a temporary password or through the out-of-band Console, you can create and append manually:
# 1. 确保用户主目录下的 .ssh 目录存在
mkdir -p ~/.ssh
# 2. 将本地 id_ed25519.pub 内容以追加模式写入目标文件
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... admin-ops-2026@vpsmap" >> ~/.ssh/authorized_keysStrict Linux Filesystem Permission Rules#
The OpenSSH daemon includes a strict permissions-checking mechanism (StrictModes). If the parent directory or key file has overly broad Group-Writable or world permissions,sshd will conclude that the current environment may have been tampered with by a malicious process on the same machine, refuse to load public-key authentication, and cause the connection to fail.
Correct the Permissions on the Server:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $(whoami):$(whoami) ~/.sshFour. In-Depth Production Hardening of the SSH Daemon (sshd)#
Once key-based access to the server works, thoroughly harden the SSH daemon's main configuration file, disable password authentication, and move the port away from commonly scanned ports.
Edit the configuration file as root:
nano /etc/ssh/sshd_config(Note: On newer Debian 12 / Ubuntu 22.04+ systems, it is recommended to check /etc/ssh/sshd_config.d/ whether the directory contains .conf override file, ensuring that hardening directives are not overridden by included configuration files)。
Production-Grade Configuration Commands#
Find and modify the following key parameters in the configuration file (append them to the end if they do not exist):
# -------------------------------------------------------------
# 1. 网络与端口绑定
# 避开众所周知的 22 端口,选择 1024~65535 范围内未被占用的高位端口
# -------------------------------------------------------------
Port 49222
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
# -------------------------------------------------------------
# 2. 身份验证核心策略
# -------------------------------------------------------------
# 开启公钥认证
PubkeyAuthentication yes
# 彻底禁用所有交互式密码验证形式,从根源粉碎字典暴破
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
# 禁用空密码账户
PermitEmptyPasswords no
# -------------------------------------------------------------
# 3. 根用户与认证尝试限制
# -------------------------------------------------------------
# 允许 root 仅通过密钥登录;后续若建立专属运维账户,可进一步改为 no
PermitRootLogin prohibit-password
# 限制单次连接最大鉴权尝试次数(若客户端尝试超过 3 次未命中则断开)
MaxAuthTries 3
# 限制未认证会话的超时断开时间(降低慢速拒绝服务攻击影响)
LoginGraceTime 30
# -------------------------------------------------------------
# 4. 连接保活与防伪造
# -------------------------------------------------------------
# 每 60 秒向客户端发送探活包,避免 SSH 长时间空闲被中间路由 NAT 丢弃
ClientAliveInterval 60
ClientAliveCountMax 3
# 严格模式核查文件属主与权限
StrictModes yes
# 禁用老旧或容易引入安全隐患的特性
X11Forwarding no
AllowAgentForwarding yes
AllowTcpForwarding yes校验配置文件语法(绝不能跳过的验证步骤)#
When restarting sshd before proceeding, you must run a static syntax check:
sshd -tIf the command returns no output, the configuration syntax is valid. If it reports any highlighted errors, such as misspelled directives or deprecated parameters, correct them immediately; otherwise, the service may fail when the daemon restarts.
五、 防火墙协同放行与防失联作业闭环#
修改默认端口是许多运维人员遭遇“服务器失联”的高发阶段。核心原因往往在于:The SSH port has been changed, but the underlying firewall has not allowed the new port. Closing the terminal at this point causes a complete loss of access.
1. Dynamically Allow the Firewall Port#
Apply the appropriate rules for the firewall used by your system:
- 如果使用 UFW(Ubuntu / Debian 常见):
# 优先允许新端口通过(以 49222 为例)
ufw allow 49222/tcp comment 'Custom-SSH'
# 检查防火墙状态确保规则生效
ufw status verbose- If using Firewalld (common on AlmaLinux / Rocky / CentOS):
firewall-cmd --permanent --add-port=49222/tcp
firewall-cmd --reload- 如果使用原生 Iptables / NFTables:
确保在
INPUTthe chain's defaultDROPrule, insert the following to allow inbound TCP traffic on the new port:ACCEPTrule.
2. Restart the SSH Daemon#
systemctl restart sshd || systemctl restart ssh3. The Golden Rule Against Lockouts: “Verify First, Disconnect Later”#
+-----------------------------------------------------------+
| 生产防失联操作 SOP 流程图 |
+-----------------------------------------------------------+
[终端 A: 维持现有活跃连接]
|
v
修改端口与加固项 -> 执行 sshd -t -> 防火墙放行新端口 -> 重启 sshd
|
v
[保持终端 A 绝对不要关闭/退出!]
|
v
[新开本地终端 B] 发起测试连接:
ssh -p 49222 -i ~/.ssh/id_ed25519 root@[服务器IP]
|
+--> [连接成功,密钥秒级登录] -> 确认无误 -> 放心关闭终端 A
|
+--> [连接超时或拒绝] --------> 立即切回终端 A 排查防火墙与配置Enable on the local workstationA Brand-New Terminal SessionTest the Connection:
ssh -p 49222 -i ~/.ssh/id_ed25519 -vvv root@[服务器IP]If the connection hangs or fails, use the original terminal window you kept open to check journalctl -u sshd -e 排查错误,或者重新放行防火墙端口。
Six. The Principle of Least Privilege: Configure a Dedicated Sudo Administration Account#
在生产环境中,长期直接以 root superuser for routine maintenance creates serious risks of excessive privilege and mistakes. Standard enterprise practice is to create a daily-use account and add it to sudo authorization chain.
1. Create a Dedicated Operations User#
# 创建普通系统账户(以 opsadmin 为例)
adduser opsadminFollow the prompts to set the user's initial password.
2. Grant Privilege-Escalation Capabilities#
- Debian / Ubuntu 系:
usermod -aG sudo opsadmin - RHEL / Rocky / AlmaLinux family:
usermod -aG wheel opsadmin
3. Copy the ED25519 Authentication Key to the Regular User#
为新建账户配置公钥免密登录能力,并严密设置权限:
# 建立用户目录下的 .ssh 文件夹
mkdir -p /home/opsadmin/.ssh
# 将 root 的 authorized_keys 复制过去,或写入专门分配给该运维的公钥
cp ~/.ssh/authorized_keys /home/opsadmin/.ssh/authorized_keys
# 更改目录和文件属主为 opsadmin 用户及其主用户组
chown -R opsadmin:opsadmin /home/opsadmin/.ssh
# 强制修正权限为安全规范
chmod 700 /home/opsadmin/.ssh
chmod 600 /home/opsadmin/.ssh/authorized_keys4. (Optional) Further Restrict Root Login Access#
Successfully use the following from the local terminal: opsadmin 用户登录并验证 sudo -i After successfully elevating privileges, you can edit again /etc/ssh/sshd_config:
# 彻底禁止 root 用户从外部任何途径登录,仅允许普通用户提权
PermitRootLogin noRun sshd -t and restart the service. External probes will then be unable to reach root account name.
Seven. Automated Intrusion Defense: Deploy Dynamic Blocking with Fail2ban#
Even after moving to a nonstandard port and disabling password authentication, malicious internet scanners continue attempting connections, consuming server connection capacity and cluttering system logs.
Fail2ban is a lightweight active intrusion-prevention tool that monitors authentication logs in real time. When an IP repeatedly fails authentication within a set period, Fail2ban dynamically invokes the underlying firewall, such as Iptables, NFTables, or UFW, to DROP traffic from that source.
1. Install Fail2ban#
- Ubuntu / Debian:
apt update && apt install -y fail2ban - Rocky / AlmaLinux:
dnf install -y epel-release && dnf install -y fail2ban
2. Configure a Protection Jail for the Custom Port#
Fail2ban Provides by Default /etc/fail2ban/jail.conf 作为模板,但升级软件包时可能覆盖该文件。生产规范必须新建本地覆盖文件 jail.local:
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
nano /etc/fail2ban/jail.localModify or define at the end of the file [sshd] 规则块:
[DEFAULT]
# 忽略的白名单 IP(例如公司出口固定 IP、本地宽带公网 IP,以空格分隔)
ignoreip = 127.0.0.1/8 ::1
# 封禁动作:使用 iptables 丢弃恶意数据包
banaction = iptables-multiport
[sshd]
enabled = true
# 务必修改为当前服务器实际配置的高位 SSH 端口!
port = 49222
filter = sshd
# 统计时间窗口(秒):600 秒(10分钟)内
findtime = 600
# 触发拉黑的失败最大尝试次数:尝试 3 次失败即封禁
maxretry = 3
# 惩罚封禁时长(秒):86400 秒(24小时);设为 -1 为永久封禁
bantime = 86400
# 针对较新的 Debian 12 / Ubuntu 22.04+ 系统,OpenSSH 日志由 systemd-journald 托管:
# 推荐显式指定后端为 systemd,避免因找不到 /var/log/auth.log 导致规则不生效
backend = systemd3. Enable the Service and Routine Monitoring#
Start Fail2ban and enable it to start automatically at boot:
systemctl enable --now fail2ban
systemctl restart fail2banUseful Commands for Routine Operations and Blocklist Management#
查看 SSH 监控牢笼(Jail)状态与实时封禁 IP 列表:
fail2ban-client status sshdExample Output:
Status for the jail: sshd |- Filter | |- Currently failed: 1 | |- Total failed: 28 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 3 |- Total banned: 3 `- Banned IP list: 198.51.100.24 203.0.113.88 192.0.2.14Manually Remove a Legitimate IP That Was Mistakenly Blocklisted:
fail2ban-client set sshd unbanip [被误封的IP地址]Manually Block a Malicious IP:
fail2ban-client set sshd banip [恶意IP地址]
Eight. Emergency Response to Lost Connectivity and Out-of-Band Console Recovery Guidelines#
If a mistake during firewall changes, SSH updates, or key replacement causes SSH to reject all access,切勿慌张尝试重装系统Mainstream high-quality providers all offer an Out-of-band Console that bypasses the public network layer.
1. BandwagonHost KiwiVM Console Recovery#
If you cannot connect to your BandwagonHost VPS because of an incorrect port, firewall blocking, or a configuration typo:
客户中心 -> 服务管理 -> 登入 KiwiVM 控制面板
|
+--> 凭据管理提示:
| KiwiVM 管理面板密码与客户中心登录密码、系统的 root 初始密码彼此独立。
| 若忘记 KiwiVM 登录密码,可在用户中心直接请求重置。
|
+--> 应急恢复路径:
1. 点击左侧导航栏的 "Interactive Console"(交互式控制台)或 "Root shell - basic"。
2. 打开类似物理显示器的终端窗口(模拟真实键盘显示器直连)。
3. 直接输入 root 账户与系统密码登录系统内部。
4. 执行 "ufw disable" 暂时关闭防火墙,或编辑 "/etc/ssh/sshd_config" 纠正错误配置。
5. 执行 "systemctl restart sshd" 恢复网络通信。[!NOTE] For major, irreversible system damage, KiwiVM offers a convenient “Install new OS” feature. However, under the official terms, if the instance IP is externally blacklisted, its cross-data-center migration (DC Migration) feature is restricted.
2. Recovery Through the DMIT Panel's Web Console#
On a DMIT instance, if a public key is accidentally deleted or sshd_config being locked out by a parsing failure:
- Log in to the DMIT client area and open the affected instance's management page.
- Launch directly from the top control area Console(Web VNC Emergency Console).
- Console access lets you take direct control of the virtual machine even when no SSH network connection is available.
- Check
~/.ssh/authorized_keyswhether it is mounted correctly, or checksystemctl status sshdConfirm the line number reported in the error. - 如果公钥完全丢失,可在面板 Access tab to reselect the associated public key, then restart through the panel to trigger key loading again.
Nine. Quick Production Hardening Checklist#
After completing the full procedure, use this checklist to verify the host's final hardening status:
| 校验维度 | 生产 Standard 要求 | 校验命令 / 验证方式 |
|---|---|---|
| Key Algorithm | Strictly Use the ED25519 Standard | ssh-keygen -l -f ~/.ssh/authorized_keys Should Display ED25519 |
| Local Private Key | A Strong Passphrase Is Required | Prompt for the Passphrase Each Time the Key Is Loaded Locally |
| File Permissions | ~/.ssh to 700,authorized_keys 为 600 | ls -la ~/.ssh Verify Permission Bits and Ownership |
| Password Authentication | Completely Disable Password and Interactive Authentication | ssh -o PreferredAuthentications=password Should Be Rejected Outright by the Server |
| Port Policy | Move to an Uncommon Port Above 1024 | ss -tulpn | grep sshd View Listening Ports |
| 自动化防御 | Fail2ban Is Blocking Correctly and Enabled at Boot | systemctl is-active fail2ban Return active |
| Out-of-Band Access | Know How to Access Your Provider's Console for Emergency Login | Confirmed that KiwiVM Interactive Console or DMIT Web Console is available |
Following these engineering practices brings the asymmetric encryption baseline and defense in depth of a Linux server's public-facing attack surface up to industry production security standards, greatly reducing exploitable opportunities for attacks against the SSH server.