做一个网站是很简单的事情。买一个域名,买一个服务器,A记录解析过去就好了。
这样做其实有一个非常大的安全隐患,不怀好意的人可以拿到你的服务器的IP,然后就可以做很多坏事,比如 (D)DoS、暴力破解SSH之类的。
一个很简单的办法,就是用 Cloudflare之类的CDN,这样可以隐藏源站IP。这样他们无法直接攻击你的服务器,只能疯狂打 Cloudflare。
就像我前不久一样,遭遇了人生中第一次DoS,峰值大概有5500万请求的样子,基本上都被Cloudflare的规则拦住了。
然而即使使用了 Cloudflare也并不是100%安全。如果使用方式不正确,也有可能暴露源站IP的。如果被抓到了源站IP,那么坏人就可以疯狂给这个IP发起请求,你的Cloudflare规则配置的再好都没有用。
泄漏源站IP的方式
网络空间测绘
有一些安全公司,如censys、shodan之类的。他们会扫描整个IPv4的地址,然后尝试连接各种常用端口来确定这个IP上都跑了什么服务。
比如说我随便输入一个域名,即使这个域名在Cloudflare之后,也可能看到相关的结果
点进去,通过证书信息就能确认,这个IP大概率是这个网站的,那还不快打?
钓鱼泄漏
利用目标网站的功能来执行服务器端请求。例如,如果一个网站允许用户输入一个 URL 来获取该 URL 的内容(如网页抓取或 URL 预览功能),可以提供一个由自己控制的 URL。
比如 WebP Cloud Services吧,这个服务是做网站图片加速的,那么自然要去用户给的地址去获取图片,这样IP也就会被泄露啦。当然了聪明如 Nova Kowk怎么会让这种事情发生?
其他泄漏方式
子域名
有一些程序可以通过常用的词语来暴力猜测子域名,有可能配置的时候不小心忘记点亮小云朵,或者自己持有的其他域名解析不小心忘记打码,那么就暴露了。
历史DNS记录
有些网站提供历史DNS记录,有概率找到
邮件MX记录
如果自建邮件服务器,那么是肯定会暴露IP了。
Cloudflare信息泄露或者内部作案
这个概率应该很低。
隐藏IP的方式
屏蔽censys并不完美
网上一搜censys 你就会发现有很多种办法,说根据UA屏蔽啦,根据IP屏蔽啦等等。
这种做法治标不治本的。今天屏蔽了censys,明天还有densys,甚至简单写个代码,花最多几百G的流量扫一遍全球的IPv4地址也没什么难度。
只允许 Cloudflare的访问很麻烦
Cloudflare公开了他们的IP地址,因此一种办法是把他们的全部IP地址加入白名单中,然后其他所有的IP地址的请求全部拒绝。
这是一种切实可行的办法,然而有如下缺点:
- 需要跟踪 Cloudflare IP变化
- 需要配置繁琐的iptables、nginx或者WAF等规则,配置起来会比较麻烦
- 80和443的规则都要配一遍
- 费心费时费力
- 一不小心手抖配置错了可能自己都没法SSH
- 如果你用docker,还会发现docker能给你的iptables开个洞 🤦
Cloudflare Argo Tunnel是未来
Argo Tunnel会在你的服务器和Cloudflare 之间创建一个加密的安全隧道,然后这个隧道可以用来承载很多不同种类型的流量,比如 http,tcp,ssh,smb,rdp,甚至是 unix 套接字都可以
你的机器没有公网IP都没关系的,只要你的服务器能够连接到Cloudflare的网络就可以。用起来很简单,甚至都不用学习奇奇怪怪的命令。
去 Cloudflare Zero Trust – Networks – Tunnel 创建 Tunnel,服务器安装 cloudflared,然后添加 Public hostname就可以了
你的应用程序甚至只用监听在 localhost而不是0.0.0.0,也就是说你的服务器只开一个SSH就够了
隐藏SSH
更进一步,我们可以连SSH都隐藏起来。在public hostname那里创建一个域名,如果担心子域名被扫到,那就起个随机的子域名
协议选择 SSH,URL选择 127.0.0.1:22
然后在你的电脑上运行 cloudflared建立隧道
cloudflared access ssh --hostname something.dmesg.app --url 127.0.0.1:10022 # 接到你的服务器 ssh [email protected] -p 10022
之后去厂商的WAF里,比如 Azure是这样的,入网全部拒绝
Vultr是这样的,随便添加一个dummy 入网规则
这样你的IP在其他人看来完全是黑洞,ping不通,什么端口都没开,就像没被使用一样,只有 Cloudflare知道背后的真相。
隐藏应用程序向外发起的请求
如果你的应用程序会向外发请求,而这个外部是可以被用户自定义的,那么就存在被钓鱼的情况。即使你配置的再好,那么也会被抓到IP。
这种情况下,要做的事情自然是全方面审查代码,如果遇到会被钓鱼的地方,那么需要让流量走代理。
至于走什么代理,一种方式是走商业VPN,比如Surfshark之类的,通过wireguard转socks5;另一种方式是走 Cloudflare WARP,WARP可以运行在 proxy mode而不是接管全局流量
warp-cli register # warp 监听本地的11111端口 warp-cli set-proxy-port 11111 # warp proxy mode warp-cli set-mode proxy # 永久开启 warp-cli enable-always-on
对于Go的应用,这样就可以了
https_proxy=socks5://127.0.0.1:11111 http_proxy=socks5://127.0.0.1:11111 go run main.go
还有一种方式是使用 Cloudflare Workers,请求由Workers转发,代码很简单
export default { async fetch(request: Request): Promise { /** * Replace `remote` with the host you wish to send requests to */ const remote = "https://example.com"; return await fetch(remote, request); }, };
更具体的使用方式可以看下面的参考阅读
总结
哎这个世界上坏人真的太多了,但是 Cloudflare 真的帮助了我很多,更重要的是这一切还都是免费的!
不得不感慨,「At Cloudflare, we have our eyes set on an ambitious goal — to help build a better Internet.」,真的不仅仅是一句口号。
—— Nova Kowk
参考阅读
- 分布式部署 cloudflared 让访客就近回源,进一步提升访问速度
- 使用 Cloudflare Argo Tunnel(cloudflared) 来加速和保护你的网站
- WebP Cloud 使用 Cloudflare Workers 回源
- 使用 Cloudflare Zero Trust 连接被墙的服务器