网易乐得RDS系列:网页终端大揭秘!

为了便于管理数据库,乐得RDS为高权限用户提供了基于网页的终端(web terminal),可以直接登录数据库所在的服务器来执行操作系统命令。本篇文章就来给列位看官说道一下我们是怎么实现这个功能的。

在最初开发阶段,我们曾使用wetty来实现web terminal功能。wetty是使用Node.js和websockets开发的一个开源网页终端,调用了纯JavaScript写的chromeOS的终端模拟器(hterm),在性能上比较有保证。但是在使用过程中,我们发现wetty存在以下几个问题:

1

不支持同时SSH到多台服务器。从安全角度考虑,我们只允许在一台中心服务器A上对外提供wetty的服务(A上运行的wetty本身可以通过SSH连接到其他的数据库服务器)。此时如果有用户想要登录数据库服务器B和数据库服务器C,就需要在A的不同端口上启动两个wetty服务端,分别连接到B和C;并且此时需要以A上的两个wetty服务端口来区分B、C的连接,依靠前置的nginx根据url参数来做动态转发,实现起来比较复杂。

2

不自带安全认证。假设在中心服务器A上开启服务端口1234之后,在任何拥有A:1234访问权限的机器上使用浏览器就能进入wetty提供的终端,因为wetty本身不提供任何访问控制。并且由于上一条所说,A可能会同时开放多个服务端口,更是增加了风险。

3

没有连接检测机制。一旦启动wetty服务端,无论有没有用户访问,都会一直保持到目标机器的SSH连接,这对资源也是一种浪费。虽然可以在应用层实现用户连接检测的机制,但是感觉还是不靠谱。

由于以上几点原因,尤其是对安全问题的担忧,推动我们继续去寻找可以替代的产品。在搜集了更多的资料后,我们发现了一个比较理想的解决方案——Gate One。

Gate One是一个开源的、基于web的终端模拟器,拥有强大的插件系统,功能上比较全面。除了解决了上述的三个问题之外,它还额外提供了一些比较实用的功能,例如显示图片和pdf、图形化的提示信息、记录和回放用户操作、ssh key管理等。官方文档的支持也比较好。

废话不多说,撸起袖子干。

安装

1

依赖:python 2.7+ or 3.2+,tornado 2.2+

源码:git clone https://github.com/liftoff/GateOne.git

安装:cd GateOne; python setup.py install

验证:whereis gateone

配置

2

默认的配置文件放在/etc/gateone/conf.d下,涉及修改的有以下几个文件:

10server.conf

Gate One的主设置文件,在官方文档http://liftoff.github.io/GateOne/About/configuration.html列出了具体的参数的用途。RDS由于前端有用nginx做https服务,这里把”disable_ssl”改为ture,在“origins”里添加RDS应用服务器的ip以允许来自应用的连接,设置“port”为”8001”。

20authentication.conf

Gate One支持包括的认证方式包括api, cas, google, ssl, pam等,把GateOne嵌入到别的应用中时需要使用api的方式。在RDS中就使用了这种方式在视图层做认证,实现方式会在后面讲到。此处把“auth”改为”api”,即只有经过api认证后才可以进入Gate One的界面。

30api_keys.conf

使用api认证需要配置key:secret密钥对,如果还没有这个文件,可以使用gateone --new_api_key命令来自动生成,里面会包含随机密钥对。

至此Gate One的配置就差不多改完,可以使用service gateone start或者gateone命令启动gateone服务器了。

嵌入RDS

3

首先需要在view里生成api的token:

这里注意upn是RDS根据想要连接的服务器按照规则生成的用户名,当一个新的upn连接到Gate One之后会在/var/lib/gateone/users下建立以upn命名的目录,里面保存了此用户的session、日志文件以及最重要的.ssh目录;如果已经存在这个upn目录,就会使用已有的这些信息。为了方便标识,RDS中upn的命名方式是user@ip,这样在.ssh目录下先成ssh秘钥对并把公钥加入到想要连接的数据库服务器的账号的authorizied_keys之后,一旦RDS用户在网页进入Gate One执行SSH,就会使用此upn下的密钥进行连接。

前台加载Gate One的js代码:

前台从view接收到的变量除了valid_json_auth_object这个令牌之外,还有ssh_url和location。ssh_url是用来设置进入Gate One之后自动连接的ssh连接串,例如“ssh://mysql@10.11.12.13:22”,这样就可以避免用户手动输入;location这个参数就比较关键,它用来保证不同的RDS用户即使同时登录同一台目标服务器也不至于出现“串台”的异常:因为这些RDS用户的令牌里会有相同的upn,不设置location就会使得多个用户都访问此upn用户的location=“default”终端,出现看到一样的终端的情况。另外可以看到此处并没有出现Gate One服务器的ip和8001服务端口,这是因为已经在RDS的前置Nginx里配置了把/gateone的访问请求路由到真正的地址的相关参数,此处不再赘述。最后,有一部分代码是放在GateOne.Base.superSandbox中执行的,大家查看官方文档就可以找到这么做的原因。

* 成功访问后执行top命令 *

可能遇到的情况

4

api token验证失败

说明到Gate One服务的网络是通的,需要去检查下后台返回的令牌是否有错误。

ssh登录失败

出现ssh配置不当导致的无法连接,一般是权限问题。

参考资料:

官方文档:http://liftoff.github.io/GateOne/

应用嵌入Gate One:https://www.jianshu.com/p/b8123a8178de

Ngixn配置:https://laucyun.com/135bc31db22920069ec1ac3e2fbe038a.html

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180326G13PDY00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券