fragments

Sep 04, 2022

基于redsocks2和pf的macOS透明代理

Last updated at: Sep 04, 2022

坑点:在[🧰EasyConnect in Dokcer](../2021-05-01-🧰EasyConnect in Dokcer/)中记录了在容器中运行Sangfor EasyConnect的步骤,并通过socks5代理来实现VPN使用,但这种方式具有一些局限性,仅对支持了socks5或http代理的程序有用。举一个不支持的例子:我在本地执行Java工程的单元测试时,单元测试中有访问zk的逻辑,尽管在JVM参数中添加了-DsocksProxySet=true -DsocksProxyHost=alpine -DsocksProxyPort=1080,但对访问zk底层的nio来说是无效的😢

还好在搜索到了这两篇文章,发现可以通过透明代理来支持这种场景:

下面是我的操作步骤

1 编译、配置redsocks

$ wget https://github.com/HaoH/redsocks/archive/release-0.68.tar.gz # 下载源码
$ tar -zxvf redsocks-release-0.68.tar.gz # 解压缩
$ cd redsocks-release-0.68

在我的电脑环境中,按照源码包的代码构建的结果,运行时会报错:

1662282301.374137 err redsocks.c:693 redsocks_connect_relay(...) [192.168.0.103:54303->10.100.*.*:80]: red_connect_relay failed!!!: Protocol not available
1662282301.375292 err utils.c:154 red_prepare_relay(...) setsockopt: Protocol not available

可以看到报错在utils.c:154,经查阅资料,此种报错可以被忽略,所以修改代码:

$ vim utils.c

将153至156行注释,忽略setsocketopt的报错:

        // if (error) {
        //     log_errno(LOG_ERR, "setsockopt");
        //     goto fail;
        // }
$ https_proxy=socks5://localhost:1080 make OSX_VERSION=master DISABLE_SHADOWSOCKS=true # 构建
$ vim redsocks.conf

内容如下:

base {
	log_debug = off;
	log_info = on;
	log = stderr;
	daemon = off;
	redirector = pf;
	reuseport = off;
}

redsocks {
    // redsocks的监听的地址和端口
	bind = "127.0.0.1:12345";
    // 代理的地址和端口
	relay = "192.168.17.128:1080";
	type = socks5;
	autoproxy = 0;
	timeout = 10;
}

2 配置pf

首先我们需要定义出需要转发到代理的cidr表,存放到文件/opt/app/redsocks/forward_cidr.txt,若需要转发10.100.0.0/1610.1.0.0/16网段的IP到代理,内容如下:

10.100.0.0/16
10.1.0.0/16

编辑/etc/pf.conf,内容如下:

scrub-anchor "com.apple/*"

table <forward_cidr> persist file "/opt/app/redsocks/forward_cidr.txt"

nat-anchor "com.apple/*"

rdr-anchor "com.apple/*"
rdr pass on lo0 proto tcp from any to <forward_cidr> -> 127.0.0.1 port 12345

pass out route-to (lo0 127.0.0.1) proto tcp from any to <forward_cidr>

dummynet-anchor "com.apple/*"

anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

3 运行

启动的脚本内容如下:

# 启动pf
sudo sysctl -w net.inet.ip.forwarding=1
sudo pfctl -e
sudo pfctl -F all
sudo pfctl -f /etc/pf.conf

# 启动redsocks
sudo ./redsocks2 -c ./redsocks.conf

使用代理完成之后,你可以Ctrl+C关闭redsocks,然后用下面的脚本关闭pf:

# 关闭pf
sudo pfctl -d
sudo pfctl -F all

(206 words)