Shadowsocks + GfwList 实现 OpenWRT / LEDE 路由器自动科学上网

本站发布的三种 shadowsocks 在 openwrt 上的自动科学上网方案:

1、Shadowsocks + ChnRoute 实现 OpenWRT / LEDE 路由器自动科学上网
2、Shadowsocks + Redsocks 实现 OpenWRT 路由器自动科学上网 (停止更新)
3、Shadowsocks + GfwList 实现 OpenWRT / LEDE 路由器自动科学上网

本方案依靠GFWList,List中的域名站点走代理,不在List中的域名不走代理,根据域名判断。然而其实本质上依然是根据IP判断是否代理IP走代理,dnsmasq-full可以将解析域名得到的IP加到一个ipset中,利用这个ipset来判断走不走代理。实际是完成了gfwlist(域名列表)到dnsmasq的ipset规则再到IP地址的转换。同样,本方案依然可以搭配ChinaDNS搭配使用,也可以使用ss-tunnel,或者是自己的DNS服务器。

本方案的优点明确,只有被墙的站点才走代理,但是gfwlist并不能100%涵盖被墙站点,而且有些国外站点直连速度远不如走代理,特别是你代理服务器速度较快,希望通过代理加速国外访问时,此方案就不是那么好用了。请酌情选择你所使用的方案。

注:由于近期OPENWRT/LEDE的一系列变化,以及作者aa65535的一系列更改,本文需要更新,下面的步骤仅供参考!本人应该会在近期休假期间更新本文。不排除鸽的可能:)

一、安装

方法一: 添加作者的软件源,直接利用opkg命令安装 (此方式快捷方便,推荐!)

软件源位置:http://openwrt-dist.sourceforge.net/packages/

前提是所用网络环境直连sourceforge.net和downloads.lede-project.org没有问题。此处仅提供LEDE 17.X 的步骤。

首先添加 a65535 的 gpg key,只有这样,第三方的包才能通过签名验证。执行:

打开Luci,定位到“系统”-“软件包”-“配置”选项卡,在“自定义feeds”末尾加入两行并点击“提交”:

请根据自己的CPU架构(可以执行 opkg print-architecture 查看,或者参考“发行版软件源”里的URL里的文本),将mipsel_24kc替换成相应的文本,最后点击提交。

然后执行命令 opkg update 更新软件列表,然后执行下列命令安装依赖包以及shadowsocks相关的软件:


方法二: 手动下载软件包,上传至路由器后安装

依赖列表

右边注释为该包在官方软件源目录下划分到了哪一类 方便查找

LEDE 安装步骤

写在前面:由于LEDE官方软件源包含最新版本shadowsocks-libev软件包,但是官方包和本文使用的aa65535的包不同,并且不兼容,因此请一定要手动下载安装aa65535的软件包,避免装成LEDE官方软件源中的包。

首次安装的话,先确保路由器联网,并更新软件包列表:

注:部分ISP访问LEDE官方站点可能会非常缓慢甚至下载失败,此时需要自行在PC上下载上面的依赖包以后自行上传至路由器目录手动安装。

首先,需要手动安装部分依赖包(并不是所有的依赖包,部分依赖包会自动从软件仓库安装)

接下来下载软件,注意需要根据自己的CPU型号来进行选择。

下载地址: http://openwrt-dist.sourceforge.net/packages/base/

需要下载的文件:

将下载的包通过WinSCP之类的工具上传至路由器的/tmp目录。

然后卸载dnsmasq并安装dnsmasq-full以及剩下的包:

注意不要装成LEDE官方源里的shadowsocks-libev包!

二、配置shadowsocks

1、配置 /etc/shadowsocks.json ,格式如下:

请自行修改好服务器IP、端口号、密码、加密方式。

新建文件: /etc/init.d/shadowsocks :

修改文件权限:

然后启动shadowsocks,并设置开机运行:

最后检查一下是否正常启动了:

如果未能正确启动,尝试手动执行,看看报什么错:

额外的优化:

开启 TCP Fast Open (TCP快速打开,缩略为TFO)

需求: 系统内核版本≥3.7,shadowsocks-libev≥3.0.4,shadowsocks服务端开启tcp fast open。

修改 /etc/sysctl.conf ,加入如下一行:

执行如下命令使之生效:

配置文件 /etc/shadowsocks.json 增加一行:

最后重启一下shadowsocks即可:

 

2、配置dnsmasq和ipset

2.1. 将如下规则加入到“网络→防火墙→自定义规则”中(最后的1080是shadowsocks的本地端口 酌情修改):

如果你需要

2.2. 修改dnsmasq配置:

OPENWRT:

修改 /etc/dnsmasq.conf,在最后加入 conf-dir=/etc/dnsmasq.d

LEDE:

执行:

如果返回值为 uci: Entry not found 或者其他非  /etc/dnsmasq.d 的值,则执行:

2.3 添加gfwlist和China-List配置文件:

新建并进入目录  /etc/dnsmasq.d ,下载 dnsmasq_gfwlist_ipset.conf 后放入该目录。

自动生成配置文件的脚本,本人放在这里:https://github.com/cokebar/gfwlist2dnsmasq

你可能需要自行修改这个文件,格式如下:

三、配置防污染DNS

1. 步骤一,有三个方案:

方案一 (由于不加密 所以有风险 不推荐):

在代理服务器上搭建DNS服务来解析国外网站,可用dnsmasq或者pdnsd,监听非53端口。

比如说DNS服务器IP是:3.4.5.6,端口是5050,那么使用替换功能将 /etc/dnsmasq.d/dnsmasq_list.conf 里面的 127.0.0.1#5353 全部替换成 3.4.5.6#5050 即可。

最后重启路由器即可。

方案二 (如果此方案较稳定那么推荐这个方案 不过不少ISP会出现UDP方式不稳定的情况,如果遇到请用方案三):

使用ss-tunnel转发UDP的DNS请求,修改 /etc/init.d/shadowsocks 文件,如需修改上游DNS,请修改 DNS=8.8.8.8:53 字段,本地端口修改 TUNNEL_PORT=5353 :

最后重启路由器即可。

方案三:使用dns-forwarder将DNS转成TCP后走ss代理解析:

dns-forwarder的安装可参考:《Shadowsocks + ChnRoute 实现 OpenWRT / LEDE 路由器自动科学上网》一文中的安装部分,到文中提到的地址,下载安装dnsforwarder_x.x.xx_xxxx.ipk,luciappdnsforwarder_x.x.xx_all.ipk即可。

配置也很简单,luci界面,“服务”→”DNS 转发”(英文界面是DNS Forwarder),如图配置:

最后需要在自定义防火墙规则里再增加一句,来确保8.8.8.8是走代理的:

其他TCP查询方式可以参考:

TCP 方式查询解决 DNS 污染问题


2. 步骤二

在WAN口配置中如图所示,将DNS手动指定为127.0.0.1:

ss222

最后在DHCP/DNS设置中将你的ISP的DNS填入(或者使用114DNS等公共DNS)

dnsmasq_localdns

 

最后你可能需要重启一下路由器,以及清空一下你的PC/PED设备的DNS缓存。


PS1:发现有不少人之前用过chnroute方案,然后改成gfwlist方案,此时记得把忽略解析文件的勾选去掉并把原来的设置填回去:

problem1

 

四、其他

一些强烈推荐的额外设置项(涉及到更新、维护)可以参考:《Shadowsocks for OpenWRT / LEDE 拾遗》

需要自己搭建服务器的,可以参考:shadowsocks – libev 服务端的部署

推荐的VPS商家见:https://cokebar.info/about

本博客有关 shadowsocks 文章合集目录

五、写在最后

本人作为一名普通使用者,水平有限,且文章也缺乏校审,肯定有错误存在,也有很多能改进的地方,如有意见或建议,请留言指出,万分感谢! 如果使用时遇到问题也欢迎留言,本人如果有空都会回复,不过请一定要将出错信息贴出来,有些错误信息需要到系统日志中查看。

 


参考文章:https//kyonli.com/p/18

618 条评论

  1. xmomowan 回复

    大神您好!我有一个问题想请教您!
    $ iptables -t nat -A PREROUTING -p tcp -m set –match-set gfwlist dst -j REDIRECT –to-port 1080
    这一条命令中,PREROUTING的指的是不是进入路由器的流量?如果是的话,转发进入路由器流量为什么能做到爬墙呢?

    1. xmomowan 回复

      啊,我自己想通了!感谢!

    2. cokebar 文章作者 回复

      这条命令加入到NAT表的PREROUTING链,使得满足条件的包在做DNAT时候转发至ss-redir.

  2. Blueness 回复

    我使用方法3并且使用自己的DNS,请问新版本的/etc/init.d/shadowsocks怎么改哇?

  3. 春夏秋冬 回复

    楼主我用方案二来解决DNS污染,每次用了个十来天DNS就会在次被污染,也不知是怎么回来,我如果改用TCP方式,安装pdnsd,是不是还得安装chaindns,pdnsd是不是用来接管dnsmasq-full的

  4. Jacky Bao 回复

    博主,我又来了。我把你这套方案做成了一个ipk的包,求推广和小广告。
    ipk介绍和下载:https://github.com/bettermanbao/openwrt-shadowsocks-libev-full

    1. cokebar 文章作者 回复

      1. 非常希望能够把luci界面独立出来
      2. 我写那个watchdog脚本非常简易 建议要么修改完善一下 否则可能会遇到一些bug 并且也推荐能独立出来 因为适合于各类FQ方案 这样用chnroute等其他方案的人也可以用上
      3. 一个问题,你对防火墙规则和dnsmasq规则是如何写入的?如果是安装时候–force-overwirte就不大合适 这样造成卸载后无法还原,建议一个启动脚本,启动时候加入防火墙规则并使其生效,停止时候去掉规则并使其生效

      1. Jacky Bao 回复

        1. 等我更新下Makefile,增加一个_noluci的package就好了。这个luci界面因为是针对我的ipk定制的,所以也没必要做成单独的ipk包。
        2. 你的watchdog我用了很久了,期间遇到各种ss死掉的情况,都很不错,暂时没有发现bug。你指的bug是?
        3. 防火墙规则和dnsmasq规则是在postinstall脚本内写入的,因为没有写postremove脚本,所以卸载后暂时无法自动清除,这个也等我更新吧。

        1. cokebar 文章作者

          1. 之前没细看 我瞅了一下貌似目前没有单抽出luci的必要 我受了aa65535做的spec版本影响了 他是分开的。我推荐luci界面可以参考他的,现在的布局挺不错。
          2. 大多数没问题 但是我这个检测只是单单wget一下百度和谷歌的网站 实际情况可能比较复杂,不过可以在遇到的时候再改脚本
          3. 建议不是写到安装和卸载的时候 而是程序启动和停止的时候。这样就可以临时暂停代理了。对于只代理被墙网站可能没啥影响,因为代理停了也访问不了,不过如果是自定义加入的非被墙的网站(比如强制某网站走代理加快访问速度),如果代理抽风连不上或者是速度突然变得缓慢,你想停代理改为直连,就得手动去掉iptables规则,或者dnsmasq的ipset规则才行。
          整个的原则希望是:对系统配置的影响是临时的,仅限于启动时,停止后还原。

        2. cokebar 文章作者

          还有一个问题,需要force-overwrite是为什么?

      2. Jacky Bao 回复

        3. 这个问题我已经考虑到了。临时增加或删除需要走ss代理的网站,可以通过我的luci界面修改custom_list.conf文件,修改是实是生效的。完全不用去改iptable,dnsmasq。

        –force-overwirte 是因为安装dnsmasq-full的时候不能自动删除预装的dnsmasq,openwrt没提供这个功能,所以只能让dnsmasq-full覆盖安装原来的dnsmasq。如果通过脚本在preinstall的时候删除dnsmasq,那安装dnsmasq-full的时候,有些依赖包就没法自动去openwrt的源下载了。暂时只能这么折中一下了。

        1. cokebar 文章作者

          我觉得应该dnsmasq-full由用户自行安装 你的包只要检测没有dnsmasq-full就无法安装就行了

    1. cokebar 文章作者 回复

      不错。最近正好想换成gfwlist方案,回头试试。
      希望能继续加强,我在想直接参照 https://github.com/shadowsocks/openwrt-shadowsocks 这个版本,把里面ss-rules改成gfwlist方式的,是否可行,这样的话,访问控制啥的也都有了。不过我知道这需要精力和时间,我看好你哦~

      我是不懂luci-app怎么写啦,不过还能稍微看懂点shell script。我很想能有个同时支持gfwlist和chnroute两种方案的集成化的openwrt版本,不过在我身上没法实现了,没精力去学那些东西了,毕竟不是在学校里那段时间充分了。

    2. cokebar 文章作者 回复

      ss-watchdog建议去掉-4 我用的CC15.05 带的wget没有-4参数 当初我加上是因为有人反映ipv6环境下会失效

      1. Jacky Bao 回复

        wget -4 的情况是这样的:op自带的busybox版的wget不支持-4和timeout,所以集成固件我是把-4去掉的,并且在编译时增加了timeout的支持。一键安装包因为无法修改已经编译好的固件,所以我在依赖关系里增加了GNU版的wget,这个版本的wget默认支持-4和timeout。
        chnroute的版本,因为chinadns作者已经不在更新,而且chinadns运行久了会傻掉,所以暂时也不考虑做了。
        接下去的发展方向是做全局和gfwlist两种方案的可切换版本,我相信这2种方案应该可以满足99%的需求了。
        PS. 之前你提到的几个问题,我今天都更新了,我看你fork了我的repro,重新fork一下吧。

        1. cokebar 文章作者

          CC15.05正式版官方源中 版本是GNU wget 1.16.3 没有 -4 选项

  5. zasl 回复

    博主,现在是否可以用spec做方案3呢?现在在图像设置里面可以看到有打开透明代理的选项,并且spec有个可以打开udp的设置,这样对游戏很有帮助,如果可以的话用spec更好了

    1. cokebar 文章作者 回复

      1. 游戏要求低延迟 海外加速的话一般要求专线才有稳定性保障 普通的用于科学上网的服务器通常延迟波动很大,不适合代理游戏。除非即时性不高的游戏。
      2. 有些游戏不用VPN没法玩。有些游戏比较奇葩,比如说用ICMP获取用户IP,但玩的时候肯定是用TCP和UDP,造成IP不一致完不成,此时必须VPN。
      3. 可以尝试打开UDP中继服务器试试。不过有些游戏不开UDP中继也可以玩,只开TCP代理就行。

  6. atshi 回复

    博主你好,我目前用的路由ss就是你博文的方案一。目前有一个问题就是我把216.58.217.206这个IP地址加进黑名单列表,无奈不生效,博主可以帮忙提点一下吗?谢谢

    1. cokebar 文章作者 回复

      仅对域名有效。IP地址请直接加入ipset中

      1. atshi 回复

        ipset表具体路径在哪里呢,我网上查了一遍如何加入去但找到具体信息。

  7. 春夏秋冬 回复

    楼主我之前用方案二解决DNS污染,用得好好的,可最近不知为什么方案二不能用了,我就改用方案三来解决DNS污染,可现在有两个问题,1,方案三会出现有一些没有被墙的网站时不时的打不开,2,方案三速度上没有方案二快,有什么解决的吗?

    1. cokebar 文章作者 回复

      1. 理论上,gfwlist方案的DNS设置只会影响到list中的域名,没有出现在list中的域名访问不稳定不是由于此方案的修改引起的,除非你的配置有问题(比如说之前用了chnroute方案 然后没有把那种方案的配置完全还原回来就换用gfwlist方案)
      2. 方案三八成会连到GOOGLE DNS HK服务器,如果代理服务器不是香港的会变慢,这是方案三的缺点。不能用用方案二可能是因为服务器关闭了UDP转发功能(请咨询服务提供者)或者ISP封杀国外UDP端口(加一层pdnsd的TCP DNS forwarder可以解决)

      1. 春夏秋冬 回复

        博主的意思是不是,可以用方案二在加一个TCP查询吗?假如我pdnsd的端口为5555,那我/etc/init.d/shadowsocks要如何转发,目前我的配置如下
        START=95

        SERVICE_USE_PID=1
        SERVICE_WRITE_PID=1
        SERVICE_DAEMONIZE=1
        SERVICE_PID_FILE=/var/run/shadowsocks.pid
        CONFIG=/etc/shadowsocks.json
        DNS=8.8.8.8:53
        TUNNEL_PORT=5353

        start() {
        #service_start /usr/bin/ss-local -c $CONFIG -b 0.0.0.0
        service_start /usr/bin/ss-redir -c $CONFIG -b 0.0.0.0
        service_start /usr/bin/ss-tunnel -c $CONFIG -b 0.0.0.0 -l 5353 -L 8.8.8.8:53 -u
        }

        stop() {
        #service_stop /usr/bin/ss-local
        service_stop /usr/bin/ss-redir
        service_stop /usr/bin/ss-tunnel
        }

        应该不需要用到CHINADNS吧

  8. SL 回复

    博主,有一点没搞清楚,还望解惑
    之前用了SS+ChinaDNS的方案,而且SS的忽略列表用的ChnRoute,我的理解是
    1,只要不是中国的IP,都会走
    2,进而,假设ChnRoute里只有一个IP地址,那么所有的流量都会通过SS

    这个方案有个不好是: 有些国外网站其实没有被墙,但是也要走SS。 所以,很难做到“精准”自动翻墙

    那么现在这个gfwlist方案,我理解是可以根据域名(最终也是解析到IP),然后转发到本地SS监听端口上实现翻墙。那么对于,不在gwflist里的域名,且IP在国外的目标,由于忽略列表的问题,也会走SS。所以,我想问博主,你加上gfwlist似乎对本身是国外IP但是本来可以不通过SS的访问地址没有什么帮助,是不是这样? 还是你的忽略列表包含了所有国内国外的IP?

    1. SL 回复

      1,只要不是中国的IP,都会走SS

      之前少打了,不好意思

    2. cokebar 文章作者 回复

      此篇文章的方案没有忽略列表一说,只有从gfwlis里解析出的IP才会走ss

    3. cokebar 文章作者 回复

      可以这么说: chnroute方案是默认走ss,除过列表中的。gfwlist方案是默认不走ss,除了列表中的。

      1. SL 回复

        博主,实际测试的情况并非这样,例如访问以下这些可以显示IP的网址
        http://iponline.co/
        http://ipinfo.io/

        以上域名都不在gfwlist里,但是显示的是我VPS的IP地址,说明走的SS链路,进而说明SS确实根据忽略列表判断,这些IP不在忽略列表里才走的SS。

        我的环境如下
        OpenWRT 14.07
        shadowsocks-libev-spec – 2.4.5-1
        luci-app-shadowsocks-spec – 1.3.8-1
        ChinaDNS – 1.3.2-3
        luci-app-chinadns – 1.3.4-1

        在SS设置里,我似乎只能选全局模式,或者根据忽略列表来选择是否走SS,而不能指定某些IP走SS。

        另外,这篇文章开头有个笔误,根据域名【只能】判断=> 根据域名【智能】判断

        1. cokebar 文章作者

          spec版本就是chnroute方案 而请仔细看 本方案使用的是非spec版本(libev原版) 请勿混用两种方案的软件

      2. SL 回复

        谢谢博主,我也是昨天才发现spec和不带spec的区别,在SS官网查看了区别,发现spec里有个ss-rules 命令,后来发现这个命令实际上是用来把忽略列表导入iptables. 最后,我的解决方案是 ss-rules -f,写到自定义防火墙中。

        考虑到应该有不少读者,是从chnroute或者其他方案过来,所以建议博主,能在文章中显眼的地方提示下 gfwlist 方案应该用不带Spec的版本,因为其实官网也没有在一个显著的位置说明spec会修改iptables,所以我想很多人不是很了解2个版本的区别。

        另外一个问题,请在本文搜索下 “上述第一条的作用可以让连入路由的设备走代理,第二条可以让路由器自身走代理。” 我猜测你的文章可能修改过,但当前文章,我相信,你说的“第二条” 指的是文章最后的 1
        iptables -t nat -A OUTPUT -p tcp -m set –match-set gfwlist dst -j REDIRECT –to-port 1080 。

        1. SL

          对了,最重要的没有说,感谢博主的精力制作,从你这篇文章学了不少知识,也受到不少启发。谢谢

  9. 春夏秋冬 回复

    博主的意思是不是,可以用方案二在加一个TCP查询吗?假如我pdnsd的端口为5555,那我/etc/init.d/shadowsocks要如何转发,目前我的配置如下
    START=95

    SERVICE_USE_PID=1
    SERVICE_WRITE_PID=1
    SERVICE_DAEMONIZE=1
    SERVICE_PID_FILE=/var/run/shadowsocks.pid
    CONFIG=/etc/shadowsocks.json
    DNS=8.8.8.8:53
    TUNNEL_PORT=5353

    start() {
    #service_start /usr/bin/ss-local -c $CONFIG -b 0.0.0.0
    service_start /usr/bin/ss-redir -c $CONFIG -b 0.0.0.0
    service_start /usr/bin/ss-tunnel -c $CONFIG -b 0.0.0.0 -l 5353 -L 8.8.8.8:53 -u
    }

    stop() {
    #service_stop /usr/bin/ss-local
    service_stop /usr/bin/ss-redir
    service_stop /usr/bin/ss-tunnel
    }

    应该不需要用到CHINADNS吧

发表回复

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

请输入验证码 *