做中轉的路由器更新到OpenWrt BarrierBreaker 14.07 後,趁熱乎把自動fucking牆也部署上了。
一、 首先得有個牆外的VPS。
VPS的好處就是方便靈活,一年不到10USD的很多,找一個速度快靠譜點的就可以。
在VPS上面用shadowsocks-libev
架一個ss服務,注意打開-u參數,做DNS中轉查詢會用到。
二、 然後是作爲網關幷已刷OpenWrt的路由器。
淘寶上一大堆。
注意OpenWrt的版本,用最新版的最好。
三、 大致思路如下:
在瀏覽器中使用PAC幷根據域名翻,瀏覽器會將包含域名的url請求發送給socks5代理幷接收返回的數據。與瀏覽正常的網站相比,瀏覽器沒有做DNS的解析請求, DNS的解析在socks5的服務端完成。
而瀏覽器訪問網站通常的流程,DNS解析與發送HTTP請求是分開的,DNS解析與HTTP都要在網關的參與下進行(隻考慮一般情況)。現在已經有了網關的最高權限,那麼隻需將那些被牆的網站根據域名做一個列表,若HTTP請求中的host在這個列表中,那麼將其轉至shadowsocks處理即可。當然,HTTP請求中的host會在HTTP請求發起前去做DNS解析的請求。在OpenWrt中,DNS服務端是dnsmasq
,做請求中轉的是Linux內核防火牆(由iptables操作),shadowsocks是ss-redir
。
於是,被牆的域名列表交給dnsmasq,dnsmasq在返回查詢記錄的同時,會給存在于域名列表中的IP打個標記(由IPSET實現)。Linux的內核防火牆會將打這個標記的請求轉發給ss-redir。
dnsmasq作爲DNS服務端,只是做DNS解析的中轉與緩存,它會將DNS解析請求進一步發送給上級DNS服務端,這個上級DNS服務端,一般由通訊運營商提供,幷在pppoe或DHCP時獲得。問題是,這個上級DNS服務端返回的解析結果幷不可靠,尤其是那些被牆的域名。好在dnsmasq可以爲每個域名指定單獨的DNS服務端,於是將之前那個被牆域名列表複製一份,幷指定去一個可靠的DNS服務端獲取解析結果。
這個可靠的DNS服務端,一般由pdnsd
、ChinaDns
、dns over tunnel
等實現,pdnsd使用TCP協議從國外可靠的DNS服務端獲取結果,ChinaDns丟棄假的幷接收真正的查詢結果,dns over tunnel就是將DNS的查詢通過一個可靠的隧道來保證查詢結果的正確,shadowsocks的ss-tunnel就可以做這個隧道。
四、 配置過程如下:
-
在OpenWrt中安裝shadowsocks。
在shadowsocks官網下載至OpenWrt中用opkg安裝即可。
-
安裝dnsmasq。
OpenWrt的固件中就集成了dnsmasq,但是幷沒有ipset的功能,需要安裝完全版。
opkg update opkg remove dnsmasq opkg install dnsmasq-full opkg install kmod-ipt-ipset ipset
-
配置參考:
(1) shadowsocks服務腳本:
#!/bin/sh /etc/rc.common START=95 USE_PROCD=1 SS_LOCAL=/usr/bin/ss-local SS_REDIR=/usr/bin/ss-redir SS_TUNNEL=/usr/bin/ss-tunnel CONFIG=/etc/shadowsocks.json start_service() { procd_open_instance procd_set_param respawn procd_set_param command "$SS_LOCAL" procd_append_param command -c "$CONFIG" procd_close_instance procd_open_instance procd_set_param respawn procd_set_param command "$SS_REDIR" procd_append_param command -c "$CONFIG" procd_append_param command -b "0.0.0.0" procd_append_param command -l "8080" procd_close_instance procd_open_instance procd_set_param respawn procd_set_param command "$SS_TUNNEL" procd_append_param command -c "$CONFIG" procd_append_param command -b "127.0.0.1" procd_append_param command -l "5353" procd_append_param command -L "8.8.8.8:53" procd_append_param command -u procd_close_instance }
(2) dnsmasq配置:
在
/etc/dnsmasq.conf
中添加一句conf-dir=/etc/dnsmasq.conf.d
/etc/dnsmasq.conf.d/agw_list
中內容如下:server=/www.google.com/127.0.0.1#5353 ipset=/www.google.com/agw
每一個域名有兩條這樣的記錄。
(3) 防火牆配置:
在
/etc/firewall.user
中增加如下內容:ipset -N agw iphash iptables -t nat -A PREROUTING -p tcp -m set --match-set agw dst -j REDIRECT --to-port 8080