HomeArchiveFeedShelf

我遭遇的网络安全事件及应对

这两天在日本的创业项目又遭遇了网络攻击,攻击者采用滥用短信验证 API 的方式拉爆了我的 SMS 服务账单。现在事态已经平息。我想回顾一下我这些年遭遇的网络攻击事件,以及我从中得到的经验教训。

国内某内容平台

这个内容平台是第一次创业的第二个项目,由于是第一次创业,其实没有刻意去做一些防御。还有一个原因是,当时的大环境,攻防烈度远不如现在这么激烈,所以一个普通的互联网项目即使不去做什么防御,可能一年到头也没几次 DDoS。人可以适应环境,但也很难超越大环境。

2017 年 DDoS 攻击

当时的应对方式是上云厂商的高防。这在现在看来其实很傻,因为各个云厂商的高防都是智商税,这些高防 IP 的成本每个月最多几百块,价格却动辄上万,使用还需要修改域名解析。你不知道攻击者什么时候会攻击,所以常常就是被攻击的时候切一下高防,这个月高防到期了又切回普通 IP。

这种防护方式的问题是

  1. 切高防 IP 的时候服务已经被打死了;
  2. 需要人工操作,修改解析后还需要用户那边的 DNS 缓存刷新了才能恢复服务;
  3. 高防 IP 价格昂贵,云厂商不过是觉得能被打的都是高净值客户,从供需关系的角度,把你当傻逼来宰杀你而已,并不是这个东西技术含量有多高。

不过当时项目的收益不错,我当时也确实是一个单纯的傻逼,所以我就傻乎乎的每次被打就买一个月的高防,也没觉得这种方式有什么不妥。

如我前文所说,当时的网络安全大环境还是比较温和的,攻击者在几次攻击后发现我可以很快地切换高防,就悻悻然离去了。

2016 年 Docker 漏洞入侵

还是这个内容平台,当时 docker 的 daemon 是监听公网端口的,如果再配置防火墙允许访问,则会导致服务器权限拱手让人。有一次我们发现服务器无特殊理由性能不足,检查发现是服务器在挖矿 😅。挖矿程序的来源是一个 downloader,而 downloader 是通过 docker 放进来的。真是一段难堪甚至有一点搞笑的往事。

2017 年的 XSS 攻击尝试

那段时间老是能看到有人在评论区里发 <script>alert(‘test’)</script><script src=”foo/xxx.js”></script>之类的东西。我知道他想干什么,于是顺着 foo/xxx.js 找到他的 XSS 平台域名,再查到注册人的微博,直接私信他让他别弄了没用的 🤣,他给我回了一串省略号。感觉他当时年纪不大,应该是高中生之类的,像当年的自己。

因为 Vue 这样的前端框架的 {{ }} 语法已经处理了 XSS 的问题,我不需要做任何事情,只要自己注意插 html 代码的时候用类似 dompurify 这样的库 sanitize 一下就可以了。

PixelCloud

PixelCloud 是我的第三个创业项目,始于 2021 年。这时候网络安全环境已经完全不一样了,自动化攻击机器人大行其道。稍有不注意就会迅速沦为待宰的羔羊。最典型的证据就是 shodan 这样的 IPv4 全感知平台的出现。IPv4 地址为 4 x 8 = 32 位(二进制),一共 2^32 = 4294967296 个 IP 地址,摩尔定律发展到这个时候,普通人去扫描一遍整个 IPv4 也不是什么困难的事情。那网络安全大公司定期遍历 IPv4 全网端口也很正常。shodan 这样的网站应运而生,后面还会提到它。

针对网站服务器主机的攻击

由于网络环境的恶劣,几乎没有网站不使用 CDN 了。网站域名解析到 CDN,攻击者无法获知源站的 IP 地址,只能看到 CDN 的集群 IP,他要打也只能打 CDN,打不到你的服务器。

但是我的服务器还是被攻击了,为什么呢,因为 nginx 在处理 https 站的域名错误时,会将证书返回客户端。这就让 shodan 这样的平台扫描到你的服务器 IP 时,通过报错获知域名。也就知道了这个域名对应的 IP 地址是什么了。攻击者在 shodan 这样的平台上搜索一下域名,立刻就能知道源站地址,绕过 CDN 进行攻击,直捣黄龙。

解决办法是需要使用新版的 nginx,新版的 nginx 支持了 ssl_handshake_reject 语句,如果访问域名不匹配(比如通过 IP 访问)直接断开连接,防止域名泄漏。

几个月前三菱 UFJ 银行遭遇 DDoS,推特上有人疑惑为什么这么大的银行不上 CDN,他们当然用了,他们用了 akamai。他们应该是跟我犯了一样的错误,使得黑客可以绕过 CDN 而进行攻击。

在 shodan 上搜索 mufg,可以看到直接出现了源站的 IP。

针对网站对象存储的攻击

攻击者使用他的下行带宽拉爆我的流量账单,使得我的对象存储被云厂商关停,达到相关业务停摆的目的。

1T 流量半小时就被打完了。

解决办法是在下载 url 签名的 API 处强制进行人类验证。具体地,由于 PixelCloud 是国内项目所以使用了 geetest。

针对 CDN 的攻击

攻击者对 CDN 也采用了类似的攻击方式,获取某个小文件的 url,然后通过下行带宽拉爆 CDN 的流量账单。通过在 T 云厂商的 CDN 设置每个 IP 的请求次数限制解决了。

针对游戏服务器的 DDoS 攻击

游戏服务器无法走 CDN,因为游戏的网络都是 L4,而 CDN(Content Delivery Network)里的 Content 一般就隐含了 HTTP 的意义,是 L7。国内也没有类似 Cloudflare Spectrum 那样的 L4 防护服务,不论是最近腾讯的 EdgeOne,还是 Cloudflare Spectrum 自己,其实也都价格昂贵,对于创业者来说都不现实。

为了低成本防 D 我合伙人想出一个法子。写一个程序,接入云厂商的 API,生成四个常驻 L4 代理虚拟机,如果某个虚拟机被打死,或者说是这个虚拟机对应的 EIP 被打死,那就按照指数关系,生成更多的 EIP 和虚拟机,直到攻击停止。比如打死一个生成两个,打死两个生成四个。攻击停止后则自动删除这些多余的 EIP 和虚拟机。

这个方法的好处在于,云服务器和 EIP 都是按小时计费的,只有攻击持续的那几个小时计费。

这个方法运作了大概一年。表现良好。但还是遭遇了意外的问题。主要是 U 云厂商不干了。

因为我们不用云厂商的高防,而是“擅自”组建弹性高防方案,U 云厂商老爷很不高兴。客户经理的原话是“你们是唯一一个被攻击这么多次还不买高防的”。哪怕在他们的商务当初 BD 我从 A 搬到 U 的时候,我已经和他们的商务详细介绍了这个方案,他们的商务也认可。哪怕这套系统在 A 厂商即使遇到再大的攻击也没人找我麻烦。

2023 年春节受到了一次很大的攻击,一次打死了十多个 IP。U 云厂商就把我们申请 EIP 的权限给封了,强制我们买他们的高防,但是当时攻击已经结束了,勉强扛下来了,就不想买高防。于是把动态抗 D 的系统给下了,只能利用手头现有的 EIP 进行分配防御,平时用两个 EIP,如果打死了一个,就手动在 U 云厂商后台重新绑定新的 EIP 给虚拟机 L4 代理,然后再手动修改 DNSPod 上的解析,24 小时后之前被打死的 EIP 就又能用了。

就这样经过了小半年,平均每两周会有一次小的攻击,造成一些玩家游戏的抖动,但都问题不大,直到 6 月 20 日。6 月 20 日又来了一次很大的攻击,耗尽了手头的所有 EIP,不得不买高防了。当时情况紧急,愤怒的 U 厂商“后端”甚至以清退我们相威胁。当时我别无选择,在 U 厂商的逼迫下购买了 U 厂商的高防,花了 15k。

PixelCloud 不比原来那个内容平台,毛利很薄,15k 无法接受。我不得不开始寻找其他的高防方案,到这时候终于知道了高防主机的租赁成本竟然只有每个月几百块!

后面的事情就简单了,把 L4 代理放到高防主机上即可。DDoS 问题至此彻底解决。

日本某内容平台

这个项目是我的第四个创业项目,主要做全球市场,而且没有 L4 防护需求,可以免费使用赛博佛祖 Cloudflare,基本上不用再考虑 DDoS 问题。

最近再次遭到了网络攻击,攻击者通过自动化请求短信验证 API 的方式,拉爆了我的 SMS 服务账单。这个攻击方式和当年 PixelCloud 的对象存储下载攻击很相似,所以第一反应是也是用人类验证来解决。但是与直接下载文件不同,每一个短信验证都需要经过我的 API,我能不能通过其他策略来解决来尽可能避免人类验证对转化率的影响?

我开始尝试限制手机号,如果某个手机号请求验证码次数过多则将这个手机号加入黑名单。这个策略是无效的,攻击者并不需要拥有某个手机号才能对我进行攻击,因为他不需要真的收到验证码才能完成攻击,他只需要确保短信发出,我的账单扣了钱,即可完成一次攻击。因此封禁手机号不会对他带来任何损失。

我又尝试封禁 IP,如果某个 IP 请求过多则将这个 IP 加入黑名单。这个策略也是无效的,因为攻击者的 IP 实在是太多了,他的 IP 比我的短信便宜,那这种防御策略也是不划算的。

最后还是老老实实上了 hcaptcha,选择它的原因是,Google reCaptcha 和 Cloudflare Turnstile 都在中国大陆不 work。

最后感想

其实每次网络攻击到来的时候都挺焦头烂额的,因为我都损失了金钱,耗费了精力,服务也受到了影响。

比如这次短信 API Abuse,攻击者好像是美国时间,我这边白天不攻击,到了凌晨开始攻击。我每次部署完新的防护策略之后,又要充 10 美金给他刷,看看攻击者的攻击是否依然有效。但攻击者好像每次把我的余额刷干一次之后就去打游戏了,一段时间内都不攻击,我又只能等他。我这两天都是凌晨四点半才睡。

作为一直在挨打的一方,小小吐槽一下,这种攻防对抗实在是不对等。我必须以最快的速度处理,并且把攻击对普通用户的影响降到最低。而攻击者只需要躲在暗处,做好准备,伺机出动即可。

接入 hcaptcha 其实我早就加入到了 todo list 里,由于 PixelCloud 的经验,我早就预料到会发生这样的事情,但是一直懒得弄,直到攻击发生。这些游荡在黑暗森里里的猎人,其实一定成程度上是中性的,因为就算他们不攻击,安全漏洞也已经在那里了,他们只是让问题尽早暴露出来而已。

但是另一方面,对比 2016 年的项目和 2021 年的项目,因为网络攻击更加频繁和普遍,挨打的从业者不得不花费更多的时间和金钱在网络安全上,以达到以前不需要怎么额外关注就能达到的相同效果。比如对象存储下载攻击,2016 年的内容平台项目也大量使用对象存储,却从来没有遭遇过如此奇葩的攻击。而在 2021 年,为了应对这样的攻击,所有用户不得不先完成一个滑动条验证码,才能使用下载功能。由于我的及时应对,攻击者也没有达到他的目的。军备竞赛有点像囚徒困境,所有人都追求自己的利益最大化,却带来了皆输。小偷的存在给全社会带来了锁的成本。

我在中二的年纪里(初二到高三里)也非常憧憬黑客,在我学习编程之前就自学了很多网络安全的知识,还渗透了高中的官方网站服务器,拿到了 3389,算是一个“脚本小子”吧。因为有这样的中二经验,当我开始从事编程工作后,我便非常注意各种网络安全问题,比如注入,跨站之类的,所以我从来没有遇到过因为我代码写得不严谨而造成黑客获得系统权限的事情。

当然,还有一种可能性。职业的网络安全攻击大多都利用未公开的 0day 漏洞,也就是“我不知道我不知道”的事情。有可能他们早就把我服务器操烂了,而且由于 rootkit 的权限甚至比我更高,所以我一直都不知道,还在自我感觉良好。

@2025-04-22 22:30