透明代理是指在路由(网关)上部署代理设置,使路由下所有设备连接到外网时自动应用该代理配置。即该代理配置对路由下的设备是透明的。

需要解决的问题

一般访问大中华区之外的部分网站,会遇到的问题主要有以下三种:

  1. DNS 缓存投毒 ,针对 DNS 协议,伪装成 DNS 服务器,给查询者返回伪造的 DNS 响应包
  2. IP 封锁 ,即使在绕过第一道屏障得到真实 IP 之后,在黑名单内的网站 IP 也是被封锁的
  3. 敏感词过滤 ,对于没在名单内的外部网站,凡检测到 TCP 报文中带有相关的敏感内容, 即向请求端和返回端分别伪装对方发送重置信号。

针对 DNS 污染,可以采用 DNS over HTTP 或者 ss-tunnel 远程解析,对于 IP 封锁和敏感词过滤直接使用 ss-redir 将相关数据包转发到代理服务器上,经由 shadowsocks 代理访问。

准备工作

安装配置 shadowsocks

  1. 安装 shadowsocks-libev-spec , shadowsocks-libev 针对 OpenWRT 的特殊版本。安装完成后 /usr/bin/ 下会有 ss-redirss-tunnel 两个二进制可执行文件。

  2. 配置 shadowsocks,编写 shadowsocks 连接到远程服务端的配置文件。创建 /etc/shadowsocks.json , 格式如下:

    {
        "server": "<远程服务器主机>",
        "server_port": <远程服务器端口>,
        "method": "<服务器采用的加密方式>",
        "timeout": 30,
        "local_port": 7777
    }
    
  3. 为 shadowsocks 配置开机启动服务(init scripts),创建 /etc/init.d/shadowsocks ,内容如下:

    #!/bin/sh /etc/rc.common
    
    START=95
    
    SERVICE_USE_PID=1
    SERVICE_WRITE_PID=1
    SERVICE_DAEMONIZE=1
    CONFIG=/etc/shadowsocks.json
    start() {
         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-redir
         service_start /usr/bin/ss-tunnel
    }
    

安装配置 GeoIP

  1. 安装 iptables-geoip 模块:

    opkg update
    opkg install iptables-mod-geoip
    opkg install iptables-mod-nat-extra
    

    启用模块: modprobe xt_geoip

  2. 生成 GeoIP 数据库

    接下来的操作引用自 How to block network traffic by country on Linux ,需要在路由外的设备上进行。首先从 xtables-addons 的官方网站下载源码包,然后按照下面的指令 编译安装它:

    wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/xtables-addons-2.10.tar.xz
    tar xf xtables-addons-2.10.tar.xz
    cd xtables-addons-2.10
    ./configure
    make
    sudo make install
    

    xtables-addons 的源码包中带有两个帮助脚本,它们被用来从 MaxMind 下载 GeoIP 数据库并将它转化为 xt_geoip 可识别的二进制形式文件;它们可以在源码包中的 geoip 目录下找到。请遵循下面的指导来在你的系统中构建和安装 GeoIP 数据库。

    cd geoip
    ./xt_geoip_dl
    ./xt_geoip_build GeoIPCountryWhois.csv
    
    # 将数据库文件上传至路由上的 /usr/share/xt_geoip 目录下
    scp -r {BE,LE} openwrt:/usr/share/xt_geoip
    

启动 shadowsocks 服务

执行 chmod +x /etc/init.d/shadowsocks ,将权限改为可执行。然后启动服务: /etc/init.d/shadowsocks start ,检查一下是否启动成功: ps | grep ss-redir

配置 iptables 转发规则

编辑 /etc/firewall.user 添加以下内容:

# 在 nat 表中创建新链
iptables -t nat -N SHADOWSOCKS

# 跳过 shadowsocks 代理服务器
iptables -t nat -A SHADOWSOCKS -p tcp --dport <远程主机端口> -j RETURN
iptables -t nat -A SHADOWSOCKS -d <远程主机 IP> -j RETURN

# 跳过本地 IP 段
iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN

# 过滤 geoip 匹配到国家代码为 CN 的数据
iptables -A prerouting_rule -t nat -m geoip -p tcp --dst-cc CN -j RETURN

# 将其余所有数据包转发到 ss-redir 监听的端口
iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 7777

# 在 PREROUTING 链前插入 SHADOWSOCKS 链,使其生效
iptables -t nat -I PREROUTING -p tcp -j SHADOWSOCKS

执行 /etc/init.d/firewall restart 重启 iptables,以应用以上规则。

现在使用路由下的设备访问 google.com,即可验证是否成功。