Jusene's Blog

ssh 端口转发详解

字数统计: 1.7k阅读时长: 7 min
2017/02/18 Share

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代理的时候要注意。

CATALOG
  1. 1. ssh端口转发概念
  2. 2. 设置定向转发
    1. 2.1. 设置本地转发
    2. 2.2. 设置远程转发
    3. 2.3. 本地转发与远程转发的区别与适用场景
  3. 3. 设置动态转发