在树莓派上,使用ss-redir作透明代理

首先安装好shadowsocks-libev

Raspbian里,直接通过apt安装即可:

apt install shadowsocks-libev

安装ChinaDNS

wget https://github.com/shadowsocks/ChinaDNS/releases/download/1.3.2/chinadns-1.3.2.tar.gz
tar zxvf chinadns-1.3.2.tar.gz
cd chinadns-1.3.2/
./configure
make && make install

mkdir /etc/chinadns/
cp -af chnroute.txt /etc/chinadns/

安装dnsmasq

apt install dnsmasq

安装ipset

apt install ipset`

安装haveged

也可以安装 rng-utils/rng-tools 可选:保证系统可以提供足够的熵来生成高质量随机数.

否则ss-redir/ss-tunnel 可能无法启动

配置ss-redir

cat > /etc/shadowsocks-libev/config-redir.json <<EOF
{
    "server":"at.kuleyang.cn",
    "server_port":9443,
    "password":"yourserverpass",
    "timeout":600,
    "method":"aes-256-cfb",
	"local_address":"0.0.0.0",
    "local_port": "60080",
    "no_delay": true,
    "fast_open": true,
    "reuse_port": true,
    "mode": "tcp_and_udp"
}
EOF

ss-redir -c /etc/shadowsocks-libev/config-redir.json 

配置ss-tunnel

cat > /etc/shadowsocks-libev/config-tunnel.json <<EOF
{
    "server":"at.kuleyang.cn",
    "server_port":9443,
    "password":"yourserverpass",
    "method":"aes-256-cfb",
    "local_address": "0.0.0.0",
    "local_port": "60053",
    "tunnel_address": "8.8.8.8:53",
    "no_delay": true,
    "reuse_port": true,
    "mode": "tcp_and_udp"
}
EOF

ss-tunnel -c /etc/shadowsocks-libev/config-tunnel.json 

配置ChinaDNS

chinadns -b '127.0.0.1' -p '65353' -s '114.114.114.114,127.0.0.1:60053' -c /etc/chinadns/chnroute.txt -m

配置dnsmasq

server=127.0.0.1#65353

配置ipset

# 获取大陆地址段
curl -4skL http://f.ip.cn/rt/chnroutes.txt | egrep -v '^\s*$|^\s*#' > chnip.txt

# 添加 chnip 表
ipset -N chnip hash:net
cat chnip.txt | xargs -n1 echo add chnip > chnip.ipset
ipset -R < chnip.ipset

# 持久化 chnip 表
ipset -S chnip > /etc/ipset.chnip

配置iptables

# 新建 mangle/SS-UDP 链,用于透明代理内网 udp 流量
iptables -t mangle -N SS-UDP

# 放行保留地址、环回地址、特殊地址
iptables -t mangle -A SS-UDP -d 0/8 -j RETURN
iptables -t mangle -A SS-UDP -d 10/8 -j RETURN
iptables -t mangle -A SS-UDP -d 127/8 -j RETURN
iptables -t mangle -A SS-UDP -d 169.254/16 -j RETURN
iptables -t mangle -A SS-UDP -d 172.16/12 -j RETURN
iptables -t mangle -A SS-UDP -d 192.168/16 -j RETURN
iptables -t mangle -A SS-UDP -d 224/4 -j RETURN
iptables -t mangle -A SS-UDP -d 240/4 -j RETURN

# 放行发往 ss 服务器的数据包,注意替换为你的服务器IP
iptables -t mangle -A SS-UDP -d 服务器IP -j RETURN

# 放行大陆地址
iptables -t mangle -A SS-UDP -m set --match-set chnip dst -j RETURN

# 重定向 udp 数据包至 60080 监听端口
iptables -t mangle -A SS-UDP -p udp -j TPROXY --tproxy-mark 0x2333/0x2333 --on-ip 127.0.0.1 --on-port 60080

# 内网 udp 数据包流经 SS-UDP 链
iptables -t mangle -A PREROUTING -p udp -s 192.168/16 -j SS-UDP

# 新建 nat/SS-TCP 链,用于透明代理本机/内网 tcp 流量
iptables -t nat -N SS-TCP

# 放行环回地址,保留地址,特殊地址
iptables -t nat -A SS-TCP -d 0/8 -j RETURN
iptables -t nat -A SS-TCP -d 10/8 -j RETURN
iptables -t nat -A SS-TCP -d 127/8 -j RETURN
iptables -t nat -A SS-TCP -d 169.254/16 -j RETURN
iptables -t nat -A SS-TCP -d 172.16/12 -j RETURN
iptables -t nat -A SS-TCP -d 192.168/16 -j RETURN
iptables -t nat -A SS-TCP -d 224/4 -j RETURN
iptables -t nat -A SS-TCP -d 240/4 -j RETURN

# 放行发往 ss 服务器的数据包,注意替换为你的服务器IP
iptables -t nat -A SS-TCP -d 服务器IP -j RETURN

# 放行大陆地址段
iptables -t nat -A SS-TCP -m set --match-set chnip dst -j RETURN

# 重定向 tcp 数据包至 60080 监听端口
iptables -t nat -A SS-TCP -p tcp -j REDIRECT --to-ports 60080

# 本机 tcp 数据包流经 SS-TCP 链
iptables -t nat -A OUTPUT -p tcp -j SS-TCP
# 内网 tcp 数据包流经 SS-TCP 链
iptables -t nat -A PREROUTING -p tcp -s 192.168/16 -j SS-TCP

# 内网数据包源 NAT
iptables -t nat -A POSTROUTING -s 192.168/16 ! -d 192.168/16 -j MASQUERADE

# 持久化 iptables 规则
iptables-save > /etc/iptables.tproxy

本机只基于白名单,内网基于黑名单的国内外分流(TCP_ONLY)


#清空iptables nat表

iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat

iptables -F -t mangle
iptables -X -t mangle
iptables -Z -t mangle

# 新建 mangle/SS-UDP 链,用于透明代理内网 udp 流量
iptables -t mangle -N SS-UDP

# 放行保留地址、环回地址、特殊地址
iptables -t mangle -A SS-UDP -d 0/8 -j RETURN
iptables -t mangle -A SS-UDP -d 10/8 -j RETURN
iptables -t mangle -A SS-UDP -d 127/8 -j RETURN
iptables -t mangle -A SS-UDP -d 169.254/16 -j RETURN
iptables -t mangle -A SS-UDP -d 172.16/12 -j RETURN
iptables -t mangle -A SS-UDP -d 192.168/16 -j RETURN
iptables -t mangle -A SS-UDP -d 224/4 -j RETURN
iptables -t mangle -A SS-UDP -d 240/4 -j RETURN

# 放行发往 ss 服务器的数据包,注意替换为你的服务器IP
iptables -t mangle -A SS-UDP -d 74.120.169.48 -j RETURN

# 放行大陆地址
iptables -t mangle -A SS-UDP -m set --match-set chnip dst -j RETURN

# 重定向 udp 数据包至 60080 监听端口
iptables -t mangle -A SS-UDP -p udp -j TPROXY --tproxy-mark 0x2333/0x2333 --on-ip 127.0.0.1 --on-port 60081

# 内网 udp 数据包流经 SS-UDP 链
iptables -t mangle -A PREROUTING -p udp -s 192.168/16 -j SS-UDP

# 新建 nat/SS-TCP 链,用于透明代理内网 tcp 流量(黑名单+国内外分流)
iptables -t nat -N SS-TCP

# 放行环回地址,保留地址,特殊地址
iptables -t nat -A SS-TCP -d 0/8 -j RETURN
iptables -t nat -A SS-TCP -d 10/8 -j RETURN
iptables -t nat -A SS-TCP -d 127/8 -j RETURN
iptables -t nat -A SS-TCP -d 169.254/16 -j RETURN
iptables -t nat -A SS-TCP -d 172.16/12 -j RETURN
iptables -t nat -A SS-TCP -d 192.168/16 -j RETURN
iptables -t nat -A SS-TCP -d 224/4 -j RETURN
iptables -t nat -A SS-TCP -d 240/4 -j RETURN

# 放行发往 ss 服务器的数据包,注意替换为你的服务器IP
iptables -t nat -A SS-TCP -d 74.120.169.48 -j RETURN

# 放行大陆地址段
iptables -t nat -A SS-TCP -m set --match-set chnip dst -j RETURN

# 重定向 tcp 数据包至 60080 监听端口
iptables -t nat -A SS-TCP -p tcp -j REDIRECT --to-ports 60080

# 将内网数据包流经 SS-TCP 链
iptables -t nat -A PREROUTING -p tcp -j SS-TCP

# 新建 nat/SS-TCP-LOCAL 链,用于透明代理本机 tcp 流量 (白名单)
iptables -t nat -N SS-TCP-LOCAL

# 重定向 tcp 数据包至 60080 监听端口
iptables -t nat -A SS-TCP-LOCAL -p tcp -j REDIRECT --to-ports 60080

# 本机 tcp 数据包流经 SS-TCP 链
iptables -t nat -A OUTPUT -p tcp -d 209.95.56.60/32 -j SS-TCP-LOCAL

iptables -t nat -A OUTPUT -p tcp -d 173.244.217.42/32 -j SS-TCP-LOCAL

iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner 1001 -j SS-TCP
iptables -t nat -A OUTPUT -p tcp -d 8.8.8.8/32 -j SS-TCP-LOCAL


# 内网NAT
iptables -t nat -A POSTROUTING -s 192.168/16 ! -d 192.168/16 -j MASQUERADE

# strongswan VPN
iptables -t nat -A POSTROUTING -o eth0 ! -p esp  -s 192.168.2/24 ! -d 192.168.2/24 -j SNAT --to-source 192.168.1.118

iptables-save > /etc/iptables

加条路由

# 新建路由表 100,将所有数据包发往 loopback 网卡
ip route add local 0/0 dev lo table 100

# 添加路由策略,让所有经 TPROXY 标记的 0x2333/0x2333 udp 数据包使用路由表 100
ip rule add fwmark 0x2333/0x2333 table 100

# 立即生效
ip route flush cache
# 删除
 ip rule show | grep "fwmark 0x2333/0x2333" | awk -F':' '{print $1}' | xargs -n1 ip rule del pref &> /dev/null
    ip route flush table 100

dns-forwarder 通过 TCP 查询 8.8.8.8 作为 ChinaDNS 的 上游 替代 ss-tunnel 使用 UDP 查询 8.8.8.8 的旧方案

GFW 干扰 UDP 丢包较严重

安装配置dnsforwarder

## 获取 dnsforwarder 源码
git clone https://github.com/holmium/dnsforwarder.git

## 编译 dnsforwarder
cd dnsforwarder/
./configure
make && make install

## 初始化 dnsforwarder (仅限"手动部署")
dnsforwarder -p
cp -af default.config ~/.dnsforwarder/config

## ~/.dnsforwarder/config 配置文件
#### 日志相关 ####
LogOn true # 启用日志
LogFileThresholdLength 5120000 # 日志大小临界值,大于该值则将原文件备份,使用新文件记录日志
LogFileFolder /var/log/ # 日志文件所在的文件夹

#### 监听地址 ####
UDPLocal 0.0.0.0:12345 # 可以有多个,使用逗号隔开,默认端口53

#### 上游dns ####
TCPGroup 8.8.8.8 * 127.0.0.1 # google 作为上游 dns 服务器 
BlockNegativeResponse true # 过滤上游 dns 未成功的响应

#### hosts文件 ####
Hosts file:///etc/hosts # 本机 hosts 文件路径
HostsUpdateInterval -1  # 运行期间不重载 hosts

#### dns缓存 ####
UseCache true # 启用缓存(文件缓存)
MemoryCache false # 不使用内存缓存
CacheSize 30720000 # 缓存大小,不能小于 102400

IgnoreTTL true  # 忽略 TTL 值
CacheControl iok.la nocache # 不缓存以 'iok.la' 结尾的域名

ReloadCache true # 启动时加载已有的文件缓存
OverwriteCache true # 当已有的文件缓存载入失败时,覆盖原文件
++++++++++++++++++ config ++++++++++++++++++

## 后台运行 dnsforwarder
dnsforwarder -d

测试dns解析

dig @127.0.0.1 -p12345  www.twitter.com
dig @127.0.0.1 -p53  www.twitter.com
dig @127.0.0.1 -p65353  www.twitter.com

## 再使用 OpenDNS 443/udp 端口进行 dns 解析
dig @208.67.222.222 -p443 www.twitter.com

开机启动自动加载所有配置

cat >> /etc/rc.local <<EOF
ipset -R < /etc/ipset.chnip
iptables-restore < /etc/iptables
EOF

//手动更新国内IP段
wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' |     awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' >     /tmp/chinadns_chnroute.txt

//ipv6
wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' |     awk -F\| '/CN\|ipv6/ { printf("%s/%d\n", $4, $5) }' > /tmp/chinadns_chnroute6.txt

原理图:

f:id:briteming:20190618134738j:plain