14

我想在我的服务器上模拟(不安全的)客户端代码,我正在寻找一种合适的语言来做到这一点。我更喜欢让客户用我将用来模拟的相同语言编写。

  • 安全是首要问题
  • 最好是众所周知的语言(便于客户学习语法)
  • 应该很容易禁用/启用沙箱中可用的语言功能
  • 如果我可以逐步模拟代码,那将是一个加号

理想情况下,我会简单地构建一些接口(并发布这些接口),加载客户端代码,并通过允许它仅使用我的接口 + 我精心选择的标准 API 的子集来模拟该代码。

在此模拟期间,我应该能够限制客户端代码使用的资源(时间和内存)。如果我可以逐步模拟代码,那么我总是可以返回一个确定性的解决方案。

性能并不是真正的问题。这个想法是允许客户为小型游戏/拼图编写自定义 AI。游戏将被模拟(在服务器上!)并将结果返回给用户。

最初我想自己构建一个外部 DSL,包括解析器和评估器,但也许有一个现成的解决方案?

4

5 回答 5

5

我的选择是使用一些无需自动提供对某些扩展框架(如 .Net 或 Java)的访问即可使用的脚本语言 - 添加功能比限制它们更容易。像LUA这样的游戏引擎脚本语言可能是一种选择,并且通常带有多个平台的实现以在其中使用它们。

一般考虑:

无论您选择哪种语言/框架,请确保您可以从以下风险中恢复/接受:

  • 致命异常(如递归函数导致的堆栈溢出)
  • 无限的内存分配/内存不足异常
  • 长时间运行的任务

谨防公开允许用户在您的控制之外创建新线程/任务/同步对象(锁/信号量)或在提供此类 API 的平台上构建的 API。允许这样的方法可能会打开服务器的资源以无限消耗或 DOS/死锁...

请注意,长时间运行的任务对于任何合理的语言都是一个问题,因为您无法通过查看程序来确定程序是否结束 -停止问题。无论您选择什么平台,您都必须找出解决方案。

.Net/C#:

您可以查看在 .Net 中执行此操作的Terrarium - 在沙盒环境中在用户机器上运行不受信任的代码。

.Net 提供了一种限制使用多个 API 的方法 -如何:在沙盒中运行部分受信任的代码是一个很好的起点。请注意,正如@Andrew 指出的那样,最好验证用户提供的程序集(直接或从用户源编译)是否不使用您不喜欢的 API(或者甚至相反 - 仅使用 API你确实允许)除了基本的沙盒。在单独的 AppDomain 中运行的部分受信任的代码可以让您免受不太敌对的代码的影响。

堆栈溢出通常很难防止,并且需要在 .Net 中处理自定义主机。长时间运行的任务可以使用 Thread.Abort 或使用用户代码关闭 AppDomain 来终止。

于 2013-01-31T06:24:57.647 回答
1

我会推荐 .NET(C#、VB 和 F#)。您可以利用 JIT 让服务器以编程方式编译代码,使用反射分析代码,并让每个客户端在单独的 AppDomain 中运行以实现安全性和代码隔离。

于 2013-01-27T00:30:58.810 回答
1

如果您想运行最终用户提供的代码,并且希望它使用他们可能已经知道的语言,为什么不使用 JavaScript?

可以在 WebWorker 中对 JavaScript 进行沙箱处理(与主 JavaScript 应用程序隔离的并发线程,无法访问共享内存或全局变量,例如 Window 对象和 DOM,并且只有与主线程通信的单一途径)。

我能想到的唯一安全问题是限制一个人消耗的硬件资源,但我还没有研究过——这很可能使用其中一个 JavaScript 运行时。您还想找到一种方法来防止一个 WebWorker 产生其他 WebWorker。您必须添加一些额外的代码来确保某人的 WebWorker 在一定时间后自动关闭。

我还没有尝试过服务器端 WebWorkers,但是从它的外观来看,NodeJS、Rhino 和 PhantomJS 都支持它。Node 和 Rhino 提供了不同于典型 Web 浏览器的环境,而 PhantomJS 是一个无头运行的完整浏览器引擎 (WebKit)。从 WebWorker 的角度来看,它们可能看起来都一样。

于 2013-01-31T17:59:03.727 回答
1

Java 具有SecurityManager的概念,它使您能够微调虚拟机中可以运行或不可以运行的内容。

它还允许您在运行时编译代码并加载生成的类。然后,您可以运行这些类中的任何代码,前提是 SecurityManager 不会因为不允许该操作而引发 SecurityException。

这篇文章展示了一个人为的例子,它在运行时编译、加载和运行一些代码(作为文本源代码提供)。

这篇另一篇文章给出了运行不受信任(并且可能是恶意)代码的指导。

于 2013-01-30T16:03:26.380 回答
0

如果你真的想要“众所周知”,ADsafe是 JavaScript 的一个子集,它被有效地沙盒化,尽管它有一些怪癖(例如避免this)。

Java 有“类加载器”,它可以限制类可以访问的类(请参阅 参考资料SecureClassLoader)。我对细节有点模糊,但它本质上是用来提供 Java 小程序安全性的。我不知道它是否可以限制内存使用,但限制 CPU 时间并不太难(不要让它产生线程并在超时后杀死运行不受信任代码的线程)。

(我深情地想起了Robocode,它运行不受信任的 AI,试图在游戏的限制范围内杀死其他不受信任的 AI。主要区别在于它旨在在最终用户的计算机上运行,​​尽管有些网站会进行自动排名。它是我对 Java 的介绍,尽管我注意到它现在支持 .NET,可能是由于这两种语言的相似性。)

于 2013-01-27T01:57:49.120 回答