基于Flask的简易webtelnet和webssh
Chinese version README of the Github repo – flask-remote-terminal.
简而言之,一台具备多用户支持的,仅限使用telnet/ssh,访问远程固定地址的,web终端。
演示截图:
有啥稀罕的
- 只可访问远程地址,非本机终端
- 目前仅限telnet(支持十几年前老设备用)和ssh访问,代码中也可增加其他协议,但始终受控
- 仅限访问固定远端地址(IP/域名),代码config可配,一旦服务运行后不可更改
- 服务端session存储pid和fd等,用于多用户支持
参考项目
- 一个教学工程 pyxterm.js 作者 Chad Smith
需求如此“扭曲”,何解
通过web终端去管理一台特定的中转机,其多数端口是(在特定时间段内)代理到真正需要管理的目标机。具体需求如下:
- 同多数web terminal一样,浏览器即开即用,免安装
- 只允许访问特定地址(中转机),避免被抓肉鸡
- 只允许使用telnet和ssh进行连接,不可自选其他客户端命令,在此基础上允许用户自行输入用户名和端口号
- 只用于远程连接,在用户exit退出终端后,也无法回到shell操作提供该服务的server
进展情况
相比几个知名web terminal项目,比如GateOne或webssh,咱这顶多算个实验性原型项目。好在简单易理解,可以被当做demo在此基础上进行扩展开发。
如何部署
Clone工程,进工程目录后,运行如下命令安装依赖。
1 2 |
python3 -m venv venv # must be python3.6+ venv/bin/pip install -r requirements.txt |
把配置文件从“config_sample.py”复制到“config.py”,然后编辑domain这字段,这就是服务起来后,telnet和ssh会去访问的唯一中间机(代理机),这里写IP或者域名当然都可以。
1 2 3 4 5 6 7 |
TERM_INIT_CONFIG = { 'domain': 'example.com', # or ip address like 192.168.10.11 'client_path': { 'telnet': '/usr/bin/telnet', # client binary absolute path 'ssh': '/usr/bin/ssh' } } |
“client_path”底下要填入正确的server端telnet和ssh客户端的绝对路径。比方说,对macOS来说,ssh的路径就是 /usr/bin/ssh 但telnet的路径,由于我是使用Brew安装,则配置文件复制到“config.py”后应当改成 /usr/local/bin/telnet
配置搞定。运行 python app.py 或者 gunicorn -b 0.0.0.0:5000 -k gevent -w 1 app:app 来启动服务。
打开浏览器(最好Chrome或者Chromium)访问服务链接 http://127.0.0.1:5000/remote/<method>/<username>/<port>
例如 –
1 2 |
http://127.0.0.1:5000/remote/ssh/usertest/6022 #等价于 ssh -p 6022 usertest@192.168.11.111 http://127.0.0.1:5000/remote/telnet/usertest/7023 #等价于 telnet -l usertest 192.168.11.111 7023 |
已知问题
- 工程可以通过uwsgi来部署,命令 uwsgi --socket :5000 --gevent 1000 --master --wsgi-file=./app.py --callable app 。但问题在于仅有ssh会工作,telnet就此挂了。花了很久都没有找到问题所在,因为python直接起服务,以及走gunicorn都是正常的。如果有人能解决该问题,将不胜感激 – 毕竟要是想做生产服务的话,gunicorn和uwsgi没法比(起码可配置项以及文档清晰程度),不是么?
- 不要考虑在使用uwsgi或gunicorn时起超过1个worker进程,除非你手头有现成的消息队列服务,比如kafka。原因超出本文范围,不具体展开,感兴趣可以去查Flask-SocketIO的官方文档。
文章的脚注信息由WordPress的wp-posturl插件自动生成
能实现远程web ssh登录本地的服务器吗
必然能,我文档里边被我参考的那个工程,就是实现web登录本地服务器(本地直接起bash就行了,跟ssh没毛关系)
而我的需求是用本地的服务器经一个固定的跳板机(代码部署后不可变),去且仅去访问跳板后的机器资源(资源的ssh/telnet端口经其他代码映射到了跳板机的非标端口上),所以才改成了这个样子