runsisi's

technical notes

socks5 代理转 http(s) 代理

2019-04-03 runsisi#proxy

Shadowsocks 在本地创建的服务是一个 socks5 代理,Chrome 浏览器使用 SwitchyOmega 插件可以很方便的使用该代理,但绝大多数的 Linux 命令行程序都只支持 http(s) 代理,因此有必要把本地的 socks5 代理转成 http(s) 代理。

goproxy

Shadowsocks 转 http 通常会推荐 polipo[1],但 polipo 当前已经停止维护了,而且 goproxy 看上去乱七八糟的功能更齐全一些。

首先下载 goproxy,由于是 Go 写的,部署无比简单,解压之后即可使用。

直接在命令行上运行:

~$ ./proxy sps -S socks -T tcp -P 127.0.0.1:1080 -t tcp -p :12306
proxy free version 7.3  by snail , email : arraykeys@gmail.com
2019/04/03 20:25:32 stop domains loaded , 40213
2019/04/03 20:25:32 use tcp socks parent [127.0.0.1:1080] [ ROUNDROBIN ]
2019/04/03 20:25:32 ss udp on [::]:12306
2019/04/03 20:25:32 tcp http(s)+socks+ss proxy on [::]:12306
2019/04/03 20:25:37 CONNECT:www.google.com:443
2019/04/03 20:25:37 connect www.google.com:443
2019/04/03 20:25:37 conn 127.0.0.1:48586 - 127.0.0.1:1080 connected [www.google.com:443]
2019/04/03 20:25:39 conn 127.0.0.1:48586 - 127.0.0.1:1080 released [www.google.com:443]

其中选项 -P 指定已有的 socks5 代理,-p 指定待创建的 http(s) 代理服务的监听地址。

然后 export http_proxy 和 https_proxy 环境变量即可让命令行程序使用 http(s) 代理:

export http_proxy=http://localhost:12306
export https_proxy=http://localhost:12306

是的,就这么简单,当然,如果有需要的话可以创建 systemd 服务保持在后台长期运行。

创建 systemd 服务

编辑 systemd 服务环境变量文件:

~$ sudo vi /etc/default/s2h
SERVER=127.0.0.1
PORT=1080
LOCAL_PORT=12306
ENCRYPT=aes-256-cfb

编辑 systemd 服务文件:

~$ sudo vi /lib/systemd/system/s2h.service
[Unit]
Description=s2h
After=network.target

[Service]
EnvironmentFile=-/etc/default/s2h
ExecStart=/home/runsisi/Application/proxy-linux-amd64/proxy sps -S socks -T tcp -P ${SERVER}:${PORT} -t tcp -p :${LOCAL_PORT}
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=simple

[Install]
WantedBy=multi-user.target

启用服务:

~$ sudo systemctl daemon-reload
~$ sudo systemctl enable s2h
Created symlink /etc/systemd/system/multi-user.target.wants/s2h.service → /lib/systemd/system/s2h.service.
~$ sudo systemctl start s2h
~$ systemctl status s2h
● s2h.service - s2h
   Loaded: loaded (/lib/systemd/system/s2h.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2019-04-03 21:47:04 CST; 1min 11s ago
 Main PID: 28153 (proxy)
    Tasks: 11 (limit: 4915)
   CGroup: /system.slice/s2h.service
           └─28153 /home/runsisi/Application/proxy-linux-amd64/proxy sps -S socks -T tcp -P 127.0.0.1:1080 -t tcp -p :12306

Apr 03 21:47:04 runsisi-hust systemd[1]: Started s2h.
Apr 03 21:47:04 runsisi-hust proxy[28153]: proxy free version 7.3  by snail , email : arraykeys@gmail.com
Apr 03 21:47:04 runsisi-hust proxy[28153]: 2019/04/03 21:47:04 use tcp socks parent [:1080] [ ROUNDROBIN ]
Apr 03 21:47:04 runsisi-hust proxy[28153]: 2019/04/03 21:47:04 ss udp on [::]:12306
Apr 03 21:47:04 runsisi-hust proxy[28153]: 2019/04/03 21:47:04 tcp http(s)+socks+ss proxy on [::]:12306

构建 goproxy

原始的 goproxy 代码已经被作者删除了,作者发布的二进制包在 systemd 下可能会出现如下的错误而导致进程退出:

~$ systemctl status s2h
● s2h.service - s2h
   Loaded: loaded (/lib/systemd/system/s2h.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2019-04-10 21:33:54 CST; 2s ago
  Process: 3662 ExecStart=/home/runsisi/Application/proxy-linux-amd64/proxy sps -S socks -
 Main PID: 3662 (code=exited, status=0/SUCCESS)

Apr 10 21:33:47 runsisi-hust systemd[1]: Started s2h.
Apr 10 21:33:47 runsisi-hust proxy[3662]: proxy free version 7.3  by snail , email : array
Apr 10 21:33:47 runsisi-hust proxy[3662]: 2019/04/10 21:33:47 use tcp socks parent [127.0.
Apr 10 21:33:47 runsisi-hust proxy[3662]: 2019/04/10 21:33:47 ss udp on [::]:12306
Apr 10 21:33:47 runsisi-hust proxy[3662]: 2019/04/10 21:33:47 tcp http(s)+socks+ss proxy o
Apr 10 21:33:54 runsisi-hust proxy[3662]: 2019/04/10 21:33:54 check update fail, please ch
lines 1-12/12 (END)...skipping...

因此只能取作者的最后一个可用版本进行构建:

~$ git clone -b wip-build https://github.com/runsisi/goproxy-1 goproxy
Cloning into 'goproxy'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5281 (delta 1), reused 3 (delta 1), pack-reused 5277
Receiving objects: 100% (5281/5281), 4.14 MiB | 488.00 KiB/s, done.
Resolving deltas: 100% (3127/3127), done.
~$ go build github.com/snail007/goproxy
go: finding github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5
go: finding github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8
go: finding github.com/klauspost/reedsolomon v0.0.0-20171001120606-6bb6130ff6a7
go: finding github.com/juju/ratelimit v1.0.1
...
go: downloading github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047
go: extracting github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047
go: extracting golang.org/x/net v0.0.0-20180611182652-db08ff08e862
~$ file goproxy 
goproxy: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, not stripped

源代码目录下 release.sh 脚本也可以用来进行构建,支持跨平台构建和链接时增加版本信息。

参考资料

[1] Convert Shadowsocks into an HTTP proxy

https://github.com/shadowsocks/shadowsocks/wiki/Convert-Shadowsocks-into-an-HTTP-proxy

[2] SOCKS5 to HTTP(S) + SOCKS5

https://github.com/runsisi/goproxy-1#63socks5-to-https—socks5