本文提供一个主线openwrt精简固件,包含opppelssh。地址 GitHub Elrori/openwrt-auto遵守GPL。该固件是在主线openwrt-19.07添加patches之后一次性编译的,不同于下文的编译过程。openwrt增加新设备的方法(添加补丁方法)将不在本文中阐述,本文主要讲两步编译方法,以及一种特殊的代理方式。如果使用Elrori/openwrt-auto固件。实测ccclass-vvvmesss-tcp协议,非tls时,200M家用带宽+200M节节点点点的测速结果为90Mbps,此时zynq cpu占用100%,直连也是90Mbps,此时zynq cpu占用50%。速度跑满了100M口,实际加CPU的能力不止90M。此外,日常加上电源的功耗为1.7W。
EBAZ4205有一个100M网口和ZYNQ ARM-A9,而且openwrt主线支持ZYNQ器件,因此EBAZ4205可以作为百兆旁路由。ZYNQ拥有两个macb,都可以通过PL引出,理论上可以自己制作一块RTL8211的扩展板,让EBAZ4205拥有双千兆网口,但是由于双核666MHz arm a9性能太弱,单口千兆实际速度大约500-700Mbps,运行加密算法时只会更慢。实际使用时可以使用速度等级为-3的器件生成FSBL,可尝试超频到866MHz。注意 5.10内核的以太网速度相较于老版更慢。
下面介绍从零开始制作EBAZ4205的OpenWrt镜像,采用的方法是先生成zed board的镜像再生成ebaz4205d的镜像:
-
下载官方OpenWrt 19.07.3源码。
git clone --depth=1 -b v19.07.3 https://github.com/openwrt/openwrt.git
-
最新的几个版本会出现内核macb驱动模块BUG,导致在使用MII接口的百兆网时必须先上电再插网线才能通网,否则内核崩溃,建议使用19.07。我也尝试了Lean’s OpenWrt,同样出现了这个问题,这可能与Linux内核源码中的macb_main.c有关,与内核版本相关。可以尝试使用最新主线Linux内核而不是5.10版本的内核。
-
进入OpenWrt目录,执行make help查看帮助,执行帮助中的命令:
./scripts/feeds update -a ./scripts/feeds install -a make menuconfig
-
Target System --> Xilinx Zynq 7000 SoCs;Target Profile --> Avnet ZedBoard;Target Images --> ext4 使用ext4文件系统;
-
Luci --> Collections --> luci 使能luci;Luci --> Modules --> Translations选择中文;
-
Luci --> Applications内选择需要的功能;建议选择luci-app-upnp用来自动端口映射。勾选Base system --> dnsmasq-full,取消勾选Base system --> dnsmasq;
-
最后保存.config文件;
-
编译:
make -j16 V=sc
-
编译成功后,修改build_dir/target-arm_cortex-a9+neon_musl_eabi/linux-zynq/linux–14.167/arch/arm/boot/dts中的zynq_zed.dts设备树,代码如下。随后再执行一次make就能生成适配ebaz4205的fit.itb。修改后的zynq_zed.dts设备树:
/dts-v1/; #include "zynq-7000.dtsi" / { model = "Ebang ebaz4205 board"; compatible = "avnet,zynq-zed", "xlnx,zynq-zed", "xlnx,zynq-7000"; aliases { ethernet0 = &gem0; serial0 = &uart1; mmc0 = &sdhci0; }; memory@0 { device_type = "memory"; reg = <0x0 0x10000000>; }; chosen { bootargs = ""; stdout-path = "serial0:115200n8"; }; ebaz-leds { compatible = "gpio-leds"; led-green { label = "green"; gpios = <&gpio0 54 1>; default-state = "off"; }; led-red { label = "red"; gpios = <&gpio0 55 1>; default-state = "off"; }; }; }; &clkc { ps-clk-frequency = <33333333>; }; &gem0 { status = "okay"; phy-mode = "mii"; phy-handle = <&phy>; /* PHY clock assigned-clocks = <&clkc 18>; assigned-clock-rates = <25000000>; */ phy: ethernet-phy@0 { reg = <0>; device_type = "ethernet-phy"; }; }; &sdhci0 { status = "okay"; }; &uart1 { status = "okay"; };
-
产生的镜像文件中的uboot不能适配ebaz4205(因为没有改任何关于uboot的代码或配置)。只用到镜像中的fit.itb,fit.itb是设备树和被压缩的内核。
-
之前的文章介绍了如何产生uboot,用之前产生的boot.bin备用。
-
编写uEnv.txt。让uboot加载内核并启动:
bootargs=console=ttyPS0,115200n8 root=/dev/mmcblk0p2 rootwait earlyprintk uenvcmd=run sdbootfit sdbootfit=echo Run uEnv.txt copying Linux from SD to RAM... && \ fatload mmc 0 0x1000000 fit.itb && \ echo Boot fit.itb from RAM && \ bootm 0x1000000;
0x1000000这个地址很关键。fit.itb中已经包含了内核的加载地址(0x8000),fit.itb不能放在0x8000附近。因为uboot会将0x1000000上的fit.itb搬运到0x8000。0x1000000在16MB位置上,在解压后的内核之后(内核大小10MB左右)。
-
将取出bin/targets/zynq/ * .img.gz解压,将 * .img烧写镜像到SD卡,把SD卡FAT分区中除了fit.itb的其他文件都删了。再把boot.bin和uEnv.txt放进去。SD卡准备完毕。插卡上电,接上网线,连到电脑。
-
登录网页192.168.1.1。固定板子lan口的IP,使得在主路由的网段下。板子的lan口网关、DNS设置为主路由器IP。
-
在自定义防火墙规则中添加:
iptables -t nat -I POSTROUTING -j MASQUERADE
-
旁路由设置完毕,这种方式不会破环原有的网络结构,需要通过旁路由上网的设备必须手动设置网关和DNS为旁路由IP才能使用。
轻量代理设置
刷openwrt几乎只有一个目的:为了xx,其他LINUX系统可以使用hostapad开热点,但使用起来没有openwrt方便。openwrt还有一些文件共享插件,ebaz4205没有把usb引出导致少了很多可玩性。
现阶段有许多现成的openwrt插件可以方便的配置代理,例如ssr|p+|||cla|sh|||passw+all|||open+ccla|s|h。通过官方源编译的openwrt是不含这些插件的。如果只是轻量使用,不需要分流,并且有稳定的v2节点,而且熟悉Linux系统,推荐采用V2 + dnsmasq-full + ipset + iptable方案。
-
采用V2 + dnsmasq-full + ipset + iptable方案,在黑名单里的域名走代理。这是一种轻量的代理方式,采用ip hash table 做自动切换,时间开销极小。开销主要集中在第一次域名查询。黑名单的方式难免会有遗漏(可手动添加),但是效率高,在一些老旧的路由上也能流畅运行(例如mt7620)。
-
greatfffirewwall的原理是通过在域名查询时返回一个不存在或者被频闭的ip,如果预先知道该域名在黑名单中,我们就可以使用代理获取真实ip。大多数时候,真实ip也是被ban的,需要一个集合存储这些ip,通过代理连接这些ip。
-
ZYNQ芯片使用的是双核Cortex-A9,属于ARMv7-A架构,可使用Xray代替V2,可直接从github下载编译好的Xray。
运行该方案时发生了什么:
-
电脑设置网关和DNS为ebaz4205的IP后,想要访问谷歌,首先发送DNS请求(UDP包)到ebaz4205的53端口,ebaz4205中的dnsmasq发现该域名在黑名单集合A中,于是把UDP包转发到5353端口。v2收到了这个包,通过outbound把它传到了彼岸,彼岸的兄弟又把包发送到了8.8.8.8:53。得到了谷歌IP。一路逆转,到ebaz4205的dnsmasq手里,dnsmasq把IP放到ipset创建的集合B中,并把IP给了电脑浏览器。dnsmasq使命完成。
-
浏览器用这个IP建立TCP连接,发起三次握手,第一次发出一个包,包的目的地是谷歌IP,ebaz4205 iptable发现这个包的目的地IP在集合B中!立即把包转到了ebaz4205的1081端口,通过v2的帮忙,数据包到了彼岸…
-
这种方式基于域名查询,如果软件直接使用内置IP发送数据,这个IP包将不会被代理。例如TG采用固定IP发送数据,我们就需要通过 ipset add mylist 的方式手动将IP放入黑名单。
v2配置文件config.json:
{
"log": {
"loglevel": "warning",
"error": "/var/error.log"
},
"inboundDetour": [
{
"protocol": "dokodemo-door",
"port": 1081,
"listen": "0.0.0.0",
"settings": {
"network": "tcp,udp",
"timeout": 30,
"followRedirect": true
}
},
{
"protocol": "dokodemo-door",
"port": 5353,
"listen":"127.0.0.1",
"settings": {
"address": "8.8.8.8",
"port": 53,
"network": "udp",
"timeout": 0,
"followRedirect": false
}
},
{
"protocol": "socks",
"port": 1082,
"listen": "0.0.0.0",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
},
"settings": {
"auth": "noauth",
"udp": true,
"ip": null,
"address": null,
"clients": null
},
"streamSettings": null
}
],
"outbound": {
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "服务器",
"port": 端口,
"users": [
{
"id": "d。。认证ID",
"alterId": 2,
"email": "t@t.tt",
"security": "auto"
}
]
}
],
"servers": null,
"response": null
},
"streamSettings": {
"network": "tcp",
"security": null,
"tlsSettings": null,
"tcpSettings": null,
"kcpSettings": null,
"wsSettings": null,
"httpSettings": null,
"quicSettings": null
},
"mux": {
"enabled": true,
"concurrency": 8
}
}
}
-
全局代理的时候用1082端口。
-
在自定义防火墙规则中加入:
ipset -N glist iphash iptables -t nat -A PREROUTING -p tcp -m set --match-set glist dst -j REDIRECT --to-port 1081 iptables -t nat -A OUTPUT -p tcp -m set --match-set glist dst -j REDIRECT --to-port 1081 #有时候,编译内核时,没有选择REDIRECT,iptables就不支持REDIRECT。这种情况一般发生在商用openwrt系统上,这时候就只能刷机后实现透明代理了
每次启动的时候会执行上面脚本。glist是集合B,由IP构成。
-
追加集合A:
-
echo “conf-dir=/etc/dnsmasq.d” >> /etc/dnsmasq.conf
-
在/etc/dnsmasq.d中新建dnsmasq_gf去掉wlist_ipset.conf。下载地址:https://cokebar.github.io/g去掉fwlist2dnsmasq/dnsmasq_gf去掉w去掉list_i去掉pset.conf。注意列表名字需要替换为glist
-
-
开机启动 vi /etc/init.d/xray 。配置文件放在xray的同目录下。
#!/bin/sh /etc/rc.common # "new(er)" style init script # Look at /lib/functions/service.sh on a running system for explanations of what other SERVICE_ # options you can use, and when you might want them. START=80 ROOT=/mnt/sda1/transmission/downloads/ SERVICE_WRITE_PID=1 SERVICE_DAEMONIZE=1 start() { service_start $ROOT/xray } stop() { service_stop $ROOT/xray }
/etc/init.d/xray enable