ssh端口转发概念
ssh 是个多用途的工具,不仅可以远程登陆,还可以搭建sock5代理、进行内网穿透,这是利用它的端口转发功能来实现的。
所谓的ssh端口转发,就是在ssh连接的基础上,指定ssh client或ssh server的某个端口作为源地址,所有发至该端口的数据包都会透过ssh连接转发出去;至于转发的目标地址,既可以指定,也可以不指定,如果指定目标地址,称为定向转发,如果不指定目标地址,则称为动态转发:
- 定向转发
定向转发把数据包转发到指定的目标地址。目标地址不限定ssh client或ssh server,既可以是二者之一,也可以是二者以外的其他机器。
- 动态转发
动态转发不指定目标地址,数据包转发的目的地是动态决定的。
在设置端口转发之前,必须确定ssh的端口转发功能是打开的。
1 | [root@node1 ~]# vim /etc/ssh/sshd_config |
2 | AllowTcpForwarding yes |
控制它的开关是叫做AllowTcpForwarding,默认打开的。
设置定向转发
定向转发可以把一个 IP:PORT 定向映射到另一个 IP:PORT,源和目的都必须指定。源地址既可以是ssh client 的某个端口,也可以是ssh server的某个端口。
- 如果源地址是ssh client的某个端口,称为本地转发,发往ssh client指定端口的数据包会经过ssh server进行转发。
- 如果源地址是ssh server的某个端口,则称为远程转发,发往ssh server指定端口的数据包会经过ssh client进行转发。
设置本地转发
先看下基本命令:
在ssh client上执行:
1 | {ssh client}# ssh -g -N -f -o ServerAlivlnterval=60 -L <local port>:<remote host>:<remote port> username@<ssh server> |
连接示意图:
{you}–{ssh client}–{ssh server}–{remote host}
比如我们想要mysql连接{remote host}的数据库,但是没有权限,但是{ssh server}有权限,你可以直连{ssh client},但没权限连接{ssh server},于是试图通过{ssh client}到{ssh server}这条通道中转:
1 | {ssh client}# ssh -g -L 2323:<remote-host>:3306 username@<ssh-server> |
eg:
{you}: 10.211.55.33
{ssh client}: 10.211.55.24
{ssh server}: 10.211.55.35
{remote host}: 10.211.55.36
{ssh client}:10.211.55.24
1 | [root@localhost ~]#ssh -g -L 2323:10.211.55.36:3306 root@10.211.55.35 |
2 | [root@localhost ~]#netstat -tnlp |
3 | Active Internet connections (only servers) |
4 | Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name |
5 | tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4980/nginx: master |
6 | tcp 0 0 0.0.0.0:2323 0.0.0.0:* LISTEN 20718/ssh |
7 | tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 926/sshd |
8 | tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1494/master |
9 | tcp 0 0 0.0.0.0:3260 0.0.0.0:* LISTEN 4427/tgtd |
10 | tcp6 0 0 :::2323 :::* LISTEN 20718/ssh |
11 | tcp6 0 0 :::22 :::* LISTEN 926/sshd |
12 | tcp6 0 0 ::1:25 :::* LISTEN 1494/master |
13 | tcp6 0 0 :::3260 :::* LISTEN 4427/tgtd |
我们可以发现在{ssh client}上出现了一个新的进程,端口为2323
{you}: 10.211.55.33
1 | [root@node3 ~]#mysql -umysql -pmysql -h10.211.55.24 -P2323 |
你会发现我们连接到了{remote host}的数据库,并且所得到是{ssh server}连接{remote host}的权限。
- -g:ssh client上的监听端口2323默认会绑定127.0.0.1上,意味这只允许ssh client才能连接。加上-g,ssh client才允许网络其他机器连接2323端口。
- -N: 告诉ssh client,这个连接不需要执行任何命令,仅做端口转发。
- -f: 告诉ssh client在后台运行。
- ServerAlivlnterval=:为了避免长时间空闲导致ssh连接被断开,我们可以加上”-o ServerAliveInterval=60″选项,每60秒向ssh server发送心跳信号。
设置远程转发
在ssh server上:
编辑/etc/ssh/sshd_config,设置以下内容然后重启sshd服务
GatewayPort yes
在ssh client上执行
1 | {ssh client}# ssh -f -N -o ServerAlivelnterval=60 -R <ssh server port>:<remote host>:<remote port> username@<ssh server> |
连接示意图:
{you}–{ssh server}–{ssh client}–{remote host}
这里与本地连接不同的是,这里我们只能连接{ssh server}
{ssh client}
1 | [root@localhost ~]#ssh -f -N -R 2323:10.211.55.36:3306 root@10.211.55.35 |
输入口令后,{ssh server}的2323端口映射到了{remote host}的3306端口,需要的权限是{ssh client}连接{remote host}的mysql权限。
注意这里没有-g选项了,所以只会监听在本地,我们可以连接到{ssh server},mysql连接到2323端口就相当于连接了{remote host}的3306端口,但是{remote host}上显示却是{ssh client}连接的。
本地转发与远程转发的区别与适用场景
定向转发(包括本地转发和远程转发)通常用于内网穿透,本地转发和远程转发的区别就在于监听端口是开在ssh client上还是ssh server上。
常见的使用场景是:
- 如果ssh client在内网里面,ssh server在Internet上,你想让Internet上的机器穿进内网之中,那就使用远程转发;
- 如果ssh server在内网里面,ssh client在外面,你想穿进内网就应该使用本地转发。
设置动态转发
定向转发(包括本地转发和远程转发)的局限性是必须指定某个目标地址,如果我们需要借助一台中间服务器访问很多目标地址,一个一个地定向转发显然不是好办法,这时我们要用的是ssh动态端口转发,它相当于建立一个SOCKS服务器。
在ssh client上执行:
1 | {ssh client}# ssh -f -N -o ServerAlivelnterval=60 -D <ssh client port> username@<ssh server> |
实际使用时有常见的两种场景:
- 你把自己的机器{127.0.0.1}当作sock5代理服务器:
{you/ssh client}–{ssh server}-{other hosys}
命令如下:
{ssh client}#ssh -f -N -D 1080 username@{ssh-server}
这种情况下,我们得到的socks5代理服务器是:127.0.0.1:1080,仅供ssh client自己使用。
然后你就可以在浏览器中或其他支持socks5代理的软件中进行设置。
- ssh client和ssh server是同一台机器,并充当sock5代理
{you}–{ssh client/ssh server}-{other hosts}
命令如下:
{ssh client} # ssh -f -N -g -D 1080 username@127.0.0.1
这种情况下,我们得到的socks5代理服务器是:
{ssh client IP}:1080,可供网络上其他机器使用,只要能连接ssh client即可。
通过SSH建立的SOCKS服务器使用的是SOCKS5协议,在为应用程序设置SOCKS代理的时候要注意。