局域网下,免设置路由,实现全局透明代理

如果你不想光为了透明代理而单独买一个可刷OpenWRT固件的路由器, 同时你在局域网内有至少一台linux机器(可虚拟机),那以下内容可以帮助你在不需要设置路由的情况下实现透明代理(当然本质上就是把那台机器当成路由来用)。

首先你需要一台linux机器,ubuntu/debian/centos等均可,能编译ss-libev,使用iptables。你可以使用真实机器(如树莓派)或虚拟机。如果使用虚拟机,网络类型需要设置为桥接到物理网络,如果是VMware,不要对“复制物理网络连接状态”打钩。我建议使用虚拟机或性能不差的真实机器,这样网速不会受到性能上的限制。

接下来,安装操作系统、安装编译依赖包、git clone ss-libev、configure、make等这里就不说了,网上说明有很多(虽然大多数是过时了)。

编译好后,如果你clone的是ssr的libev版本,里面自带了一个ssrlink.py,可以通过此脚本快速生成一个客户端使用的配置文件,例如执行:
python ssrlink.py ssr://MTkyLjE2OC4xLjI6MTA4MDphdXRoX2FlczEyOF9tZDU6YWVzLTEyOC1jZmI6dGxzMS4yX3RpY2tldF9hdXRoOk1USXpORFUyLz9vYmZzcGFyYW09ZEdWemRDNWpiMjAmZ3JvdXA9ZEdWemRB > config.json

即可生成一个配置好了的config.json

东西都准备好了,现在开始配置。首先是开启ipv4转发

编辑/etc/sysctl.conf,解除net.ipv4.ip_forward = 1的注释,或直接添加这么一行,保存文件,并执行sysctl -p使修改立即生效。然后,设置IP为静态的,例如你的路由器地址为192.168.0.1,那么你可以设置为192.168.0.2,具体设置方法参考linux文档。设置好以后,在需要全局代理的机器上,把网关地址改为192.168.0.2,测试能不能正常上网(现在还没有通过代理),如果不能,那检查防火墙配置,或尝试重启它再测试。能正常上网后再进行后面的配置。

然后,创建一个ipt.sh文件,文件内容如下:
#!/bin/bash

subnet="192.168.0.0/16"           # your subnet config
localaddr="192.168.0.2"           # this server ip (must be subnet ip)
boardcastaddr="192.168.0.255"
listenport=1080                   # local listen port (tcp)
    udplistenport=0               # set it if not the same udp port
NAT_OUTPUT=0                      # if 0: do not need to set server ip
if [ $NAT_OUTPUT -eq 1 ]; then
    serverip="100.86.100.10"          # ss server ip (tcp)
    serverip_udp=""                   # ss server ip (for udp), keep empty if the same
fi

iptables -t nat -D PREROUTING -p tcp -j SHADOWSOCKS
if [ $NAT_OUTPUT -eq 1 ]; then
    iptables -t nat -D OUTPUT -p tcp -j SHADOWSOCKS
fi
iptables -t nat -F SHADOWSOCKS
iptables -t nat -X SHADOWSOCKS

iptables -t mangle -D PREROUTING -p udp -j SHADOWSOCKS
iptables -t mangle -F SHADOWSOCKS
iptables -t mangle -X SHADOWSOCKS

ip rule del fwmark 0x01/0x01 table 100
ip route del local 0.0.0.0/0 dev lo table 100


if [ $udplistenport -eq 0 ]; then
    udplistenport=`expr $listenport`
fi

iptables -t nat -N SHADOWSOCKS
iptables -t nat -I PREROUTING -p tcp -j SHADOWSOCKS
if [ $NAT_OUTPUT -eq 1 ]; then
    iptables -t nat -I OUTPUT -p tcp -j SHADOWSOCKS
fi

ip rule add fwmark 0x01/0x01 table 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -N SHADOWSOCKS
iptables -t mangle -A SHADOWSOCKS -d ${boardcastaddr} -j RETURN
iptables -t mangle -A SHADOWSOCKS -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A SHADOWSOCKS -p udp --dport 137 -j RETURN
iptables -t mangle -A SHADOWSOCKS -p udp --dport 138 -j RETURN
iptables -t mangle -A SHADOWSOCKS -p udp -d ${localaddr} -j RETURN
iptables -t mangle -A SHADOWSOCKS -p udp -s ${localaddr} -j RETURN
iptables -t mangle -A SHADOWSOCKS -p udp -s ${subnet} -j TPROXY --on-port ${udplistenport} --tproxy-mark 0x01/0x01
iptables -t mangle -I PREROUTING -p udp -j SHADOWSOCKS

if [ $NAT_OUTPUT -eq 0 ]; then
    iptables -t nat -A SHADOWSOCKS -d ${localaddr} -j RETURN
    iptables -t nat -A SHADOWSOCKS -s ${localaddr} -j RETURN
else
    iptables -t nat -A SHADOWSOCKS -d ${serverip} -j RETURN
    iptables -t nat -A SHADOWSOCKS -s ${serverip} -j RETURN
    if [ -z $serverip_udp ]; then
        iptables -t nat -A SHADOWSOCKS -d ${serverip} -j RETURN
        iptables -t nat -A SHADOWSOCKS -s ${serverip} -j RETURN
    fi
fi

iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SHADOWSOCKS -d ${subnet} -j RETURN

iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports ${listenport}

   
注意你应该按你的本地设定修改前四行的配置,一般你也只需要修改前四行的配置项就行了,然后保存并执行。执行后,它可以重定向你所有的出网TCP和UDP包。

最后,运行ss-redir:./ss-redir -c config.json -u

此时便应该是全局,可以愉快地玩耍了

注意的一点:UDP包如果不能成功转发,可能是被GFW拦截,那么这时只能更换服务器了。而这可能导致DNS查询失败,可以先把DNS设置为路由的DNS地址以便于排查问题。

ipt.sh参数说明:
listenport 应该与你的ss配置文件所配置的local_port一致

localaddr 你的这台linux机器的静态IP地址

subnet 你的局域网网络地址段

boardcastaddr 你的局域网的广播地址(地址段中最大的地址,由网络掩码决定)

其它说明:如果你不需要全局代理,你可以在ipt.sh中模仿以下指令

iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN

在此后面添加你不需要代理的地址段即可.