举几个例子说一下ssh port forward的应用吧,假设:
A:192.168.1.123,linux,有sshd,httpd服务,没有路由,能通过网关访问外网
B:218.104.xxx.xxx,linux,有sshd,有路由
C:172.16.1.123,linux,有sshd,没有路由,能通过网关访问外网
D:192.168.1.111,windows,没有sshd,没有路由,能通过网关访问外网络
其中:A,D通网断,可以互相访问,与C不在同一网段,不能直接访问。
例一:让B访问A的服务
1) 从A上建立远程端口转发:
A#ssh -f -N -g -R9999:localhost:22 -l root 218.104.xxx.xxx
说明:需要认证root@218.104.xxx.xxx的密码,且9999端口在218.104.xxx.xxx未被占用,一旦命令执行成功,在B上运行 netstat -an |grep 9999可以看到该端口正在监听。如果不用root,只能创建1024以上的端口监听。
2) 从B上连接A的sshd端口:
B#ssh -p 9999 -l user localhost
说明:B-ssh->B:9999->B-ssh->A:22此时用户从B上即可连接到A的sshd端口,实现了vpn的功能。但是如果用户从B以外仍然无法访问A,即使在B上用ssh -p 9999 -l user 218.104.xxx.xxx都无法登陆。
问题:-g参数本来是允许远程机器访问转发端口的,但是实际使用中似乎不起作用。当不使用-g时,用netstat -na看到的端口监听是ServerName:listen_port的形式,使用-g参数之后看到的情况是*:listen_port的形式(-L,- D时如此,-R无效)。如果要让B以外的机器也能访问A,即能访问B的9999端口,可以在/etc/ssh/sshd_config中加入下面一行:
GatewayPorts Yes
或者用我们后面介绍的方法。
例二:让C访问A的服务,理论上说有两个途径
方法一:在B上建立本地端口转发到自身,并且使用-g参数,允许远程主机访问
B#ssh -f -N -g -L7777:loaclhost:9999 -l root localhost
如果-g起作用(实际尝试中,在有些机器中成功,有些失败,但是端口确实是在监听所有地址,即*:listen_port),则:
C#ssh -p 7777 218.104.xxx.xxx -l user
将能连接到A的sshd服务
C-ssh->B:7777-ssh->B->localhost(B):9999->B-ssh->A:22
方法二:在C上通过B建立本地端口转发到localhost(B),因为B上可以访问自身9999端口,即可访问到A
C#ssh -f -N -g -L6666:localhost:9999 -l root 218.104.xxx.xxx
C#ssh -p 6666 -l user localhost
C->localhost(C):6666-ssh->B->localhost(B):9999->B-ssh->A:22
先到这里,下次介绍-D的作用吧。实践的OS是redhat enterprise 3,由于家里没有试验环境,所以麻烦比较多。
ssh的三个强大的端口转发命令:
ssh -C -f -N -g -L listen_port:DST_Host:DST_port -l user Tunnel_Host
ssh -C -f -N -g -R listen_port:DST_Host:DST_port -l user Tunnel_Host
ssh -C -f -N -g -D listen_port -l user Tunnel_Host
I) 先看看linux下面ssh命令的相关帮助:
# ssh -help
……
-l user Log in using this user name.
用来登录sshd服务器的用户名,相当于user@remote-host。
-f Fork into background after authentication.
后台认证用户/密码,通常和-N连用,不用登录到远程主机。
-p port Connect to this port. Server must be on the same port.
被登录的ssd服务器的sshd服务端口。
-L listen-port:host:port Forward local port to remote address
在本地创建监听端口,一旦有连接建立到该端口,就转发到host:port。
-R listen-port:host:port Forward remote port to local address
在远程创建监听端口,一旦有连接建立到该端口,就转发到host:port。
These cause ssh to listen for connections on a port, and
forward them to the other side by connecting to host:port.
-D port Enable dynamic application-level port forwarding.
在本地建立监听端口,一旦有连接建立到该端口,动态转发,相当于创建了socks代理服务器。
-C Enable compression.
压缩数据传输。
-N Do not execute a shell or command.
不执行脚本或命令,通常与-f连用。
-g Allow remote hosts to connect to forwarded ports.
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。注:这个参数我在实践中似乎始终不起作用,参见III)
……
II) 参见:
-L port:host:hostport
将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport
-R port:host:hostport
将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport
-D port
指定一个本地机器 “动态的'’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.
III) ssh port forward相关配置
一般sshd配置文件路径为/etc/ssh/sshd_config
添加一行:
GatewayPorts Yes
则允许远程主机连接到转发端口,相当于-g
最后是我的理解:
Localhost->Localhost:listen_port-ssh(encrypt)->Tunnel_Host-(unencrypt)->DST_Host:DST_port
Tunnel_Host->Tunnel_Host:listen_port-ssh(encrypt)->DST_Host:DST_port
Localhost->Localhost:listen_port-ssh(encrypt)->Tunnel_Host-(unencrypt)->AnyHost:Any_port
阅读(3176) | 评论(0) | 转发(1) |