在OpenWRT路由器上使用iptables对英雄联盟随机丢包

室友天天开黑,这就算了,还老是用外放,不得已,只能让他们打不爽,从根本上阻止他们开黑,还我寝室一个安静的环境,至少,让他们按时睡觉。

寝室的网络环境

路由器

一台捡垃圾的小米CR6608,刷入了 OpenWRT ,承担我们寝室所有的网络流量,由于是一所垃圾大学,校园网限制一套餐一终端,寝室里又只有一个网络口,大家都用我的套餐,整个寝室的网络控制权当然在我的手上。

室友上网的设备

其余三个室友都打英雄联盟,其中两个使用笔记本,一个是台式机,没有无线网卡,而且台式机恰巧是打的最凶的那位。

决定采用的方案

首先,肯定不能彻底阻断寝室网络与英雄联盟服务器的连接,这样明显感知太强,容易被发现,其次由于另外两个室友都是笔记本电脑,发现丢包率太高肯定会开热点换移动网络,所以最终的方案确定为模仿GFW对网站随机丢包的干扰模式。

具体行动

首先先给每个室友分配静态的IP地址,原因看到后面你就知道了。

上网查找资料,可以知道英雄联盟所使用的端口:

项目端口号
League of Legends Game Client5000 - 5500 UDP
Patcher and Maestro8393 - 8400 TCP
PVP.Net2099 TCP
PVP.Net5223 TCP
PVP.Net5222 TCP
HTTP Connections80 TCP
HTTPS Connections443 TCP
Spectator Mode8088 UDP and TCP

向路由器的iptables里添加以下随机丢包的规则:

1
2
3
4
5
6
7
8
# Block LOL
iptables -I FORWARD -p udp --dport 5000:5500 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 8393:8400 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 2099 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 5223 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 5222 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 5233 -m statistic --mode random --probability 0.3 -j DROP 
iptables -I FORWARD -p tcp --dport 8088 -m statistic --mode random --probability 0.3 -j DROP 

关于如何在 OpenWRT 上自定义 iptables 规则,有两种方法,第一种方法,打开 系统 -> TTYD终端 将上面的命令一行一行复制进去回车,用这种方法,规则会在路由器重启或者 iptables 重启后失效,第二种方法,打开 网络 -> 防火墙 找到 自定义规则 选项卡,将上述内容粘贴到这个页面已有内容的后面,注意不要覆盖文本框里原先的内容,完成后点击页面下方的 保存并应用,这样即使是重启路由器也不会重置 iptables 规则。

这些 iptables 规则用到了 ipopt 模块,而一些固件不会默认安装 ipopt 模块,如果发现 iptables 对这些规则报错,请看后文的安装 ipopt 部分

生效后,室友打英雄联盟就会在校园网本就1%到5%丢包率的基础上增加30%的丢包率。经过室友的盲测反馈(我怎么可能会让室友知情呢?!)放技能总是放不出去,打的非常不爽。

但是这种方法似乎不适用于室友开加速器的情况,所以我们可以针对这种情况直接限制室友所有的流量,也就是说,不论室友的电脑发出什么数据包,都能享受到30%的丢包率,除非室友开热点,当然台式机是不可能的,这种方法就可以让所有的加速器都失效。前提是,室友的ip地址必须要提前确定,这也就是为什么需要提前给室友的电脑分配静态IP。

向路由器的iptables里添加以下规则

1
2
3
# Block specific roommate
iptables -I FORWARD -s 你室友的内网ip -m statistic --mode random --probability 0.3 -j DROP
# 以此类推

即可“照顾”室友所有的流量。

很好,现在每天11点我都会准时更新防火墙规则,至少让寝室安静一点。

授人以鱼不如授人以渔

这些参数都是些什么?

iptables

iptables是运行在用户空间的应用软件,通过控制Linux内核netfilter模块,来管理网络数据包的处理和转发。

——维基百科

简单点说:iptables是Linux的防火墙软件,可以通过设定的规则过滤掉特定的数据包达到防火墙的目的。OpenWRT基于Linux,自然也用iptables作为防火墙。

-I FORWARD

iptables有所谓的“五链”和“四表”。

“五链”是指 netfilter 定义的 5 个规则链。每个规则表中包含多个数据链:INPUT(入站数据链)、OUTPUT(出站数据链)、FORWARD(转发数据链)、PREROUTING(路由前数据链)和POSTROUTING(路由后数据链),防火墙规则存储在这些数据链里。

“五链”的结构如下:

graph LR A[PREROUTING] --> B[路由决策] B --> C[FORWARD] B --> D[INPUT] D --> E[Local Process] E & C --> F[POSTROUTING]

四表分别是:

  • filter:过滤整个数据包,在 INPUT、FORWARD 和 OUTPUT 链可用
  • nat:控制数据包的地址转换,在 PREROUTING 、INPUT、OUTPUT 和 POSTROUTING 链可用
  • mangle:修改过滤数据包中的原数据,在 PREROUTING、INPUT、OUTPUT、FORWARD 和 POSTROUTING 链可用
  • raw:控制 nat 表连接追踪机制的启用与否,在 PREROUTING、OUTPUT 链可用

路由器的功能是转发数据,这些数据显然经过 FORWARD 链,故规则都在 FORWARD 链上添加。在 iptables 上使用 -I 参数插入规则时,默认会插入 filter 表,也就是我们需要的表。

-p xxx –dport xxxx

使用 iptables 时,-p 参数用于指定规则适用的协议,–dport,即destination port的缩写,支持范围匹配,可以匹配数据包所去往的端口,这里参照英雄联盟所使用的端口和与之对应的协议一一阻止。

-m statistic –mode random –probability 0.3

这些都是自定义的 丢包参数,可以实现很多其他的功能,因为iptables功能太多,故这里不做赘述,感兴趣的话可以自行查阅iptables相关的教程。

-j DROP

iptables 可以对符合规则条件的数据包做多种处理:

  • ACCEPT:允许数据包通过
  • DROP:丢弃数据包
  • REJECT:拒绝数据包通过
  • LOG:记录日志
  • DNAT:目标地址NAT
  • SNAT:源地址NAT
  • MASQUERADE:地址欺骗
  • REDIRECT:重定向

需要随机丢弃数据包,自然是选择DROP。

特定时间自动添加/删除丢包规则

在路由器的 Crontab 里添加如下规则

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#Automatic Block
0 0 23 * * ? iptables -I FORWARD -p udp --dport 5000:5500 -m statistic --mode random --probability 0.3 -j DROP 
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 8393:8400 -m statistic --mode random --probability 0.3 -j DROP 
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 2099 -m statistic --mode random --probability 0.3 -j DROP 
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 5223 -m statistic --mode random --probability 0.3 -j DROP 
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 5222 -m statistic --mode random --probability 0.3 -j DROP
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 5233 -m statistic --mode random --probability 0.3 -j DROP 
0 0 23 * * ? iptables -I FORWARD -p tcp --dport 8088 -m statistic --mode random --probability 0.3 -j DROP 
#Automatic unblock
0 0 7 * * ? iptables iptables -D FORWARD -p udp --dport 5000:5500 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 8393:8400 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 2099 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 5223 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 5222 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 5233 -m statistic --mode random --probability 0.3 -j DROP 
0 0 7 * * ? iptables -D FORWARD -p tcp --dport 8088 -m statistic --mode random --probability 0.3 -j DROP 

即可实现每天晚上11点自动添加丢包规则,每天早晨7点自动删除丢包规则。

补充:安装 ipopt 模块

部分固件可能存在没有ipopt模块的问题,而这些规则大部分都使用到了这个模块,这种情况下需要手动安装。

ipopt 的安装有两个选择,一般出于稳定性考虑会安装用户层的iptables-mod-ipopt,而内核级的kmod-ipt-ipopt则在设备 CPU 性能孱弱或存储空间不够用的情况下选择。

内核级的模块一般需要预先编译固件才能安装,而用户层只需执行以下opkg命令即可:

1
opkg install iptables-mod-ipopt

后期计划

  • 后续可能会写一个每天指定时间自动添加,自动删除iptables规则的脚本,实现应该相对容易。最近要期末考试,备考要紧。

  • 其次可能会补充iptables的常用功能解说。