SSH端口转发详解
SSH端口转发详解
SSH端口转发(隧道)可以建立SSH通道,并将TCP链接放到这个通道中。
man ssh
选项及参数解释
首先我们通过man
命令来查看一下ssh关于转发部分的说明,然后再详细讲解不同的转发方式是什么意思。
- 本地转发
本地转发通过-L
选项指定
-L
选项后可跟多种形式的参数
1 | -L [绑定地址:]端口:主机:主机端口 |
链接到本地(ssh客户端)主机上的给定的TCP端口(unix socket)将被转发到**远端的给定的主机和端口(unix socket)**。这一过程指定了本地这一侧的TCP端口(同时可以指定绑定的地址),或unix socket。
(译注:就是指定[绑定地址:]端口
这个参数,要么只提供端口,要么既提供地址也提供端口)
一旦有连接到本地端口或socket的链接,这个链接就会通过安全的通道进行转发,相当于作用在远端主机对应的端口或socket上。
(译注:前两个参数( [绑定地址:]端口
)指定本地的地址和端口,后两个参数指定远端的地址和端口(主机:主机端口
),对本地这个端口的访问,相当于作用在了远端的相应的端口上)
端口转发同样也可以在配置文件中指定。只有超级用户可以转发特权端口。IPv6地址可以用方括号括起来指定。
默认情况下,本地端口按照
GatewayPorts
设置进行绑定。但是,可以使用显示的绑定地址
将链接绑定到特定的地址。使用localhost
这个绑定地址
表示监听的端口仅能本地使用,而不指定地址或使用*
则表示监听的端口可以被所有接口所访问。
(译注:使用localhost
仅能本地访问,相当于127.0.0.1
,不指定或使用*
,则相当于0.0.0.0
)
远程转发
远程转发通过
-R
选项指定-R
选项后可接多种形式的参数1
2
3
4
5-R [绑定地址:]端口:主机:主机端口
-R [绑定地址:]端口:本地socket
-R 远端socket:主机:主机端口
-R 远端socket:本地socket
-R [绑定地址:]端口连接到远端(服务端)主机上给定TCP端口的链接会本转发到本地这一侧。这一过程分配了一个socket来在远端监听给定的TCP
端口
或unix socket。一旦有访问这个端口
的链接,这个链接便会通过安全通道进行转发至本地这一侧,本地这一侧可以显示的指定主机
及主机端口
或本地socket,或者如果没有显示指定本地这一侧的主机的话,ssh将充当socks 4/5
代理,并将链接转发到远程socks客户机请求的目的地址 (译注:最后一句话如何使用暂不解释)。
端口转发同样可以在配置文件中指定。特权端口只能登录远端机器的root用户进行转发。IPv6地址可以用方括号括起来指定。
默认情况下,TCP仅监听本地环回接口的sockets。这一情况可以通过
绑定地址
来进行覆盖,空的绑定地址
或*
,表示远端socket应该监听所有接口。只有远端服务的GatewayPorts
选项打开,才可以指定远端的绑定地址
。如果
端口
参数是0
,将会在服务端动态分配监听的端口,然后将端口返回客户端。如果同时使用-O
选项,返回分配的端口将会输出在标准输出。动态转发
动态转发通过
-D
选项指定-D
选项后可跟如下形式的参数1
-D [绑定地址:]端口
本地动态应用级端口转发。这一过程会分配一个socket来监听本地侧的
端口
,可选是否指定绑定地址
。一旦有链接访问这个端口,这个链接将会通过安全通道进行转发,并且应用协议决定了随后访问远端机器的哪个端口。目前支持SOCKS4
和SOCKS5
,并且ssh将作为SOCKS
服务端。只有root用户可以转发特权端口。动态端口转发可以通过配置文件指定。
IPv6地址可以用方括号括起来指定。只有超级用户可以转发特权端口。
默认情况下,本地端口受限于
GatewayPorts
的设置。但是显示的指定绑定地址
可以用来指定具体的地址。使用localhost
这个绑定地址
表示监听的端口仅能本地使用,而不指定地址或使用*
则表示监听的端口可以被所有接口所访问。
TCP FORWARDING
可以通过命令行或配置文件通过安全通道转发任意TCP链接。一个可能的TCP转发应用场景是通过安全链接访问邮件服务或穿透防火墙。
在下面的例子中,我们看一下IRC客户端与服务器之间的加密通信,即便IRC服务器不直接支持加密通信。
这一工作流程如下:用户通过ssh指定了一个端口用来转发链接到远程主机,随后,在客户端机器开启了一个被加密的服务,链接到相同的本地端口(译注:这个本地端口就是上一句话提到的
通过ssh指定了一个端口
),ssh将会加密并转发链接这个例子将从本地机器(
127.0.0.1
)到远程服务器(server.example.com
)的IRC会话装入隧道。
1
2 $ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
$ irc -c '#users' -p 1234 pinky 127.0.0.1这个隧道连接到IRC服务器“server.example.com”,加入通道“#users”,昵称“pinky”,使用端口1234。使用哪个端口无所谓,只要大于1023(只有root用户可以使用特权端口),并且不能和其他已用的端口冲突。这个链接被转发到远程服务器的6667端口,这是IRC服务的标准端口
-f
选项在后台运行ssh,并且远端执行命令sleep 10
指定了被装入隧道中的服务开启的时间。如果在指定时间内没有链接,ssh将会退出。
自定义用例
本地转发
本地转发示例如下。
场景1
考虑这样一个场景,
主机A
需要访问主机C
上的一些服务,但由于安全问题主机C
仅将主机B
的IP加入了白名单中,而这时我们又已知可以在主机A
上通过ssh链接到主机B
。这时我们在主机A
上可以通过主机B
去访问主机C
上的一些服务。我们在
主机A
上执行如下操作:1
$ ssh -L 12345:ip_c:service_port user@ip_b
其中,
ip_c
表示主机C
的ip地址,service_port
表示在主机C
上运行的服务的访问端口,user
表示主机B
上你用的用户名,ip_b
表示主机B
的ip地址,12345
表示主机A
上的端口。这时,你访问ip_a:12345
便相当于访问了ip_c:service_port
。场景2
当然,有的时候我们可能只是想穿透防火墙,如下图所示,
主机B
的防火墙仅打开了22端口,但主机B
上运行着许多服务,在防火墙外的主机A
无法直接访问。这时我们也可以通过本地转发的方式来访问主机B
上的一些服务。在
主机A
上执行如下操作:1
$ ssh -L 12345:localhost:80 user@ip_b
这样访问
主机A
的12345端口,便相当于访问主机B
的80端口,从而达到了穿透防火墙的目的。远程转发
在使用远程转发时,我们考虑这样一个场景,
主机C
上运行着一个服务,但是主机C
没有公网ip,主机A
无法直接访问服务。而主机B
则有公网IP,这时又不想将主机C
上的服务转移到主机B
上。这时我们就可以考虑使用远程转发。
我们在**主机C
**上执行以下操作:
1 | ssh -R [ip_b:]port_b:ip_c:port_c user@ip_b |
这样我们从主机A
访问主机B
的port_b端口,就相当于访问了主机C
的port_c
端口。
所以,通过这种方式也意味着,只要你有个公网ip的服务器,并不一定要将服务部署在服务器上,只要做好转发你就可以做很多事情。
其他选项
持久化ssh链接(ssh保活)
以下两种方式均可,推荐使用客户端配置
。
服务端配置
编辑服务器上/etc/ssh/sshd_config
文件,增加如下内容,设置完成后需要重启sshd服务
1 | # 服务器每隔60秒发送一次请求给客户端,实现保活 |
客户端配置
编辑客户端上的/etc/ssh/ssh_config
文件,注意与服务端不是同一个文件。
1 | # 客户端每隔60秒发送一次请求给服务端,实现保活 |
其他参数
-N
不执行远程命令,表示仅用来进行端口转发,常常与
-T
结合使用-T
不分配伪终端,
-f
请求ssh在命令执行之前转到后台,如果ssh要求输入密码或密码短语,但用户希望在后台输入密码,那么这是非常有用的。这表示
-n
,在远程站点启动X11程序的推荐方法是使用ssh -f host xterm之类的工具。如果
ExitOnForwardFailure
选项被设置成yes
,使用-f
选项开启的客户端会等待所有远程端口转发成功建立链接后在将程序转入后台。要关闭这个后台链接,只能用kill命令去杀掉。
-C
请求压缩所有数据,压缩算法和
gzip
相同,压缩在调制解调器线路和其他慢速连接上是可取的,但在高速网络上只会减慢速度。默认值可以在配置文件中按主机设置;请参阅压缩选项。
后台持久化执行端口转发
修改/etc/ssh_config文件,设置保活时间
使用下面命令执行端口转发
1
2# 以下ip和端口均为示例
$ ssh -f -NTC -L 12345:192.168.2.123:12345 user@192.168.1.10