返回首页
当前位置: 主页 > 路由器设置 >

翻墙路由器的原理与实现(8)

时间:2016-02-01 13:38点击:

   subprocess.call('iptables -D OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)  

   subprocess.call('iptables -D INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)      

   

signal.signal(signal.SIGINT, clean_up)      

   

try:  

   subprocess.call('iptables -I INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)  

   subprocess.call('iptables -I OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)  

   print('running..')  

   nfqueue.run()  

except KeyboardInterrupt:  

   print('bye') 

执行python dns_hijacking_observation.py,再使用dig @8.8.8.8 twitter.com应该可以看到类似如下的输出:

DNS(ar=[RR(type=41, cls=4096)], qd=[Q(name='twitter.com')], id=8613, op=288)
DNS(an=[RR(name='twitter.com', rdata=';\x18\x03\xad', ttl=19150)], qd=[Q(name='twitter.com')], id=8613, op=33152)
59.24.3.173
DNS(an=[RR(name='twitter.com', rdata='\xc7;\x95\xe6', ttl=27), RR(name='twitter.com', rdata='\xc7;\x96\x07', ttl=27), RR(name='twitter.com', rdata="\xc7;\x96'", ttl=27)], ar=[RR(type=41, cls=512)], qd=[Q(name='twitter.com')], id=8613, op=33152)
199.59.149.230
199.59.150.7
199.59.150.39

可以看到我们发出去了一个包,收到了两个包。其中第一个收到的包是GFW发回来的错误答案,第二个包才是正确的答案。但是由于dig只取第一个返回的答案,所以我们实际看到的解析结果是错误的。

观测劫持发生的位置

利用IP包的TTL特性,我们可以把TTL值从1开始递增,直到我们收到错误的应答为止。结合TTL EXECEEDED ICMP返回的IP地址,就可以知道DNS请求是在第几跳的路由器分光给GFW的。代码如下(https://gist.github.com/4524927):

from netfilterqueue import NetfilterQueue  

import subprocess  

import signal  

import dpkt  

import traceback  

import socket  

import sys      

   

DNS_IP = '8.8.8.8'     

   

# source %E5%9F%9F%E5%90%8D%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BC%93%E5%AD%98%E6%B1%A1%E6%9F%93  

WRONG_ANSWERS = {  

   '4.36.66.178',  

   '8.7.198.45',  

   '37.61.54.158',  

   '46.82.174.68',  

   '59.24.3.173',  

   '64.33.88.161',  

   '64.33.99.47',  

   '64.66.163.251',  

   '65.104.202.252',  

   '65.160.219.113',  

   '66.45.252.237',  

   '72.14.205.99',  

   '72.14.205.104',  

   '78.16.49.15',  

   '93.46.8.89',  

   '128.121.126.139',  

   '159.106.121.75',  

   '169.132.13.103',  

   '192.67.198.6',  

   '202.106.1.2',  

   '202.181.7.85',  

   '203.161.230.171',  

   '207.12.88.98',  

   '208.56.31.43',  

   '209.36.73.33',  

   '209.145.54.50',  

   '209.220.30.174',  

   '211.94.66.147',  

   '213.169.251.35',  

   '216.221.188.182',  

   '216.234.179.13'  

}      

   

current_ttl = 1     

   

def locate_dns_hijacking(nfqueue_element):  

   global current_ttl  

   try:  

       ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())  

       if dpkt.ip.IP_PROTO_ICMP == ip_packet['p']:  

           print(socket.inet_ntoa(ip_packet.src))  

       elif dpkt.ip.IP_PROTO_UDP == ip_packet['p']:  

           if DNS_IP == socket.inet_ntoa(ip_packet.dst):  

------分隔线----------------------------
推荐内容