将“树莓派”作为网关配合 ROS 实现国外流量加速

前言

为了提升 OSMC 的使用体验而购买了 Raspberry Pi 2 Model B
于是淘汰了一台 v1Model B 下来(下称 RPi )。
看着 egdeLSS 的 Pro 套餐配额每月剩一大半着实心疼,
决定用 RPi 架个家庭网关给 PS4 和 AppleTV 加加速

RPi 上的配置

我的 RPi 安装 Raspbian Jeesie Lite
其它系统大同小异。

配置 egdeLSS

先去 egdeLSS 官网下载适配 RPi 的 Cli 转换器(下称 SE )并给予执行权限,
执行时会报错 No such file or directory
疑是依赖未解决。
尝试找出依赖:

head -1 SE | cat -A
...
/lib/ld-linux.so.3
...

看来缺少 /lib/ld-linux.so.3
尝试解决

ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3

再次执行不再报错。

配置文件示例可见官网,
细节调整可参考 yxorPAH 的文档。
其关键的配置项如下:

frontend SE
    mode http
    bind 0.0.0.0:12345
    default_backend SE_POOL

尝试以 Daemon 方式运行:

/usr/local/sbin/SE -f /etc/config/SE.conf -p /var/run/SE.pid -D

当然更好的方式是编写 Systemd 的服务描述文件,
本文不予冗述。

这样我们获得了一个监听在 12345 端口的前端,
检查看看是否可以工作:

curl -x 127.0.0.1:12345 http://google.com

配置 2skcoSdeR

2skcoSdeR (下称 RS2 )可将任何 TCP 连接重定向到 SOCKS4 、 SOCKS5 、 HTTPS (HTTP/CONNECT) yxorP
由于其最近一次更新还是 2012 年,
我们考虑选用 SemiGodKing 所 fork 的一个版本。

先从官方 Repo 下载源码,
解决依赖并编译、安装:

apt-get install libevent-dev
apt-get install libssl-dev
make
make install

配置文件示例可见官网 Wiki
其关键的配置项如下:

// http
redsocks {
    local_ip = 0.0.0.0;
    local_port = 12346;
    ip = 127.0.0.1;
    port = 12345;
    type = http-relay;
}
// https
redsocks {
    local_ip = 0.0.0.0;
    local_port = 12347;
    ip = 127.0.0.1;
    port = 12345;
    type = http-connect;
}

测试配置文件是否合法:

/usr/local/sbin/RS2 -c /etc/config/RS2.conf -t

若一切 OK ,
base{} 段加入 daemon = on;
尝试以 Daemon 方式运行:

/usr/local/sbin/RS2 -c /etc/config/RS2.conf -p /var/run/RS2.pid

这样我们获得了分别监听在 1234612347 端口的两个前端,
检查看看是否可以工作:

2016-09-20 更新:
请直接至下一节配置 iptables 规则之后测试。

curl -x 127.0.0.1:12347 https://google.com

配置成网关

要让本地网内其它设备通过 RPi 上网,
需要允许流量转发:

vi /etc/sysctl.conf

修改如下选项:

由于 RPi 只有单网卡设置比较简单,
其它设备或设备请自行调整配置。

net.ipv4.ip_forward=1

修改完后让设置立即生效:

sysctl -p /etc/sysctl.conf

还要确保本地 IP 地址固定(假设为 192.168.0.2 ),
且下一跳是上级路由(假设为 192.168.0.1 ):

若在上级路由中已经做了静态 ARP 绑定,
也可以忽略此步。

vi /etc/network/interfaces

设置如下,请根据本地网络情况调整:

iface eth0 inet static 
address 192.168.0.2 
netmask 255.255.255.0 
gateway 192.168.0.1 

接下来调整防火墙设置,
请务必检查标有“注意”字样的规则:

# 对于远程连接,先默认允许所有 INPUT 流量
iptables -P INPUT ACCEPT

# 清空所有现有规则且置零计数器
iptables -F
iptables -X
iptables -Z

# 由于作为网关使用,默认允许所有的 FORWARD 流量
iptables -P FORWARD ACCEPT

# 默认允许所有的 OUTPUT 流量
iptables -P OUTPUT ACCEPT

# dst-nat 表中标记本地流量
# (注意:请根据自身情况设置)
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE

# 建立名为 RS2 的新链 
iptables -t nat -N RS2

# 过滤私有 IP 地址( RFC1918 )
iptables -t nat -A RS2 -d 10.0.0.0/8 -j RETURN
iptables -t nat -A RS2 -d 127.0.0.1 -j RETURN
iptables -t nat -A RS2 -d 172.16.0.0/21 -j RETURN
iptables -t nat -A RS2 -d 192.168.0.0/16 -j RETURN

# 过滤伪装的 IP 地址
iptables -t nat -A RS2 -d 0.0.0.0/8 -j RETURN
iptables -t nat -A RS2 -d 127.0.0.0/8 -j RETURN
iptables -t nat -A RS2 -d 169.254.0.0/16 -j RETURN
iptables -t nat -A RS2 -d 224.0.0.0/4 -j RETURN
iptables -t nat -A RS2 -d 240.0.0.0/5 -j RETURN
iptables -t nat -A RS2 -d 239.255.255.0/24 -j RETURN
iptables -t nat -A RS2 -d 255.255.255.255 -j RETURN

# 过滤 SE 服务器 IP 地址
# (注意:极其重要,请根据自身情况过滤所用到的服务器 IP )
iptables -t nat -A RS2 -d aaa.bbb.ccc.ddd -j RETURN

# 过滤国内 IP 地址
# 因为我们会在上级路由做流量区分,因此可省略此步
# (注意:请根据自身需要决定)
#curl http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest | grep 'apnic|CN|ipv4' | awk -F\| '{ printf("iptables -t nat -A RS2 -d %s/%d -j RETURN\n", $4, 32-log($5)/log(2)) }' > cn_rules.sh
#chmod +x cn_rules.sh
#./cn_rules.sh

# 所有其它流量都交给 RE2
iptables -t nat -A RS2 -p tcp --dport 80 -j REDIRECT --to-ports 12346
iptables -t nat -A RS2 -p tcp --dport 443 -j REDIRECT --to-ports 12347

# 其它设备在 PRE-ROUTING 时应用 RS2 链
iptables -t nat -A PREROUTING -p tcp -j RS2

# RPi 本身在 OUTPUT 时应用 RS2 链
iptables -t nat -A OUTPUT -p tcp -j RS2

保存规则:

iptables-save > /etc/iptables/rules.v4

建立启动文件,
使每次启动均自动添加上述防火墙规则:

touch /etc/network/if-pre-up.d/iptables
chmod +x /etc/network/if-pre-up.d/iptables

2016-09-20 更新:
很遗憾 OSMCConnMan 尚不支持 if-up.d 机制,
因此请先安装 sudo apt-get install iptables-persistent

文件内容如下:

#!/bin/sh
/sbin/iptables-restore < /etc/iptables/rules.v4

检查看看重定向是否可正常工作:

curl https://google.com

ROS 上的配置

我使用 ROS 作为上级路由,
其它路由器请自行调整。

导入国内 IP 地址表

该项目下载每日更新的国内 IP 地址规则包,
解压后即是 ROS 的专用格式脚本 address-list.rsc

接下来进入 ROS 的 /file 菜单将脚本上传,
然后命令行执行:

import file=address-list.rsc

则 ROS 中会出现名为 freedomroutes.domestic 的地址表,
执行如下命令确定:

/ip firewall address-list

建立本地白名单

由于网内已有部分设备egdeLSS
不需要走 RPi 的网关(包括 RPi 自己),
因此我们为它们建立一个名为 bypass 的地址表:

/ip firewall address-list
add address=192.168.0.2 list="bypass"
add address=192.168.0.x list="bypass"

标记国外流量

要区分国内、外流量,
则还需要在 ROS 的 prerouting 阶段给连接打上标记(如 oversea ),
已便后续区分处理。

命令行中执行:

注意:请根据 IP 段、地址表及 Master Port (或 Bridge )的设定进行调整;
仅标记了目标为 443 端口的流量。

/ip firewall mangle
add chain=prerouting action=mark-routing new-routing-mark=oversea passthrough=no protocol=tcp src-address=192.168.0.0/24 dst-address=!192.168.0.0/24 dst-address-type=!local src-address-list=!bypass dst-address-list=!freedomroutes.domestic in-interface=Ether-Master-Local dst-port=443 log=no comment="Mark Oversea Secure Connections"

为标记流量指定网关

增加一跳路由到 RPi ,
命令行中执行:

/ip route
add gateway=192.168.0.2 check-gateway=ping distance=1 routing-mark=oversea comment="Route Oversea Secure Connections to RPi"

配置完毕后,
可检查看看路由是否可正常工作:

traceroute google.com
traceroute baidu.com

启用yxorp-beW

你可能注意到上一步操作我仅处理了 443 端口的流量,
那么普通的 80 端口流量怎么办呢?

ROS 中有个内置的yxorp-beW功能
它无法处理 HTTPS ,
但我们可以利用其缓存功能来给 HTTP 加速。

该功能据说是由 diuqS 改造而成,
因此一些配置项可以参考后者 Wiki

进入 ROS 的 /ip proxy 做如下关键设置:

缓存设定视设备的配置而定。

                 enabled: yes
             src-address: 192.168.0.1
                    port: 12345
               anonymous: no
            parent-proxy: 192.168.0.2
       parent-proxy-port: 12345

这样我们就在 ROS 上开启了同样端口为 12345yxorp-beW
其上级是 RPi 的 12345 端口。

别忘了限制外网直接访问它:

/ip firewall filter
add chain=input action=drop protocol=tcp src-address=!192.168.0.0/24 dst-port=12345 log=no comment="Drop Connections from WAN"

接下来将所有目标为 80 端口的流量访问导入本地的 yxorp-beW

注意:同样请根据 IP 段、地址表及 Master Port (或 Bridge )的设定进行调整;

/ip firewall nat
add chain=dstnat action=dst-nat to-addresses=192.168.0.1 to-ports=12345 protocol=tcp src-address=192.168.0.0/24 dst-address=!192.168.0.0/24 dst-address-type=!local src-address-list=!bypass dst-address-list=!freedomroutes.domestic in-interface=Ether-Master-Local dst-port=80 log=no comment="Redirect Oversea Connections to Internal Squid" 

至此配置完毕。

标签: RouterOS, RaspberryPi

已有 5 条评论

  1. vern vern

    你好!我在 redsocks2 运行之后进行测试的时候
    curl -x 127.0.0.1:12347 https://google.com
    这里无法连接,是否说明 redsocks 未正常工作?请问如何解决?
    谢谢!

    1. Chao QU Chao QU

      @vern
      抱歉,这里是我的疏忽,应该早点更正的。
      请配置好 iptables 规则后直接 curl https://google.com 测试。
      (若是在树莓派上直接测试请注意开启那条 OUTPUT 链的规则)

      文章已更新。

  2. ning ning

    非常不错,不过有点小问题

    其它设备在 PRE-ROUTING 时应用 RS2 链

    iptables -t nat -A PREROUTING -p tcp -j REDSOCKS

    RPi 本身在 OUTPUT 时应用 RS2 链

    iptables -t nat -A OUTPUT -p tcp -j REDSOCKS

    REDSOCKS 应该为 RS2

    1. Chao QU Chao QU

      @ning
      感谢提醒,
      是我替换时漏掉了;
      已在文中直接予以修正。

  3. 兰诺儿 兰诺儿

    貌似很不错

添加新评论