作者:焕昭君 原帖地址:https://blog.huan666.de/posts/server-website-getting-started/
前言#
作者搜集各类教程自己边折腾边记录整理了以下这篇文章内容。本文概要:
- 从零开始,由浅入深地介绍配置服务器到网站上线的全流程指南。本文涵盖了终端软件选择、SSH配置、系统优化、安全加固、Docker和Nginx部署、域名和Cloudflare配置等核心内容。
- 实操性强:包含大量命令行示例、配置文件范例和一键脚本,能够直接复制使用。
- 内容详细:文章内容层次分明,逻辑清晰。不仅告诉你”怎么做”,还解释”为什么”。引用大量参考文献,便于更深入研究
- 解决常见痛点:SSH安全加固、VSCode增强远程连接、docker与ufw防火墙兼容、彻底隐藏源站IP、从Cloudflare获取原始访客IP等等
终端软件#
为了更好使用命令行和 SSH 连接服务器管理,一个好的终端软件必不可少。以下推荐几个软件(个人主观次序排名):
Tabby#
- 开源免费
- 简洁美观
- 支持SSH和SFTP
- 用于纯命令行很舒服,该有功能不少,没有太多繁杂的花里胡哨,看着也美观舒心。

FinalShell#
- 闭源+基础免费/增值付费
- 简洁,简单显示必要信息
- 支持SSH和SFTP
- 特点:底部有命令输出框和方便使用的SFTP

Termora#
- 开源免费
- 极简
- 支持SSH和SFTP
- 比上面的Tabby简陋,喜欢极简的可以尝试。

Termius#
- 没有简体中文
- 闭源+大部分功能收费(如代理设置)
- 多端数据同步,无缝切换
- 现代化UI、高颜值
如果愿意付费的话,亦是一个不错的选择。

Xterminal#
- 闭源+基础免费/增值付费(换肤要钱)
- 功能丰富,但也非常繁杂和花里胡哨,一般我不用。

参考文章:
SSH 客户端收集 – 砖头@runbrick – LINUX DO
其他的,在这篇文章有人搜集了很多客户端软件
SSH远程连接#
阅读完前面相信你已经选上一个好的软件用于 SSH 来连接你的服务器了吧。想要使用 SSH 连接服务器首先要知道以下这几个概念:
- 主机地址:即
IP地址或域名 - 端口:默认是
22,但你的服务商可能有所不同,还有网络策略组会限制端口放行。默认端口数字不安全,下文会介绍到如何修改端口 - 用户:登录的用户,默认一般是
root,这通常不安全,下文-系统安全配置会详细介绍怎么修改用户。 - 密码密钥:验证登录所需。常见是直接使用密码,但不安全,后续会关闭密码而使用密钥🔐
尽管软件提供可视化页面方便操作,但接下来我会展示命令操作,概念原理是一致的,理解了命令其他就简单了。
基础命令#
#默认22端口连接
ssh <user>@<HostIP>
ssh <user>@<HostName>
#指定端口连接
ssh <user>@<HostName> -p <port>
#指定密钥文件
ssh <user>@<HostName> -p <port> -i <filePath>
密钥登录#
1、生成公私密钥对#
选取 ed25519[这是什么?- Gemini深度研究🧐] 这个现代安全且高效的加密算法,在自己电脑生成密钥对。
⚠️警告
注意⚠️:如果之前有生成过密钥对或者用过其他的SSH服务如GitHub免密登录,小心密钥对被覆盖导致失效!请使用-f指定路径和文件名
ssh-keygen -t ed25519
#指定文件名
ssh-keygen -t ed25519 -f ~/.ssh/my_key_ed25519
#或在Windows PowerShell下使用:
ssh-keygen -t ed25519 -f $HOME\.ssh\my_key_ed25519
#添加注释
ssh-keygen -t ed25519 -f $HOME\.ssh\my_key_ed25519 -C "注释"
#为密钥设置密码
ssh-keygen -t ed25519 -f $HOME\.ssh\my_key_ed25519 -N "your_passphrase" -C "[email protected]"
然后就会生成私钥id_ed25519和公钥id_ed25519.pub,把公钥上传到服务器。
2、上传公钥#
两种方式,一是命令自动上传、二是手动编辑,无论哪种方法最终是要把公钥追加保存在对应用户主目录的 ~/.ssh/authorized_keys 文件。
ssh-copy-id 命令#
#Linux、macOS
ssh-copy-id -i key_file user@host
很遗憾,window并不直接支持。
编辑 authorized_keys 文件#
1.手动编辑:
mkdir ~/.ssh
vi ~/.ssh/authorized_keys 或 echo "<复制的公钥粘贴到这里>" >> ~/.ssh/authorized_keys
或者自动上传编辑:
#在windows下(但追加的密钥的中文注释会乱码)
type $HOME\.ssh\filename.pub -Encoding UTF8 | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
#Linux或macOS
cat ~/.ssh/filename.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys
2.设置权限
chown -R username:somegroup ~/.ssh #设置文件所有者(如果配置者和所有者不同)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
#查看权限
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
3、进行连接#
#指定客户端本机的对应私钥文件
ssh <user>@<HostName> -p <port> -i <filePath>
更多操作比如关闭密码登录等具体看配置文件的设置
日志查看:#
#系统使用Systemd,可以使用journalctl命令查看日志
journalctl -u ssh
journalctl -u ssh | code - #使用VSCode打开缓存的日志
查看最近一天的SSH日志并统计处理缓存输出到VSCode(去掉| code -直接输出到命令行)
(
CMD="sudo journalctl -u ssh -r --since -1d"
echo "=== 密码失败登录尝试总数 ==="
$CMD | grep "Failed password" | wc -l
echo -e "\n=== 其他登录错误总数 ==="
$CMD | grep "error:" | wc -l
echo -e "\n=== 按 IP 统计密码失败尝试 ==="
$CMD | grep "Failed password" | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr
echo -e "\n=== 按 IP 统计其他错误尝试 ==="
$CMD | grep "error:" | awk '{for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) {print $i; break}}' | sort | uniq -c | sort -nr
echo -e "\n=== 按用户名统计的失败尝试 ==="
$CMD | grep "Failed password" | awk '{for(i=1;i<=NF;i++) if($i=="for") print $(i+1)}' | sort | uniq -c | sort -nr
echo -e "\n=== 最近25次失败尝试 ==="
$CMD | grep -E "(Failed password|error:)" | tail -25
) | code -
配置文件#
SSH的配置文件不仅有服务端,还有客户端的。
SSH服务端#
SSH服务端配置文件路径:/etc/ssh/sshd_config,注意⚠️是否有/etc/ssh/sshd_config.d文件夹📂下配置覆盖生效。
想要密钥连接确保以下配置设置(一般默认不用改)
#PubkeyAuthentication yes
#AuthorizedKeysFile .ssh/authorized_keys
关闭密码登录
🚨小心
警告⚠️!!!关闭前请确保你能密钥登录成功!妥善保管好私钥!以防云服务器失联!
PasswordAuthentication no
重启和应用服务端配置文件
#1.测试配置文件是否有语法错误
sudo sshd -t
#2.使用systemctl 重启 SSH 服务
sudo systemctl restart sshd
#或
sudo systemctl restart ssh
#或老旧系统使用service
sudo service sshd restart
#3.验证重启是否成功-检查 SSH 服务状态,确保它正在运行
sudo systemctl status sshd
#或
sudo systemctl status ssh
SSH客户端#
本地主机的 ~/.ssh下还存在config和信任主机列表known_hosts
config文件举例:
Host *
Port <端口>
# 每隔 60 秒自动发送一个 keepalive 信号以保持连接
ServerAliveInterval 60
# 断开时重试连接的次数
ServerAliveCountMax 15
Host <自定义别名>
HostName <服务器地址>
Port <端口>
User <用户名>
IdentityFile <私钥路径>
Host *表示对所有主机生效,设置了端口对所有主机配置项都生效。IdentityFile指定私钥路径。这下VSCode不用每次远程连接手动输入密码了,自动验证登录。
VSCode远程连接#
只要安装了VSCode远程系列插件就能使用VSCode的SSH功能远程连接服务器,有时候不想使用 Vim 或者不熟悉它,就能用”宇宙第一编辑器“──VSCode来查看和编辑服务器的文件了,实在太方便了
缺点:貌似服务器内存占用不低🙁,内存小的小鸡很可能无法承受….😫
测试脚本#
整到一台服务器首先要干的事情是什么?当然是立马上鸡测试一下配置!CPU、内存硬盘的性能,IP质量、网络质量等。
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
NodeScriptKit – nodeseek社区驱动脚本合集
bash <(curl -sL https://sh.nodeseek.com)
NodeQuality – 沙箱测试并排版测试结果
bash <(curl -sL https://run.NodeQuality.com)
在 【存档】Netcup的RS1000硬盘翻倍版的测试和一些测试脚本的使用 中我使用过一些测试脚本测试了我的rs1000小鸡,详细可以去看看~
重装系统#
使用一键DD重装脚本[什么是DD脚本?- Gemini深度研究🧐],比较出名的有三个:
① leitbogioro/Tools 和搭配 黑海洋Wiki 的文章
② bin456789/reinstall 这个更加整洁和方便,直接下载官方源,而且近期有更新。
③ LloydAsp/OsMutation 这个脚本适用于 OpenVZ / LXC 虚拟化技术的 VPS
bin456789/reinstall:#
下载(Linux):
国外服务器:
curl -O https://raw.githubusercontent.com/bin456789/reinstall/main/reinstall.sh || wget -O reinstall.sh $_
国内服务器:
curl -O https://cnb.cool/bin456789/reinstall/-/git/raw/main/reinstall.sh || wget -O reinstall.sh $_
安装 Debian12 改SSH端口和设置 root 密码,仅供参考命令:
bash reinstall.sh debian 12 --password 你的密码 --ssh-port 你的端口
更多请参阅 GitHub文档 …
重装完服务器系统紧接着就是要配置系统了Gemini深度研究🧐和导出文档。第一时间就要去修改SSH配置如端口、密码和公私钥设置等和创建非root新用户。
系统配置#
基础优化#
更新系统的软件包#
apt update && apt upgrade -y
安装一些常用的基础工具#
如sudo、手册、网络、git、文件管理、系统监控、防火墙等,可以方便后续的管理操作
apt install sudo man-db curl wget telnet iperf3 git vim tree htop ufw -y
语言、地区和时区#
locale
sudo update-locale LANG=en_US.UTF-8
timedatectl
sudo timedatectl set-timezone Asia/Shanghai
IP地址#
直接查看本地 IPv6 地址
ip -6 addr show
服务器主要对外网卡的那个IP一般就是本机IPV6了
或简化版:
ip a | grep inet6
你会看到类似:
inet6 2408:xxxx:xxxx::xx/64 scope global
其中scope global就是你的公网IPv6类型地址(不是fe80::...这类链路本地地址)。
查询外网看到的 IPv6(公网出口地址)
使用curl等方式直接访问外网服务:
curl -6 ifconfig.co
curl -6 ip.sb
curl -6 icanhazip.com
SWAP-虚拟内存#
SWAP可以优化内存的使用,延缓内存压力,对于内存小的系统帮助很大。(用一定的硬盘、IO换取内存,硬盘配置差的小鸡不建议开启)
有两个一键自动脚本:spiritLHLS的 addswap 和 woniu336/open_shell – swap.sh,根据具体情况测验后谨慎使用。下面是说明纯手动配置的方法步骤。
检查现有SWAP#
sudo free -h #查看当前内存
sudo swapon --show #查看当前启用的SWAP
cat /proc/swaps
创建SWAP文件#
关于创建SWAP是选择创建分区还是创建文件,我最终选择创建SWAP文件的方式
因为SWAP分区虽可能性能更好但创建需预留未分配空间来硬盘分区,操作繁琐,非常不灵活,后续调整大小麻烦,有一定风险。而SWAP文件更加灵活、可以随时创建、删除或调整大小;管理方便,不需要处理分区表。
#1️⃣创建一个8GB大小的SWAP文件:
#这个大小根据个人所需自定义,后续也能修改。众说纷纭,有说一半也有说1~2倍,我的服务器8G内存
#`fallocate`和`dd`命令二选一
sudo fallocate -l 8G /swapfile #快速预分配磁盘空间,仅支持现代文件系统如ext4、XFS、Btrfs
sudo dd if=/dev/zero of=/swapfile bs=1M count=8192 #(耗时较长)
#2️⃣权限设置
sudo chown root:root /swapfile # 修改所有者为 root
sudo chmod 600 /swapfile # 设置权限:仅允许root读写
sudo ls -lh /swapfile # 检查文件的权限和大小是否符合预期
#3️⃣文件格式化为SWAP
sudo mkswap /swapfile
sudo file /swapfile # 验证是否为 "Linux swap file"
#4️⃣启用SWAP(目前只是临时的)
sudo swapon /swapfile
#5️⃣永久启用:系统重启时自动激活SWAP:编辑/etc/fstab
#1.备份原文件
sudo cp /etc/fstab /etc/fstab.bak
#2.将SWAP文件配置信息追加到`/etc/fstab`文件末尾
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
#3.检查一下
sudo blkid /swapfile
sudo reboot #重启一下看看是否持久化了
#6️⃣验证
sudo free -h #查看当前内存
sudo swapon --show #查看当前启用的SWAP
cat /proc/swaps
#7️⃣设置SWAP策略:vm.swappiness值(可选)
#1.查看当前值(默认60)
cat /proc/sys/vm/swappiness
sudo sysctl vm.swappiness
#2.临时更改 (用于测试):系统重启后失效
sudo sysctl vm.swappiness=40
#3.永久更改 (重启后保持生效)
sudo cp /etc/sysctl.conf /etc/sysctl.conf.bak #备份源文件
echo 'vm.swappiness=40' | sudo tee -a /etc/sysctl.conf
sudo sysctl --system #显示即将应用的参数(不实际执行),验证配置正确性
sudo sysctl -p #立即应用内核参数调整
修改SWAP大小#
停用 → 删配置 → 删文件
#1️⃣停用SWAP
sudo swapoff -a # 停用所有SWAP
sudo swapoff /swapfile # 停用SWAP文件:在调整Swap大小或删除前需要先执行此操作
sudo swapon --show # 确认 Swap 已禁用(无输出或无 /swapfile)
free -h # 检查 Swap 是否归零
#2️⃣删除旧文件和删除`/etc/fstab`对应配置
#⚠️警告!在删除旧swap文件后请立即移除`/etc/fstab`中的配置!避免系统后续意外可能崩溃!
sudo rm /swapfile # 删除旧文件(确保已禁用 Swap)
sudo sed -i '/\/swapfile/d' /etc/fstab # 从 /etc/fstab 移除
sudo grep -i swapfile /etc/fstab # 检查
#3️⃣重复上面👆`创建SWAP文件`的操作
删除SWAP#
重复上面👆修改SWAP大小的操作1️⃣和2️⃣
额外的关于硬盘与分区?#
#硬盘分区
sudo blkid
lsblk
sudo fdisk -x
df -hT
zRAM – 压缩内存#
zRAM 是一种在 RAM 中创建的压缩交换空间,而 SWAP 文件是硬盘上的交换空间。读写性能上 zRAM 在内存上比SWAP 在硬盘快很多,但需要一定CPU开销作为代价。(用CPU换内存,吃CPU,CPU配置差的小鸡不建议开启)
压缩算法主要是二选一:zstd 压缩率高而速度相对慢(接近三倍的压缩率),而 lz4 速度快很多(2.1 的压缩率,而速度是前者的几倍)。
有两个一键配置脚本:spiritLHLS – addzram 和 woniu336/open_shell – zram_manager.sh 请根据具体情况测验后谨慎使用。下面是说明纯手动配置的方法步骤。
手动配置zRAM#
#1️⃣开启/加载 zRAM 模块
sudo modprobe zram num_devices=1
lsmod | grep zram
#持久化:开机自动开启/加载 zRAM 模块
echo "zram" | sudo tee -a /etc/modules-load.d/zram.conf
echo "options zram num_devices=1" | sudo tee -a /etc/modprobe.d/zram.conf
#2️⃣配置 zRAM
#⚠️警告!:必须按照`指定压缩算法再指定大小`的顺序配置!
sudo cat /sys/block/zram0/comp_algorithm #查看压缩算法
sudo cat /sys/block/zram0/disksize #查看压缩大小
echo "zstd" | sudo tee /sys/block/zram0/comp_algorithm #设置压缩算法:lz4 或 zstd
echo "8G" | sudo tee /sys/block/zram0/disksize #设置压缩大小
#持久化:自动进行 zRAM 配置
echo 'KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="8G", TAG+="systemd"' | sudo tee /etc/udev/rules.d/99-zram.rules
#3️⃣挂载 zRAM
sudo mkswap /dev/zram0
sudo swapon -p 2 /dev/zram0
#持久化:自动挂载 zRAM
sudo bash -c 'cat > /etc/systemd/system/zram.service <<EOF
[Unit]
Description=zram
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStartPre=/sbin/mkswap /dev/zram0
ExecStart=/sbin/swapon -p 2 /dev/zram0
ExecStop=/sbin/swapoff /dev/zram0
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable zram.service'
#4️⃣检验
sudo swapon --show #检查一下
free -h #发现是SWAP和zRAM的累和
sudo lsblk
#查看 zRAM 的实际压缩效率
sudo zramctl
sudo zramctl --output-all
sudo cat /sys/block/zram0/mm_stat
sudo awk '{print "压缩率: " ($1/$2)}' /sys/block/zram0/mm_stat
sudo zramctl | awk 'NR>1 {printf "压缩率: %.2fx\n", $4*1024/$5}'
sudo watch -n 1 -c 'bash -c '\''
read -r original compressed <<< $(cat /sys/block/zram0/mm_stat | awk "{print \$1,\$2}");
ratio=$(awk "BEGIN {printf \"%.1fx\", $original/$compressed}");
percent=$(awk "BEGIN {printf \"%.0f%%\", ($compressed/$original)*100}");
echo -e "原始: \e[32m$(numfmt --to=iec --suffix=B $original)\e[0m";
echo -e "压缩: \e[33m$(numfmt --to=iec --suffix=B $compressed)\e[0m";
echo -e "压缩率: \e[36m$ratio\e[0m (\e[35m$percent\e[0m)";
'\'''
#或不支持numfmt,纯awk实现
sudo watch -n 1 -c 'awk '\''
function fmtsize(bytes) {
if(bytes > 1024^3) return sprintf("\033[32m%.1fGB\033[0m", bytes/1024^3);
if(bytes > 1024^2) return sprintf("\033[33m%.1fMB\033[0m", bytes/1024^2);
return sprintf("\033[36m%.1fKB\033[0m", bytes/1024);
}
NR==1 {
printf "原始: %s\n压缩: %s\n压缩率: \033[35m%.1fx\033[0m (\033[31m%.0f%%\033[0m)\n",
fmtsize($1), fmtsize($2), $1/$2, ($2/$1)*100;
}
'\'' /sys/block/zram0/mm_stat'
手动修改压缩算法和大小#
# 1. 停用zram
systemctl stop zram.service
sudo swapoff /dev/zram0
# 2. 重置设备
echo 1 | sudo tee /sys/block/zram0/reset
# 3. 设置新算法和大小
echo "lz4" | sudo tee /sys/block/zram0/comp_algorithm
echo "4G" | sudo tee /sys/block/zram0/disksize
# 4. 重新挂载zram
sudo mkswap /dev/zram0
sudo swapon /dev/zram0
# 5. 更新持久化配置
echo 'KERNEL=="zram0", ATTR{comp_algorithm}="lz4", ATTR{disksize}="4G", TAG+="systemd"' | sudo tee /etc/udev/rules.d/99-zram.rules
# 6. 重启服务(如果使用systemd)
sudo systemctl restart zram.service
手动卸载zRAM#
#停止并禁用 zram 的服务
sudo systemctl stop zramswap.service
sudo systemctl disable zramswap.service
#卸载 zram 模块
sudo swapoff /dev/zram0
sudo rmmod zram
#移除/注释相关的 fstab 条目
#如果 /etc/fstab 文件中有关于 zram 的条目,应该将其注释掉或删除
sudo sed -i '/^\/dev\/zram0 none swap/d' /etc/fstab
调优:zRAM与SWAP搭配#
优先级(Priority)#
确保zRAM的优先级高于SWAP即可,这在前面swapon的时候已经设置好了
sudo swapon --show #查看所有SWAP设备
内核参数调优#
通常这三个参数保持默认即可,不调整也没啥问题**???**
具体看 路人甲的世界的这篇文章 关于不同参数调优会有更深理解。
根据文中的推荐,在使用zRAM与SWAP分层共存下:vm.swappiness=100,vm.page-cluster=0(避免不必要的预读和CPU解压缩开销,提高 zRAM 的效率)
| 参数 | 推荐值 | 作用说明 | 适用场景 |
|---|---|---|---|
vm.swappiness /proc/sys/vm/swappiness | 默认:60 保守:10-30 激进:100以上 | 回收文件页和匿名页的权重,越高越积极把匿名页换出zRAM/SWAP | 机械硬盘:默认 SSD:降低值 |
vm.vfs_cache_pressure /proc/sys/vm/vfs_cache_pressure | 默认:100 敏感50 | 调整内核回收 inode/dentry 缓存的倾向。 值越低,保留缓存越多。 | 文件服务器、数据库 |
vm.page-cluster /proc/sys/vm/page-cluster | 默认:3 SSD建议:1 zRAM:0 | 每次 SWAP I/O 预读的页面数(2^n),SSD降低减少开销,zRAM 为0减少CPU开销 | 机械硬盘:默认;SSD:调低 |
# 查看
sudo cat <具体路径>
sudo sysctl <参数名>
# 临时修改
sudo sysctl <参数名>=<数字>
# 永久生效
echo "<参数名>=<数字>" | sudo tee -a /etc/sysctl.conf
sudo sysctl --system
sudo sysctl -p
stress – 压测工具#
stress 是一个常用的系统压力测试工具,用于模拟 CPU、内存、I/O 或磁盘负载,帮助管理员测试系统在高负载下的稳定性。
sudo apt update
sudo apt install stress
sudo apt install stress-ng #更强大的压力测试工具(支持更多选项)
#CPU 压力测试:
stress --cpu 4 --timeout 10s #启动4个进程占用CPU,持续10秒
#内存压力测试:
stress --vm 2 --vm-bytes 1G --timeout 10s #启动2个进程,每个占用1GB内存
stress-ng --vm 1 --vm-bytes 90% --vm-keep --timeout 10s #进程持久占用内存
#磁盘 I/O 压力测试:
stress --io 4 --timeout 10s -v # 启动4个I/O密集型进程
#混合负载:
stress --cpu 2 --io 1 --vm 1 --vm-bytes 512M --timeout 1m
BBR – 网络优化#
BBR 是 Google 提出的一种新型 TCP 拥塞控制算法(Bottleneck Bandwidth and RTT)
特点和作用:提高网络性能和稳定性,显著提高吞吐量和降低 TCP 连接延迟;适应不同网络环境,尤其是高延迟、高丢包网络。目前 BBR 已被集成到 Linux 新版内核中。
BBR 启用#
# 1.备份原有配置(谨慎起见)
sudo cp /etc/sysctl.conf "/etc/sysctl.conf.bak_$(date +%Y%m%d_%H%M%S)"
# 2.启用BBR(无需重启服务器)
printf "%s\n" "net.core.default_qdisc=fq" "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf # 写入两行配置;
sudo sysctl --system # 检查
sudo sysctl -p # 立即生效
# 3.检查是否生效
sudo sysctl net.core.default_qdisc net.ipv4.tcp_congestion_control #应输出`fq`和`bbr`
sudo lsmod | grep bbr # 检查内核模块
iperf3#
iperf3 是一款开源的网络性能测试工具,用于测量带宽、延迟、抖动、丢包率等网络性能指标。它通过发送和接收 TCP/UDP 数据流来评估网络的最大吞吐量,广泛应用于服务器、路由器、VPN、云服务等场景的网络调优和故障排查。
Windows 版本下载,添加iperf3.exe所在路径作为系统环境变量PATH,就能使用iperf3命令了。
#1.安装
sudo apt update && sudo apt install iperf3
#2.启动 iperf3 服务器模式
sudo iperf3 -s # 默认端口:5201
sudo systemctl status iperf3 # 查看状态
#3.防火墙临时允许端口 5201 入站
sudo ufw allow 5201
sudo ufw delete allow 5201 # 测试完之后记得删除规则
sudo ufw status
#4.客户端测试: (确保能访问服务器的 5201 端口,防火墙放行)
# 测试上传 (客户端 -> 服务器):
iperf3 -c <服务器IP>
iperf3 -c <服务器IP> -u -b 100M # 测试100Mbps UDP 上传
# 测试下载 (服务器 -> 客户端): 添加 -R 参数
iperf3 -c <服务器IP> -R
iperf3 -c <服务器IP> -u -b 100M -R # 测试100Mbps UDP 下载
# 常用选项
-s 以服务器模式运行。
-c 以客户端模式运行,连接到指定的主机。
-t 控制测试总时长
-R 反向模式:让服务器发送数据,客户端接收(用于从客户端角度测试下载速度)。
-u 使用 UDP 协议,而不是默认的 TCP。
-b 设置目标比特率(带宽):UDP是必须指定速率,TCP是设置带宽上限。K, M, G 作为单位后缀。
-P 并发数
-p 指定服务器监听或客户端连接的端口号(默认是 5201)。
-i 每次报告时间间隔
#5.停用
sudo systemctl stop iperf3 # 停用服务
sudo systemctl disable iperf3 # 禁止自启
系统安全#
SSH配置#
第一时间修改强密码和端口,使用密钥登录和禁用密码登录。
添加新用户#
adduser 新用户名 #创建新用户
usermod -aG sudo 新用户名 #赋予新用户管理员权限
#切换新用户检测是否添加了管理员权限
su - 新用户名
sudo apt update
如果SSH配置了密钥登录和关闭密码登录,那需要为用户添加公钥
#假如新用户和root用户共用同一个公钥
su - 新用户名
mkdir -p ~/.ssh
sudo cp /root/.ssh/authorized_keys ~/.ssh/authorized_keys
#设置所有者和权限
sudo chown -R 新用户名:新用户名 ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
#检查
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
cat ~/.ssh/authorized_keys
(可选)修改 sudo 生效时间:
sudo visudo /etc/sudoers.d/sudo_timeout
#添加以下的配置项并保存
Defaults timestamp_timeout=30
UFW-防火墙#
UFW(Unfirewall)是一款简单易用的防火墙配置工具,通过简化 iptables 命令帮助用户快速管理网络规则,非常适合初学者使用。服务器和外网中间有一层防火墙防止非法入站流量,比如不开放端口外网无法访问。
❗重要
值得注意⚠️的是:UFW 和 docker 的网络不兼容,需要特殊配置!!!
安装#
sudo apt install ufw
设置默认策略#
🚨小心
⚠️注意:避免锁死 SSH!请开放对应的 SSH 端口!
sudo ufw default deny incoming #默认拒绝所有入站
sudo ufw default allow outgoing #默认允许所有出站
允许开放对应的服务和端口#
#查看所有的应用程序配置文件
#所有配置都在 /etc/ufw/applications.d/,如需修改,前往此目录修改即可。
sudo ufw app list
sudo ufw app info OpenSSH #查看app具体信息
less /etc/services #查看服务和端口
#允许SSH
sudo ufw allow ssh
sudo ufw allow OpenSSH
sudo ufw allow SSH自定义端口/tcp #如果自定义SSH端口
#开放WEB
sudo ufw allow http
sudo ufw allow https
#或
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
查看添加的规则#
⚠️警告
⚠️注意:请检查是否开启 SSH 端口!自定义 SSH 端口是否正确!
sudo ufw show added #查看添加的规则
sudo ufw delete <自定义规则> #删除添加的规则
开启防火墙#
🚨小心
警告⚠️!请再次检查是否允许 SSH 端口!以防被锁住失联
sudo ufw enable #启动
sudo systemctl enable ufw #设置成自动重启
sudo ufw reload #重启
sudo ufw disable #关闭
#检查 UFW 的状态
sudo ufw status verbose
sudo ufw status numbered
sudo systemctl status ufw
UFW具体语法规则在 Ubuntu 的文档wiki 讲的很清楚了;全部语法使用man ufw或sudo ufw --help查看。
日志查看#
# 查看所有被防火墙拦截的网络连接
sudo journalctl -r -g "UFW BLOCK" #倒序查看
sudo journalctl -g "UFW BLOCK" -f #实时查看
Fail2Ban#
Fail2Ban 用于系统防御入侵,保护SSH,自动封禁多次错误的SSH登录防止系统被爆破密码
❗重要
注意⚠️:Debian12及以上因弃用rsyslog,Fail2Ban 直接安装和使用可能会有问题!需要特殊配置!
安装#
sudo apt install fail2ban #安装
#Debian12:检查python3-systemd是否安装(默认和fail2ban一起安装了)
dpkg -s python3-systemd
sudo apt install python3-systemd -y #如果不存在就安装
sudo systemctl start fail2ban #启动
sudo systemctl enable fail2ban #重启后自动运行
sudo systemctl status fail2ban #查看状态
配置#
主配置文件:/etc/fail2ban/fail2ban.conf,可复制fail2ban.local副本来修改。
封禁行为配置文件:/etc/fail2ban/jail.conf,可复制jail.local副本来修改。
默认日志文件路径: /var/log/fail2ban.log
#复制为本地配置文件
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
jail.local 文件配置参考:
⚠️这里在[sshd]中设置backend为systemd使得适用于 Debian12 的systemd-journalbanaction = ufw设置集成了 UFW 来封禁IP,这个选项根据使用的防火墙配置。
#默认配置:封禁时间、查找时间、最大重试次数、封禁动作(集成UFW防火墙)等
[DEFAULT]
bantime = 600
findtime = 300
maxretry = 5
banaction = ufw
banaction_allports = ufw
#SSH:白名单、读取日志方式、启用功能、SSH端口、最大重试次数、查找时间为、封禁时间(会覆盖DEFAULT部分设置)
#⚠️注意修改端口!
[sshd]
ignoreip = 127.0.0.1/8 192.168.1.0/24
backend = systemd
enabled = true
filter = sshd
port = 你的SSH端口
maxretry = 3
findtime = 5m
bantime = 10m
一般修改完 sshd 部分就能满足日常防御所需。
应用生效配置#
# 重启 Fail2ban
sudo systemctl restart fail2ban
# 检查 Fail2ban状态
sudo systemctl status fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
# 查看日志
sudo journalctl -u fail2ban -f #实时查看
sudo less /var/log/fail2ban.log #分页查看
sudo tail -f /var/log/fail2ban.log
查看封禁IP和手动封禁IP
sudo fail2ban-client banned
fail2ban-client set sshd banip 封禁的IP地址 #封禁
sudo fail2ban-client set sshd unbanip 封禁的IP地址 #解封
应用安装#
Docker#
必装之一,现在很多服务使用 docker 容器来部署实在太方便不过辣!不过国内的服务器是连不上 docker 的还需要配置镜像的麻烦(当然也是有一键脚本解决这个问题),而直接整国外服务器直接没有这个麻烦了。。
⚠️警告
⚠️警告!!! docker不兼容UFW!Docker 暴露容器端口会绕开防火墙!需要后续特殊配置!
安装#
分为一键安装脚本和手动安装两个办法。docker官方有便捷脚本但按官方的说法:“不建议在生产环境中使用此便捷脚本”,手动安装可以掌握更多配置细节。(笔者:未考证过不清楚~)
关于 Docker Compose:默认自动安装,Docker Compose 自 V2 版本起开始作为 Docker CLI 的一部分,不再需要单独安装,请使用
docker compose命令替代docker-compose。
一键脚本#
都需要 sudo 或 root 管理员权限执行命令
官方:#
curl -fsSL https://get.docker.com | sudo sh
测试安装步骤(不会实际安装):
curl -fsSL https://get.docker.com | sudo sh -s -- --dry-run
国内:#
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
来源:大名鼎鼎的 linuxmirrors脚本 ,GitHub仓库
手动安装#
教程来自 – 官方安装教程(Debian系统) 的翻译和整理
卸载旧的冲突软件包#
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
设置 Docker 的 apt 仓库#
# 添加Docker官方GPG密钥:
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
# 将仓库添加到Apt源:
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
安装 Docker 软件包#
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
运行镜像验证安装#
sudo docker run hello-world
卸载#
有时候因为一些原因比如安装错误❌、版本依赖、从头再来等想要卸载干净docker。
1、卸载 Docker Engine、CLI、containerd 及 Docker Compose 软件包:
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
2、主机上的镜像、容器、卷或自定义配置文件不会被自动删除。要删除所有镜像、容器和卷:
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
3、移除软件源列表及密钥环
sudo rm /etc/apt/sources.list.d/docker.list
sudo rm /etc/apt/keyrings/docker.asc
您需要手动删除所有修改过的配置文件。
配置#
以非 root 用户身份管理 Docker#
#1.创建 docker 用户组。
sudo groupadd docker
#2.将您的用户添加到 docker 用户组中
sudo usermod -aG docker $USER
#3.注销并重新登录或命令激活 对用户组的更改
newgrp docker
#4.验证是否能在无需 sudo 的情况下运行 docker 命令
docker run hello-world
设置开启自启#
#查看当前docker状态
systemctl status docker
systemctl status containerd
#设置开启自启
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
#禁用
sudo systemctl disable docker.service
sudo systemctl disable containerd.service
docker-ufw防火墙 兼容问题#
先来个简单小脚本,全选复制到命令行后回车执行。
这将创建一个 Nginx 测试容器来检测 Docker 是否绕过了 UFW 防火墙规则,浏览器访问显示的IP地址和端口即可判断。测试完成后按回车即可自动清理所有测试痕迹,不会对系统造成任何残留。
#!/bin/bash
d=~/d_$(date +%s);mkdir -p $d
echo "<html><meta charset=UTF-8><h1>Docker UFW绕过测试</h1><p>如果您能看到此页面,<b style=color:red>Docker可能绕过了UFW防火墙!</b></p>">$d/index.html
trap 'docker rm -f ufw_test 2>/dev/null;rm -rf $d;echo 已清理' EXIT
echo 启动容器,端口12345...;docker run --name ufw_test -d -p 12345:80 -v $d:/usr/share/nginx/html nginx >/dev/null
echo 测试: $(hostname -I|awk '{print $1}'):12345
echo 若能访问,Docker绕过了UFW;echo 按回车清理...;read
docker rm -f ufw_test 2>/dev/null;rm -rf $d;echo 已清理
发现没有?!UFW并没有放行12345端口但 docker 容器居然绕过了!这真是一件非常危险⚠️的事情!!!
这就不得不提到 ufw-docker 和 ufw-docker-automated 这两个GitHub项目就是为解决这个而诞生的!
下载 ufw-docker 脚本#
sudo wget -O /usr/local/bin/ufw-docker \
https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker
使用ufw-docker#
在开始一切之前,建议先手动备份一下规则文件以防万一:
sudo cp /etc/ufw/after.rules "/etc/ufw/after.rules.bak.$(date +"%Y-%m-%d_%H-%M-%S")"
使用管理员权限执行这个命令,修改 ufw的 after.rules 文件。
本质其实就是在/etc/ufw/after.rules末尾增加一块修复的规则。
ufw-docker install
然后重启 ufw 就能生效了。存在特殊情况,还需要额外重启docker服务或者重启服务器。
#重启ufw
sudo systemctl restart ufw
#或
sudo ufw reload
赶紧来测试一下!用回开头那个测试脚本,这时候发现公网IP:123456再也不能访问了!成功✌️有效拦住了!
这时候再执行 sudo ufw allow 12345 命令放行12345端口对于docker容器是无效的,需要通过别的方式。
实际上是 ufw 防火墙路由允许外部访问容器的80端口,而不是映射绑定主机的12345端口。路由转发行了之后公网就能通过容器映射的端口访问到容器80端口了。
#ufw路由转发规则
sudo ufw route allow 80
sudo ufw route delete allow 80
sudo ufw status #查看ufw规则
或者 ufw-docker 也提供对应的命令
ufw-docker allow 容器名 80 #暴露容器的80端口
ufw-docker allow 容器名 #暴露容器所有已发布端口
ufw-docker allow 容器名 443/tcp myNet #暴露容器443的端口、协议为TCP、网络为`myNet`
ufw-docker delete allow 容器名 #移除容器相关所有规则
ufw-docker delete allow 容器名 80 #移除容器80端口的规则
ufw-docker status #显示当前防火墙允许的转发规则
更多用法请参阅:GitHub文档
当然这种还是有一定的缺陷, ufw-docker 加的规则是静态的,只对当前容器有效,万一容器重启、服务器重启、容器对应的那个 172.17.0.X IP发生变化了呢?
所以 ufw-docker-automated 就是为了解决这个而生,这个工具是一个常驻后台小程序,自动监听Docker事件。它能检测到容器启动、停止、IP变化,自动同步UFW规则,不用你手动维护。
个人感觉暂时先用不上了,因为在实际生产环境更多是 -p 127.0.0.1:8080:80 ,只允许服务器本地访问!然后本地所有暴露端口的服务或者 docker 容器全部通过 Nginx 作为最终网关来管理,最后统一对外开放443端口提供 web 服务。
运行用户安全#
未完待续…
Nginx#
Nginx 是一款轻量级、高性能的Web服务器和反向代理服务器,以高并发、低资源占用著称。
虽然说可以docker快速部署,但这种管理全局网络应用入口的我更喜欢原生安装。
想要快速入门配置又不想这么枯燥无味,这里推荐几个我觉得不错👍的视频:
- Nginx入门必须懂3大功能配置 – Web服务器/反向代理/负载均衡 – 技术蛋老师 – bilibili
- Nginx实战 – 配置HTTPS | 数字证书和私钥 | Docker Compose容器 – 技术蛋老师 – bilibili
- 【GeekHour】30分钟Nginx入门教程 – bilibili
安装#
#1️⃣安装必备组件
sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring
#2️⃣导入官方的 nginx 签名密钥,以便 apt 能够验证软件包的真实性
#1.获取密钥:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
#2.验证下载的文件是否包含正确的密钥
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg | grep "573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62" > /dev/null && echo -e "\e[32m✅ Nginx key verified successfully with fingerprint: \e[34m573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62\e[0m" || echo -e "\e[31m❌ Key verification failed\e[0m"
#3️⃣设置 stable-稳定版 的Nginx软件包的apt仓库
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-G7DNlW9Zt4cV5e9keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
#4️⃣设置仓库优先级,使官方软件包优先于发行版提供的版本
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
#5️⃣正式安装
sudo apt update
sudo apt install nginx
#Nginx的所有命令要以sudo管理员身份运行
sudo nginx -V #查看版本
sudo systemctl enable nginx #开启自启
sudo systemctl status nginx #查看状态
如果一切顺利和成功,浏览器访问 公网IP地址:80 将会看见 Welcome to nginx! 的经典 Nginx 测试界面。
配置#
首先我们来明确配置文件在哪?Nginx相关的文件在 /etc/nginx/ 路径下,其中 /etc/nginx/nginx.conf 是 Nginx 默认的主配置文件(当然可以通过命令修改成其他文件),/etc/nginx/conf.d 路径下包含所有的子配置文件,一般会在这里面定义各种网站服务,然后通过主配置文件导入加载生效。(还不明白?继续往下看就悟透!)
先来简单看看 Nginx 配置文件的层次结构
+--------main---------+
| +-----events------+ |
| +------http-------+ |
| | +---server----+ | |
| | | location | | |
| | | location | | |
| | | location | | |
| | +-------------+ | |
| | +---server----+ | |
| | +-------------+ | |
| | +---server----+ | |
| | +-------------+ | |
| +-----------------+ |
+---------------------+
main # 全局配置,对全局生效
├── events # 配置影响 nginx 服务器或与用户的网络连接
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分
│ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块
│ ├── server
│ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...
在一切开始动手操作之前,我们来备份一下配置文件以防万一
#备份配置文件
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
修改完配置文件可以测试语法和热重载来生效:
nginx -t #测试配置文件语法
nginx -s reload #热重载
systemctl reload nginx
#检查 Nginx 的错误日志 (error_log) 和访问日志 (access_log)在`/var/log/nginx/`路径
nginx.conf 配置文件的语法规则
- 配置文件由指令与指令块构成
- 每条指令以 “;” 分号结尾,指令与参数间以空格符号分隔
- 指令块以 {} 大括号将多条指令组织在一起
- include 语句允许组合多个配置文件以提升可维护性
- 通过 # 符号添加注释,提高可读性
- 通过 $ 符号使用变量
- 部分指令的参数支持正则表达式,例如常用的 location 指令
# 全局块 (Main context) - 配置影响 Nginx 全局的指令
user nginx; # Nginx 工作进程运行的用户和组
worker_processes auto; # 工作进程数量,通常设置为 auto 或 CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志路径和级别
pid /var/run/nginx.pid; # Nginx 主进程的 PID 文件路径
# events 块 - 配置影响 Nginx 服务器与用户的网络连接
events {
worker_connections 1024; # 每个工作进程允许的最大连接数
}
# http 块 - 配置 HTTP 服务器的主要参数
http {
include /etc/nginx/mime.types; # 引入文件扩展名与文件类型的映射表
default_type application/octet-stream; # 默认文件类型
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 日志格式
access_log /var/log/nginx/access.log main; # 访问日志路径和使用的格式
sendfile on; # 开启高效文件传输模式
#tcp_nopush on; # 防止网络阻塞
keepalive_timeout 65; # 长连接超时时间
#gzip on; # 开启 Gzip 压缩
# 可以在 http 块中包含其他的配置文件,通常用于定义虚拟主机 (server 块)
include /etc/nginx/conf.d/*.conf; # CentOS/RHEL 风格
include /etc/nginx/sites-enabled/*; # Debian/Ubuntu 风格
# server 块 (虚拟主机配置) - 每个 server 块定义一个虚拟主机
server {
listen 80; # 监听的端口
server_name localhost; # 服务器名 (域名或 IP)
# location 块 - 根据请求的 URI 进行匹配和处理
location / {
root /usr/share/nginx/html; # 网站根目录 (存放网页文件的地方)
index index.html index.htm; # 默认首页文件
}
# 错误页面重定向
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# 示例:反向代理配置
# location /myapp/ {
# proxy_pass http://backend_server_address; # 代理到后端的应用服务器
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
}
# 可以定义更多的 server 块来配置多个网站或应用
# server {
# listen 80;
# server_name example.com www.example.com;
# root /var/www/example.com/html;
# index index.html;
# ...
# }
}
nginx 常用的内置全局变量,可以在配置中随意使用:
| 变量名称 | 含义 |
|---|---|
$host | 请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名 |
$request_method | 客户端请求类型,如 GET、POST 等 |
$remote_addr | 客户端的 IP 地址 |
$remote_port | 客户端的端口号 |
$args | 请求中的查询字符串参数(如 ?key=value&key2=value2) |
$content_length | 请求头中的 Content-length 字段 |
$http_user_agent | 客户端的 User-Agent 信息(通常是浏览器或爬虫标识) |
$http_cookie | 客户端发送的 Cookie 信息 |
$server_protocol | 请求使用的协议,如 HTTP/1.0 或 HTTP/1.1 |
$server_addr | 服务器的 IP 地址 |
$server_name | 服务器名称(匹配 server_name 指令) |
$server_port | 服务器监听的端口号 |
$document_root | 当前请求的根目录(对应 root 指令的值) |
$uri | 请求的 URI(不包含查询字符串部分) |
$request_uri | 请求的完整 URI(包含查询字符串) |
$query_string | 查询字符串部分(与 $args 类似) |
$status | 响应的 HTTP 状态码(如 200、404、500) |
$scheme | 请求的协议,如 http 或 https |
$is_args | 如果有查询字符串则为 ?,否则为空 |
$binary_remote_addr | 客户端 IP 的二进制表示形式 |
$time_local | 当前请求的时间(本地时间) |
域名与Cloudflare#
前面辛苦配置服务器,终于到了最后一个环节──配置域名和Cloudflare,网站能够正式投入使用的最后一步。
添加到Cloudflare托管#
Cloudflare 是全球领先的云安全和性能服务提供商,主要提供 CDN、DDoS 防护和 DNS 服务。也被称作“大善人”──CDN(小橙云)、DDoS 防护、DNS 服务等都是免费开箱即用的,还有更多功能等待探索。
- 首先在 Cloudflare 账户主页 -> ➕加入域 -> 填入你的域名。
- 根据 Cloudflare 提示,在你购买域名所处 -> DNS -> 修改名称服务器(Name Server)为 Cloudflare 提供的名称服务器。
- 等待生效。根据不同域名商有快有慢,生效时间大约为 1~ 48 小时内。成功生效后 Cloudflare 会第一时间发送邮件通知。
- 成功将域名托管到 Cloudflare 后,接下来你可以修改 DNS、使用免费的 CDN、DDoS 防护设置、免费的 SSL 证书等等
修改DNS和使用CDN#
域名托管到 Cloudflare 之后,我们就可以来修改域名的 DNS 记录和使用免费的小橙云(CDN)
导航至:Cloudflare 账户主页 -> 选择对应域名 -> DNS -> 记录,点击 ➕添加记录,我们主要关心三种类型:A、AAAA、CNAME
- A:指向 IPv4 地址
- AAAA:指向 IPv6 地址
- CNAME:别名,指向其他域名
- 比如现在有一个服务器,有 IPv4 和 IPv6 的独立公网地址,在这个服务器上面部署了 web 网页等服务。那可以添加 DNS 记录,根据自己的喜好,根域名或者子域名甚至二三级子域名指向这个服务器的 IP 地址。可以多个子域名指向同一个 IP 地址,区分哪个子域名是哪个部署的网页──这就是服务器的任务了──即前面所说的 Nginx 配置
- Cloudflare CDN(小橙云)在添加新的 DNS 记录时是默认开启的,代理状态显示
已代理,并且还有一个小橙云的图标。这样我们就用了 Cloudflare 大善人的免费 CDN 了,好处多多!比如隐藏服务器的源 IP(对此,想要更进一步请看后面的内容)、自动缓存静态资源、节省流量带宽、DDoS 防护、WAF 防火墙、全球加速(除了中国🇨🇳…国内延迟没这么好看,相对高些,但也没有很夸张,直连是完全能正常访问的,直连我博客看~一点也不慢。这 Cloudflare 胜在免费、简单!如果追求极致低延迟访问,你还是选择国内的吧,域名备案先搞个十天半个月,然后多爆点金币买流量计费的 CDN 服务,速度肯定嘎嘎快,不过你最好祈祷睡一觉起来没有”欠下一套房子“的天价账单😂🤪好吧没有这么夸张但小小博客网站平时没啥人看的,除非是被人 DDoS 攻击刷爆了) - CNAME 的用法常见有:部署的静态博客在 GitHub Page 或 Netlify 上,它们会提供一个子域名,这时候就可以使用 CNAME 来让我们的域名指向这个子域名。如果你想了解更多这方面的内容亦对搭建博客感兴趣,可以看我博客另外一篇教程──《Hugo搭建博客入坑》,其中谈到了这一点。
SSL证书#
域名托管到了 Cloudflare 并开启了小橙云(CDN)之后,Cloudflare 已经默认开启了 HTTPS 了,Cloudflare 会自动帮我们管理和续订三个月有效期的证书。
加密模式#
导航至:Cloudflare 账户主页 -> 选择对应域名 -> SSL/TLS -> 概述 的页面,可以看到当前加密模式,默认是自动模式。点击 配置 按钮,我们可以自定义选择不同的模式,这将会影响:
访问者 -> Cloudflare -> 源服务器 的流量加密。
还没完! 目前只是 访问者 -> Cloudflare 这一段是流量加密的,但Cloudflare -> 源服务器这一段的流量没有加密,仍然是 HTTP !
所以需要设置加密模式为 完全(严格),这有个前提是源服务器要有一个公开可信的证书,你可以使用诸如 acme.sh 来自动管理证书,或者直接使用 Cloudflare 最高可达15年的证书。
配置证书#
接下来我将以使用 Cloudflare 的证书为例,当然你使用其他公开可信的证书也是没问题的
- 导航至:Cloudflare 账户主页 -> 选择对应域名 -> SSL/TLS -> 源服务器(Origin Server),点击创建证书。
- 配置:私钥类型可选 RSA (2048) 或 ECC,有效期最高可选15年。
- 创建了之后下载保存证书文件: 原始证书(Origin Certificate)(.pem格式)和 私钥Private Key(.key格式)。
- 然后在服务器
/etc/nginx/ssl保存这两个文件,自定义有标识性的名字,注意文件 .pem 和 .key 的文件格式! - 接下来配置 Nginx。只需要在server 块中配置
ssl_certificate和ssl_certificate_key就完成了~
/etc/nginx/nginx.conf文件示例:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
/etc/nginx/conf.d/test.conf示例:
# HTTP (端口 80) - 自动重定向到 HTTPS
server {
listen 80;
listen [::]:80; # 支持 IPv6
server_name 你的域名;
# 将所有 HTTP 请求重定向到 HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS (端口 443)
server {
listen 443 ssl;
listen [::]:443 ssl; # 支持 IPv6
http2 on;
server_name 你的域名;
# SSL 证书文件
ssl_certificate /etc/nginx/ssl/Cloudflare_你的域名.pem;
ssl_certificate_key /etc/nginx/ssl/Cloudflare_你的域名.key;
# SSL/TLS 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-%% POLY1305 %%:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# 网站根目录和默认索引文件
root /usr/share/nginx/html; # !!! 请务必修改为您的网站文件实际存放路径 !!!
index test.html; # 根据您的应用需求调整
# Location 块: 尝试匹配文件或目录, 否则返回 Nginx 默认 404 错误
location / {
try_files $uri $uri/ =404;
}
# 错误页面处理
# 对于 404 错误, 上面的 try_files 会直接返回 404 状态码, Nginx 将使用其内置的默认 404 页面。
# 对于 50x 系列服务器错误, 使用 Nginx 默认的 50x.html 页面。
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html; # Nginx 默认错误页面的存放路径
}
# 日志文件路径
access_log /var/log/nginx/test.你的域名.access.log;
error_log /var/log/nginx/test.你的域名.error.log warn;
}
应用生效
# 测试配置语法
sudo nginx -t
# 热重载
sudo nginx -s reload
最后配置完成了后,可以设置加密模式为 完全(严格)了。然后访问域名https://你的域名测试一下,看看是否能正常连接访问。不过你可能会发现,访问https://服务器IP显示证书不安全,其实对于 Cloudflare 与 源服务器之间的加密用 Cloudflare 证书完全够了;况且下文我还会讲到仅允许CloudFlare的IP段访问80/443端口,直连IP不能访问网站。
Cloudflare配置#
访客与 Cloudflare 节点之间流量还有一些必要的配置选项,导航至:SSL/TLS -> 边缘证书。
| 选项 | 建议 | 备注 |
|---|---|---|
| 始终使用 HTTPS | 开启 | |
| 最低 TLS 版本 | TLS 1.2 | |
| 随机加密 | 开启 | |
| TLS 1.3 | 开启 | |
| 自动 HTTPS 重写 | 开启 | |
| 证书透明度监视 | 开启 |
UFW仅允许CloudFlare的IP段访问80/443端口#
前面开启了小橙云隐藏了服务器源 IP 了,看似高枕无忧,但还暗藏隐患。殊不知,还能通过反向扫服务器 IP 地址的网页与域名的网页一一反映射起来,这不就建立域名与 IP 地址的关联了么?不信的话,你现在可以自动尝试一下,直接在浏览器输入你的服务器 IP 地址或者加上https://|http://的前缀来访问~
所以现在就需要限制:只能 CloudFlare 的 IP 段访问 80/443 端口~ 好在,Cloudflare 提供了 CDN 的 IP 段,把它们添加到防火墙规则了里面即可。
当然不能一个个手动添加,这里我从别处复制了一个 bash 脚本,你可以直接粘贴运行(注意可能存在的 root权限问题,可以使用sudo -i切换),或者保存成单独的脚本文件设置定期执行:
#!/bin/bash
# 下载最新 Cloudflare IP 列表
cf_ips_v4=$(curl -s https://www.cloudflare.com/ips-v4)
cf_ips_v6=$(curl -s https://www.cloudflare.com/ips-v6)
# 给新规则添加特殊标记 comment,便于识别
RULE_COMMENT="cf-update-$(date +%s)"
# 先添加新的 Cloudflare IP规则(带标记)
for ip in $cf_ips_v4; do
ufw allow proto tcp from $ip to any port 80 comment $RULE_COMMENT
ufw allow proto tcp from $ip to any port 443 comment $RULE_COMMENT
done
for ip in $cf_ips_v6; do
ufw allow proto tcp from $ip to any port 80 comment $RULE_COMMENT
ufw allow proto tcp from $ip to any port 443 comment $RULE_COMMENT
done
# 等待1-2秒,确保新规则生效
sleep 2
# 删除旧的 Cloudflare 80/443 端口规则(但排除刚刚加的)
EXISTING_RULES=$(ufw status numbered | grep -E '80\/tcp|443\/tcp' | grep -v "$RULE_COMMENT" | awk -F'[][]' '{print $2}' | sort -rn)
for rule in $EXISTING_RULES; do
ufw --force delete $rule
done
# 设置默认拒绝 80/443 的外来访问(如果没有就添加一次)
ufw status | grep -q "DENY.*80" || ufw deny 80/tcp
ufw status | grep -q "DENY.*443" || ufw deny 443/tcp
echo "✅ Cloudflare IP 更新完成(零中断),80/443 只允许 Cloudflare访问。其他端口规则未受影响。"
在用 Cloudflare CDN 后获取真实的用户 IP#
当我们为网站启用 Cloudflare CDN(小橙云) 后,所有访客流量都会先经过 Cloudflare 的全球网络节点,再转发到我们的源服务器。这就有个核心问题摆在面前────服务器看到的所有请求都来自 Cloudflare 的 IP 地址,而不是真实的客户端 IP
这会导致:
- 日志记录错误:访问日志中全是 Cloudflare 的 IP
- 安全防护失效:基于 IP 的访问控制、限流等功能失效
- 数据分析偏差:无法准确统计访客地理位置等信息
- 应用功能异常:依赖客户端 IP 的功能(如登录异常检测)无法正常工作
幸运的是,Cloudflare 在转发请求时,会在 HTTP 头中添加 CF-Connecting-IP,记录真实的客户端 IP。我们只要简单配置一下 Nginx,让它智能识别并使用这个请求头。
基于原理:Nginx 的 RealIP 模块#
Nginx 内置了 ngx_http_realip_module 模块来处理这个问题。这个模块的功能是,从指定的 HTTP 头中提取真实 IP,并用它覆盖 Nginx 内部的 $remote_addr 变量。
其工作原理包含两个关键部分,缺一不可:
- 信任代理 (
set_real_ip_from): 定义一个或多个受信任的 IP 地址或地址段。Nginx 只会处理来自这些 IP 的请求头。这是至关重要的安全措施,可以防止恶意用户直接访问你的服务器并伪造 IP 请求头。接下来我们就是需要添加只信任来自 Cloudflare IP 段的请求 - 指定头 (
real_ip_header): 告诉 Nginx 去哪个 HTTP 头里寻找真实 IP。对于 Cloudflare,就是CF-Connecting-IP。
当 Nginx 收到一个请求时,它会检查:
“这个请求的来源 IP 是否在我的信任列表中?如果是,我就读取
CF-Connecting-IP头,并用它的值作为真实 IP;如果不是,我就忽略这个头,保持来源 IP 不变。”
通过这个机制,我们就能安全、准确地恢复真实访客的 IP。
配置步骤#
1️⃣创建配置文件并下载 Cloudflare 的 IP 地址范围#
sudo touch /etc/nginx/conf.d/cloudflare-ips.conf
# IPv4
echo "# Cloudflare IPv4 ranges" | sudo tee /etc/nginx/conf.d/cloudflare-ips.conf > /dev/null
curl -s https://www.cloudflare.com/ips-v4 | sed 's/^/set_real_ip_from /' | sed 's/$/;/' | sudo tee -a /etc/nginx/conf.d/cloudflare-ips.conf > /dev/null
# IPv6
echo "" | sudo tee -a /etc/nginx/conf.d/cloudflare-ips.conf > /dev/null
echo "# Cloudflare IPv6 ranges" | sudo tee -a /etc/nginx/conf.d/cloudflare-ips.conf > /dev/null
curl -s https://www.cloudflare.com/ips-v6 | sed 's/^/set_real_ip_from /' | sed 's/$/;/' | sudo tee -a /etc/nginx/conf.d/cloudflare-ips.conf > /dev/null
如果一切正常,最终/etc/nginx/conf.d/cloudflare-ips.conf文件内容就像这样:
# Cloudflare IPv4 ranges
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
... (更多IP段)
# Cloudflare IPv6 ranges
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
... (更多IP段)
当然,这个Cloudflare IP地址范围肯定会变的,不过我看最近一次更新还是2023 年 9 月 28 日;
也可以写一个定时脚本定期获取IP地址列表。
2️⃣编辑 /etc/nginx/nginx.conf,在 http 块中引入 Cloudflare IP 配置#
include /etc/nginx/conf.d/cloudflare-ips.conf;
3️⃣在站点配置文件的server模块中添加真实 IP 头#
real_ip_header CF-Connecting-IP;
完整示例:
/etc/nginx/nginx.conf文件:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# 自动加载所有配置文件(推荐)
include /etc/nginx/conf.d/*.conf;
# 或者,如果想精确控制加载顺序:
# include /etc/nginx/conf.d/cloudflare-ips.conf;
# include /etc/nginx/conf.d/你的项目名.conf;
}
/etc/nginx/conf.d/你的项目名.conf:
server {
listen 80;
listen [::]:80;
server_name 你的域名;
# HTTPS强制重定向(如有证书,建议加上)
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name 你的域名;
# 从 Cloudflare 获取源客户端请求IP
real_ip_header CF-Connecting-IP;
# SSL 证书文件
ssl_certificate /etc/nginx/ssl/Cloudflare公钥证书.pem;
ssl_certificate_key /etc/nginx/ssl/私钥.key;
# SSL/TLS 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
location / {
proxy_pass http://127.0.0.1:端口号;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 日志、错误
access_log /var/log/nginx/你的项目名.access.log;
error_log /var/log/nginx/你的项目名.error.log warn;
}
4️⃣测试并应用配置#
# 测试配置语法
sudo nginx -t
# 热重载
sudo nginx -s reload
# 查看日志-访问IP
tail -f /var/log/nginx/你的项目名.access.log
参考资料#
- SSH 客户端收集 – 砖头@runbrick – LINUX DO
- SSH 教程 – 阮一峰 – 网道/WangDoc.com
- VPS 初体验(二)使用 SSH 连接远程主机 – Kiku 的个人博客
- SSH 工具教程 (Tutorial of SSH tools) – Jarvis’ Blog
- SSH小白入门教程一次弄懂SSH入门到精通 – Colin Chang
- 服务器配置SSH密钥登录 – 繁星点点
- 史上最强 Linux一键DD重装脚本 – 黑海洋 – Wiki
- VPS 基本配置:新买的 VPS 怎么整备和调教? – 怪文
- [长期更新]VPS脚本收集和分享 – ggsmida – LINUX DO
- 【配置优化】我拿到VPS服务器必做的那些事 – Yuju – LINUX DO
- 一台新到手的VPS服务器必做十二项配置(以Ubuntu为例)- pppfz- LINUX DO
- 一台新到手的VPS服务器必做的十二项配置(以Ubuntu为例)- PPPFZ’s Blog
- Debian 12 系统安装及个人常用配置分享 – 开发调优 – LINUX DO
- 拿到新的 digital ocean 的一台 vps 需要做哪些事情 – azuginnen – V2EX
- 年轻人的第一台 VPS 设置 – Layton – 少数派
- 路飞工具箱 – 路飞博客
- 小内存服务器生存指南——SWAP虚拟内存-我不是咕咕鸽
- Linux 服务器如何更改 swap 分区大小、优化内存 – SkyWT
- Linux 交换分区要点汇总 – 知乎
- 在Linux创建和使用swap文件以替代swap分区 – Orz小窍门
- Linux 修改swap虚拟内存 | Timber_Blog
- linux 之虚拟内存swap – X-Wolf – 博客园
- 一键开启 zram 内存脚本,解决硬盘读写不佳 (或容量小) 的鸡鸡
- 【Linux内核】另一种增大内存方法:适合CPU性能过剩但RAM少,硬盘读写不佳(或容量小)的鸡鸡 – NodeSeek
- 配置 ZRAM,实现 Linux 下的内存压缩,零成本低开销获得成倍内存扩增 – 个人文章 – SegmentFault 思否
- 配置 ZRAM,实现 Linux 下的内存压缩,零成本低开销获得成倍内存扩增 – 知乎
- 【Linux内核工具】zram的开启、挂载与使用-Crzax的博客
- 关于Ubuntu下ZRAM的配置和使用 – LibXZR 的小本本
- Linux zram 开启 | myfreax
- Linux开启zram命令 • Worktile社区
- ubuntu开启zram彻底解决高I/O引起的卡顿,复制文件无比流畅_ubuntu zram-CSDN博客
- zram: Compressed RAM-based block devices – Documentation-guide – torvalds/linux – github
- ZRAM 与磁盘交换分区对比测试 – NodeSeek
- TCP 网络优化配置指南 – 路飞博客
- VPS基本安全措施 – Raven95676 – LINUX DO
- ufw简易使用教程 – 咸鱼的小站
- 简明教程|Linux中UFW的使用 – 知乎
- ubuntu防火墙ufw使用教程 – zqifa – 博客园
- How to Set Up a Firewall with UFW on Ubuntu – DigitalOcean
- UFW – Community Help Wiki – Ubuntu documentation
- Fail2ban详细教程 · IT迷途小书童
- 保护好自己的服务器,fail2ban使用基本教程 – 知乎
- 保护服务器,fail2ban使用教程 – 幽夜卡尔 – 博客园
- I can’t get fail2ban working on Debian 12 – Super User
- 使用Fail2Ban防火墙工具 – Escape
- 在防火墙或代理后端的fail2ban配置 – 阅心笔记
- 怎样使用 Debian 的 ufw 和 Fail2ban – 柏舟
- 在 Debian 上安装 Docker Engine – Docker 文档
- chaifeng/ufw-docker: 在不禁用 iptables 的情况下修复 Docker 和 UFW 的安全漏洞
- ufw-docker 防火墙工具 – 路飞博客
- Nginx + SSL + Acme + Frp SSL免费证书申请+自动续期+反向代理配置 极细致教程 – 资源荟萃 – LINUX DO
- Nginx入门必须懂3大功能配置 – Web服务器/反向代理/负载均衡 – 技术蛋老师 – bilibili
- Nginx实战 – 配置HTTPS | 数字证书和私钥 | Docker Compose容器 – 技术蛋老师 – bilibili
- 【GeekHour】30分钟Nginx入门教程 – bilibili
- 这是一个 Nginx 极简教程,目的在于帮助新手快速入门 Nginx – dunwu/nginx-tutorial – GitHub
- Nginx配置最全详解(万字图文总结) – 知乎
- Nginx 最全操作总结 – 知乎
- Nginx全面配置 – 知乎
- 分享一套Cloudflare功能系列教程(教程+实践)(强烈推荐!!!)(已完结) – 资源荟萃 – LINUX DO
- Cloudflare – IP 范围
- UFW仅允许CloudFlare的IP段访问80 443端口脚本 彻底防止源站泄露 – NodeSeek
- 开源的 SSL 证书管理工具 – certimate – 路飞博客
- ZeroSSL 免费证书申请与自动配置 – 路飞博客