最近因为不可描述的原因,我在aws soul的云主机访问不了,ssh、80、ss全部都被禁掉了。
80端口在chrome配置SwitchyOmega就可以了,但ssh不太好办,shell上配置http_proxy对ssh没什么用。
其实ssh自己就支持proxy。
注意这跟在ssh端口转发:远程和本地中介绍过使用ssh作为proxy的方法不同,ssh -D是为了用ssh做proxy,而不是通过proxy来连接ssh服务器。
TL;DR
ssh -o ProxyCommand='nc -x 192.0.2.0:1080 %h %p' user@awshost
原理解析
$ man ssh_config
ProxyCommand
Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed using the user's shell ‘exec’ directive to avoid a lingering shell process.
In the command string, any occurrence of ‘%h’ will be substituted by the host name to connect, ‘%p’ by the port, and ‘%r’ by the remote user name. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd(8) server running on some machine, or execute sshd -i somewhere. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). Setting the command to “none” disables this option entirely. Note that CheckHostIP is not available for connects with a proxy command.
This directive is useful in conjunction with nc(1) and its proxy support. For example, the following directive would connect via an HTTP proxy at 192.0.2.0:
ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
ProxyCommand可以利用nc做中间通道,从而达到代理的目的。要明白这个过程,需要先了解下nc的用法。
$ man nc
DESCRIPTION
The nc (or netcat) utility is used for just about anything under the sun involving TCP, UDP, or UNIX-domain sockets. It can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6.
Common uses include:
· simple TCP proxies
· shell-script based HTTP clients and servers
· network daemon testing
· a SOCKS or HTTP ProxyCommand for ssh(1)
· and much, much more
-X proxy_protocol
Requests that nc should use the specified protocol when talking to the proxy server. Supported protocols are “4” (SOCKS v.4), “5” (SOCKS v.5) and “connect” (HTTPS proxy). If the protocol is not specified, SOCKS version 5 is used.
-x proxy_address[:port]
Requests that nc should connect to destination using a proxy at proxy_address and port. If port is not specified, the well-known port for the proxy protocol is used (1080 for SOCKS, 3128 for HTTPS).
举个例子。
nc以服务器身份,起一个tcp监听连接。
$ nc -l 2222
netstat可以看到一个2222的监听socket。
然后,nc以客户端身份,连接到上面的tcp的监听socket。
$ nc localhost 2222
此时nc接管shell,随便输入几个字符,就可以在nc服务器端看到刚刚输入的字符。
从这个例子可以看到,nc其实是创建了一个非常单纯的tcp连接,没有任何协议;任何从client输入的数据,都会直接传给server端。
那么,在ssh over socks5这里,nc做了什么呢?
在一个已经通过socks5代理的ssh连接建立的环境上,可以看到有个nc的进程:
nc -x 192.0.2.0:1080 awshost 22
试试直接在shell里输入上面nc的命令,会发现nc与ssh-server建立连接以后,ssh-server发过来了其ssh版本,然后等着nc继续按ssh协议与其交互。随便输入一个’ha!’,由于这个显然不符合ssh协议,所以ssh-server会关掉连接,提示Protocol mismatch。
nc -x 192.0.2.0:1080 awshost 22
SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1
ha!
Protocol mismatch.
明白了吗?我无法手工输入ssh协议,但ssh-client可以;nc作为客户端连接到了awshost(当然通过-x指定了nc的socks5代理)后,ssh-client将nc作为一个管道,按ssh协议与ssh-server交互,从而建立了ssh连接。
拓扑如下。
ssh-client --- nc --- proxy --- ssh-server
期待的是,通过ssh-server1做代理,连接到ssh-server2上。没找到直接的做法,不过可以这样实现:
先ssh -D 127.0.0.1:1080 user1@ssh-server1
,通过ssh-server1建立本地的socks5代理
ssh -o ProxyCommand='nc -x 127.0.0.1:1080 %h %p' user2@ssh-server2
,连接到ssh-server2
如果你需要给chrome配置socks5代理,可以在第二步的基础上,再加上-D 127.0.0.1:2080,通过ssh-server1+ssh-server2建立socks5代理。
最近国内网络比较复杂,似乎某些公司网络直接访问有点问题,可以通过上面的方法来绕。
评论
发表评论