SSH端口转发(本地端口转发、远程端口转发、动态端口转发)工作原理、应用详解

作者: lesca 分类: Concept,Tutorials,Ubuntu,Web 发布时间: 2011-03-01 15:19

实验条件:
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

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

2 Comments