chisel 是一个 TCP over HTTP 隧道工具,这里我们仅用它来转发 SSH 流量。
方案一
chisel 类似于一个端口映射工具,访问 chisel 客户端的监听地址的流量会通过 chisel 服务端转发至定义的地址。
服务端
外网机器(IP 地址为 123.123.123.123)启动 chisel 服务端,在 80 端口进行监听,指定客户端连接所需的用户名和密码:
$ chisel server --port 80 --auth userabc:pass123
客户端
chisel 的客户端命令行参数如下所示:
$ chisel client -h
Usage: chisel client [options] <server> <remote> [remote] [remote] ...
其中 remote
的定义为 <local-host>:<local-port>:<remote-host>:<remote-port>
。
内网机器启动 chisel 客户端连接服务端,在本地监听指定的端口并依据 remote
定义的规则将 TCP 流量进行转发:
$ chisel client --proxy http://proxy.example.com:80 --auth userabc:pass123 123.123.123.123:80 3344::22
2019/09/18 13:56:22 client: Connecting to ws://123.123.123.123:80 via http://proxy.example.com:80
2019/09/18 13:56:22 client: proxy#1:0.0.0.0:3344=>0.0.0.0:22: Listening
2019/09/18 13:56:22 client: Fingerprint 73:6e:f2:0c:ad:cc:92:96:37:da:68:ba:8a:c7:ac:03
2019/09/18 13:56:22 client: Connected (Latency 35.535686ms)
上述命令行的参数解释如下:
--proxy
选项指定 chisel 客户端通过 HTTP 代理 http://proxy.example.com:80 连接外网机器的 chisel 服务端;
--auth
选项指定 chisel 客户端连接服务端所需的用户名和密码;
chisel 服务端监听地址为 123.123.123.123:80;
chisel 客户端监听地址为 :3344,并将流量转发至 chisel 服务端的 22 端口。
此时访问 chisel 客户端监听的地址就会访问 chisel 服务端的 22 端口:
$ ssh root@localhost -p 3344
root@localhost's password:
Last login: Wed Sep 18 13:32:20 2019 from 127.0.0.1
方案二
显然,上述类似端口映射的方案非常不灵活,我们更希望 chisel 以类似代理服务器的形式访问外网。
服务端
外网机器启动 chisel 服务端,在 80 端口进行监听,指定客户端连接所需的用户名和密码,并启动内部的 socks5 服务:
$ chisel server --port 80 --auth userabc:pass123 --socks5
客户端
$ chisel client --proxy http://proxy.example.com:80 --auth userabc:pass123 123.123.123.123:80 3344::socks
2019/09/18 15:16:24 client: Connecting to ws://123.123.123.123:80 via http://proxy.example.com:80
2019/09/18 15:16:24 client: proxy#1:127.0.0.1:3344=>socks: Listening
2019/09/18 15:16:24 client: Fingerprint 29:bf:81:9b:e1:c0:a5:3f:83:52:91:d5:b1:2e:89:ba
2019/09/18 15:16:24 client: Connected (Latency 38.31468ms)
注意,我们把前面方案一中的远端端口 22
替换成了 socks
。
此时需要把 chisel 客户端监听的地址作为 socks5 代理地址进行访问:
$ ssh -o ProxyCommand='nc -X 5 -x localhost:3344 %h %p' runsisi@234.234.234.234 -p 22
The authenticity of host '234.234.234.234 (<no hostip for proxy command>)' can't be established.
ECDSA key fingerprint is SHA256:hnMK72IdBxGQWTPVnpoZpZPsURyGcQ4Do+LLP43KZGg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '234.234.234.234' (ECDSA) to the list of known hosts.
runsisi@234.234.234.234's password:
Last login: Wed Sep 18 15:24:36 2019 from 127.0.0.1
如果不想在 ssh 命令行上显式指定 ProxyCommand
选项(man ssh_config),可以在配置文件中进行指定:
$ cat ~/.ssh/config
Host 234.234.234.234
# ProxyCommand nc -X connect -x proxy.example.com:80 %h %p
ProxyCommand nc -X 5 -x localhost:3344 %h %p
注意:socat 不支持 SOCKS5 代理,因此这里无法用 socat 替代 nc。
netcat
需要注意的是 Ubuntu 下的 nc(netcat-openbsd)和 CentOS 下的 nc(nmap-ncat)是两个完全不同的实现:
$ lsb_release -i
Distributor ID: Ubuntu
$ dpkg -L netcat-openbsd
/.
/bin
/bin/nc.openbsd
...
$ ll /bin/nc
lrwxrwxrwx 1 root root 20 Sep 9 2016 /bin/nc -> /etc/alternatives/nc*
$ ll /etc/alternatives/nc
lrwxrwxrwx 1 root root 15 Sep 9 2016 /etc/alternatives/nc -> /bin/nc.openbsd*
$ lsb_release -i
Distributor ID: CentOS
$ rpm -ql nmap-ncat
/usr/bin/nc
/usr/bin/ncat
...
因此,在 CentOS 下 ProxyCommand
的选项如下(上面给出的 ProxyCommand
的配置都仅适用于 Ubuntu):
nc -4 --proxy-type socks5 --proxy localhost:3344 %h %p
注意:CentOS 下需要显式指定 -4
选项以使用 IPv4 地址。
最后修改于 2019-09-18