低成本家庭网络解决方案

先说结论:软路由+ 二手运营商定制 WIFI6 路由器

家里是 500M 联通宽带,但是现有的路由设备无法跑满带宽,存在明显的性能瓶颈。

对于家庭网络有以下要求:

  1. 不浪费带宽能跑满尽量能跑满
  2. 所有设备都在一个大内网,方便设备间文件传输、投屏等需求
  3. 支持透明代理科学上网,并且速度稳定
  4. 有一定扩展性支持折腾

为了达成这个目的最佳的配置是软路由+ WIFI6 AP

首先是软路由,软路由是指用普通PC+专门的路由操作系统实现的路由器,区别于硬路由是通过专门芯片实现。

网上有很多软路由的实现方案,为了实现低成本方案淘了一个10年前的 PC,奔腾 E6700 3.2Ghz 双核,性能足够。再加上一个 18块的前兆无线网卡。最终配置是:

CPU:Pentium(R) Dual-Core CPU E6700 @ 3.20GHz

内存:DDR3 3G

硬盘:16G U盘(系统盘)+ 512 GB 机械硬盘(数据盘)

网络:双千兆网口,一个作为 WAN、一个作为 LAN

系统:基于 Openwrt 封装的 iStoreOS (来自koolshare 团队)

这样一个配置对于 500M 带宽来说绰绰有余,跑满带宽只占了 30% CPU。

对于硬路由的选择,由于只需要做一个无线 AP,我们不再要求他能刷固件、配置高,因为耗资源的路由功能都交给软路由了。有一类路由器正好满足我们的需求,那就是运营商定制的 WIFI6 路由器,这类路由器基本都是大厂贴牌为运营商定制的,在安装宽带会赠送(打包到套餐里面)。

这里有一个帖子对这里路由器有一个总结,可按需挑选:全网最全92个型号的运营商WiFi6 mesh路由的超详细配置总结 含可刷op型号

这类路由器最大的特点就是低价高配、但是扩展性不高,一般不能刷机,也只能用运营商的手机 App 进行管理。但是对于作为一个 AP 来说完全足够了。

我最终选择的是 H3C RC3000,入手价格 123 。

MODEL:H3C RC(T/W)-3000(01/10)
CPU:IPQ5000 (2C 1.0GHz, ARM A53)	
2.4G无线芯片:集成	
5G无线芯片:QCN6102	
交换机:QCA8337	
2.4G FEM:集成	
5G FEM:KCT8539S	
闪存:128MB	
内存:256MB集成	
天线:外置	
无线:WiFi6 2x2 3000Mbps (160MHz)	
接口:1WAN+3LAN	
备注:移动、联通、电信均定制,型号不同内部电路一样,NX30换壳

将RC3000 接入软路由 Lan 口,配置有线中继(AP)模式,最终完成了整个家庭网络的配置。

同时还在软路由内安装了网心云容器魔方,贡献自己的闲置上行带宽赚一点点电费 bingo~

网件 NETGEAR R6300V2 TTL救砖记

这台 R6300V2 是去年闲鱼上以 80 块收的路由器,当时是因为之前用的小米 R3G 突然挂掉,不得已同城闲鱼淘了一个。淘路由的时候还是做了一个小调查,选择了R6300V2 这个经典款,450M+1300M 的配置,加上可以刷梅林固件,造型别致有着电磁炉的称号,至今还在各大平台销售。

去年到手后已经是 koolshare 梅林 380 固件最后的版本了(最后绝版在x7.9.1), 新的 384/386固件只有新的设备才支持。

由于疫情在家实在无聊,开始折腾起了路由器。先是闲鱼入了京东云无线宝挂机赚金豆,接着就是在几个路由器:R6300V2/无线宝加速版/小米 4A千兆版 几个路由器之间折腾。既想要好好科学上网、又想好好挂机赚金豆、还想所有设备都在一个子网里面。在这期间还发现我的联通宽带居然是 500M 的,只是因为路由设备原因速度跑不满,要求里面又加了一条尽量能把带宽用满。而且还有一个特殊情况,家里光猫在沙发后,主机在对面的电视柜上,两边只能用无线中继的方式连接,这对网络要求更高了。

正好在恩山论坛上看到了 R6300V2 可以刷 386 的帖子:网件NETGEAR R6300V2(国行版本) 原厂固件直刷380_X7.9.1梅林成功 附升级梅林386教程 ,并且已经有很多人为了组 mesh 网络升级了 386。

一直心痒痒想要升级试试看,于是在纠结了一两天便照着教程开始了升级之旅,非常顺利地完成了升级。然而升级之后发现了新问题,翻墙变得不稳定了! 平时经常用电视看 youtube 就变得非常不方便。差不多两三天后就决定要降级回去。

正好上面的帖子有讲如何降级退回 380的,简单地说就是先刷之前备份好的 380固件,接着通过 TFTP方式刷入梅林380固件。然而照着教程操作一番之后却悲剧了:刷入 380 CFE 重启后,路由器直接进入 TFTP 状态,但是固件始终无法刷入。期间尝试了各种各样的固件:380、386、原版固件、原版CH版固件(这台机器是美版的CH版本,类似运营商定制版)、还有不知道哪儿来的华硕过渡固件等等,统统没反应。

尝试几次无果后在恩山论坛上寻找救砖方法。唉,原来悲剧的不是我一个人,从年初到现在已经有 4、5个人中招了,表现都是路由器重启直接进入 TFTP,但是无法刷入任何固件。同时也有大佬指出了问题的原因:路由器会校验固件的 board_id,由于 board_id 不匹配因此无法刷入,解决方法是通过 TTL 进入 CFE,输入:

nvram set bypass_board_id=1
tftpd

可以绕过固件的 board_id 检查,进而修复。

这里稍微科普一下:TTL 指的是路由器暴露的串口通信端口,通过该端口可以进行串口通信,在电脑端可以通过 putty 开启串口通信,获得路由器的 terminal,进而观察系统启动的输出信息或进行输入。

然而关键问题是进 TTL 需要一个专门的 USB-TTL转接器,虽然他很便宜但是当时上海已经是疫情封禁快递都停了,因此这台 R6300V2 只能暂时当一个砖头。

在这期间只有两个路由器:无线宝、小米4A 支撑,由于一定要有科学上网环境只能让小米4A这个弱鸡作为主路由。

后来等到5月底的时候,疫情开始恢复拼多多上买的 TTL 转接线终于到了,当天就迫不及待地把 R6300V2 大卸八块准备修复,然而拆开之后又傻眼了,怎么跟拆机图不一样啊。

如上图,正常在 TTL 位置应该是有 4个接线柱的(Vcc、G、T、R),方便直接将转接线插入进行连接,然而我的 R6300V2 对应位置居然是空的,只有4个裸露的触点。这就意味着要想连接我还需要用电烙铁把接线焊在上面才行。

闲鱼上看了一下,电烙铁也很便宜,电烙铁+焊锡+焊油 15块包邮,下单后迟迟没有发货,我又等不及了!!!直接上手开搞。

我是怎么弄的呢,拆了一条多余的 USB 数据线,拆开里面会有 4 条很细的线作为连接线。

TTL 对应有三条线:电源、输入、输出,我取了3条电,烧掉两头露出铜丝,一头绑在 TTL接线柱上,另一头分别贴在 R6300V2 电路板的焊点上,用胶布把他固定住。但是这样是不稳的,我必须要用手按住电源才能接通。

之前的帖子还提到一点,直接用 TTL 连接 R6300V2 后,路由器是启动不了的,必须要等电源灯亮了之后再接通 TTL 才行,于是整个流程是这样的:

  1. 断开 TTL 数据线
  2. 控制插座打开
  3. 等待1S 让电源灯亮起
  4. 插入 TTL 数据线
  5. 按住电路板焊点处
  6. 观察 PC 屏幕 putty 界面是否有输出
  7. 狂按 ctrl+c 停止路由启动,进入 CFE 界面(这个时候右手必须按住电路板触点位置,不然键盘命令是发送不到路由器的)

这真是一个细致活,总之我成功了。在右手按住电路板的情况下,通过左手单手操作,完成了一下命令:

路由器输入:
->nvram set bypass_board_id=1
->tftpd
电脑端输入:
tftp -i 192.168.1.1 PUT r63oov2.trx

试了刷入 koolshare版本的固件发现并不行(事后想起来应该是刷错了,应该刷 CHK格式),继续尝试别的固件。命令行自动补全了之前下载的华硕固件,我想也没想就回车了(PS:为什么会有华硕固件,是因为华硕有一款 AC68U跟这台的配置是完全相同的)。没想到还真刷进去了,然而更大的悲剧来了。

这个华硕固件成功刷入,看到 TTL 的输出系统已经成功启动,然而没有 WIFI信号,电脑通过有线连接拿不到 IP (DHCP 有问题?),甚至手动指定同网段的 IP 也不能连接。这下岂不是比之前的砖还砖了,简直是石头了。

不死心继续折腾,再次按照上面的步骤一手按着电路板,一手 CTRL+C 进入 CFE,我勒个去,TFTPD没有这个命令、CFE 模式下也 ping不通了,也就是说电脑跟路由器彻底无法连接了。这样还想靠之前的方法刷入不可能了,几乎没有希望了。期间各种查资料学习,想了两条路:1 通过USB 拷贝固件进行刷机、2 通过 TTL 传输固件。

第一个方法很快就发现行不通了,虽然 flash 命令的 help 说了支持读取 FAT 格式磁盘下的文件,但 CFE 下压根就不识别优盘。

第二个方法网上查到一些别的场景有通过 TTL传输文件的,然而都不是路由器刷机的场景,而且又学习了串口通信的波特率概念。

波特率、比特率、通信速度的区别有哪些

在115200波特率的情况下,1秒只能传输 14k的内容,20M的固件要传半个小时,意味着我得按着电路板半个小时中间不能中断,想想就算了。

不死心的我又想到了既然能启动成功进入系统,那是不是可以在系统里面刷机呢,于是经过漫长的启动等待进入系统,发现一切都挺正常,就是没有 WIFI、有线也连不上,但是 USB是可以识别的,这是一个重大的突破口。

几番研究奔着死马当活马医的办法我刷入了之前备份的 380 CFE,刷入后重启进入 CFE,嘿 TFTPD 命令又回来了,而且电脑上也能ping通了。

后面就很顺利了,尝试了几个固件(包括官方固件)失败后,最终通过刷入 DD-WRT的过度固件成功,成功启动进入 DD-WRT系统,也可以通过网页端进入系统。最后再通过网页上 DD-WRT 的系统更新直接刷入 koolshare 的380固件,哎嘿我的 R6300V2 又复活了。

最后的最后,发现复活的 R6300V2 也不能满足我的网络需求,果断挂闲鱼出手。并开始物色下一个路由器,目标是支持 WIFI6。

利用 kcp 加速跨地区 grpc 请求

背景

目前维护的长链消息推送系统,拥有一个中心节点和上百个边沿节点。需要将消息从中心节点推送到所有边沿节点。为了保障用户就近接入,这些边沿节点分布在全国(世界)多个地区。

在从中心节点推送中我们发现到边沿节点的速度非常不稳定,特别是晚高峰的时候 99 分位耗时抖动严重。

“KCP” 是基于 UDP 协议上实现的一套可靠传输协议,其主要特点是面向流速、降低高丢包场景的延迟。早年间多用来“翻墙”,如知名的 kcptun,v2ray 也内建了 KCP 支持。

中心向边缘推送的场景、晚高峰的抖动跟 KCP 的应用场景非常类似。遂决定尝试让 grpc 底层走 kcp 来传输数据以达到 kcp 宣称的低延迟。

正文

kcptun 是利用 kcp协议来实现的远程端口映射,通过对其源代码的阅读发现其核心是 kcp-go 来完成 KCP 连接的建立和管理,得益于 go 良好的 interface 设计,可以几乎 0 成本地将 grpc 改造支持 KCP 协议传输。

我们支持 grpc server 启动分成三个部分:

1.listener,即 net.Listener interface,通常是通过 net.Listen(“tcp”,”127.0.0.1:9000″) 获得的。

2.grpc server,即通过 grpc.NewServer() 创建的 grpc server 对象。

3. service implement,即 proto 中定义的 service 的实现对象,最终会通过 pb.RegisterXXServer 将 pb 定义和实现进行绑定。

而要替换成 KCP 协议只会涉及到 listener 的替换,即提供一个实现了net.Listerner 接口的对象,而这个在 kcp-go 已经实现了。

因此我们要做的只是调用 kcp-go 中的 kcp.ListenWithOptions() 来创建自己的 Listerner,最后通过 server.Serve(listener) 即可启动支持 KCP 协议访问的 grpc server。其本质是 grpc->http2-> kcp->udp 这样的协议结构。

同时 grpc 可以同时绑定多个 listerner 进行 serve,因此你既可以监听 TCP ,也可以通过监听基于 UDP 实现的 KCP,即一个端口上实现两种协议的访问。

对于客户端,我们可以通过实现自己的 Dialer 来实现以 KCP 协议连接 grpc server。grpc 提供了 grpc.DialOption 来自定义连接行为,只要 Dial 之后获得兼容 net.Conn 的对象即可。因此通过在 grpc.Dial 中使用 grpc.WithContextDialer 来自定义我们的连接方式。在具体实现中使用 kcp.DialWithOptions 来完成 KCP 连接的创建。

得益于 kcp-go 良好的设计实现,我们只需要了很少几行代码即完成了 grpc 对 kcp 的支持。最终实现的效果如下:

服务端通过一个端口监听 TCP/UDP

客户端可以根据配置选择以 TCP 连接或者 KCP 协议连接服务端

问题:

1.kcp-go 本身没有连接状态和超时机制,在 server 端重启后,客户端无法感知到连接变化,此时发生消息会一直阻塞,因此需要通过配置 grpc 协议层面的心跳来维持连接,当心跳失败后触发自动重连,即使用 grpc.WithKeepaliveParams 设置。通过测试发现此问题是由于 kcp-go v5 版本客户端实现导致,kcp-go v4 无此问题,具体原因还在调查中。

2.多网卡问题:在使用UDP 协议监听 0.0.0.0:9999 这样的地址时,如果是多网卡的场景,当客户端向网卡 2 发送消息,服务端在回传时会出现向 网卡 1 回包的情况。这在同一个局域网不会出现问题,但如果跨越多层网络则通过网卡 1 的回包无法到达客户端(因为链路上 nat 都是只认网卡2 的)。这个问题只能通过在监听时分别监听每个网卡地址(IP)来解决。参考文章(双网卡UDP通信问题

结果

最终通过 kcp 完成海外节点消息推送的优化,耗时曲线趋于平稳,基本保持在一个 RTT 时间。

以上过程代码已整理到 gitbub: https://github.com/Lynnworld/grpc-kcp-transport