编辑
2025-11-27
Linux备份教学
00
请注意,本文编写于 56 天前,最后修改于 56 天前,其中某些信息可能已经过时。

目录

新到手的 Linux 服务器,我这样设置
概要#
重装系统#
选择脚本#
执行脚本#
安装常用软件包#
安装 Docker#
安装 Nginx#
SSH 基本加固#
配置 Fail2ban#
SSH 守护配置#
配置 UFW 防火墙#
设置默认策略#
Cloudflare 回源访问规则#
计划任务#
防止 Docker 在 UFW 上打洞#

新到手的 Linux 服务器,我这样设置

目录

  • 概要
  • 重装系统
    • 选择脚本
    • 下载脚本
    • 执行脚本
  • 安装常用软件包
    • 基本工具包
    • 安装 Docker
    • 安装 Nginx
  • SSH 基本加固
  • 配置 Fail2ban
    • 安装 Fail2ban
    • SSH 守护配置
    • 启动 Fail2ban
    • 检查配置
  • 配置 UFW 防火墙
    • 安装 ufw
    • 设置默认策略
    • Cloudflare 回源访问规则
    • 启动 ufw 服务
    • 检查 ufw 规则
    • 计划任务
  • 防止 Docker 在 UFW 上打洞

概要#

本文介绍每次上手一台新的 Linux 服务器后,我的一些 基本设置步骤 ,包括:

  • 使用一键 DD 脚本重装纯净的 Debian GNU/Linux 操作系统
  • SSH 安全和 Fail2ban 设置
  • 配置 UFW 防火墙
  • 安装 Nginx Web 服务器
  • 安装 Docker CE 及必要插件
  • 使用 Cloudflare CDN 保护服务和全球加速

并不一定适合所有人的需求,仅作为我每次快速设置新服务器的速查手册。

重装系统#

选择脚本#

网络上支持一键 DD 重装系统的脚本有很多,我主要使用这两个:

  1. bin456789/reinstall
  2. bohanwood/debi

前者支持的系统选择更多,后者则专注于 Debian GNU/Linux 的最小发行版。两者都在 GitHub 上开源,且经过长期的社区关注和审查,安全性大可以放心。

无论如何,在正式开始之前,仔细阅读一遍脚本作者的说明(文档说明详细易读),知道自己在做什么,预期会出现什么。

我在所有服务器上都一直使用 Debian,下面以 debi 脚本为例。

下载脚本#

curl -fLO https://raw.githubusercontent.com/bohanyang/debi/master/debi.sh

执行脚本#

赋予脚本可执行权限

chmod +x debi.sh

开始重装系统

sudo ./debi.sh \ --version 13 \ --architecture arm64 \ --cloudflare \ --user viamoe \ --authorized-keys-url https://github.com/githubUserName.keys \ --ssh-port 22122 \ --bbr

上面参数的意义:

  • --version 13

指定 Debian 13(代号 Trixie)为安装的版本

  • --architecture arm64

指定系统架构,这里的 arm64,只适用于 ARM64 架构的机器(比如甲骨文 ARM VPS)

  • --cloudflare

使用 Cloudflare 作为系统默认 DNS

  • --user viamoe

创建一个普通用户,用户名为 viamoe,脚本自动配置该用户的 sudo 权限

  • --authorized-keys-url https://github.com/githubUserName.keys

指定 SSH 公钥 URL 来源,用于设置 SSH 免密码登录

  • --ssh-port 22122

修改 SSH 默认端口为 22122,你应当修改它,减少被自动扫描攻击的风险

  • --bbr

启用 BBR(TCP 拥塞控制算法),提升网络在高延迟或跨国网络环境下传输性能

一切就绪,开始重装系统

sudo reboot

期间你可以使用 VNC 查看系统安装进度,根据服务器性能或网络环境,稍等几分钟,新的系统即将就绪。之后,使用重装阶段预设的用户名密码或 SSH 密钥登录服务器。

安装常用软件包#

我们的服务器正在运行的是一个纯净、最小、最新的 Debian GNU/Linux 操作系统,需要安装一些基础或常用的软件包。

基本工具包#

sudo apt update sudo apt install \ ca-certificates \ apt-transport-https \ man \ build-essential \ git \ curl \ wget \ unzip \ screen \ btop \ net-tools \ tree \ neovim

安装 Docker#

参考 Docker 官方文档 说明的步骤,下列命令不保证时效性

# Add Docker's official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl status docker

安装 Nginx#

同样地,参考 Nginx 项目文档——在 Debian 上的 安装步骤

# install the prerequisites sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring # import gpg key curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null # verify gpg key mkdir -m 700 ~/.gnupg gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ http://nginx.org/packages/debian `lsb_release -cs` nginx" \ | sudo tee /etc/apt/sources.list.d/nginx.list # install nginx sudo apt update sudo apt install nginx # start nginx sudo systemctl start nginx

SSH 基本加固#

编辑 SSH 配置文件

sudo nvim /etc/ssh/sshd_config

这里有一些我们需要关注的配置项目:

  • Port 22122

SSH 服务监听的默认端口,我们已在重装脚本中指定

  • PermitRootLogin no

禁止 Root 用户直接登录,使用普通用户登录,使用 sudo 提权

  • PasswordAuthentication no

禁止使用密码登录 SSH,我们应当使用密钥对或实体安全密钥(如 Yubikey、Canokey 等)进行登

  • PermitEmptyPasswords no 禁止空密码登录

  • ChallengeResponseAuthentication no 禁用键盘交互式密码认证

  • PubkeyAuthentication yes 启用公钥认证,此前已在重装脚本中指定

  • UseDNS no 禁用 DNS 反查

  • X11Forwarding no 禁用 X11 转发,如果你不知道这是什么那就可以禁用

保持当前的 SSH 会话不要断开连接,重启 SSH 服务

sudo systemctl restart sshd

重开一个 SSH 会话,再次登录当前服务器,确保连接正常,否则返回第一个 SSH 会话中进行检查。

配置 Fail2ban#

使用 Fail2ban 保护我们的服务器免受 SSH 爆破,并合理封禁异常的 IP 地址

安装 Fail2ban#

sudo apt update sudo apt install fail2ban

SSH 守护配置#

创建一个最小的,仅用于守护 SSH 登录的 Fail2ban 配置文件

sudo nvim /etc/fail2ban/jail.local

配置内容如下:

[DEFAULT] # 忽略 IP 地址:防止将自己封禁。 # 如果您使用动态 IP,不要设置您的公网 IP。 # 127.0.0.1/8 和 ::1 忽略本地回环地址。 ignoreip = 127.0.0.1/8 ::1 # 封禁时间:封禁 1 小时(3600 秒) bantime = 1h # 查找时间:在 10 分钟内(600 秒) findtime = 10m # 最大重试次数:如果在 findtime (10 分钟) 内失败了 3 次,则封禁。 maxretry = 3 [sshd] # 启用 SSH 保护 enabled = true # SSH 服务的监听端口:确保这里设置为您的自定义端口 22122 port = 22122 # 日志文件路径:Debian/Ubuntu/CentOS 通常使用 auth.log,默认配置会自动检测。 # logpath = /var/log/auth.log # filter:使用默认的 sshd 过滤器(无需修改) # filter = sshd

启动 Fail2ban#

sudo systemctl enable fail2ban sudo systemctl restart fail2ban

检查配置#

sudo fail2ban-client status sshd sudo fail2ban-client status

如果输出显示 Jail status: ... Status: running,在 Jail list 中看到了 sshd,应该就配置成功了。

配置 UFW 防火墙#

安装 ufw#

sudo apt install ufw

设置默认策略#

默认拒绝所有传入/入站连接

sudo ufw default deny incoming

默认允许所有传出/出站连接

sudo ufw default allow outgoing

现在大多数服务器有 IPv6 公网 IP,启用 IPv6 支持

sudo sed -i 's/IPV6=no/IPV6=yes/' /etc/default/ufw

允许 SSH 传入/入站连接

千万不要忘记 SSH 端口,以免自己被「锁在」UFW 外面!

# 替换为实际 SSH 端口 sudo ufw allow 22122/tcp

Cloudflare 回源访问规则#

Nginx 默认监听端口 80(HTTP) 和 443(HTTPS),要允许 Cloudflare CDN 回源访问,必需将 Cloudflare IP 段添加到 UFW 白名单里。

新建一个 Cloudflare IPs 自动更新脚本

sudo nvim /usr/local/bin/ufw-cf-whitelist

该脚本用于:

  • 移除之前旧的 Cloudflare IP 白名单规则
  • 获取 Cloudflare 最新的 IPv4 和 IPv6 列表
  • 允许列表中每个 IP 段访问 80/443 端口

脚本内容如下:

#!/bin/bash # Cloudflare 官方 IP 列表 IPV4_URL="https://www.cloudflare.com/ips-v4" IPV6_URL="https://www.cloudflare.com/ips-v6" echo "=== 1. 清除现有的 Cloudflare UFW 规则..." # 清除旧的规则(通过删除带有 "Cloudflare" 注释的规则) # 注意:UFW 不直接支持注释删除,所以这个步骤需要手动或使用更复杂的工具, # 这里我们采用简单的清理,如果规则不多,可以手动检查 `ufw status numbered`。 # 更好的方法是在每次运行前删除所有 80/443 的 ALLOW 规则,但风险更高。 # 暂时只删除明确的 Cloudflare 规则,以防万一 # sudo ufw delete allow in on any to any port 80/tcp # sudo ufw delete allow in on any to any port 443/tcp echo "=== 2. 下载最新的 Cloudflare IP 范围列表..." # 使用 tempfile 确保下载的文件安全 IPV4_TEMP=$(mktemp) IPV6_TEMP=$(mktemp) curl -s $IPV4_URL -o $IPV4_TEMP curl -s $IPV6_URL -o $IPV6_TEMP echo "=== 3. 添加 IPv4 规则 (80/443)..." while read ip; do if [[ ! -z "$ip" ]]; then sudo ufw allow proto tcp from $ip to any port 80 comment 'Cloudflare IPv4 HTTP' sudo ufw allow proto tcp from $ip to any port 443 comment 'Cloudflare IPv4 HTTPS' fi done < $IPV4_TEMP echo "=== 4. 添加 IPv6 规则 (80/443)..." while read ip; do if [[ ! -z "$ip" ]]; then sudo ufw allow proto tcp from $ip to any port 80 comment 'Cloudflare IPv6 HTTP' sudo ufw allow proto tcp from $ip to any port 443 comment 'Cloudflare IPv6 HTTPS' fi done < $IPV6_TEMP echo "=== 5. 清理临时文件..." rm $IPV4_TEMP $IPV6_TEMP echo "=== 6. 完成 Cloudflare 白名单配置。" ufw status numbered

赋予脚本可执行权限

sudo chmod +x /usr/local/bin/ufw-cf-whitelist

执行脚本,更新 ufw 规则

sudo ufw-cf-whitelist

启动 ufw 服务#

sudo ufw enable sudo ufw reload

若是提示:

Command may disrupt existing ssh connections. Proceed with operation (y|n)?

检查 ufw 规则#

sudo ufw status numbered

计划任务#

实际上 Cloudflare IP 段几乎很少变动(最起码最近两年多完全没有变化),因此这个步骤不是必须的。使用 Crontab 计划:

sudo crontab -e

比如每天凌晨 3 点执行一次

0 3 * * * /usr/local/bin/ufw-cf-whitelist.sh > /dev/null 2>&1

防止 Docker 在 UFW 上打洞#

这个 check-if-docker-break-ufw.sh 脚本用于检查是否出现了这种情况

#!/usr/bin/env bash # =============================================================== # check-docker-ports.sh # 检查 Docker 容器端口暴露与 UFW 状态 # =============================================================== RED="\033[0;31m" GREEN="\033[0;32m" YELLOW="\033[1;33m" RESET="\033[0m" echo "🔍 正在检查 Docker 端口暴露情况..." echo "==============================================================" # 获取 docker ps 输出 docker_ps=$(docker ps --format '{{.Names}}|{{.Ports}}') if [ -z "$docker_ps" ]; then echo "❌ 没有正在运行的容器。" exit 0 fi printf "%-25s %-25s %-20s\n" "容器名" "绑定地址" "状态" echo "--------------------------------------------------------------" while IFS='|' read -r name ports; do if [[ -z "$ports" ]]; then printf "%-25s %-25s ${GREEN}%-20s${RESET}\n" "$name" "无对外端口" "安全" continue fi # 分析每个映射 for port in $(echo "$ports" | tr ',' '\n'); do port=$(echo "$port" | sed 's/ //g') if [[ "$port" =~ 0\.0\.0\.0 ]]; then printf "%-25s %-25s ${RED}%-20s${RESET}\n" "$name" "$port" "⚠️ 公网暴露" elif [[ "$port" =~ 127\.0\.0\.1 ]]; then printf "%-25s %-25s ${GREEN}%-20s${RESET}\n" "$name" "$port" "本机安全" else printf "%-25s %-25s ${YELLOW}%-20s${RESET}\n" "$name" "$port" "内部网络" fi done done <<< "$docker_ps" echo "--------------------------------------------------------------" echo "🧱 检查宿主机端口监听状态..." ss -tlnp | grep -E 'docker|LISTEN' | awk '{print $4, $6}' | sed 's/users://g' | sed 's/"//g' | sed 's/,//g' | sed 's/\[::\]://g' echo "--------------------------------------------------------------" echo "🧩 检查 UFW 规则..." sudo ufw status numbered echo "==============================================================" echo "✅ 检查完成。绿色=安全,黄色=内部安全,红色=公网暴露。"

最简单的方式,不要将任何 Docker 容器的端口绑定到 0.0.0.0 上,只需将暴露端口绑定到 127.0.0.1 上即可。

(完)

本文作者:口水

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!