我想在我的服务器上模拟(不安全)客户端代码,我正在寻找合适的语言来实现这一点。我希望客户端使用与我用来模拟的语言相同的语言。
理想情况下,我只需构建一些接口(并发布这些接口),加载客户端代码,并通过允许它仅使用我的接口+我仔细选择的标准API的子集来模拟该代码。
在此模拟期间,我应该能够限制客户端代码使用的资源(时间和内存)。如果我可以一步一步地模拟代码,那就是奖励,这样我就可以总是返回一个确定性的解决方案。
性能不是真正的问题。这个想法是允许客户为小型游戏/拼图编写自定义AI。游戏将被模拟(在服务器上!),结果返回给用户。
最初我在考虑自己构建一个外部DSL,包括一个解析器和评估器,但也许有一个现成的解决方案吗?
答案 0 :(得分:3)
我的选择是使用一些可以在不自动提供对某些广泛框架(如.Net或Java)的访问权限的情况下使用的脚本语言 - 添加功能比限制功能更容易。像LUA这样的游戏引擎脚本语言可能是一个选项,通常会有多个平台的实现来使用它们。
一般注意事项:
无论您选择何种语言/框架,请确保您可以从/接受以下风险中恢复:
小心暴露允许用户在您的控件之外创建新线程/任务/同步对象(锁定/信号量)或在提供此类API的平台上构建的API。允许这样的方法可能会打开服务器的资源以限制消耗或DOS /死锁......
请注意,长时间运行的任务是任何合理语言的问题,因为您无法通过查看程序来确定程序是否结束 - halting problem。无论您选择何种平台,都必须找出解决方案。
<强>净/ C#:强>
你可以在.Net中查看Terrarium,它在沙盒环境中的用户机器上运行不受信任的代码。
.Net提供了一种限制多个API使用的方法 - How to: Run Partially Trusted Code in a Sandbox是一个很好的起点。请注意,正如@Andrew指出的那样,最好验证用户提供的程序集(直接或从用户的源代码编译)是否不使用您不喜欢的API(或者反过来说 - 只使用API)除了基本的沙盒之外你还允许)。在单独的AppDomain中运行的部分受信任的代码可以提供对不太恶意的代码的正确保护。
Stack overflows一般很难预防,需要自定义主机来处理.Net。可以使用Thread.Abort终止长时间运行的任务,或使用用户代码关闭AppDomain。
答案 1 :(得分:1)
我建议使用.NET(C#,VB和F#)。您可以利用JIT让服务器以编程方式编译代码,使用反射来分析代码,并让每个客户端在单独的AppDomain中运行以实现安全性和代码隔离。
答案 2 :(得分:1)
Java具有SecurityManager的概念,使您可以微调虚拟机中可以运行或不可运行的内容。
它还允许您在运行时compile代码和load生成的类。然后,您可以运行这些类中的任何代码,前提是SecurityManager不会因为不允许该操作而抛出SecurityException。
This post显示了一个人为的例子,它在运行时编译,加载和运行一些代码(作为文本源代码提供)。
This other post提供了运行不受信任(也可能是恶意)代码的说明。
答案 3 :(得分:1)
如果您想运行最终用户提供的代码,并且希望它使用他们可能已经知道的语言,为什么不使用JavaScript?
可以在WebWorker中沙箱化JavaScript(与主JavaScript应用程序隔离并且无法访问共享内存或全局变量(如Window对象和DOM)的并发线程,并且只有一个与主要进行通信的途径线)。
我能想到的唯一安全问题是限制一个人所消耗的硬件资源,但我没有考虑过这个问题 - 很可能使用其中一个JavaScript运行时。您还希望找到一种方法来阻止一个WebWorker生成其他WebWorker。您必须添加一些额外的代码,以确保某人的WebWorker在一段时间后自动关闭。
我还没有尝试过服务器端的WebWorkers,但从外观上看,NodeJS,Rhino和PhantomJS都支持它。 Node和Rhino提供的环境与典型的Web浏览器不同,而PhantomJS是一个无头运行的完整浏览器引擎(WebKit)。从WebWorker的角度来看,它们看起来可能都是一样的。
答案 4 :(得分:0)
如果你真的想要“众所周知”,ADsafe是有效沙盒的JavaScript子集,虽然它有一些怪癖(例如避免this
)。
Java有“类加载器”,它可以限制类可以访问的类(请参阅SecureClassLoader
)。我对细节有点模糊,但它基本上是用来提供Java applet安全性的。我不知道它是否可以限制内存使用,但限制CPU时间并不太困难(不要让它产生线程并在超时后终止运行不受信任代码的线程)。
(我很高兴地提醒Robocode运行不受信任的人工智能试图在游戏的限制范围内杀死其他不受信任的人工智能。主要区别在于它的目的是在最终用户的计算机上运行,尽管那里是自动排名的网站。这是我对Java的介绍,虽然我注意到它现在支持.NET,可能是由于两种语言的相似性。)