SSH,


用ssh反向隧道访问内网机器

有时候我们需要从公网访问内网的机器。现在一般家里都会有个路由器,路由器一般都会带防火墙,所以从墙外要访问内部的机器,都需要设置防火墙,做端口映射。

今天我看到ssh有一个有趣的功能,可以在不设置端口影射的情况下直接建立一个隧道,允许从外部访问内网的机器。

假设我们有两台机器,一台在内网中,IP是192.168.1.2,命名为dest;另一台在公网上,地址是pub.server.net,命名为src。我们需要从pub.server.net去访问内网那台192.168.1.2.

一、从dest发起ssh连接到pub.server.net,建立一个反向隧道

ssh -R 19999:localhost:22 user@pub.server.net

二、从src发起ssh连接

ssh localhost -p 19999

因为之前dest到src的ssh反向隧道建立之后,src上的本地19999端口就被转发到dest的22端口了,所以上面这个ssh命令就建立了从src到dest:22的连接。

其中第一步可以加上-fN参数,这样就可以把ssh进程放到后台运行,且无需打开服务器端的shell。

提醒:easeway告诫我说,ssh的-R、-D用法有很多安全漏洞。所以提醒大家,不要在公司内网玩这个东东,否则等于是給公司的防火墙上掏了个洞,很危险的。

又,这种隧道一般而言需要长期保持,而ssh连接会超时断开,所以需要用autossh来保持隧道可用。

方法如下:

autossh -M 5678 -NR 19999:localhost:22 user@pub.server.net

为方便计,又可将以上命令作为一个upstart服务,令其自动加载。当别撰一文详述upstart服务设置方法。


早就听说过ssh反向隧道,却一直没有尝试过,今日偶得之,简单做个记录。

ssh反向隧道可以解决这样的场景:

比如在公司内部都是局域网,但是我想从公司外访问公司内的机器,该怎么办呢?当然了,vpn肯定没问题,但更快捷的方式就是ssh反向隧道。

为了简单明白,下面示例如何使用:

公网有台机器叫public,内网有台机器叫private,现在要实现从public到内网的访问,一条命令即可搞定。

在private上执行: ssh -NfR2222:localhost:22 root@public

在public上确认:root@public:~# netstat -tnl| grep 2222

tcp        0      0 127.0.0.1:2222          0.0.0.0:*               LISTEN

在public上登陆private:root@public:~# ssh root@127.0.0.1 -p 2222

解释ssh参数:

-N:不执行何指令

-f:后台执行

-R:建立reverse tunnel

进一步简化操作:

上面不方便的地方是,每次要在外面登陆内网,都需要先登陆到public上,再从public上登陆内网,如果可以类似网页代理,我在任何地方都可以直接登陆内网那不就完美了,别急,还真可以。

在public上执行下面的命令:

root@public:~# ssh -g -L 9099:localhost:2222 localhost

即将本地9999端口映射到本地2222端口,2222端口在之前已经映射到了private,那么,hahaha

在公司外任何一台机器上执行:

ssh root@public -p 9099输入private机器的密码即可登陆到private这台机器上。

还有个autossh工具,它可以帮助断线后自动重连,需要的时候可以研究研究


SSH反向连接的使用

1、什么是反向连接?

反向连接是指主机A(受控端)主动连接主机B(控制端),在主机A和主机B之间建立一个远程连接,通过这个连接主机B可以主动的向主机A发送一些请求。

2、为什么需要主机A主动去连接主机B呢?

这是因为主机A在局域网内,如果没有对主机A进行端口映射,对于主机B来说主机A是不可见的,如果在主机B这边向主机A发送连接请求,这个请求是不可达的。而主机B有自己独立的IP,对于主机A来说是可见的,可以直接向主机B请求连接。

3、SSH反向连接的过程

方法就是主机A主动去连接主机B,主机B响应主机A的连接请求,它们之间就建立了一个远程连接。然后主机B在本地再创建一个本地连接,重定向到主机A和主机B刚才建立的远程连接上,之后对这个本地连接的操作都会反馈到远程连接上去。整个过程类似于文件的DUP,这就在主机A和主机B之间建立了连接通道,此时对于主机B来说,主机A已经是可见了。

连接流程如下:

3.1、主机A ssh客户端向主机B sshd服务端发送请求,建立远程连接。

3.2、主机B sshd服务端创建本地连接很远程连接的映射(反向连接通道)。

3.3、主机B ssh客户端向主机B sshd服务端的连接通道发送请求, 建立主机B ssh和主机A sshd的连接。

完成连接后,主机A对于主机B可见的形式就是存在于主机B的那个本地连接。

4、为什么需要在主机B对远程连接映射一个本地连接?

反向连接就是CS架构,不过是受控端主动向控制端请求连接,让它们之间的连接建立。传统的CS方式是可以解决主机A和主机B之间的连接问题,但是那样主机A和主机B的连接方式并不灵活,两者之间能做的事情,只能是CS之际协议规定的事情。在主机B上建立了主机A的连接映射后, 对于主机B来说主机A已经不是局域网内那台不可见的主机,主机A已经是存在主机B的一台可见主机,这样就消除了局域网和广域网的阻碍。 主机A和主机B之间建立的那个远程连接就是主机A和主机B的通道-“网线”。


2.一开始提到,这种反向连接(Reverse Connection)不稳定,可能随时断开,需要内网主机B再次向外网A发起连接,这时需要个“朋友”帮你在内网B主机执行这条命令。它就是Autossh。

在此之前还要解决之前的一个问题,那就是每次内网主机B连接外网主机A时都需要输入密码,这个问题ssh本身是提供另外一种验证方式——通过密钥验证用户身份,实现自动登录。

2.1.在内网B主机上生产公钥和私钥

$ssh-keygen...(一直按Enter,最后在~/.ssh/下生成密钥)

$ls~/.ssh/id_rsa id_rsa.pub known_hosts

2.2.复制B主机上生成的id_rsa.pub公钥到外网A主机上,并将内容加入到~/.ssh/authorized_keys中

$catid_rsa.pub >> ~/.ssh/authorized_keys

试下,内网B主机连接外网A主机,就不再输入密码验证了

补充:今天了解到ssh-copy-id这个命令,上面这个操作就变的简单了

$ssh-copy-iduser1@123.123.123.123

2.3.再来看看Autossh的用法

$autossh-M5678-NR1234:localhost:2223user1@123.123.123.123-p2221

比之前的命令添加的一个-M 5678参数,负责通过5678端口监视连接状态,连接有问题时就会自动重连,去掉了一个-f参数,因为autossh本身就会在background运行。

3.终极方案:当重启内网B主机,谁来自动Autossh呢,加入daemon吧

以daemon方式执行,相当于root去执行autossh, ssh,这时刚才普通用户目录下的.ssh/authorized_keys文件会不起效。有两种办法解决,一种是用autossh的参数指定.ssh路径;另外一种是以普通用户身份执行daemon,下面是第二种方式。

/bin/su-c'/usr/bin/autossh-M5678-NR1234:localhost:2223user1@123.123.123.123-p2221'- user1

autossh还有很多参数,用来设置重连间隔等等。

将上面命令放入下面各启动方式中,根据自己系统自己配置:

SysV:/etc/inid.d/autossh

Upstart: /etc/init/autossh.conf

systemd: /usr/lib/systemd/system/autossh.service

P.S.

1.家里是ADSL的话,用DDNS,解决ip问题

2.外网有路由的可设下端口映射

3.虽然有密钥和密码保护,但还请小心使用

相关内容

    暂无相关文章