Ssh Tunnel,即通常所说的Ssh隧道,其基本原理非常简单,如下图所示:
从图中可以看到,由于防火墙的设置,客户端浏览器Firefox想要直接访问Web服务器Nginx是不行的;但经过ssh工具可在客户端和服务器之间建立一条Ssh隧道,而Firefox直接访问本地的12345端口即可间接的访问到Nginx,这是否很神奇?
怎么做到的?从操作上来说,有两种方法可以做到。
1,在客户端上操作(假设为Linux系统,因此采用ssh命令):
$ ssh -Nf -L 127.0.0.1:12345:192.168.30.163:80
lenky@192.168.30.163
用Firefox访问Web服务端口:
http://127.0.0.1:12345/
查看当前连接,客户端的情况:
lenky@lenky-local:~$ sudo netstat -natp | grep 12345
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN 4011/ssh
tcp 0 0 127.0.0.1:12345 127.0.0.1:52194 ESTABLISHED 4011/ssh
tcp 0 0 127.0.0.1:52194 127.0.0.1:12345 ESTABLISHED 2604/firefox
lenky@lenky-local:~$ sudo netstat -natp | grep ssh
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 925/sshd
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN 4011/ssh
tcp 0 0 192.168.30.162:57567 192.168.30.163:22 ESTABLISHED 4011/ssh
tcp6 0 0 :::22 :::* LISTEN 925/sshd
即:Firefox(52194) <---> Ssh(12345)
服务器端情况:
lenky@lenky-VirtualBox:~$ sudo netstat -natp
激活Internet连接 (服务器和已建立连接的)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3463/nginx: master
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 955/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3185/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 754/cupsd
tcp 0 0 192.168.30.163:22 192.168.30.162:57567 ESTABLISHED 4115/sshd: lenky [p
tcp 0 0 192.168.30.163:47634 192.168.30.163:80 ESTABLISHED 4208/sshd: lenky
tcp 0 0 192.168.30.163:80 192.168.30.163:47634 ESTABLISHED 3464/nginx: worker
tcp6 0 0 :::80 :::* LISTEN 3463/nginx: master
tcp6 0 0 :::22 :::* LISTEN 3185/sshd
tcp6 0 0 ::1:631 :::* LISTEN 754/cupsd
tcp6 1 0 ::1:45743 ::1:631 CLOSE_WAIT 847/cups-browsed
即:Ssh(47634) <---> Nginx(80)
整个连接起来就是:
(Firefox(52194) <---> Ssh(12345))客户端 <---> Ssh(192.168.30.162:57567) <---> Ssh(192.168.30.163:22) <---> 服务器(Ssh(47634) <---> Nginx(80))
2,在服务器端操作(假设同样是Linux系统,因此采用ssh命令):
$ ssh -Nf -R 127.0.0.1:12345:192.168.30.163:80
lenky@192.168.30.162
在客户端用Firefox访问Web服务端口:
http://127.0.0.1:12345/
查看当前连接,客户端的情况:
lenky@lenky-local:~$ sudo netstat -natp | grep 12345
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN 4445/sshd: lenky
tcp 0 0 127.0.0.1:52207 127.0.0.1:12345 ESTABLISHED 2604/firefox
tcp 0 0 127.0.0.1:12345 127.0.0.1:52206 TIME_WAIT -
tcp 0 0 127.0.0.1:12345 127.0.0.1:52207 ESTABLISHED 4445/sshd: lenky
tcp6 0 0 ::1:12345 :::* LISTEN 4445/sshd: lenky
lenky@lenky-local:~$ sudo netstat -natp | grep ssh
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 925/sshd
tcp 0 0 127.0.0.1:12345 0.0.0.0:* LISTEN 4445/sshd: lenky
tcp 0 0 127.0.0.1:12345 127.0.0.1:52207 ESTABLISHED 4445/sshd: lenky
tcp 0 0 192.168.30.162:22 192.168.30.163:55747 ESTABLISHED 4325/sshd: lenky [p
tcp6 0 0 :::22 :::* LISTEN 925/sshd
tcp6 0 0 ::1:12345 :::* LISTEN 4445/sshd: lenky
即:Firefox(52207) <---> Ssh(12345)
服务器端情况:
lenky@lenky-VirtualBox:~$ sudo netstat -antp
激活Internet连接 (服务器和已建立连接的)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3463/nginx: master
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 955/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3185/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 754/cupsd
tcp 0 0 192.168.30.163:47641 192.168.30.163:80 ESTABLISHED 4344/ssh
tcp 0 0 192.168.30.163:80 192.168.30.163:47641 ESTABLISHED 3464/nginx: worker
tcp 0 0 192.168.30.163:55747 192.168.30.162:22 ESTABLISHED 4344/ssh
tcp6 0 0 :::80 :::* LISTEN 3463/nginx: master
tcp6 0 0 :::22 :::* LISTEN 3185/sshd
tcp6 0 0 ::1:631 :::* LISTEN 754/cupsd
tcp6 1 0 ::1:45743 ::1:631 CLOSE_WAIT 847/cups-browsed
即:Ssh(47641) <---> Nginx(80)
整个连接起来就是:
(Firefox(52207) <---> Ssh(12345))客户端 <---> Ssh(192.168.30.162:22) <---> Ssh(192.168.30.163:55747) <---> 服务器(Ssh(47641) <---> Nginx(80))
上面用到的ssh命令的格式说明如下(更具体的介绍请看man手册):
ssh -C -f -N -g -L [bind_address:]listen_port:DST_Host:DST_port user@Tunnel_Host
ssh -C -f -N -g -R [bind_address:]listen_port:DST_Host:DST_port user@Tunnel_Host
其中-L和-R的参数格式为[要打开的监听IP:]要打开的监听端口:要映射到的监听 IP:要隐射到的监听端口,监听IPbind_address默认为127.0.0.1。
-f Fork into background after authentication.
后台认证用户/密码,通常和-N连用,不用登录到远程主机。
-p port Connect to this port. Server must be on the same port.
被登录的ssd服务器的sshd服务端口。
-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 才能转发特权端口. 可以在配置文件中指定动态端口的转发.
-C Enable compression.
压缩数据传输。
-N Do not execute a shell or command.
不执行脚本或命令,通常与-f连用。
-g Allow remote hosts to connect to forwarded ports.
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。
总得来说,Ssh Tunnel通常主要是实现3个基本功能:
1) 数据加密传输:采用了SSH加密。
2) 穿透防火墙:作为通用端口22或443,大多被防火墙放通。
3) 远程接入:这属于第1个功能的延生,在SSL VPN里应用得淋漓尽致。