SSH端口转发(本地端口转发、远程端口转发、动态端口转发)工作原理、应用详解
实验条件:
1.本文所述之实验,本地主机操作系统基于Ubuntu 10.04,远程主机操作系统基于BSD发行版
2.本地主机安装了ssh client(ssh),也安装了ssh server(sshd)
基础知识:
文章中客户端指ssh,用于发出连接请求;服务端指sshd,监听端口22。
安全通道是指ssh与sshd之间已建立的连接通道,该连接是加密的。
SSH 端口转发格式[1]
[-L [bind_address:]port:host:hostport]
[-R [bind_address:]port:host:hostport]
[-D [bind_address:]port]
动态端口转发
-D <port>
这会使本地主机监听端口port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道发送到远程主机。远程主机的sshd会根据数据包的应用层协议(如HTTP)自动建立对应的连接。
$ ssh -D 7070 sisca@216.194.70.6
登陆前本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp6 0 0 :::22 :::* LISTEN 927/sshd
登陆后本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp 0 0 127.0.0.1:7070 0.0.0.0:* LISTEN 5205/ssh tcp6 0 0 :::22 :::* LISTEN 927/sshd tcp6 0 0 ::1:7070 :::* LISTEN 5205/ssh
登陆后远程主机端口监听状态:
$ sockstat -4l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS (什么都没有)
小结:我们发现,动态端口转发的时候确实是本地主机的ssh在监听端口7070的
本地端口转发
-L <local_port>:<host>:<host_port> <ssh_server>
这会使本地主机监听端口local_port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道,同时远程主机会与主机host的端口host_port建立连接。
$ ssh -L 7001:localhost:7070 sisca@216.194.70.6
登陆前本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp6 0 0 :::22 :::* LISTEN 927/sshd
登陆后本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN 3475/ssh tcp6 0 0 :::22 :::* LISTEN 927/sshd tcp6 0 0 ::1:7001 :::* LISTEN 3475/ssh
登陆后远程主机端口监听状态:
$ sockstat -4l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS (什么都没有)
小结:我们从中可以看出,本地端口转发的时候确实是本地主机的ssh在监听端口7001
远程端口转发
-R <remote_port>:<host>:<host_port> <ssh_server>
这会使ssh_server(远程端)监听端口remote_port,一旦与该端口建立连接,经过该端口的数据会被转发到安全通道,并且本地主机会与主机host的端口host_port建立连接。
$ ssh -R 7001:localhost:7070 sisca@216.194.70.6
登陆前本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp6 0 0 :::22 :::* LISTEN 927/sshd
登陆后本地主机端口监听状态:
$ sudo netstat -lnput | grep ssh tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 927/sshd tcp6 0 0 :::22 :::* LISTEN 927/sshd
登陆后远程主机端口监听状态:
$ sockstat -4l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS sisca sshd 66196 7 tcp4 127.0.0.1:7001 *:*
小结:很明显,使用远程端口转发时,本地主机的端口监听并没有发生变化,相反远程主机却开始监听我们指定的7001端口
小提示:
这里的remote_port,local_port可以归并为listen_port,因此我们得到这样的助记格式:
ssh [-L|-R] <listen_port>:<host>:<host_port>
本地端口转发应用:[2]
背景:在实验室里有一台 LDAP 服务器(LDAP Server),但是限制了只有本机上部署的应用才能直接连接此 LDAP 服务器。现在我们想临时从本地机器(LDAP Client)直接连接到这个 LDAP 服务器,只需要在LDAP Client上运用本地端口转发:
$ ssh -L 7001:localhost:389 LdapServerHost
图1 本地端口转发
数据流向:
该命令首先使本地主机(LDAP Client)与远程主机(LDAP Server)建立一个SSH安全连接(安全通道)
然后本地主机会监听端口7001(注意是ssh在监听)
一旦本地LDAP客户端程序将数据发送到端口7001(即建立连接),远程主机上的sshd将主动与端口389(LDAP服务的端口)建立连接
从而来自LDAP客户端的请求转发到该端口389上(当然是通过安全通道)
注意:
本地主机有两个客户端:
1) ssh – 用于与远程主机建立ssh连接
2) LDAP客户端 – 用于与远程主机的LDAP服务程序进行通讯
远程主机对应地有两个服务进程:
1) sshd – 监听端口22
2) ldapd -监听端口389
远程端口转发应用:[2]
背景:这次假设由于网络或防火墙的原因我们不能用 SSH 直接从 LDAP Client 连接到 LDAP 服务器(LDAP Server),但是反向连接却是被允许的。那此时我们的选择自然就是远程端口转发了。我们这次在LDAP Server上运用远程端口转发,因此LDAP Client必须安装了sshd
$ ssh -R 7001:localhost:389 LdapClientHost
图2 远程端口转发
数据流向:
该命令首先使LDAP Server与 LDAP Client 建立一个SSH安全连接(安全通道)
然后LDAP Client开始监听端口7001(注意是sshd在监听)
一旦LDAP Client将数据发送到端口7001(即建立连接),LDAP Server上的ssh将主动与端口389(LDAP服务端口)建立连接
从而来自LDAP客户端的请求转发到该端口389上(当然是通过安全通道)
本地转发与远程转发的对比与分析
本地端口转发:ssh客户端发起ssh连接,并且监听指定端口
远程端口转发:ssh客户端发起ssh连接,但是由远程主机上的sshd监听指定端口
多主机转发应用[2]
图3 多主机端口转发
$ ssh -g -L 7001:<B>:389 <D>
注意:我们在命令中指定了“ -g ”参数以保证机器(A)能够使用机器(C)建立的本地端口转发。
References:
[1] man 1 ssh
[2] IBM DeveloperWorks – 实战 SSH 端口转发
版权声明
本文出自 Lesca 技术宅,转载时请注明出处及相应链接。
本文永久链接: https://www.lesca.cn/archives/ssh-port-forwarding-principle-and-praticle-application.html
- Pingback: ssh 端口转发 | GooRockey's Life
- Pingback: SSH端口转发应用详解 | iJiaer