发布于 2026 年 5 月 9 日· 10 分钟阅读

新 VPS 到手第一件事:一键初始化脚本

VPSLinux安全ShellzshtmuxDocker

买完 VPS 登上去,你面对的是一台空白的机器。

不做任何配置,它每分钟都在被互联网上的机器人扫描和尝试登录。我们的服务器开放不到三天,SSH 暴力破解记录就超过了 28,000 次,单个 IP 打了 14,000 次以上。

这篇文章提供一个一键初始化脚本,涵盖安全加固、现代 CLI 工具、开发环境配置,适配主流 Linux 发行版。


一键运行

curl -fsSL https://raw.githubusercontent.com/baiyedev/baiye-scripts/main/vps-init.sh | bash

脚本需要 root 权限。运行前会要求你粘贴 SSH 公钥,留空跳过(前提是已有其他方式登录)。

源码:github.com/baiyedev/baiye-scripts


脚本做了什么

安全加固

禁用 SSH 密码登录

默认情况下服务器允许用密码 SSH 登录,这是暴力破解的入口。脚本会将其关闭,只允许密钥登录:

PasswordAuthentication no
PermitRootLogin prohibit-password

⚠️ 写了不等于生效:一定要用 sshd -T 验证

这两行写进 /etc/ssh/sshd_config.d/70-hardening.conf、sshd -t 语法检查通过、 reload 也成功了——但实际可能根本没生效。

因为 sshd 的配置优先级是「第一个出现的值赢」,而 drop-in 目录按字典序加载。 云厂商镜像(cloud-init、阿里云 swas)经常往 50-cloud-init.conf 里塞一行 PasswordAuthentication yes,它排在 70- 前面,永远压过你的加固配置:

/etc/ssh/sshd_config.d/50-cloud-init.conf   PasswordAuthentication yes   ← 这个赢
/etc/ssh/sshd_config.d/70-hardening.conf    PasswordAuthentication no    ← 轮不到

这跟 nginx / systemd 的 drop-in 语义(后面覆盖前面)正好相反,极容易想当然。 主配置里如果在 Include 之前已经设了同名指令,也会赢过 drop-in。

所以改完必须看最终生效值,而不是自己写的文件内容:

sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|kbdinteractive)'

还有两个容易漏的点:

  • KbdInteractiveAuthentication 要一起关。只关 PasswordAuthentication 的话,某些 PAM 配置下键盘交互认证仍能走密码,等于没关。
  • PermitRootLogin 用 prohibit-password 而不是 no。备份拉取、反向隧道 这类自动化经常以 root + 密钥运行,一刀切 no 会把它们全打断。

动手前先确认你能用密钥登录(ssh -o PreferredAuthentications=publickey <host>), 改完用一个新终端验证能进去再关掉当前会话——否则就是把自己锁在门外。

fail2ban — 自动封禁暴力破解

安装后,10 分钟内 SSH 登录失败 5 次,该 IP 自动封禁 1 小时:

fail2ban-client status sshd
# 查看已封禁的 IP 列表

如果你改过 SSH 端口,jail 里的 port 必须跟着改——默认配置写的是 port = ssh (即 22),你把 sshd 挪到 8822 之后,fail2ban 拦的还是 22,等于没装:

# /etc/fail2ban/jail.local —— 用 jail.local 而不是改 jail.conf,后者会被包更新覆盖
[sshd]
enabled = true
port    = 8822          # 跟 sshd -T | grep '^port' 的结果对齐
backend = systemd

[DEFAULT]
# 别把自己关外面:本机 / 内网 / Tailscale 网段永不封禁
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 100.64.0.0/10

⚠️ 最坑的一点:装完必须 restart,enable --now 不算

apt install fail2ban 之后服务会自动启动。如果你像大多数教程那样按 「装包 → 写 jail.local → systemctl enable --now fail2ban」的顺序操作, 最后那步对一个已在运行的服务是空操作——你的配置根本没被读取。

后果是 jail 还用着默认的 port = ssh(22)。我把 sshd 挪到了 8822,于是防火墙 规则长这样:

f2b-sshd  tcp  --  0.0.0.0/0  0.0.0.0/0  multiport dports 22
                                                         ^^ 一个没人用的端口

表面上一切正常:服务 active、fail2ban-client status sshd 显示封了 2 个 IP。 但日志里那个 IP 反复出现 already banned,然后每 11 秒又打进来一次—— 封禁记在 fail2ban 的账上,却没落到防火墙上。

sudo systemctl restart fail2ban    # 不是 enable --now

restart 之后规则挂到 8822,4 分钟内 REJECT 计数从 3 涨到 24 包, sshd 日志里那个 IP 再没出现过。

怎么确认它真的在拦(别只看 status 的封禁数):

# 1. jail 实际认的端口,跟 sshd 对不对得上
sudo fail2ban-client -d | grep -oE "\['port', '[0-9]+'\]"
sudo sshd -T | grep '^port'

# 2. 防火墙规则的计数器在不在涨(涨 = 真的在丢包)
sudo iptables -L f2b-sshd -n -v        # iptables 后端
sudo nft list chain inet f2b-table f2b-sshd   # nftables 后端(Debian 12+ 默认)

注意别用 grep iptables 去验证——Debian 12 起 fail2ban 默认走 nftables, 查 iptables 什么也看不到,会让你以为坏了。

顺便给个真实的量级参考:我那台阿里云机器半个月被打了 389219 次,但来源只有 47 个 IP,其中一个就占了 60%(234954 次)。这种「少数 IP 高频死磕」正是 fail2ban 最擅长的场景——封掉头部几个,日志立刻安静下来。

不过要明确:fail2ban 是降噪,不是防线。真正让你睡得着的是密码认证已经关掉—— 对方无论试多少次都撞不开,因为他没有私钥。fail2ban 只是让你不用在满屏的失败日志里 找真正的问题。

防火墙

只开放必要端口:SSH(22)、HTTP(80)、HTTPS(443),其余全部拒绝。Ubuntu/Debian 用 UFW,RHEL/Fedora 用 firewalld。


系统配置

时区:设置为 Asia/Shanghai,让日志时间可读。

Swap:内存不足 2GB 时自动创建 2GB swap 文件,避免 OOM 杀掉进程。swappiness=10 让系统尽量用内存而不是 swap。


基础工具

工具 用途
htop 交互式进程监控,比 top 好用
ncdu 磁盘使用分析,找大文件神器
mtr 网络路由追踪,比 traceroute 直观
jq 命令行 JSON 处理,调试 API 必备
tree 目录结构可视化

现代 CLI 工具

这些是对传统命令的现代替代,用过就回不去:

工具 替代 亮点
bat cat 语法高亮、行号、Git 变更显示
fd find 语法简单,速度快,默认忽略 .git
rg(ripgrep) grep 极速全文搜索,自动忽略 .gitignore
fzf 无 模糊搜索,Ctrl+R 搜历史命令神器
zoxide cd 记录访问历史,z proj 直接跳到常用目录
duf df 磁盘使用一览,颜色区分、单位自动换算
tldr man 命令速查手册,只看常用例子
lazydocker docker 命令 Docker TUI,不用记命令就能管容器

几个常用例子:

# 搜索当前目录所有包含 "error" 的文件
rg "error"

# 找所有 .go 文件
fd -e go

# 查看磁盘使用
duf

# 跳到之前去过的目录(不用记完整路径)
z baiye

# tldr 查命令用法
tldr tar
tldr docker

Docker

使用官方安装脚本,支持所有主流发行版:

curl -fsSL https://get.docker.com | sh

zsh + oh-my-zsh

脚本安装 zsh 并配置:

  • zsh-autosuggestions:根据历史记录自动补全,按 → 采纳
  • zsh-syntax-highlighting:命令正确时高亮绿色,错误时红色
  • fzf 集成:Ctrl+R 模糊搜索历史,Ctrl+T 搜索文件

SSH 登录时自动进入 tmux,断线后 session 保持,重连直接 attach。


tmux 配置

主要改动:

快捷键 功能
Ctrl+A 前缀键(替代默认的 Ctrl+B,更顺手)
`Ctrl+A + `
Ctrl+A + - 上下分屏
鼠标 可以点击切换 pane,滚轮翻历史

vim 配置

基础但够用:相对行号、语法高亮、4 空格缩进、鼠标支持、搜索高亮。


脚本支持的发行版

发行版 版本
Ubuntu 20.04 / 22.04 / 24.04
Debian 11 / 12
CentOS / Rocky / AlmaLinux 8 / 9
Fedora 36+
Arch Linux 滚动更新

运行之后

重新 SSH 登录,你会看到:

  • shell 变成 zsh,命令有颜色和自动补全
  • 自动进入 tmux session
  • z、bat、fd、rg 等命令直接可用

查看 fail2ban 状态:

fail2ban-client status sshd

查看防火墙规则:

ufw status          # Ubuntu/Debian
firewall-cmd --list-all  # RHEL/Fedora

延伸阅读