你在家里的 NAS 上跑了一堆服务,心里想的是"反正在内网,别人进不来"。直到有天在一个公网端口扫描网站上输入自家公网 IP,看到一串熟悉的端口号。
现象
家里 NAS 上的 Web 管理面板、代理端口等,都能在公网上被扫到。打开 NAS 系统自带的防火墙一看,默认是关闭状态,规则链里空空如也——也就是说,你以为的"内网服务"其实从外面就能访问。
用在线扫描工具跑一遍,输出通常是这样的:
PORT STATE SERVICE
5000/tcp open upnp
8080/tcp open http-proxy
9091/tcp open xmltec-xmlmail
每一个 open 都是一扇没锁的门。更麻烦的是,这些服务很多是"装完就默认起来"的,你可能都不记得自己开过。
根因
两个前提条件同时成立,缺一不可。
一是宽带光猫不封 IPv6 入站。 运营商的默认策略通常不拦截入站 IPv6,所以只要设备有公网 IPv6、又在对应接口上监听,外面就能连上。这一点和 IPv4 时代完全不同:IPv4 需要你自己手动做端口映射才通,而 IPv6 是"上游不拦就通"。
二是 NAS 系统自带的防火墙默认关闭。 很多 NAS 系统为了"开箱即用、不打扰用户",防火墙出厂就是关的,规则链是空的。它不会过滤任何东西。
两者叠加:设备默认监听所有接口 + 没有防火墙拦截 + 上游不封入站 = 公网可达。
关键在于,这三步里没有任何一步是"你主动做的"——全是默认值。所以风险不来自某个具体操作,而来自一句口头禅:"反正在内网,别人进不来。"
还有一个容易忽略的放大因素:NAS 上的服务往往共享同一套凭据习惯。你在上面登录过网盘、下载站、云盘,面板如果没单独设密码,很可能用的就是那套常用账号密码。一旦面板被扫到并进得去,攻击者顺手就能试出你在其他站点用的同一组凭据——"只暴露了一个面板"的实际影响会被放大很多倍。
解决
三件事一起做,缺一不可。
① 所有容器端口显式绑内网 IP,而不是 0.0.0.0。
# 不要这样
docker run -p 8080:8080 镜像名
# 要这样
docker run -p 192.168.0.10:8080:8080 镜像名
② 代理加绑定地址。 同上一类问题——不能指望 0.0.0.0 当"只绑本机",它会绑所有地方。如果代理的配置里有 listen / bind 项,写成内网地址或回环地址。
③ 开启系统防火墙。 这是最后一道兜底,即使某个程序又偷偷绑回了全接口,防火墙也能拦住。检查一下规则链是不是空的:
# 一般发行版
sudo iptables -L -n
# 或者用 nftables / firewalld
sudo nft list ruleset
sudo firewall-cmd --list-all
如果规则链是空的,先把默认策略设成"拒绝入站、放行出站",再按需放行内网访问:
sudo iptables -P INPUT DROP
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
做完之后,用外面的网络去访问各端口,确认全部不可达。特别注意用手机蜂窝网络测——那才是真正的"外部",连着家里 Wi-Fi 测是没有意义的。
延伸与预防
养成一个习惯:家里每新增一个服务,就顺手做一遍"外网可达性抽查"。
有个很直观的方法:把自家公网 IP 丢进在线的端口扫描服务,看开放了哪些端口。定期做一次,你就知道自己家里到底敞了多少东西。
另外值得单独提一句:别把"内网"当成安全边界。 在家庭网络环境里,"公网可达"才是默认状态,"只有内网能访问"是需要主动配置才能达到的目标。所有依赖"反正外面访问不到"的设计,在 IPv6 普及之后都不再成立。
最后补一条操作习惯:把防火墙规则和端口绑定一起写进配置管理(NAS 的启动脚本、compose 文件、或者一份截图笔记)。家庭环境没有同事帮你 review,配置一旦"配一次就忘",下次换设备或重装系统时就又会回到默认的敞开状态。让"暴露面检查"变成可重复执行的动作,比记住某一条具体规则更重要。