randybai / autoddvpn

Automatically exported from code.google.com/p/autoddvpn
0 stars 0 forks source link

用户需要自己维护域名黑名单 #120

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
請描述一下您進行怎樣的操作之後碰到了問題
1.为了使用本地的CDN,用户需要自己维护被GFW墙掉的域名列表
2.
3.

你期待是怎樣的結果,然而卻出現了什麼情形?
只需一次设置,以后就可以即能用本地CDN,又不会被域名污��
�

請提供以下資訊:
由于GFW的黑名单是不断变化的,在现有模式下,只有当撞了��
�以后才能将域名添加入列表中,对于经常访问外国网站的用�
��,体验很不好

分析:
1 
GFW污染掉的域名返回的IP是有限的,即使用不提供的DNS服务的
国外IP地址作为DNS服务器查询被污染的域名,GFW也会返回解析
出的错误IP地址。
2 
使用提供DNS服务的国外IP地址作为DNS服务器查询被污染的域名
,GFW会返回解析出的错误IP地址,但是正确的IP地址也会在随�
��被返回。
3 
使用本地ISP提供的DNS查询被污染的域名,由于DNS的逐级查询��
�而且域名在国外,查询过程会通过GFW,因此查到的结果也是�
��GFW污染的,但是和第2点不同,这次不会返回正确的IP

解决思路:
1 
为了使用本地CDN,主DNS需要设置成本地ISP提供的DNS服务器,��
�DNS设置为国外的DNS比如8.8.8.8
2 
在系统启动时多次查询被污染的域名,获得GFW返回的错误IP列
表
3 
使用iptables判断DNS数据包是否包含被污染的IP,如果是则直接�
��弃

这么做的好处是:
1 查询首先使用本地DNS,会返回CDN结果
2 
如果查的是被污染的域名,数据包会被丢弃,DNS客户端会使��
�位于国外的副DNS查询,GFW依然会返回错误IP,但是还是会被��
�弃,紧接着正确的IP就会返回,可以避免DNS污染
3 
DNS查询不需要通过VPN通道,即使VPN再不稳定,用户也可以正��
�查询DNS

坏处:
1 
启动时为了获得GFW返回的错误IP列表,多次查询被污染的域名
,耗时过长
2 
需要一开始设置一个被污染的域名列表(但是即使域名以后��
�封也无所谓,这点后面会说)
3 当第一次查询被污染的域名时需要等待主DNS超时

下面是我在OpenWRT上写的脚本
{{{
#!/bin/sh

NONEXISTDOMAIN="non.exist.domain"
POSIONEDDOMAIN="www.twitter.com www.facebook.com www.youtube.com"
LOOPTIMES=30

badip=""

for DOMAIN in $NONEXISTDOMAIN ; do
        for IP in $(dig $DOMAIN +time=1 +tries=1 +retry=0 | grep ^$DOMAIN | grep -o -E "([0-9]+\.){3}[0-9]+") ; do
                if [ -z "$(echo $badip | grep $IP)" ] ; then
                        badip="$badip   $IP"
                fi
        done
done

for i in $(seq $LOOPTIMES) ; do
        for DOMAIN in $POSIONEDDOMAIN ; do
                for IP in $(dig @$DOMAIN $DOMAIN +time=1 +tries=1 +retry=0 | grep ^$DOMAIN | grep -o -E "([0-9]+\.){3}[0-9]+") ; do
                        if [ -z "$(echo $badip | grep $IP)" ] ; then
                                badip="$badip   $IP"
                        fi
                done
        done
done

for IP in $badip
do
        hexip=$(printf '%02X ' ${IP//./ }; echo)
        iptables -I INPUT -p udp --sport 53 -m string --algo bm --hex-string "|$hexip|" --from 60 --to 180  -j DROP
        iptables -I FORWARD -p udp --sport 53 -m string --algo bm --hex-string "|$hexip|" --from 60 --to 180 -j DROP
done
}}}

由于上面脚本在查询GFW返回的错误IP时,使用了被污染的域名
本身作为DNS服务器,因此如果以后GFW将该域名解禁,查询将��
�返回任何结果(但是会超时,使得耗时更长),并不会影响b
adip列表,只需要在开始把足够多的被污染域名填入POSIONEDDOMAI
N即可。放入POSIONEDDOMAIN的域名应保证该域名以后不会提供DNS��
�析服务,同时该域名也不太容易被GFW解封

PS:可以使用策略路由使得仅对80端口和443端口的访问走VPN,�
��他诸如DNS、P2P的数据包即使发往国外,也使用本地线路。

Original issue reported on code.google.com by hack...@aim.com on 13 Feb 2012 at 7:34

GoogleCodeExporter commented 9 years ago
滿有意思的想法,聽起來是基於graceMode模式來增加智能的判��
�最新被污染的域名,進而進行一些腳本的處理是嗎?

graceMode已經可以解決CDN問題,透過dnsmasq的static 
config也可以解決部分常用域名的DNS污染問題,您希望透過新��
�腳本來做到怎樣的功能呢?

Original comment by pahud...@gmail.com on 13 Feb 2012 at 8:08

GoogleCodeExporter commented 9 years ago
以下摘自graceMode 的介绍
----------------------------------------------
使用本地DNS(ISP提供的DNS或local DNS), 
讓DNS查詢可以非常快速穩定,同時具有CDN加速的優勢,然而��
�於有劫持風險的域名例如twitter, youtube, 
facebook等則強迫使用Google DNS, 
這樣一來如果VPN不穩導致DNS解析不穩,頂多也只是影響twitter,
 youtube, 
facebook等有劫持風險的網站,其他網站完全不用擔心解析問題
。(注:事實上本文最後的dnsmasq_options設置方式完全可以避免t
witter facebook等劫持風險) 
----------------------------------------------

实际上GFW的域名污染列表是一直变化的,去年我用autoproxy的��
�候就遇到敏感时期封锁一些常用网站(例如华尔街日报),�
��后再解封的例子。特别是像我这种经常通过Google搜索到国外
网站、论坛上搜索资料的人,事前不可能知道我将访问哪些��
�名,也不可能知道哪些域名被污染。如果每次遇到域名被污�
��都要手动添加并刷新本地DNS缓存太累了,所以才弄了个这个
办法。

这个目的就是为了通过手中有限的被污染域名列表来避免任��
�域名被污染。
对比下graceMode和该方法的区别:
graceMode:只要访问的域名不在graceMode的域名列表中就会导致��
�页打不开,需要手动上路由器修改
该方法:除非POSIONEDDOMAIN里所有的域名都解封或者GFW改变其行
为使得返回的IP完全随机,才会导致需要用户手动干预。个人
认为当POSIONEDDOMAIN里所有的域名都解封的时候,墙也该倒了,
也用不到翻墙了。

Original comment by hack...@aim.com on 13 Feb 2012 at 8:46

GoogleCodeExporter commented 9 years ago
了解,這個討論蠻有意思的。

進一步再問問:

1. 
你在國外網站上網的時候,打不開一個網站,你如何知道這��
�一個DNS污染的情況?

2. 如果確定是DNS污染的話,是否你需要手動加入 NONEXISTDOMAIN 
variables裡面重新執行一次你的腳本,執行了腳本之後如果是��
�個已知的污染IP則封鎖國內DNS對這個IP的解析,而讓2nd DNS(via 
VPN的國外DNS)來進行正確的解析,長久下來就可以累積自己的 
POSIONEDDOMAIN 是嗎?

Original comment by pahud...@gmail.com on 13 Feb 2012 at 8:56

GoogleCodeExporter commented 9 years ago
還有一個我擔心的問題, /etc/resolv.conf裡面設置兩台nameservers, 
一般來說都是先讓第一台解析,如果沒有回應才讓第二台解��
�,但如果ISP 
DNS回應慢了的情況,或是其他無法預期的網路狀況造成1st 
DNS來不及解析,fall-back給2nd DNS了(或者OS直接選了2nd 
DNS來解析),這樣很可能國內網站的CDN架構也會亂套了。上海�
��信的user連到北京網通去,而用戶一直沒發現。

這個情況也是有可能的,我在一般公司環境內網有兩台DNS, 
但有時候總是會跑到第二台DNS進行解析。

Original comment by pahud...@gmail.com on 13 Feb 2012 at 9:03

GoogleCodeExporter commented 9 years ago
對了,這段是怎麼做到的?

2 
如果查的是被污染的域名,数据包会被丢弃,DNS客户端会使��
�位于国外的副DNS查询,GFW依然会返回错误IP,但是还是会被��
�弃,紧接着正确的IP就会返回,可以避免DNS污染

如果2nd DNS在國外,也不走VPN, 2nd DNS被污染的返回結果被DROP, 
為什麼接著正確的IP就會返回呢?

Original comment by pahud...@gmail.com on 13 Feb 2012 at 9:19

GoogleCodeExporter commented 9 years ago
这样设置了以后应该不会再遇到DNS污染了。因为GFW返回的伪��
�包是有特征的(即返回的IP是固定的那几个),通过识别该��
�征来丢弃GFW伪造的数据包。

NONEXISTDOMAIN 
那段其实是为了防止ISP提供的DNS对于不存在的域名会返回他��
�己IP,如果用dnsmasq的话可以用bogus-nxdomain来解决,就不需要��
�这段代码了。

POSIONEDDOMAIN 
是不积攒的,只是为了通过POSIONEDDOMAIN来识别GFW伪造的数据包
的特征。

一般来说ISP的DNS返回速度要比国外的DNS快很多啊,如果真慢��
�,确实会造成CDN错乱,不过这种情况应该并不多见,实在不�
��可以多设置几个ISP的DNS在前面(当然,这样的话第一次查询
被污染域名等的时间就更长了)。对了,dnsmasq需要加 -o 选项
-o, --strict-order 
By default, dnsmasq will send queries to any of the upstream servers it knows 
about and tries to favour servers that are known to be up. Setting this flag 
forces dnsmasq to try each query with each server strictly in the order they 
appear in /etc/resolv.conf 

目前GFW是在旁路监听的,并没有像防火墙一样串连到主干网��
�所以GFW无法丢弃数据包,只能产生干扰数据包,包括TCP的RST�
��是一样的,如果客户端和服务器都忽略就能无视GFW继续通讯��
�.

不信的话你可以拿抓包工具看下,用8.8.8.8查询www.twitter.com是否
最终正确的IP会返回

Original comment by hack...@aim.com on 13 Feb 2012 at 10:18

GoogleCodeExporter commented 9 years ago
了解,我看懂你的設計了,非常不錯!!

不知道DDWRT的iptables是否也支持 -m string --algo bm --hex-string , 
如果有的話我找時間來玩看看。

Original comment by pahud...@gmail.com on 13 Feb 2012 at 10:25

GoogleCodeExporter commented 9 years ago
剛剛仔細玩了一下,你這個方法真的非常不錯,可惜DDWRT的ipt
ables不支持這些module, OpenWRT很適合做這樣的運用。

這樣的確是最好的方法,學習了!

Original comment by pahud...@gmail.com on 13 Feb 2012 at 2:10

GoogleCodeExporter commented 9 years ago
不支持string模块吗?

抱歉我手头没有DD-WRT路由器,不过翻了下DD-WRT的代码,发现��
�面有这个模块的代码的。
http://svn.dd-wrt.com:8000/browser/src/linux/brcm/linux-2.6.23/net/netfilter/xt_
string.c

不知道是不是默认没有带这个模块?

不过这个脚本的耗时我还是不太满意,刚我又看了下dig命令��
�用法,发现可以用批量查询,试了下速度提升也没有多少提�
��。估计只有写成程序才能做到异步发起大量DNS查询请求再等
待回应了。

Original comment by hack...@aim.com on 13 Feb 2012 at 5:18

GoogleCodeExporter commented 9 years ago
lz我是小白
想问问 这个代码可以加入到番茄固件吗?
能不能搞个教材.
那真是服务大众了.
先谢谢了.

虽然看不大懂,但是判断机制是很棒的,更加智能化~

Original comment by linjimmyiphone@gmail.com on 1 Apr 2012 at 3:09

GoogleCodeExporter commented 9 years ago
现在手头只有openwrt的路由器。
不过上面的脚本用到的有些模块估计番茄固件不会默认自带��
�(基于固件大小考虑),你可能需要重新编译固件(如果可�
��的话)才能把脚本移植到番茄上

Original comment by hack...@aim.com on 12 Apr 2012 at 8:22

GoogleCodeExporter commented 9 years ago
tomato 固件可以用 u32 模块。

iptables -I INPUT -p udp -m udp --sport 53 -m u32 --u32 
"0&0x0F000000=0x05000000 && 
22&0xFFFF@16=0x5d2e0859,0xcb620741,0x0807c62d,0x4e10310f,0x2e52ae44,0xf3b9bb27,0
xf3b9bb1e,0x9f6a794b,0x253d369e,0x9f1803ad" -j DROP
iptables -I INPUT -p udp -m udp --sport 53 -m u32 --u32 
"0&0x0F000000=0x05000000 && 22&0xFFFF@16=0x3b1803ad" -j DROP

Original comment by lir...@gmail.com on 14 Sep 2012 at 7:00