任务一:正向端口转发
现在开始我们的第一个任务:假设主机D上面安装有数据库服务,监听的端口是8888,如果我想通过Office域中的主机A直接访问D主机中的数据库那该怎么办呢?这就要用到SSH的正向端口功能了。在这先要说明一下,在Linux中,所有的端口转发的操作都可以通过使用自带的工具ssh来完成。
完成任务一的命令很简单,如下:
ssh -L 8000:host-d.prod.mycompany.com:8888 oracle@host-c.prod.mycompany.com -N
现在解释一下上面的命令:
参数-L
表示在本地开启监听的端口,后面紧跟的参数格式为::,表示将本地的8000端口转发到远程主机D的8888端口。
orainst@host-c.prod.mycompany.com
这个参数指定要使用ssh登录的主机以及登录的用户名,这里使用的主机和前一个参数中的主机必须是在同一个网域当中,并且能相互访问,当然也可以是同一个机器。
参数-N
不执行远程的命令。这个参数在这里是可选的。
现在在主机A上面运行上面的命令之后输入正确的密码,然后我们先登录主机A查看一下当前端口的状态:
oracle@host-a[orcl]:~$ netstat -natp|grep 8000
任务二:反向端口转发
因为网域Prod不能以任何的方式访问网域Office,假设这两个网域所处的物理位置完全的不同,那当那一天处于网域Prod的时候又想操作处于网域Office中的主机A,那怎么办呢?这就是要用到反向端口转发的时候了。
反向端口转发的基本思想就是从主机A建立到主机C的ssh连接的同时在主机C上打开一个端口可以反向连接到主机B上面的某一个端口,当然从主机控制上面来说连接到主机B的22(ssh端口)是最实惠的了,现在要做的就是在主机A上面运行如下的命令:
ssh -R 8888:localhosthost-b.office.mycompany.com:22 oracle@host-c.prod.mycompany.com -N
同样的,先解释下上面的命令:
参数-R
创建一个反向的端口转发,后面紧跟的参数格式为 ::,这里监听的端口是8888,反向连接要到C主机原来根本无法访问的主机B的22端口。
oracle@host-c.prod.mycompany.com
这个参数指定要使用ssh登录的主机以及登录的用户名,这里使用的主机和前一个参数中的主机必须是在同一个网域当中,并且能相互访问,当然也可以是同一个机器。
参数-N
不执行远程的命令。这个参数在这里是可选的。
任务三:动态端口转发
动态端口转发实际上是建立一个ssh加密的SOCKS4/5代理通道,任何支持SOCKS4/5协议的程序都可以使用这个加密的通道来进行代理访问,现在这种方法最常用的地方就是翻墙了,使用的方法也很简单,命令如下:
ssh -D 8888 username@proxyhost.mycompany.com -N
命令解释:
参数-D
建立一个动态的SOCKS4/5的代理通道,紧接着的是本地监听的端口号。
username@proxyhost.mycompany.com
这个参数指定要使用ssh登录的主机以及登录的用户名,这里使用的主机和前一个参数中的主机必须是在同一个网域当中,并且能相互访问,当然也可以是同一个机器。
参数-N
不执行远程的命令。这个参数在这里是可选的。
ssh是一个非常棒的工具, 不但能建立动态转发, 例如chrome的Switchy插件用到的就是这个技术.
http://blog.163.com/digoal@126/blog/static/163877040201141821810103/
还能建立TCP的转发隧道, 例如我以前写过的关于使用ssh 隧道加密和加速WAN传输的几个例子.
http://blog.163.com/digoal@126/blog/static/163877040201342383123592/
http://blog.163.com/digoal@126/blog/static/16387704020115294425540/
上面的例子可以理解为正向的TCP端口转发代理(如local$ ssh -L 7001:1.1.1.1:1000 remote_A), 即本地服务器local建立和远程服务器的SSH连接, 本地监听一个端口7001, 连接本地的监听端口7001相当于"通过远程服务器remote_A访问指定的IP 1.1.1.1和PORT 1000".
这种方法适用于本地网络中其他服务器想访问远程的服务器, 但是其他服务器没有直接访问远程服务器的权限, 通过本地网络中有权限的服务器做端口转发的场景.
还有一种应用场景是这样的, 本地网络环境中没有任何一台服务器可以直接访问远程服务器, 但是远程服务器可以反过来访问本地的某台服务器, 这样的话也能实现本地服务器去访问远程服务器的目的. 这就是反向代理.
实际的应用场景如, 1. 家里的网络是动态拨号网络, 没有固定IP, 如果想在上班的时候控制家里的电脑怎么办呢? 如果公司有一台服务器是可以在家拨号过去访问的, 那么你可以在家里的电脑上建立和这台公司服务器的反向代理, 到公司后, 就可以连接这台服务器上的反向代理(监听)来连接家里的电脑了.
2. 有的客户可能不希望提供VPN给你去访问他们的服务器, 但是又需要得到你的远程协助, 怎么办呢?
你可以提供一台服务器让客户主动来访问你的服务器, 客户建立这样的反向代理, 然后你通过这个反向代理来连接客户开放的端口如VNC桌面共享, 进行远程协助. (这种方法比QQ远程协助是更安全的, 因为客户和这台服务器之间的数据时加密的, QQ远程协助毕竟有一定的风险存在.)
以下是反向代理的图例, 如图1 :
箭头表示允许访问的方向, 也就是说Server C可以访问Server A和Server B以及Client A.
而Client B和Client C可以访问Client A.
我们的目的是要让Client 可以访问Server. 这里就要用到SSH的反向端口转发, 或远程端口转发.
反向代理应用场景.
例如, 以下虚线表示Client C最终要访问Server A的22端口.
实现的步骤
1. Client A需要修改一下sshd_config, 开启GatewayPorts, 这样才能监听回环地址以外的地址, 如0.0.0.0, 这样的话其他服务器才能访问到这个端口.
2. Server C建立和Client A的反向端口转发, 让Client A在0.0.0.0上监听7001端口, 访问这个端口的数据转发到IP_SA的22端口.
ssh -CqTfnN -R 0.0.0.0:7001:IP_SA:22 IP_CA
其实再深层次一点, 因为client c和server a已经可以建立ssh了, 那么通过client c和server a建立反向代理, Server A也可以访问Client c. 这样需要经过了多层ssh隧道( IP_CA->IP_SC, IP_SA->IP_CC )
这种反向代理的用法很容易应用到实际的场景中, 例如前面提到的 :
有的客户可能不希望提供VPN给你去访问他们的服务器, 但是又需要得到你的远程协助, 怎么办呢?
你可以提供一台服务器让客户主动来访问你的服务器, 客户建立这样的反向代理, 然后你通过这个反向代理来连接客户开放的端口如VNC桌面共享, 进行远程协助.
如图 :
Public A是一台公用主机, 可以被客户和服务提供商同时访问.
当客户需要远程协助时.
1. 客户在SERVER C上开启一个VNC server
2. 客户将需要远程协助的窗口先登录好, 例如某些内网服务器(SERVER A , SERVER B)的telnet或ssh终端. 以供服务提供商使用.
3. 客户在SERVER C主动建立和这台公用主机的反向代理, 将端口转发到server c的vnc监听端口.
4. 服务提供商使用VNC客户端连接这台公共服务器的SSH代理监听端口, 相当于连接到了server c的vnc server. 以提供远程协助.
5. 客户可以在server c上观看, 录像, 控制这个VNC会话等.
下面来举个例子 :
场景 :
家里有一台WINDOWS服务器, 通过VPN拨号到公司网络.
WINDOWS服务器上跑了两个VMWARE的虚拟机, 分别是FreeBSD和CentOS.
公司有1台主机172.16.3.150, 安装了CentOS,
拨号后, 家里的虚拟机FreeBSD可以访问172.16.3.150.
现在要让公司的其他服务器如172.16.3.167可以访问到家里的192.168.198.129虚拟机.
1. 拨号, 略
2. 172.16.3.150上需要修改sshd_config.
[root@db-172-16-3-150 ~]# vi /etc/ssh/sshd_config
GatewayPorts yes
[root@db-172-16-3-150 ~]# service sshd reload
Reloading sshd: [ OK ]
3. 通过虚拟机192.168.198.130连接到172.16.3.150开启反向端口代理. (如果130不是LINUX是WINDOWS, 也可以用securecrt类似的软件进行代理配置.)
root@digoal:~ # ssh -CqTfnN -R 0.0.0.0:7001:192.168.198.129:22 172.16.3.150
root@172.16.3.150's password:
4. 在172.16.3.150上可以看到这个监听.
[root@db-172-16-3-150 ~]# netstat -anp|grep 7001
tcp 0 0 0.0.0.0:7001 0.0.0.0:* LISTEN 2392/sshd
tcp 0 0 :::7001 :::* LISTEN 2392/sshd
5. 现在到172.16.3.167上连接172.16.3.150的7001端口.
[root@db5 ~]# ifconfig
bond0 Link encap:Ethernet HWaddr 00:23:7D:A3:F0:4E
inet addr:172.16.3.176 Bcast:172.16.3.255 Mask:255.255.255.0
inet6 addr: fe80::223:7dff:fea3:f04e/64 Scope:Link
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
RX packets:200422824 errors:0 dropped:0 overruns:0 frame:0
TX packets:16849618 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:23012276676 (21.4 GiB) TX bytes:3567071726 (3.3 GiB)
[root@db5 ~]# ping 172.16.3.150
PING 172.16.3.150 (172.16.3.150) 56(84) bytes of data.
64 bytes from 172.16.3.150: icmp_seq=1 ttl=64 time=0.337 ms
— 172.16.3.150 ping statistics —
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.337/0.337/0.337/0.000 ms
[root@db5 ~]# ssh -p 7001 172.16.3.150
Password for root@digoal.org:
root@digoal:~ # ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
ether 00:0c:29:c0:4b:65
inet 192.168.198.129 netmask 0xffffff00 broadcast 192.168.198.255
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active
到这里反向代理的测试完成.
接下来我们看看如何在反向代理的基础上, 再做一层反向代理.
例如我要在172.16.3.167建立和192.168.198.129的反向代理, 让192.168.198.130通过192.168.198.129来访问172.16.3.150.
1. 首先要修改192.168.198.129的sshd_config
root@digoal:~ # vi /etc/ssh/sshd_config
GatewayPorts yes
root@digoal:~ # service sshd reload
Performing sanity check on sshd configuration.