【译】SSH隧道:本地和远程端口转发

本文是:SSH Tunnel - Local and Remote Port Forwarding Explained With Examples 的译文

  有两种方法可以创建SSH隧道,本地和远程端口转发(也有动态转发,但我们不在这里讨论)。最好的理解方法是通过一个示例,让我们从本地端口转发开始。

本地端口转发

  假设您处于一个不允许连接到特定服务器的专用网络上。比方说,你在工作,imgur.com被*。为了绕过这个,我们可以通过一台服务器创建一个不在我们的工作网络的隧道,从而可以访问Imgur。

$ ssh -L 9000:imgur.com:80 user@example.com

  这里的关键是-L选项, 告诉我们正在进行本地端口转发,将端口9000转发到imgur.com:80, 80是HTTP的默认端口。现在,只需要打开浏览器然后访问:

http://localhost:9000

  SSH隧道的好处在于它们是加密的。没有人会看到你访问的网站,他们只看到SSH连接到你的服务器。

连接到防火墙后面的数据库

  另一个很好的例子是,如果你需要访问服务器端口,且只能从本地主机访问,而不能远程访问。

  这里的一个例子是当您需要连接到数据库控制台时,出于安全上的考虑,仅允许本地连接。 假设您在服务器上运行PostgreSQL,默认情况下在端口5432上监听。

ssh -L 9000:localhost:5432 user@example.com

  在这里更改的部分是localhost:5432,它表示将连接从本地端口9000转发到服务器的5432端口。 现在我们可以直接连接到我们的数据库。

psql -h localhost -p 9000

  现在让我们在这里停下来一点点解释实际发生了什么。 在第一个例子中,9000:imgur.com:80实际上是将本地端口9000转发到imgur.com端口80。您可以想象您的服务器上的SSH实际上是在两个端口之间建立连接(一个隧道),一个在您的本地机器,一个在目标机上。

  但是如果我们说的是9000:localhost:5432,那就意味着从服务器的角度来看localhost,而不是本机上的localhost。 这意味着将本地端口9000转发到服务器上的端口5432,因为当您在服务器上时,localhost表示服务器本身。[因为这里,ssh登陆到目标机器上]

  这可能让人有点困惑,但重要的是要了解语法实际上意味着什么。 

远程端口转发

  现在是本教程的第二部分,远程端口转发。 这最好以一个例子来解释。  

  假设您正在本地计算机上开发Rails应用程序,并且希望将其显示给朋友。 不幸的是,您的ISP没有为您提供公共IP地址,因此无法通过互联网直接连接到您的计算机。

  有时这可以通过在您的路由器上配置NAT(网络地址转换,其实就是在路由器上做内网端口映射,也即端口转发)来解决,但这并不总是能够正常工作,并且需要您更改路由器上的配置,这并不总是可取的。 当您的网络上没有管理员访问权限时,此解决方案也不起作用。

  要解决这个问题,您需要另一台可以公开访问并具有SSH访问权限的计算机。 只要您可以连接到互联网上,它可以是任何服务器。 我们会告诉SSH在服务器上打开一个新端口的隧道,并将其连接到本机端口。

ssh -R 9000:localhost:3000 user@example.com

  这里的语法非常类似于本地端口转发,将-L变成-R。 但是与本地端口转发一样,语法保持不变。

  首先,您需要指定远程服务器将侦听的端口,在这里为9000,接下来的本地机器的本地端口(在这种情况下为3000)。

  还有一件事情你需要做,以实现这一点。 SSH不默认允许远程主机转发端口。 要启用,需要打开配置文件:/etc/ssh/ssh_config,并在配置文件中某个地方添加以下行:

$ sudo vim /etc/ssh/sshd_config
GatewayPorts yes

  确保你只添加了一次。重启SSH服务:

sudo service ssh restart

  此后,您应该能够远程连接到服务器,甚至可以从本地计算机连接到服务器。 这样做的方式是您首先创建一个SSH通道,将流量从端口9000上的服务器转发到端口3000上的本地计算机。这意味着如果您从本地计算机连接到端口9000上的服务器, 实际上通过SSH隧道向您的机器发出请求。

一些小提示

  您可能已经注意到,每次创建一个隧道时,您也可以将SSH登录到服务器并获得一个shell。 这通常不是必需的,因为您只是想创建一个隧道。 为了避免这种情况,我们可以使用-nNT标志运行SSH,如下所示,这将导致SSH不分配tty,只能做端口转发。

ssh -nNT -L 9000:imgur.com:80 user@example.com

  SSH有很多功能,所以建议您在man ssh上检查手册页面,其中包含更多提示。

【例】映射巡风扫描器到外网

  其实我要做的是将内网部署的web服务,通过外网ip能够访问,VPS你懂的,又贵,所以不能完全将一个很大的东西放在VPS上...

  本想映射乌云镜像的,无奈不在本机上...

  现在有的是一个内网机器上的巡风扫描系统:http://192.168.1.108/login     一个可SSH登陆的VPS:165.227.29.209

【译】SSH隧道:本地和远程端口转发

  VPS上还搭建了一个DVWA: http://165.227.29.209/dvwa/login.php

  现在就想在VPS上做一个远程端口转发,通过访问VPS上的端口就能直接访问到本地的服务。

Step 1: 登陆配置SSH

starnight:~ starnight$ ssh root@165.227.29.209
root@165.227.29.209's password: [input your login password here]
root@ubuntu-512mb-sfo2-01:~# ifconfig eth0 | grep inet
    inet addr:165.227.29.209 Bcast:165.227.31.255 Mask:255.255.240.0
    inet6 addr: fe80::5446:75ff:fe13:726e/64 Scope:Link
root@ubuntu-512mb-sfo2-01:~# vim /etc/ssh/sshd_config 

  在你喜欢的地方加上下面这行, 记住,只能出现一次。

    【译】SSH隧道:本地和远程端口转发

  重启SSH服务:

root@ubuntu-512mb-sfo2-01:~# service ssh restart

Step 2: 远程端口转发

  在你需要将web服务映射出去的机器上运行如下命令:

root@starnight:~# ifconfig ens33 | grep inet
root@starnight:~# ssh -R 8080:localhost:80 root@165.227.29.209

  因为VPS上的80端口已经部署了dvwa,现使用8080端口:

【译】SSH隧道:本地和远程端口转发

Step 3: 访问测试

  访问远程VPS的8080端口:http://165.227.29.209:8080/login

【译】SSH隧道:本地和远程端口转发

  这样就能通过外部ip访问到本地机器上部署的服务了。


SSH连接不掉线

  用SSH进行连接有个小问题就是过段时间之后,ssh连接会断开,当然服务器不可能让ssh连接一直保持的。如果想一直保持ssh连接的话,可以参考如下解决方案。

打开服务器 /etc/ssh/sshd_config,我在最后增加一行
ClientAliveInterval
ClientAliveCountMax

  再重启一下SSH服务器:

service sshd restart

SSH不get shell

  一般来讲,如果我们只需要进行端口转发,而不需要拿到一个shell的话,可以设置一个选项:-nNT

$ ssh -nNT -L :imgur.com: user@example.com
上一篇:lcx端口转发


下一篇:实战 SSH 端口转发