使用ipset让openwrt上的shadowsocks更智能的重定向流量

本文编写于3457天前,最后编辑于 2677天前,部分内容可能已经过时,请您自行斟酌确认。

OpenWRT上从2.66版开始的Dnsmasq已经支持IPSET,但是默认的版本不支持ipset,需要dnsmasq-full.
查看dnsmasq是否支持ipset

[root@PandoraBox:/root]# dnsmasq -v
Dnsmasq version 2.72  Copyright (c) 2000-2014 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth DNSSEC loop-detect

如果 Compile time options显示ipset就是支持的.no-ipset就是不支持.

但是PandoraBox默认源里面没有dnsmasq-full,在网上找到了aa65535编译的版本,已经加上了chinadns,非常给力.使用ipset的主要优势在于直接将所有被污染的域名解析结果交给ipset,不需要动态维护IP列表,在路由上更智能.
以下是设置步骤
1.卸载默认的dnsmasq

opkg remove dnsmasq

2.安装dnsmasq-full

opkg install http://sourceforge.net/projects/openwrt-dist/files/depends-libs/ramips/libnettle_2.7.1-1_ramips_24kec.ipk
opkg install http://sourceforge.net/projects/openwrt-dist/files/depends-libs/ramips/libgmp_6.0.0-1_ramips_24kec.ipk
opkg install http://sourceforge.net/projects/openwrt-dist/files/dnsmasq/2.72-8372a82/ramips/dnsmasq-full_2.72-6_ramips_24kec.ipk

3.安装ipset

opkg update //安装前必须更新包数据库缓存。
opkg install ipset iptables-mod-nat-extra

安装的时候会报错,需要重启一次路由才可以正常使用.
4.安装配置shadowsocks就不细说了,参考这里
5.用ipset创建一个set,这里我创建的set名字为fuckgfw,然后将这个set中所有IP均转发到shadowsocks(这里本机的shadowsocks监听的是默认的1080端口)。建议将下面的命令写入 /etc/rc.local 。每次开机自动运行。

ipset -N gfwlist iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080

设置 dnsmasq 对某些域名使用pdnsd进行解析并且加入fuckgfw这个set:
为了保持配置文件整洁,建议在 /etc/dnsmasq.conf 最后加入:

conf-dir=/etc/dnsmasq.d

然后新建目录 /etc/dnsmasq.d,自定义的配置文件就放这里面.在这里我们使用一个python脚本转换gfwlist里面的网址为符合dnsmasq格式要求的配置文件.
脚本内容为如下

#!/usr/bin/env python  
#coding=utf-8
#  
# Generate a list of dnsmasq rules with ipset for gfwlist
#  
# Copyright (C) 2014 http://www.shuyz.com   
# Ref https://code.google.com/p/autoproxy-gfwlist/wiki/Rules    
 
import urllib2 
import re
import os
import datetime
import base64
import shutil
 
mydnsip = '127.0.0.1'
mydnsport = '1053'

# the url of gfwlist
baseurl = 'https://www.vpnhot.com/gfwlist.txt'
# match comments/title/whitelist/ip address
comment_pattern = '^\!|\[|^@@|^\d+\.\d+\.\d+\.\d+'
domain_pattern = '([\w\-\_]+\.[\w\.\-\_]+)[\/\*]*' 
tmpfile = 'gfwlisttmp'
# do not write to router internal flash directly
outfile = 'gfwlist.conf'
rulesfile = 'gfwlist.conf'
 
fs =  file(outfile, 'w')
fs.write('# gfw list ipset rules for dnsmasq\n')
fs.write('# updated on ' + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '\n')
fs.write('#\n')
 
print 'fetching list...'
content = urllib2.urlopen(baseurl, timeout=15).read().decode('base64')

# write the decoded content to file then read line by line
tfs = open(tmpfile, 'w')
tfs.write(content)
tfs.close()
tfs = open(tmpfile, 'r')

print 'page content fetched, analysis...'

# remember all blocked domains, in case of duplicate records
domainlist = []

for line in tfs.readlines():    
    if re.findall(comment_pattern, line):
        print 'this is a comment line: ' + line
        #fs.write('#' + line)
    else:
        domain = re.findall(domain_pattern, line)
        if domain:
            try:
                found = domainlist.index(domain[0])
                print domain[0] + ' exists.'
            except ValueError:
                print 'saving ' + domain[0]
                domainlist.append(domain[0])
                fs.write('server=/.%s/%s#%s\n'%(domain[0],mydnsip,mydnsport))
                fs.write('ipset=/.%s/gfwlist\n'%domain[0])
        else:
            print 'no valid domain in this line: ' + line
                    
tfs.close()    
fs.close();

#print 'moving generated file to dnsmasg directory'
#shutil.move(outfile, rulesfile)

#print 'restart dnsmasq...'
#print os.popen('/etc/init.d/dnsmasq restart').read()
 
print 'done!'

gfwlist的地址默认是访问不了的,我们替换为镜像地址.生成的配置文件很长,有伍仟多行,这里就不放上来了.用ftp工具穿到/etc/dnsmasq.d里面.
然后重启dnsmasq

/etc/init.d/dnsmasq restart

6.通过下面的命令查看set中的IP,这样可以确定解析是否正常,并且查看某网站是否正确的被加到了ipset:

ipset list gfwlist

7.通过下面的命令可以清理掉set中所有ip。更多的ipset用法请查看ipset help

ipset flush gfwlist

8.本文参考了北落师门的教程
更新:我目前是配合shadowvpn+pdnsd tcp解析使用的,但是现在dns解析似乎也不太稳定了,直接让Google Dns 走VPN吧

[root@PandoraBox:/etc/dnsmasq.d]#route add -host 8.8.8.8 dev tun0
[root@PandoraBox:/etc/dnsmasq.d]#route add -host 8.8.4.4 dev tun0

使用ipset让openwrt上的shadowsocks更智能的重定向流量》上有 8 条评论

  1. 弓长十二 弓长十二

    我看到了两个从gfwlist生成dnsmasq conf的方案。感觉这个生成的列表应该要小一些

    问题是2000多域名应该有很多都是无效的吧- -
    蛋疼啊
    我看看性能什么的吧

    PS 你贴的这个脚本是自动把生成文件移动到dnsmasq目录并且重启dnsmasq的。。。你就不能悄悄的删掉么。。。。

    回复
  2. Theosoft Theosoft

    我按照博主的文章配了路由。现在http的请求可以正常自动分流到1080端口走vpn,但是https的网页都打不开。比如我打开http://www.facebook.com,会自动302到https://www.facebook.com,然后就打不开了。手动设置代理到路由的1080端口就没问题,是iptable的设置问题吗?

    回复
  3. actg actg

    我不信你这句话能执行成功:
    ipset -N gfwlist iphash

    ipset不支持-N参数不说,iphash是什么东西? ipset支持这种类型? ipset help看看吧。
    我猜的没错应该是hash:ip

    回复

发表评论 取消回复

电子邮件地址不会被公开。 必填项已用 * 标注