之前在淘宝 3000 块买了个 R720XD,体验不错。于是在这个机器上做了个虚拟路由,以单臂路由的形式接入路由器,提供科学的路由和 DNS 服务。
安全的局域网
一旦得到内网权限,对于普通的家庭网络,我们可以通过 ARP 劫持拿到流量并可以 MITM;对于部分 HTTPS 流量可以通过 sslstrip 等工具降级至 HTTP 继而拿到明文;利用 SNI 扩展和 DNS 流量也可以轻松地拿到用户的访问记录。如果内网部署的服务、或者路由器本身存在漏洞,则影响可以进一步扩大。
这里我们不考虑物理 Hack,那基本上需要重点关注的就是守好 WIFI 这道门。
无线网络的脆弱性
很久以前研究过 Wi-Fi 密码破解,那时候光驱还是电脑标配,刻了几张 Backtrack3 的 live cd,还蛮好使的,特别是对 WEP 加密的邻居们,这个加密简直不存在。如果是 WPA,拿到握手包就可以离线破解,只要资源足够跑出来也不是什么难事。所以如果想搭建安全的无线网络,WEP 和 WPA 都是不可靠的加密方式。
进了大学以后发现还有 EAP 这种认证方式,校园网或者是 eduroam 都是走这类认证。设计上有对认证服务器证书的验证,但是不像针对域名的证书一样,可以方便准确地确认域名所有权下发证书,SSID 是不存在绝对的拥有权的,所以这块的认证只能靠一些预共享的信息,比如连接时去人肉验证证书,或者是在连接时预先导入 CA 证书或信任 Server 证书。这种预共享信息的分发往往很难:在我设备(特别是 PC、Mac 这种无法扫码的设备)还没有网络可用的情况下,可能还真的只有键盘输入方便一些。
于是往往学校或公司的这类网络会提供给你用户名和密码,在连接时你会选择忽略证书(Windows 配这个很麻烦)或者信任单个证书。可能由于这种操作太过普遍,旧版本的安卓甚至直接忽略了证书(如果你没有明确指定一个预先导入的 CA 的话),这样做的问题就是单向认证容易被钓鱼。本科时尝试过用 hostapd 搭建伪造的 EAP 热点骗取用户 token,借用实验室的卡用 hashcat 跑出来过同学的 UIS 密码,虽然跑密码花了点时间,但是是可行的,和 WPA 的问题一样,拥有足够多资源就可以足够快。
要解决信任问题,那双向认证基本是不可避免的。
配置 EAP-TLS
这里环境是 ESXi + Debian + Docker,路由器 ASUS-AX88U。
配置并启动 freeradius:
1 | version: '2.4' |
同目录需要从原镜像中拷贝出一份 /etc/freeradius
,并修改部分配置。
修改 certs/ca.cnf
, certs/server.cnf
, certs/client.cnf
后,生成一套证书:
1 | openssl dhparam -out dh 2048 |
之后在路由器上修改认证方式为 EAP,Radius 服务器配好 IP、Port 和 Secret 即可。
生成配置文件
对于 Windows,我们直接导入已生成的 CA 和 client.p12 ,然后在连接时选择 CA 证书和用户证书即可。但是对于 macOS 和 iOS 用户就很麻烦了。iOS 还可以手动信任并选择证书连接, macOS 连配置的地方都没有。
研究了一下发现对于苹果的设备需要下发一个 mobileconfig 文件,这个文件需要专门的工具来制作。
根据官方的一些资料,发现专业的 Server 是有这类管理工具可以制作的;还有一个上古软件 “iPhone 配置实用工具” 可以制作,但是实测 mac 版已不兼容跑不起来,Windows 版却还能正常工作;另外还有一个开源的软件可以做这件事:https://github.com/ProfileCreator/ProfileCreator ,但实际使用体验我感觉还不如上古版本的iPhone 配置实用工具的 Windows 版。
做出这个文件之后就可以导入到设备啦,airdrop 丢过去装一下就好。连接时直接单击即可,并且由于是通过描述文件安装,“忘记网络”的按钮也消失了,手残党的福音。
描述文件 | CA 证书 |
---|---|
后续还有很多事情要做,比如 IP-MAC 绑定等,在此不写了。
不可信网络
对于家庭网络,有访客要连接是常有的事情;家庭内的部分智能设备也需要 Wi-Fi 密码;部分个人设备也只需要连接外网。这些设备的共同之处是不需要连接内网,只需要外网访问权限。所以我们需要提供一个只有外网连接的网络。
一个方案是在路由器上再开一个 Wi-Fi,以及 DHCP 服务。
路由器固件是 Merlin,我感觉使用体验不如 OpenWRT。以普通用户的视角,在修改某些根本不需要重启网络的设置时,路由器往往也会重启,这明显是代码写的不太行;并且只能开 2.4G、5G 两个广播,加上内置的访客 Wi-Fi 功能是四个广播。以 root 用户的视角,当我想要修改内部文件时,是只读的,对外只提供了 JFFS 可写,可控制性很差。再开一套广播和 DHCP 的方案不太可行。
另一个方案是在某台设备上插张网卡自己做一个广播出来。折腾了半天发现我的那张网卡不支持 AP 模式,方案 GG。
最后采用的方案是再插一个路由器做广播,并在路由器的启动脚本里添加 iptables -I FORWARD -d 192.168.x.x/24 -j DROP
来丢弃通往内网的流量。
为什么不直接使用主路由器的访客模式?这个模式的确挺好用的,可以直接隔离内网以及访客间的互通;但是由于我在路由器 DHCP 配置里下发的网关和 DNS 路由是虚拟机 IP,因为是个内网 IP,这时会导致访客 Wi-Fi 不通。而绝大多数智能设备是不支持手动配置网关的,所以该方案不可行。
2022-06:更新了一下该方案,见下文。
科学的外部网络
啥叫科学的外部网络大家都明白。这里也是通过前文提到的 ESXi 虚拟机做的。
VPN in Docker
【免得被查水表,本部分已删除】
写一写 docker compose 配置就跑起来啦!
踩过的坑
在处理 VPN 与 Docker 的时候经常会踩到一个有关 MTU 的坑。Docker 默认的网桥 mtu 是 1500。
对于在宿主机开启 VPN,在容器内使用的用户,会因为宿主机出口是 1500,减去 VPN 的一些头之后只剩 1400 多,所以 1500 的包就 gg 了。这时一个简单的做法就是把这个网桥 MTU 改小一些。如果使用 docker-compose,则添加类似如下配置:
1 | networks: |
对于我这种在容器内起 VPN 容器外使用的情况更蛋疼一些:VPN 容器的出入流量都是走这个,所以怎么限制都没用。这时可以强制 TCP 握手时协商较小的 MSS,如 1300,这样即便是加上 IP 和 TCP 的头(40)也不会超那个 1400 多的值:
1 | iptables -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1300 |
分流
不能所有的流量都走 VPN,否则排位是要输的。
针对路由,这里就用了很老的那套策略路由的方法,做了两个 ipset:一个是走国内 A 线路的(连 Google 等已经做了专线出国的),一个是直连国外 B 线路的(没有在白名单内的)。然后分别打标记并走各自的路由表。为了维护方便,做了个小脚本可以把带有语义化的注释的 ipset 列表转换为可以直接导入 ipset 的文件。
针对 DNS,起了 unbound,针对名单中的域转发一下就 ok。
这套算是黑名单机制(政治正确一点应该说屏蔽名单机制?)的路由,还是会有漏网之鱼,见到只能手动搞一下。但是好处是不会错误地把国内 IP 路由出去,之前用 CHNList 做白名单路由踩过这个坑,还是很蛋疼的:打开淘宝有时就会提示你是否跳转国外版本。
比较尴尬的是,这套东西刚配起来没两周,那个直连国外的线路就 GG 了。
网络隔离
UPDATED AT 2022-06
前面对于不可信网络的处理是再插个路由器搞。这套用了很久之后出了两个问题:
- 光猫的电源适配器坏了,被封在家里没得换,只能把那个次级路由的电源挪用了
- 想在服务器上开 VM 给小伙伴使用
- 顺便省点电
由于上面的问题,我在想要么就直接用一个路由器搞一搞好了。
首先是 esxi 上要创建一个额外的虚拟交换机,之后为其添加一条特殊的上行链路。之后将那个特殊链路对应的网口插到路由器的特殊网口上。之后创建一个非信任的端口组,并将其虚拟交换机配置为刚刚创建的非信任虚拟交换机。
所以现在 esxi 上的网络配置是 Trusted VM Network 和 Management Network 走 vSwitchTrusted,Untrusted VM Network 走 vSwitchUntrusted,该 switch 绑定了 vmnic3。
我这里使用的是 AX88U,有 8 个网口。vmnic3 对应的网口插入了 LAN4,而 LAN4 对应的设备是 eth1。梅林默认会将非 eth0 的口全部桥接起来,这里我们需要将这类特殊网口解除桥接并拉入另一个独立的 bridge。
1 | # Move eth1, wl0.2 and wl1.2 to untrusted |
之后为 untrusted 添加 ip 和相关 iptables 规则。
1 | # Set network for untrusted |
后续只需要为该子网提供 DHCP 即可,这个直接用现成的 dnsmasq。
效果是,2.4G/5G 访客网络 2 和归属于 Untrusted VM Network 的 VM 都会被分配独立网段的 ip,并且不能主动连接可信网络;而可信网络可以主动连接非信任网络。
完成配置见链接。