Google Wifi نسل اول (برد Gale، کد AC-1304) یک روتر ارزان و کممصرف با چیپست ipq40xx است که زیر نظر پروژهٔ OpenWrt بهخوبی پشتیبانی میشود. در این نوشته، مسیر ساخت یک فریمور سفارشی روی OpenWrt ۲۵.۱۲.۵ (زیرشاخهٔ ipq40xx/chromium) را مرور میکنم: از رفع یک باگ عجیب در وایفای دایرکت گرفته تا مالتیWAN واقعی با mwan3 و یک منوی اختصاصی در پنل.
۱. هدفهای فریمور
فریمور سفارشی با سه ایدهٔ اصلی بسته شد:
- پسوال (PassWall) بهعنوان پروکسی پیشفرض، با لیست دایرکت/بلاک دستی و بدون نودِ پیشفرض (کاربر نود خودش را میدهد).
- وایفای دایرکت («Google Router Direct») که ترافیکش اصلاً وارد پروکسی نشود — این بزرگترین چالش بود.
- مالتیWAN: یک کابل + تا ۳ وصلهٔ بیسیم بهعنوان WANهای فرعی، با failover و load balance همزمان.
۲. رفع باگ وایفای دایرکت (پچ nftables)
در نسخههای قبل، SSID دایرکت (زیرشبکهٔ ۱۹۲.۱۶۸.۱۱.۰/۲۴ روی بریج br-direct) اشتباه وارد زنجیرهٔ پروکسی پسوال میشد. علت: پسوال در حالت «پیشفرض = پروکسی»، بدون فیلتر رابطِ ورودی، کل ترافیک را میگرفت. راهحل، تزریق یک قانون return در ابتدای زنجیرههای پسوال بود — از طریق override کردن فایل /usr/share/passwall/nftables.sh:
nft "insert rule $NFTABLE_NAME PSW_MANGLE ip saddr 192.168.11.0/24 counter return comment \"direct-bypass\""
nft "insert rule $NFTABLE_NAME PSW_MANGLE_V6 iifname \"br-direct\" counter return comment \"direct-bypass\""
nft "insert rule $NFTABLE_NAME PSW_NAT ip saddr 192.168.11.0/24 counter return comment \"direct-bypass\""
nft "insert rule $NFTABLE_NAME PSW_DNS ip saddr 192.168.11.0/24 counter return comment \"direct-bypass\""
دقت کنید: چون شبکهٔ دایرکت IPv6 ندارد، خط ششم از تطبیق اشتباهِ «کل IPv6» به تطبیق بر اساس نام بریج (iifname "br-direct") تغییر یافت تا واقعاً فقط ترافیک آن بریج از پروکسی خارج شود. با این پچ، دستگاههایی که به «Google Router Direct» وصل میشوند مستقیم و بدون پروکسی بیرون میروند.
۳. مالتیWAN با mwan3 (failover + load balance)
بستهٔ mwan3 سیاستمحور عمل میکند: هر وصله را health-check میکند (با track_ip) و ترافیک را بر اساس سیاست مسیر میدهد. ما یک سیاست balanced ساختیم که هر ۴ وصله را با وزن مساوی میپذیرد — یعنی هم توزیع بار (load balance) و هم جایگزینی خودکار (failover).
تنظیمات از طریق /etc/uci-defaults/99-mwan اعمال میشود:
# وصلههای WAN فرعی: DHCP از هر مودم/روتر مقصد
for n in wan2 wan3 wan4; do
uci -q set network.$n='interface'
uci -q set network.$n.proto='dhcp'
uci -q set network.$n.peerdns='0'
uci -q set network.$n.metric='0'
done
# افزودن wan2/3/4 به زون wan در فایروال
for i in $(seq 0 9); do
[ "$(uci -q get firewall.@zone[$i].name)" = "wan" ] && {
uci -q add_list firewall.@zone[$i].network='wan2'
uci -q add_list firewall.@zone[$i].network='wan3'
uci -q add_list firewall.@zone[$i].network='wan4'
break
}
done
# mwan3: اینترفیسها + ترکینگ (فقط IPv4)
for n in wan wan2 wan3 wan4; do
uci -q set mwan3.$n='interface'
uci -q set mwan3.$n.enabled='1'
uci -q add_list mwan3.$n.track_ip='8.8.8.8'
uci -q add_list mwan3.$n.track_ip='1.1.1.1'
uci -q set mwan3.$n.family='ipv4'
uci -q set mwan3.$n.interval='5'
uci -q set mwan3.$n.down='3'
uci -q set mwan3.$n.up='3'
done
# اعضا با وزن مساوی
for n in wan wan2 wan3 wan4; do
uci -q set mwan3.${n}_m1_w1='member'
uci -q set mwan3.${n}_m1_w1.interface="$n"
uci -q set mwan3.${n}_m1_w1.metric='1'
uci -q set mwan3.${n}_m1_w1.weight='1'
done
# سیاست balanced + قانون پیشفرض
uci -q set mwan3.balanced='policy'
uci -q add_list mwan3.balanced.use_member='wan_m1_w1'
uci -q add_list mwan3.balanced.use_member='wan2_m1_w1'
uci -q add_list mwan3.balanced.use_member='wan3_m1_w1'
uci -q add_list mwan3.balanced.use_member='wan4_m1_w1'
uci -q set mwan3.default_rule='rule'
uci -q set mwan3.default_rule.dest_ip='0.0.0.0/0'
uci -q set mwan3.default_rule.use_policy='balanced'
uci commit mwan3
وصلههای بیسیم (STA) در /etc/uci-defaults/99-wan-wifi بهصورت غیرفعال و با SSID/رمز پیشفرض تعریف میشوند؛ کاربر در پنل پرشان میکند و فعالشان میکند:
uci -q set wireless.wifinet_wan2='wifi-iface'
uci -q set wireless.wifinet_wan2.device='radio0' # 2.4GHz
uci -q set wireless.wifinet_wan2.network='wan2'
uci -q set wireless.wifinet_wan2.mode='sta'
uci -q set wireless.wifinet_wan2.ssid='SET-WAN2-SSID'
uci -q set wireless.wifinet_wan2.encryption='psk2'
uci -q set wireless.wifinet_wan2.key='change-me-wan2'
uci -q set wireless.wifinet_wan2.disabled='1'
# wan3 -> radio1 (5GHz)، wan4 -> radio0 (یک رادیو دو VAP ستا میگیرد)
سناریوهای پیشنهادی: ۱ کابل + ۲ وایفای ایدهآل است (یکی روی ۲.۴GHz، یکی روی ۵GHz). اگر ۳ وایفای بخواهید، یک رادیو باید ۲ VAP ستا داشته باشد — روی Gale با ۲ رادیو شدنی است.
inet passwall) و mwan3 (جدول inet mwan3) هر دو به prerouting وصله میشوند؛ در تست روی دستگاه تداخلی دیده نشد، اما چون mwan3 فعلاً IPv4 است، خروجیهای IPv6 را جداگانه چک کنید.
۴. منوی Developer و رمز root خالی
یک آیتم منو به نام Developer زیر Network و پیش از Logout اضافه شد که صفحهٔ changelog (نسخههای ۸ تا ۱۳) را نشان میدهد، همراه با «برنامهنویسی: مهدی عسکری» و لینک mehdiaskari.ir. تعریف منو در /usr/share/luci/menu.d/luci-app-dev.json است:
{
"admin/dev": {
"title": "Developer",
"action": { "type": "view", "path": "dev/changelog" },
"order": 60
}
}
همچنین رمز root در اولین بوت پاک میشود (/etc/uci-defaults/99-root-empty → passwd -d root) تا ورود به پنل و SSH بدون رمز باشد. پنل OpenWrt ۲۵.۱۲ هم صفحهٔ اجبارِ تغییر رمز در اولین ورود ندارد، پس این تنظیم پایدار میماند.
۵. بیلد با ImageBuilder + داکر
بیلد روی ImageBuilder رسمی (فرمت .tar.zst) داخل یک کانتینر Alpine انجام شد. دو نکتهٔ فنی که در مسیر رخ داد:
- mwan3 به صورت legacy به
iptablesوابسته است که چند فایل افزونه (libxt_*.so) را میخواهد؛ این فایلها در rootfs بهصورت «شبح» (ghosting) غیرقابلخواندن درمیآمدند و cp نهایی شکست میخورد. فایلهای واقعی را از داخل بستهٔ.apk(باapk extract --allow-untrusted) استخراج و در overlay قرار دادم. - سپس در Makefile، پیش از کپیِ نهایی rootfs، این شبحها حذف و نسخهٔ واقعی رونویسی شد تا تصویر بهدرستی بسته شود.
۶. نصب و بکاپ
روتر از طریق sysupgrade (با حفظ تنظیمات) آپدیت شد؛ چون آدرس LAN روی ۱۹۲.۱۶۸.۱۰.۱ ثابت است و پس از فلش، اسکریپتهای mwan3/STA بهصورت دستی اعمال شدند. همیشه پیش و پس از بیلد، sha256 ثبت میشود:
# factory (فلش از فریمور کارخانه / USB)
b2a4353ab608c0f73b3c8d44b9d444e3053b5685bd6d0a1386d799a118523a2e
# sysupgrade (آپدیت از روی OpenWrt موجود)
42176e2b4d50f1e4315f7df76fd040f5e1086844fd79c59c3c603a162a14a8a6
چک: shasum -a 256 -c sha256.txt
۷. چنجلاگ (v8 → v13)
| نسخه | نکتهٔ کلیدی |
|---|---|
| v8 | وایفای دو‑بانده + netmon (مانیتورینگ) |
| v9 | مهاجرت از PassWall2 به PassWall1 |
| v10 | تمام کلاینتهای پروتکل (xray/sing-box/ss-rust/…) |
| v11 | ایراندایرکت با geoip:IR + geoview |
| v12 | ایراندایرکت با IP/دامنهٔ واقعی (۲۷۷۲ بازه + ۳۶۵ دامنه) و بلاک تبلیغات |
| v13 | مالتیWAN mwan3 (failover+load balance)، رفع باگ دایرکت، منوی Developer، رمز root خالی |
نتیجه: Gale با این فریمور، یک روتر چند‑WANِ کوچک و بیصدا میشود که ترافیک دایرکتش را بدون پروکسی عبور میدهد و پهنای باند چند اینترنت را ترکیب میکند.