一、背景
也许大家平时会有用到一些在线代码运行的网址, 方便我们做一些语法测试或者学习。 例如执行Python代码、Java代码、Shell代码等等, 有时候自己本地环境不具备的时候做一些简单的脚本测试还是蛮实用和方便的。
例如这个在线运行的代码站点: https://r.xjq.icu/
但是你知道这种平台是怎么实现的吗? 首先大家试想你作为站点管理员,考虑以下几个问题:
1、站点怎么防止客户端执行恶意指令代码?
例如执行Shell脚本,如果你的实现机制是用过物理机或者虚拟机的方式执行,客户端执行一条rm -rf /*,此时阁下将如何应对? 大家可能想到的第一种方案就是,关键词过滤或者限定某些高危指令不能执行或者限定执行的Linux用户。 虽然说这种方式也不是说不可以,但是存在局限性,例如说你支持的编程语言越多,那么过滤的成本就越高,万一过滤漏了呢,那又该怎么办?
2、怎么限定运行程序所需的资源?
如果客户端写恶意执行代码,例如while死循环,这种情况又该如何应对?如果直接在传统环境这么弄,你的网址第一天上线就被rm -rf /*了或者CPU飙升,最后挂了.
这里和大家分享我的想法。
其实我想到了"沙箱"Docker容器, 可以来做上面的这么一件事情。
1、安全性问题, 防止用户执行高危指令破坏系统
Docker属于进程隔离级别,启动一个Docker几秒就搞定,不会影响用户体验。同时将要运行的代码传递给Docker容器进行执行,如果执行高危指令也无妨,这一切都只发生在容器中,宿主机不会受到影响。容器执行完毕后进行销毁即可
2、资源限制问题,防止用户写死循环等操作
Docker本身就有资源限制的功能,例如占用CPU、内存等, 我们可以在执行时限定启动的容器的CPU、内存,一旦这个代码的执行资源超过,那么这个容器就会出现异常停止,不会影响宿主机
二、实现架构与原理
验证我的猜想,在Github上确实有人做过类似的开源项目: https://github.com/xjq7/runcode
我们通过分析源代码一探究竟:
1、F12看下代码执行请求接口
接口地址: /code/run
参数信息: 可以看到code【要执行的代码字符串】、type【代码编程语言类型】
2、查看server的run接口源码实现逻辑
找到server/controller/code.ts
这里代码很简单,调用了docker.run2()函数执行,最后拿到结果,展示给前端.
3、继续查看run2()函数的实现逻辑
定位到run2()函数位置:
可以看到使用docker的sdk,创建了容器,将代码进行执行,最后销毁容器,拿到代码执行的输出
三、总结
从上面的分析过程我们就可以发现了,Docker作为测试"沙箱"很方便,这个项目代码也不是很多,大家感兴趣可以进行深度的探索。 但是本质还是使用Docker来解决了安全性问题和资源限制问题。即使你执行rm -rf /*还是死循环,还是其它恶意代码,你都被限定在我的"沙箱"里面了,不会对我的宿主机产生破坏性的影响。
今天就分享到这里,感谢大家一直以来的支持~