如果你只是需要一個能在熄燈之後使用的路由器,請在網上買一個帶電池的路由器,只要大約100元即可。
本解決方案主要包括:
- 通過ISATAP隧道使用IPv6
- 直接翻BEEP牆
- 離線下載
- 一個比較靠譜的DNS
如果讀者對路由器有所瞭解,很可能會聽說過OpenWrt這個東西。
OpenWrt是什麼?
OpenWrt是適合於嵌入式設備的一個Linux發行版。
相對原廠固件而言,OpenWrt不是一個單一、靜態的固件,而是提供了一個可添加軟件包的可寫的文件系統。這使使用者可以自由的選擇應用程序和配置,而不必受設備提供商的限制,並且可以使用一些適合某方面應用的軟件包來定製你的設備。對於開發者來說,OpenWrt是一個框架,開發者不必麻煩的構建整個固件就能得到想要的應用程序;對於使用者來說,這意味着完全定製的能力,與以往不同的方式使用設備。
以上摘自Wikipedia。
根據這段描述,我們知道,OpenWrt是一個Linux發行版,因此理論上幾乎任何事情都可以通過OpenWrt來完成。但實際上,受到設備的限制(包括組件和性能等方面),人們通常會從更實際的角度考慮,它能做什麼。
除了本文開始列出的一些功能外,在網上也能找到一些有趣的小玩意,包括遙控小車、視頻監控等。當然,考慮到我們的實際需求,本文將不對這些新奇的想法展開描述。
路由器的選擇
可以安裝OpenWrt的路由器有很多,完整的列表可以在這裏找到:
http://wiki.openwrt.org/toh/start
在挑選路由器前,我們需要再次明確我們的需求:
- 不怕斷電
- 能裝OpenVPN等程序
市面上有電池的路由器還是有一些的,例如TP-Link的MR11U、它的馬甲——Mercury M301等。
而能裝一些程序則是一個比較高的要求,因爲通常路由器的Flash都很小,主流容量是4M,個別路由器甚至只有2M。這給我們在上面安裝一個操作系統,再裝一些程序帶來了比較大的困難。因此,在一些論壇,經常可以看到有人動手改裝路由器,換大一些的Flash,並增加內存。
這一次,我選擇的是淘寶上,有人改裝過的Mercury M301,改裝後的Flash有16M,內存有64M,足夠滿足我們的全部需求。
預編譯OpenWrt
在網上可以下載到很多人編譯好的OpenWrt,但它們並不滿足我們的需求。所以必須自行編譯OpenWrt。
如果讀者有過編譯嵌入式Linux內核或其他嵌入式程序的經驗,那麼編譯OpenWrt的體驗則會相當好。我們不需要去找老舊的交叉編譯器和舊版Linux內核,只需要使用簡單的Make命令,即可編譯出一個OpenWrt出來。
編譯的教程在http://wiki.openwrt.org/doc/howto/buildroot.exigence,簡單的流程如下:
1. 爲了避免不必要的麻煩,裝一個32位版本的Ubuntu,分區容量建議至少15GB。
2. 安裝subversion和build tools,因爲OpenWrt是存放在SVN上的。
$ sudo apt-get update
$ sudo apt-get install subversion build-essential
3. 使用SVN下載源碼。
$ mkdir ~/openwrt
$ cd ~/openwrt
$ svn co svn://svn.openwrt.org/openwrt/trunk/
$ cd trunk
4. 下載安裝feeds,feeds是OpenWrt的包。
$ ./scripts/feeds update -a
$ ./scripts/feeds install -a
5. 依次執行以下命令以完成配置:
$ make defconfig
$ make prereq
$ make menuconfig
此處可能會遇到一些包的缺失信息,只需要按照提示使用apt-get
安裝好即可。
6. 執行make
來編譯。
對於這個流程,有一些問題需要加以說明:
- 從SVN上下載源碼和feeds的文件大概有500MB,在make的時候還會下載大量包(根據menuconfig的選項而不同),因此請儘量使用一個快速的網絡。
- make的時候,很可能會因爲網絡的原因無法下載到需要的包而導致錯誤,這個時候,請使用
make V=99
編譯,可以看到是哪個包下載失敗,然後自行去網上找到這個包,放置在./dl
目錄下。 - 可以使用
make -j n
(把n替換成CPU線程數+1)來多線程編譯,但這樣可能會難以找到錯誤的地方。 - 流程第5步中的
make menuconfig
中需要選擇包,我們在此時只要選擇好路由器的型號,並選中IPv6下的radvd,其他的可以先不選擇。這是因爲,只有在第一次make的時候,編譯腳本纔會去網上下載Linux內核源碼和相關的包,而我們接下來需要修改一些源碼。 - 修改openvpn的編譯選項,以便openvpn能從文件中讀取用戶名和密碼:
打開
./package/feeds/packages/openvpn-devel/Makefile
文件,在define Build/Configure
段的若干選項中(例如在「--enable-small
」之後)增加一行「--enable-password-save
」。
要解決的問題
在我們的需求中,有一個需求是很特殊的——IPv6。在清華,IPv6是一個很奇葩的東西。在不少地方,我們可以使用到原生的IPv6,而且這個IPv6地址還是動態的。但遺憾的是,很多時候,IPv6還需要通過一個Portal來認證,而這個Portal總是不能正常工作。因此,很多人會選擇適用ISATAP服務來訪問IPv6。
如果使用Native IPv6,一切都很簡單,我們只需要讓IPv6橋接,讓IPv4 NAT就可以了。
如果使用ISATAP,則問題變得很複雜:
- 一方面,ISATAP得到的IPv6地址的前綴是64位,這意味着我們不能再劃分子網。
- 在RFC的文檔中,IPv6是不支持NAT的。
於是,我們找到了北郵同學的一個解決方案:napt66。這個方案通過Netfilter,實現了一個私有的NAT服務。該方案的部署比較複雜,但幸運的是,作者給出了一個在OpenWrt上部署的文檔。這裏簡單的總結如下(路徑可能略有不同):
1. 修改Linux內核中IPv6轉發的代碼。該文件位於./build_dir/linux-arch/linux-version/net/ipv6/ip6_output.c
,將以下兩行註釋掉:
if (net->ipv6.devconf_all->forwarding == 0)
goto error;
更新:Linux 3.7開始,內核提供了對NAT6的原生支持。
2. 修改radvd的探測IPv6轉發參數的代碼。該文件位於./build_dir/target-mips_uClibc-version/radvd/radvd.c
,註釋掉以下部分(代碼可能略有不同):
int check_ip6_forwarding(void) {
......
// if (value != 1)
// flog(LOG_DEBUG, "IPv6 forwarding setting is: %u, should be 1", value);
// return -1;
// }
......
}
3. 新建./package/base-files/files/etc/radvd.conf
文件,內容如下:
interface br-lan {
AdvSendAdvert on;
MinRtrAdvInterval 5;
MaxRtrAdvInterval 10;
AdvManagedFlag off;
AdvOtherConfigFlag off;
AdvDefaultPreference high;
prefix fc00:0101:0101::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
};
};
4. 下載napt66.zip,解壓縮到./package/
目錄下,刪除files
目錄,同時刪除Makefile
文件裏的KernelPackage/napt66/install
這一部分,因爲我們需要自行配置。
至此,我們的準備工作全部就緒。
正式編譯OpenWrt
再次運行make menuconfig
,新選擇以下包:
- Base system
- block-mount(自動掛載)
- IPv6
- firewall
- ip6tables
- LuCI
- Collections
- luci
- Applications
- luci-app-ntpc(NTP客戶端,openvpn對時間有要求)
- luci-app-transmission
- Kernel modules
- Filesystems
- kmod-fs-ext4(移動硬盤推薦用此格式)
- Native Language Support
- kmod-nls-utf8
- Netfilter Extensions
- kmod-ip6tables
- kmod-napt66
- Network Support
- kmod-ipip
- kmod-iptunnel4
- kmod-iptunnel6
- kmod-ipv6
- kmod-sit
- kmod-tun
- USB Support
- kmod-usb-storage-extras
- Network
- BitTorrent
- transmission-web
- File Transfer
- vsftpd(有FTP會方便很多)
- Firewall
- iptables
- Routing and Redirection
- ip
- VPN
- openvpn-devel-openssl
完成這些步驟之後就可以執行make
或make -j n
來編譯。經過幾分鐘到幾十分鐘(視網絡環境而定)的編譯,即可在./bin/
目錄下,找到編譯好的固件。
需要注意的是,這樣編譯出來的文件可能太大,而無法生成bin文件。所以根據路由器的型號,還可能需要修改生成固件鏡像的代碼,以我們選擇的此款路由器爲例:
1. 修改固件打包工具:打開./tools/firmware-utils/src/mktplinkfw.c
,找到『8Mlzma』,然後在這段下面添加一段16M的定義:
.id = "16Mlzma",
.fw_max_len = 0xfc0000,
.kernel_la = 0x80060000,
.kernel_ep = 0x80060000,
.rootfs_ofs = 0x100000,
2. 修改Makefile:
打開./target/linux/ar71xx/image/Makefile
,找到含有『MR11U』的這一行,將行末的『4Mlzma』改爲『16Mlzma』。
路由器配置
注:以下配置均以本文選定的路由器及清華實際的網絡環境爲例進行說明。
初始配置
將電腦的IP設置爲192.168.1.2,然後訪問http://192.168.1.1,直接登錄,按照提示修改一個新密碼。
然後在System->Software下卸載firewall,因爲我們需要手動配置NAT。
建議使用ssh直接操作。
網絡配置
網絡配置主要包括/etc/config
目錄下的network
、wireless
和dhcp
文件。
network文件如下:
config interface 'loopback' option ifname 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0'config interface 'lan' option type 'bridge' option proto 'static' option ipaddr '192.168.1.1' option ip6addr fc00:0101:0101::1/64 option netmask 255.255.255.0
config interface 'wan' option ifname 'eth0' option proto 'static' option ipaddr 'your-ip' option netmask '255.255.255.0' option gateway 'your-gateway' option dns '8.8.8.8 8.8.4.4'
wireless文件如下:
config wifi-device 'radio0' option type 'mac80211' option channel '11' option hwmode '11ng' option path 'platform/ar933x_wmac' option htmode 'HT20' list ht_capab 'SHORT-GI-20' list ht_capab 'SHORT-GI-40' list ht_capab 'RX-STBC1' list ht_capab 'DSSS_CCK-40' option txpower '27' option country 'CN'config wifi-iface option device 'radio0' option network 'lan' option mode 'ap' option ssid 'your-ssid' option encryption 'psk2' option key 'your-password'
務必注意這裏的第一段配置,請保持原有的參數。
dhcp文件的dhcp部分如下:
config dhcp 'wan' option interface 'wan' option ignore '1'config dhcp 'lan' option start '100' option leasetime '12h' option limit '150' option interface 'lan'
至此,路由器已經能連通外網,也能給無線設備分配IP地址,但我們發現無線設備並不能訪問外網,因爲我們還沒有配置NAT。
打開/etc/rc.local
文件,在exit 0
前加入:
iptables -t nat -F
iptables -t filter -F
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
然後重啓路由器即可。
IPv6配置
1. 配置ISATAP
在`/etc/rc.local`中加入:ip tunnel add sit1 mode sit remote 59.66.4.50 local your-ip
ifconfig sit1 up
ifconfig sit1 add 2001:da8:200:900e:0:5efe:your-ip/64
ip route add ::/0 via 2001:da8:200:900e::1 metric 1
2. 啓動IPv6轉發和radvd
同樣繼續修改/etc/rc.local
:
sysctl -w net.ipv6.conf.br-lan.forwarding=1
radvd
insmod /lib/modules/3.3.8/napt66.ko wan_if=sit1
重啓路由器之後IPv6應該就生效了。
其他配置
爲了使用CDN,我們可以將一些國內網站交給學校的DNS去解析,只需要修改/etc/dnsmasq.conf
文件爲:
server=/cn/166.111.8.28 server=/100tjs.com/166.111.8.28 server=/115.com/166.111.8.28 server=/126.com/166.111.8.28 server=/126.net/166.111.8.28 server=/163.com/166.111.8.28 server=/17kuxun.com/166.111.8.28 server=/19lou.com/166.111.8.28 server=/2345.com/166.111.8.28 server=/360buy.com/166.111.8.28 server=/360buyimg.com/166.111.8.28 server=/39.net/166.111.8.28 server=/4399.com/166.111.8.28 server=/51.com/166.111.8.28 server=/51.la/166.111.8.28 server=/51buy.com/166.111.8.28 server=/51job.com/166.111.8.28 server=/56.com/166.111.8.28 server=/58.com/166.111.8.28 server=/admin5.com/166.111.8.28 server=/ads8.com/166.111.8.28 server=/aizhan.com/166.111.8.28 server=/alibaba.com/166.111.8.28 server=/alimama.com/166.111.8.28 server=/alipay.com/166.111.8.28 server=/apple.com/166.111.8.28 server=/arpg2.com/166.111.8.28 server=/baidu.com/166.111.8.28 server=/baixing.com/166.111.8.28 server=/bing.com/166.111.8.28 server=/bitauto.com/166.111.8.28 server=/cache.netease.com/166.111.8.28 server=/cctv.com/166.111.8.28 server=/china.com/166.111.8.28 server=/chinanews.com/166.111.8.28 server=/chinaz.com/166.111.8.28 server=/cmbchina.com/166.111.8.28 server=/cn/166.111.8.28 server=/cnbeta.com/166.111.8.28 server=/cnblogs.com/166.111.8.28 server=/cnzz.com/166.111.8.28 server=/csdn.net/166.111.8.28 server=/ct10000.com/166.111.8.28 server=/ctrip.com/166.111.8.28 server=/dangdang.com/166.111.8.28 server=/dianping.com/166.111.8.28 server=/discuz.net/166.111.8.28 server=/docin.com/166.111.8.28 server=/duowan.com/166.111.8.28 server=/eastmoney.com/166.111.8.28 server=/etao.com/166.111.8.28 server=/fastcdn.com/166.111.8.28 server=/ganji.com/166.111.8.28 server=/gtimg.com/166.111.8.28 server=/hao123.com/166.111.8.28 server=/hc360.com/166.111.8.28 server=/hiapk.com/166.111.8.28 server=/hoopchina.com/166.111.8.28 server=/huanqiu.com/166.111.8.28 server=/hudong.com/166.111.8.28 server=/icson.com/166.111.8.28 server=/ifeng.com/166.111.8.28 server=/iloveyouxi.com/166.111.8.28 server=/img.cctvpic.com/166.111.8.28 server=/iteye.com/166.111.8.28 server=/jysq.net/166.111.8.28 server=/kaixin001.com/166.111.8.28 server=/ku6.com/166.111.8.28 server=/lashou.com/166.111.8.28 server=/letv.com/166.111.8.28 server=/live.com/166.111.8.28 server=/love21cn.com/166.111.8.28 server=/lxdns.com/166.111.8.28 server=/meituan.com/166.111.8.28 server=/microsoft.com/166.111.8.28 server=/mop.com/166.111.8.28 server=/mosso.com/166.111.8.28 server=/msn.com/166.111.8.28 server=/nipic.com/166.111.8.28 server=/oeeee.com/166.111.8.28 server=/onlinedown.net/166.111.8.28 server=/paipai.com/166.111.8.28 server=/pchome.net/166.111.8.28 server=/pcpop.com/166.111.8.28 server=/pengyou.com/166.111.8.28 server=/pptv.com/166.111.8.28 server=/qidian.com/166.111.8.28 server=/qiyi.com/166.111.8.28 server=/qq.com/166.111.8.28 server=/qunar.com/166.111.8.28 server=/renren.com/166.111.8.28 server=/sina.com/166.111.8.28 server=/sogou.com/166.111.8.28 server=/sohu.com/166.111.8.28 server=/soku.com/166.111.8.28 server=/soso.com/166.111.8.28 server=/soufun.com/166.111.8.28 server=/taobao.com/166.111.8.28 server=/taobaocdn.com/166.111.8.28 server=/tenpay.com/166.111.8.28 server=/tmall.com/166.111.8.28 server=/tom.com/166.111.8.28 server=/tudou.com/166.111.8.28 server=/v.iask.com/166.111.8.28 server=/vancl.com/166.111.8.28 server=/verycd.com/166.111.8.28 server=/weibo.com/166.111.8.28 server=/wikipedia.org/166.111.8.28 server=/xinhuanet.com/166.111.8.28 server=/xunlei.com/166.111.8.28 server=/yahoo.com/166.111.8.28 server=/yesky.com/166.111.8.28 server=/ynet.com/166.111.8.28 server=/yocc.net/166.111.8.28 server=/youboy.com/166.111.8.28 server=/youdao.com/166.111.8.28 server=/youku.com/166.111.8.28 server=/zhaopin.com/166.111.8.28 server=/zhubajie.com/166.111.8.28 server=/sanguosha.com/166.111.8.28 server=/.phobos.apple.com/178.79.131.110