记赛场网络代理配置

背景

众所周知在一些线下赛中,允许选手连接外网,然而赛场网络并不提供互联网连接。在这种场景下,每位选手通常需要连接手机热点,然后通过配置路由表的方式同时连接外网和平台/靶机。然而,路由表的配置较为繁琐(Windows/Linux/Mac OS下配置的方式不同),并且容易出差错。例如以下三种情况:

  1. 路由漏配错配导致无法连接靶机,然而可以正常连接平台/外网,造成迷惑
  2. 一些网络服务会不断添加错误的默认路由,使得无法正常连接外网
  3. 假如赛中出现网络断连(网线松了/热点断了等等),则部分路由会消失,需要重新配置

此外,使用手机热点也可能遇到5G信号不佳、Wifi信道干扰的问题。这些不稳定的问题,使得在赛场需要随机应变的网络配置,也为搭建代理带来了很大挑战。因此,我们迫切地需要一种易于配置、“一劳永逸”的方案,其中最显而易见的就是加入一个软路由小主机,通过小主机统一连接合适的外网出口(简单来说就是看赛场四个人手机谁信号好用谁的x),并统一配置路由表。

方案

为了方便展示方案,我们在这里需要为软路由划分三个网络:

WAN1(赛场网络):174.35.1.0/24 网关174.35.1.254

是的,这个段属于公网段,想知道为什么要用这个段可以去问问赛宁为什么喜欢这么配网

WAN2(公网):192.168.5.0/24 网关192.168.5.1

LAN(选手网络,在没有软路由时,WAN1和LAN是同一个网络)

方案一:NAT

说到软路由,第一想法就是通过NAT访问赛场网络:

LAN:192.168.8.0/24

在软路由上为LAN配置DHCP服务,选手的主机全部连接LAN即可

然而,这样做有两个问题:

  1. 在渗透等场景下,例如反弹shell,需要靶机反向连接选手主机。因为选手主机在NAT后,除非手动配置端口转发,否则无法反向连接
  2. 尽管设想选手可以全部连接软路由的LAN,但假如出现LAN口不够等情况,选手被迫直连现场网络时,同样除非手动配置端口转发,否则无法连接到LAN后的设备

那么,软路由上不使用NAT,直接和选手主机一同连入赛场网络怎么样呢?

方案二:修改网关

回想我们的需求,我们的目标只是让选手的流量流经软路由,而不是共用一个IP地址。因此,我们完全不需要引入NAT,甚至不需要选手连接软路由的LAN,而是直接在选手主机上设置网关为软路由自身IP即可。在软路由上设置转发规则,从而完成流量的路由操作。

这是个理想的方案,并且在最近的线下比赛中我们也是这么做的,但完美主义发作的我还是鸡蛋里挑骨头发现了两个问题:

  1. 在选手主机配置中,只有两种IP配置方法:DHCP或静态IP。因此在实际操作时,为了避免撞IP,我们都是先走DHCP拿到IP后,再设为静态IP,地址为DHCP获取到的IP,网关为软路由IP。这引入了不一致性,并且在DHCP租约过期时依然可能会出现问题
  2. 尽管选手需要配置的内容已经大大减少,但这仍然需要选手手动配置,而我们希望透明地实现网络代理与流量路由

如何使得选手仍然依赖赛场DHCP,却能将流量导向软路由并完成分流呢?最直接的办法是修改由WAN到LAN的DHCP响应包,并修改其中的Option 3。然而由于DHCP的复杂性(这可是一个应用层协议),并没有一个简单、稳定的方案实现这一点。此时,我的队友提出了一个绝妙的想法

方案三:劫持ARP

既然不便劫持DHCP报文,我们能否劫持更简单、更底层的ARP报文呢?答案是可行的!我们只需要拦截由WAN流向LAN的赛场网关ARP响应报文。当LAN中有主机通过ARP协议寻找网关时,我们伪造一个响应,使得MAC指向软路由自身即可

实现

假设WAN1, WAN2, LAN分别对应ens18, ens19, ens20三个网络接口

配置系统

首先需要开启系统的ipv4转发功能

1
2
sysctl -w net.ipv4.ip_forward=1
# 持久化需要修改/etc/sysctl.conf

然后将WAN1和LAN连接到一个虚拟网桥(此处使用netplan)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
network:
version: 2
ethernets:
ens18:
dhcp4: no
ens19:
dhcp4: yes
ens20:
dhcp4: no
bridges:
br0:
dhcp4: yes
interfaces:
- ens18
- ens20

配置路由

此处比较简单,删除赛场网络的默认路由,并配置靶机路由,配置ens19的masquerade等,就不过多赘述了

1
2
ip route del default via 174.35.1.254
# ...

劫持ARP

当ens20发出arp请求包时,判断其请求的目的ip地址,若为网关地址则响应一个指向虚拟网桥br0的MAC

当ens18发出arp响应包流向ens20时,检查其源ip,若为网关地址,则丢弃

1
2
3
BR0_MAC=$(cat /sys/class/net/br0/address)
ebtables -t nat -A PREROUTING -i ens20 -p arp --arp-op Request --arp-ip-dst 174.35.1.254 -j arpreply --arpreply-mac $BR0_MAC --arpreply-target DROP
ebtables -A FORWARD -i ens18 -o ens20 -p arp --arp-op Reply --arp-ip-src 174.35.1.254 -j DROP

总结

通过这样的配置,我们成功在赛场网络中加入了一个透明的路由器。配置完成软路由后,选手无需手动配置路由表和IP地址,只需要连接到软路由的LAN即可在信息高速路上冲浪

而劫持ARP的方案实现起来并不繁琐,完全可以手写一个自动配置脚本完成配置,从而降低了配网的难度,允许在赛场网络环境中快速、有效、稳定地配置网络

而为了实现这一切,我们最少只需要额外带一台双网口小主机即可:LAN口借用赛场提供的交换机,而WAN2使用手机的NDIS通过USB完成网络共享,并没有额外引入太多配件。假如小主机只有一个网口,也可以额外带一台VLAN交换机,不过这就有些太显眼了。