打开/关闭搜索
搜索
打开/关闭菜单
54
691
62
1945
md5.pw
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
上传文件
打开/关闭外观设置菜单
通知
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
登录
请求账号
查看“︁搬瓦工 VPS 遭遇 DDoS 攻击深度排障与自救手册”︁的源代码
来自md5.pw
分享此页面
更多语言
查看
阅读
查看源代码
查看历史
associated-pages
页面
讨论
更多操作
←
搬瓦工 VPS 遭遇 DDoS 攻击深度排障与自救手册
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
面对搬瓦工 VPS 突然全网失联且无法 <code>Ping</code> 通的情况,需要结合实际运维经验,深入剖析 DDoS 攻击下的空路由(Nullrouted)触发机制,并建立一套从精准判定到彻底自救的实战方案。 == 一、 为什么我的搬瓦工服务器会突然“消失”? == 搬瓦工绝大多数套餐方案在设计上更偏向于提供高性能的底层架构,而非自带硬件级 DDoS 防御。这意味着当特定 IP 遭遇大规模恶意请求时,机房会采取自动化保护措施以确保整体链路的稳定。 * 空路由(Nullrouted)机制:当流量超过阈值,系统会将指向该 IP 的所有数据包丢弃,形成所谓的“黑洞”。此时网站无法打开、<code>SSH</code> 无法登陆、<code>Ping</code> 测试也会完全失效。 * * 1800 秒封禁周期:触发空路由后,默认的屏蔽时长通常为 <code>1800 秒</code>(30 分钟)。如果封禁解除后攻击仍在继续,屏蔽时间会循环延长,导致服务器反复失联。 == 二、 如何确认自己的服务器正处于 DDoS 攻击中? == 在排查网络故障时,首先需要区分是软件配置错误还是受到了流量攻击。通过以下数据特征可以快速锁定故障性质。 '''1. 查看系统邮件通知''' 当 IP 触发空路由时,系统会自动向注册邮箱发送一封包含 <code>is currently under a (D)DoS attack</code> 的邮件,明确告知 IP 已被暂时屏蔽。 '''2. 分析流量特征曲线''' 在排查过程中,通过图形化的数据回馈能最直观地捕捉攻击痕迹。相比于命令行,KiwiVM 后台的统计图表能更清晰地展现出入站流量的异常脉络。 :* 进入路径:登录 <code>KiwiVM</code> 管理后台,在左侧 <code>Security & Records</code> 栏目下点击 <code>Detailed statistics</code> 页面。 :* 观察指标:在右侧详情页中,重点观察 <code>Network I/O (Bits per second)</code> 图表。 :* 黑洞特征判定: ::* 流量尖峰:如果图表中出现如绿色阴影所示的垂直状极高尖峰,说明该时段遭受了大规模入站流量冲击。 ::* 断崖式归零:在尖峰之后,如果流量瞬间掉落并呈水平直线(接近 <code>0 bps</code>)持续延伸,说明 <code>IP</code> 已被系统自动放入黑洞(空路由)进行清洗。 [[File:kiwivm-detailed-statistics-ddos-traffic.png|thumb|center|800px|alt=KiwiVM 详细统计页面显示 DDoS 攻击导致的流量断崖|通过 <code>Detailed statistics</code> 中的流量断层判定 <code>IP</code> 是否被封禁]] '''3. 状态矛盾核对''' 如果控制面板显示服务器状态为 Running 且未执行 重装系统 或主动关闭服务,但外部一切连接手段均失效,基本可以判定为遭受了 DDoS 攻击。 == 三、 应急方案:利用 Cloudflare 建立前端防线 == 由于搬瓦工普通套餐无法提供高防线路,利用 <code>Cloudflare</code> 的全球节点接住流量是目前成本最低且效果最好的自救方式。 '''1. 接入与隐藏逻辑''' 通过将域名 <code>DNS</code> 托管至 <code>Cloudflare</code> 并点亮橙色云朵图标(代理模式),访客的请求会先打到防护节点而非搬瓦工源站。这种方式能有效隐藏真实 IP,屏蔽掉大量的扫描与流量攻击。 '''2. 防护策略加固''' * 开启攻击模式:在攻击期间开启 <code>Under Attack Mode</code>,强制访客进行 5 秒安全验证。 * * 防火墙规则 (WAF):在后台针对异常频率的请求或特定国家/地区设置拦截规则。 * * 优化缓存设置:适当提高静态资源的缓存比例,减少回源请求,减轻服务器的 <code>CPU</code> 与网络压力。 == 四、 利用快照功能实现数据迁移与 IP 更换 == 如果攻击方持续对特定 IP 进行攻击,即使配置了 <code>Cloudflare</code>,旧 IP 一旦解封仍可能被再次打进黑洞。此时,利用快照功能进行业务迁移是更为彻底的办法。 '''数据迁移与环境恢复流程:''' * 制作快照:在 KiwiVM 界面进入 <code>Snapshots</code> 页面,为当前受攻击的服务器做一个全量 备份。 * * 快照还原与迁移:利用'''搬瓦工的快照'''功能,可以新建一台同配置的 VPS 并还原该镜像。或者通过面板功能进行'''更换机房'''来获取全新的 IP 地址。 * * 解析同步更新:在获取新 IP 后,只需在 <code>Cloudflare</code> 后台修改 <code>A 记录</code>,新 IP 会在几秒钟内生效,从而切断旧 IP 的受攻击链路。 == 五、遇DDoS自动断开网卡5分钟 == 检测DDoS就自动断网5分钟 '''如果你的服务器只入 不出的话..那么这个脚本就不适合你了''' 可修改的参数 <nowiki>#</nowiki> 1.触发检查的起步阈值 (MB/s) 这个可以填写你的最大带宽 注意单位是MB TRIGGER_LIMIT_MB=50 <nowiki>#</nowiki> 2.出站流量比例因子 (0.0 - 1.0) 如果流出的流量比进入的流量*设置的值(默认是0.4)就认为发生了ddos 如果你的服务器只入 不出的话..那么这个脚本就不适合你了 如果 (出站 TX) < (入站 RX * 因子),则判定为攻击。 SAFE_RATIO=0.4 <nowiki>#</nowiki> 3. 连续确认次数 防止误报 MAX_RETRIES=3 <nowiki>#</nowiki> 4. 检查间隔 (秒) CHECK_INTERVAL=2 <nowiki>#</nowiki> 5. 黑洞时长 (秒) - 300秒 = 5分钟 断网时长.. BLACKHOLE_TIME=300 <nowiki>#</nowiki> 6. 安全模式 (true=只报警不操作, false=执行断网) SAFE_MODE=false <nowiki>#</nowiki> 7. 日志显示阈值 (MB/s) 只有高过这个阈值才有显示出来的文本 就是 一些流入和 流出 数据计算的值 LOG_LIMIT_MB=5 Bash脚本版本<syntaxhighlight lang="bash"> #!/bin/bash # ================= 用户配置区域 ================= # 1. 触发检查的起步阈值 (MB/s) TRIGGER_LIMIT_MB=50 # 2. 出站流量比例因子 (0.0 - 1.0) # 如果 (出站 TX) < (入站 RX * 因子),则判定为攻击。 SAFE_RATIO=0.4 # 3. 连续确认次数 MAX_RETRIES=3 # 4. 检查间隔 (秒) CHECK_INTERVAL=2 # 5. 黑洞时长 (秒) - 300秒 = 5分钟 BLACKHOLE_TIME=300 # 6. 安全模式 (true=只报警不操作, false=执行断网) SAFE_MODE=false # 7. 日志显示阈值 (MB/s) LOG_LIMIT_MB=5 # =============================================== # 自动获取默认网卡 IFACE=$(ip route get 8.8.8.8 | awk '{print $5; exit}') OVERLOAD_COUNT=0 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' echo -e "${GREEN}=== 智能流量保镖 v3.0 (黑洞版) 启动 ===${NC}" echo "监控网卡: $IFACE" echo "黑洞时长: $BLACKHOLE_TIME 秒" echo "安全模式: $SAFE_MODE" echo "========================================" get_bytes() { cat "/sys/class/net/$IFACE/statistics/$1" } # 初始化读数 PREV_RX=$(get_bytes "rx_bytes") PREV_TX=$(get_bytes "tx_bytes") while true; do sleep $CHECK_INTERVAL CURR_RX=$(get_bytes "rx_bytes") CURR_TX=$(get_bytes "tx_bytes") # 使用 awk 计算速度和逻辑 read RX_MB TX_MB IS_HIGH IS_ATTACK <<< $(awk -v r1=$PREV_RX -v r2=$CURR_RX \ -v t1=$PREV_TX -v t2=$CURR_TX \ -v time=$CHECK_INTERVAL \ -v limit=$TRIGGER_LIMIT_MB \ -v ratio=$SAFE_RATIO ' BEGIN { delta_rx = r2 - r1 delta_tx = t2 - t1 # 防止负数 (重启网卡后可能发生) if (delta_rx < 0) delta_rx = 0 if (delta_tx < 0) delta_tx = 0 rx_speed = delta_rx / 1024 / 1024 / time tx_speed = delta_tx / 1024 / 1024 / time is_high = (rx_speed > limit) ? 1 : 0 limit_tx = rx_speed * ratio is_attack = (tx_speed < limit_tx) ? 1 : 0 printf "%.2f %.2f %d %d", rx_speed, tx_speed, is_high, is_attack }') # 更新上一轮数据 PREV_RX=$CURR_RX PREV_TX=$CURR_TX # 打印日志 RX_INT=${RX_MB%.*} RX_INT=${RX_INT:-0} if [ "$RX_INT" -ge "$LOG_LIMIT_MB" ]; then echo "[$(date +%T)] RX: $RX_MB MB/s | TX: $TX_MB MB/s" fi # 核心判断逻辑 if [ "$IS_HIGH" -eq 1 ] && [ "$IS_ATTACK" -eq 1 ]; then ((OVERLOAD_COUNT++)) echo -e "${RED}[警报 $OVERLOAD_COUNT/$MAX_RETRIES] 流量异常 (RX高 TX低) 疑似攻击!${NC}" if [ "$OVERLOAD_COUNT" -ge "$MAX_RETRIES" ]; then echo -e "${RED}!!! 确认攻击,触发黑洞防御 !!!${NC}" if [ "$SAFE_MODE" = true ]; then echo -e "${YELLOW}[测试] 安全模式开启,不执行断网。${NC}" OVERLOAD_COUNT=0 else # === 执行黑洞 === echo -e "${RED}正在关闭网卡 [$IFACE]...${NC}" ip link set dev "$IFACE" down echo -e "${YELLOW}网卡已关闭,进入 $BLACKHOLE_TIME 秒静默期...${NC}" sleep "$BLACKHOLE_TIME" echo -e "${GREEN}黑洞结束,正在恢复网卡...${NC}" ip link set dev "$IFACE" up # 等待网络恢复 sleep 5 # === 关键:重置状态 === # 网卡重启后计数器会清零,必须重新获取基准值,否则下次计算会出错 PREV_RX=$(get_bytes "rx_bytes") PREV_TX=$(get_bytes "tx_bytes") OVERLOAD_COUNT=0 echo -e "${GREEN}监控已恢复。${NC}" fi fi else # 流量正常或恢复 if [ "$OVERLOAD_COUNT" -gt 0 ]; then echo -e "${GREEN}流量特征恢复正常,警报解除。${NC}" fi OVERLOAD_COUNT=0 fi done </syntaxhighlight>'''bash版本使用''' 一、 前置要求 * '''权限''':必须以 '''Root''' 用户身份运行(脚本需要控制网卡开关)。 * '''依赖''':脚本依赖 <code>ip</code> 和 <code>awk</code> 命令(BandwagonHost 的绝大多数系统已内置,无需额外安装)。 二、 安装脚本 # '''创建存放目录(推荐)''' <code>mkdir -p /root/scripts</code> <code>nano /root/scripts/traffic_guard.sh</code> # '''粘贴代码''' 将上方的脚本完整复制并粘贴进去,按 <code>Ctrl+O</code> 保存,<code>Ctrl+X</code> 退出。 # '''赋予执行权限''' <code>chmod +x /root/scripts/traffic_guard.sh</code> 三、 运行方式 方式 A:Systemd 托管运行(推荐,生产环境标准) 这种方式可以实现'''开机自启''',后台静默运行,且脚本意外退出会自动重启。 # '''创建服务文件''' <code>nano /etc/systemd/system/traffic_guard.service</code> # '''填入以下内容'''<syntaxhighlight lang="bash"> [Unit] Description=BandwagonHost Traffic Guard Service After=network.target [Service] Type=simple # 确保此处的路径与你实际保存的路径一致 ExecStart=/root/scripts/traffic_guard.sh Restart=always User=root [Install] WantedBy=multi-user.target </syntaxhighlight> # '''启动并设置开机自启''' #重载配置文件 <code>systemctl daemon-reload</code> <nowiki>#</nowiki>设置开机自动启动 <code>systemctl enable traffic_guard</code> <nowiki>#</nowiki>运行此服务 <code>systemctl start traffic_guard</code> '''查看运行日志''' <code># 查看实时日志</code> <code>journalctl -u traffic_guard -f</code> 方式 B: 临时运行(测试用) 如果你不想配置 Systemd,或者想在 SSH 窗口看着它 <code>/root/scripts/traffic_guard.sh</code> go版本<syntaxhighlight lang="go"> package main import ( "fmt" "io/ioutil" "log" "os/exec" "strconv" "strings" "time" ) // ================= 配置区域 ================= const ( TriggerLimitMB = 50.0 // 入站流量触发阈值 (MB/s) SafeRatio = 0.4 // 出站/入站 最小安全比例 MaxRetries = 3 // 连续确认次数 CheckInterval = 2 // 检查间隔 (秒) BlackholeTime = 300 // 黑洞时长 (秒) LogLimitMB = 5.0 // 日志打印阈值 SafeMode = false // true=仅打印, false=执行操作 ) // =========================================== var overloadCount = 0 func main() { // 自动获取默认网卡 iface, err := getDefaultInterface() if err != nil { log.Fatalf("无法获取网卡: %v", err) } fmt.Printf("=== Go流量保镖启动 | 网卡: %s | 阈值: %.0fMB/s ===\n", iface, TriggerLimitMB) // 初始化读取 prevRx, prevTx := getBytes(iface) for { time.Sleep(time.Duration(CheckInterval) * time.Second) currRx, currTx := getBytes(iface) // 计算速度 (MB/s) rxSpeed := float64(currRx-prevRx) / 1024 / 1024 / float64(CheckInterval) txSpeed := float64(currTx-prevTx) / 1024 / 1024 / float64(CheckInterval) // 防止负数(网卡重置后可能出现) if rxSpeed < 0 { rxSpeed = 0 } if txSpeed < 0 { txSpeed = 0 } // 更新基准 prevRx = currRx prevTx = currTx // 日志输出 if rxSpeed > LogLimitMB { log.Printf("[流量] RX: %.2f MB/s | TX: %.2f MB/s\n", rxSpeed, txSpeed) } // 判断逻辑 isHighTraffic := rxSpeed > TriggerLimitMB isAttackPattern := txSpeed < (rxSpeed * SafeRatio) if isHighTraffic && isAttackPattern { overloadCount++ fmt.Printf("\033[31m[警报 %d/%d] 异常流量检测! RX: %.2f, TX: %.2f\033[0m\n", overloadCount, MaxRetries, rxSpeed, txSpeed) if overloadCount >= MaxRetries { triggerBlackhole(iface) // 黑洞结束后,重置计数器和基准值 overloadCount = 0 prevRx, prevTx = getBytes(iface) } } else { if overloadCount > 0 { fmt.Println("\033[32m流量恢复正常,警报解除。\033[0m") } overloadCount = 0 } } } // 执行黑洞逻辑 func triggerBlackhole(iface string) { fmt.Println("\033[31m!!! 确认攻击,正在执行黑洞防御 !!!\033[0m") if SafeMode { fmt.Println("[安全模式] 模拟执行:关闭网卡...") time.Sleep(2 * time.Second) fmt.Println("[安全模式] 模拟执行:开启网卡...") return } // 关闭网卡 log.Printf("正在关闭网卡 %s ...", iface) if err := exec.Command("ip", "link", "set", "dev", iface, "down").Run(); err != nil { log.Printf("关闭网卡失败: %v", err) return } log.Printf("网卡已关闭,等待 %d 秒...", BlackholeTime) time.Sleep(time.Duration(BlackholeTime) * time.Second) // 开启网卡 log.Printf("正在恢复网卡 %s ...", iface) if err := exec.Command("ip", "link", "set", "dev", iface, "up").Run(); err != nil { log.Printf("CRITICAL: 恢复网卡失败,请手动处理! Error: %v", err) return } // 给一点时间让网络重新协商 time.Sleep(5 * time.Second) log.Println("网络已恢复,重新开始监控。") } // 读取系统文件获取流量字节 func getBytes(iface string) (uint64, uint64) { rxPath := fmt.Sprintf("/sys/class/net/%s/statistics/rx_bytes", iface) txPath := fmt.Sprintf("/sys/class/net/%s/statistics/tx_bytes", iface) rx, _ := readUint64(rxPath) tx, _ := readUint64(txPath) return rx, tx } func readUint64(path string) (uint64, error) { data, err := ioutil.ReadFile(path) if err != nil { return 0, err } return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) } // 简单的获取默认网卡方法 func getDefaultInterface() (string, error) { out, err := exec.Command("sh", "-c", "ip route get 8.8.8.8 | awk '{print $5; exit}'").Output() if err != nil { return "", err } return strings.TrimSpace(string(out)), nil } </syntaxhighlight>'''一、环境准备''' 在编译运行之前,你需要先在 VPS 上安装 Go 语言环境。 '''Debian / Ubuntu:''' <code>apt update && apt install golang -y</code> '''CentOS / AlmaLinux:''' <code>yum install golang -y</code> 验证安装是否成功: go version 输出类似 go version go1.x.x linux/amd64 即为成功 '''二、 编译与安装''' # '''创建文件''' 创建一个名为 <code>traffic_guard.go</code> 的文件,并将上方的代码完整粘贴进去。Bash <code>nano traffic_guard.go</code> ''(粘贴代码后,按 <code>Ctrl+O</code> 保存,<code>Ctrl+X</code> 退出)'' # '''修改配置(可选)''' 代码顶部的 <code>const</code> 区域是配置项。 #* <code>TriggerLimitMB</code>: 触发阈值(默认 50MB/s)。 #* <code>SafeMode</code>: 如果设为 <code>true</code>,只会报警不会真断网(适合测试)。 # '''编译生成可执行文件''' <code>go build -o traffic_guard traffic_guard.go</code> ''此时你会发现当前目录下多了一个名为 <code>traffic_guard</code> 的可执行文件。'' # '''赋予权限并移动''' <code>chmod +x traffic_guard mv traffic_guard /root/traffic_guard</code> '''三、运行方式''' 方式 A:Systemd 托管运行(强烈推荐) 这是最稳健的方式,支持开机自启和进程守护。 # '''创建服务文件''' <code>nano /etc/systemd/system/traffic_guard.service</code> # '''填入以下内容''' <syntaxhighlight lang="bash"> [Unit] Description=BandwagonHost Traffic Guard (Go Version) After=network.target [Service] Type=simple # 确保这里的路径是你实际存放二进制文件的路径 ExecStart=/root/traffic_guard Restart=always User=root [Install] WantedBy=multi-user.target </syntaxhighlight>3.'''启动并设置开机自启''' <nowiki>#</nowiki>重载配置文件 <code>systemctl daemon-reload</code> <nowiki>#</nowiki>设置开机自动启动 <code>systemctl enable traffic_guard</code> <nowiki>#</nowiki>运行此服务 <code>systemctl start traffic_guard</code> '''4.查看状态与日志''' <nowiki>#</nowiki>查看运行状态 <code>systemctl status traffic_guard</code> <nowiki>#</nowiki>查看实时日志 <code>journalctl -u traffic_guard -f</code> === 方式 B:临时测试运行 === 如果你只是想看看它能不能正常工作: <code>./traffic_guard</code> ''(注意:必须以 Root 身份运行,否则无法控制网卡)'' === 💡 常见问题 (FAQ) === * '''Q: 编译时报错 <code>command not found</code> 怎么办?''' ** '''A:''' 说明 Go 环境没装好,请重新执行 <code>apt install golang</code>。如果 VPS 系统太老源里没有 Go,建议使用 Bash 版本脚本。 * '''Q: 程序报错 <code>panic: 无法获取网卡</code>?''' ** '''A:''' 程序会自动尝试检测默认网卡。如果检测失败,请检查你的 VPS 是否有特殊的网络配置,或者尝试手动修改代码中的 <code>getDefaultInterface</code> 函数,直接返回字符串 <code>"eth0"</code>。 ** '''关键配置说明''' * '''如何测试脚本是否有效?''' 建议将脚本中的 <code>SAFE_MODE=false</code> 改为 <code>SAFE_MODE=true</code>。 这样当流量超标时,脚本只会输出红色警报文字,而不会真的断网。确认触发逻辑正常后,再改回 <code>false</code> 。 * '''触发黑洞断网后,我会彻底失联吗?''' 不会。黑洞防御只是暂时关闭网卡,您可以通过以下三种方式恢复: ** '''方法 1:等待自动恢复''' 耐心等待 <code>BLACKHOLE_TIME</code>(默认 300秒/5分钟)结束,脚本会自动重新开启网卡,无需任何操作。 ** '''方法 2:通过 KiwiVM VNC 恢复''' 登录 KiwiVM 面板,打开 '''VNC Console'''(类似于物理显示器,不受网卡关闭影响)。在 VNC 窗口中按 <code>Ctrl+C</code> 终止脚本,然后输入 <code>ip link set dev eth0 up</code> 手动恢复网络。 ** '''方法 3:重启服务器''' 如果以上方法您都不会操作,可以直接在 KiwiVM 面板点击 '''Reset''' 或 '''Force Stop''' 后再 '''Start''' 重启服务器。重启后网卡会默认恢复连通状态。(注意:这会导致您未保存的数据丢失或服务短暂中断)。 == 六、 长期预案:建立高可用的 VPS 使用环境 == 防御 DDoS 攻击是一项长期工作。通过完善的预案体系和日常的加固措施,可以将潜在的停机风险降到最低。 '''安全预防建议:''' * 双机备份方案:建议准备一台速度快的线路(如 香港CN2 GIA 或 日本东京CN2 GIA)作为直连主力机,同时准备一台便宜的KVM常规套餐作为备份服务器。一旦主力机被黑洞,立即切换解析到备份机并开启 <code>Cloudflare</code> 防御。 * * 系统加固与监控:日常运维中应当修改SSH端口,定期通过 <code>Audit Log</code> 观察异常操作,并确保开启了'''搬瓦工自动备份'''功能以应对极端情况。 * * 资源合理分配:若业务量增长明显,建议及时'''升级套餐'''。如果 IP 已被打残无法解封,可咨询'''搬瓦工客服'''关于'''购买IP'''的具体事宜或申请 退款。 '''注意事项''' * 当 IP 处于空路由状态时,所有的 <code>SSH</code> 工具(如 <code>Xshell</code>、<code>Xftp</code>)均无法连接,请耐心等待 1800 秒解封。 * * 若服务器因 CPU 占用过高被暂停(Suspended),处理流程会有所不同。请务必确认失联原因属于流量攻击而非资源超载。 [[index.php?title=Category:400 常见问题与故障排查 — Troubleshooting]]
返回
搬瓦工 VPS 遭遇 DDoS 攻击深度排障与自救手册
。
查看“︁搬瓦工 VPS 遭遇 DDoS 攻击深度排障与自救手册”︁的源代码
来自md5.pw