在我的服务器上运行任意不友好的Python代码
我正在制作一个游戏,用户可以编写Python程序来控制相互争斗的机器人。每回合(千回合游戏)他们的脚本都会在我的服务器上运行,以确定机器人的下一步行动。如何防止这些用户对我的服务器恶意 我想到/研究了以下几点:在我的服务器上运行任意不友好的Python代码,python,virtual-machine,chroot,ptrace,jail,Python,Virtual Machine,Chroot,Ptrace,Jail,我正在制作一个游戏,用户可以编写Python程序来控制相互争斗的机器人。每回合(千回合游戏)他们的脚本都会在我的服务器上运行,以确定机器人的下一步行动。如何防止这些用户对我的服务器恶意 我想到/研究了以下几点: eval在有限的环境中评估他们的代码(即禁用\uuuu内置\uuuu) 使用特定于操作系统的监狱,如chroot/ptrace 在某种VM中运行代码 我有一个Python程序,可以运行用户脚本一千次。我如何强制执行一分钟的最大总持续时间,限制其内存资源,阻止其访问任何文件或网络连接,
在有限的环境中评估他们的代码(即禁用eval
)\uuuu内置\uuuu
- 使用特定于操作系统的监狱,如
/chroot
ptrace
- 在某种VM中运行代码
我有一个Python程序,可以运行用户脚本一千次。我如何强制执行一分钟的最大总持续时间,限制其内存资源,阻止其访问任何文件或网络连接,等等?理想的解决方案或解决方案组合是什么?在cpython中没有内置的方法来运行沙盒代码,但在pypy中有 pythonwiki上还描述了一些其他方法(比如使用jailkit),但它们似乎有各种缺点
我会选择平淡的路线。我看了你的个人资料,决定这是一项持续的爱的工作!这就是 鉴于您的需求,我假设您正在计划通过internet提供的内容 关于你的第二条查询: 我有一个Python程序,可以运行用户脚本一千次。 我如何强制执行一分钟的最大总持续时间(限制) 他们的内存资源,阻止他们访问任何文件或 网络连接等等?理想的解决方案是什么 解决方案的组合 正如你可能知道的那样,这是一个可以追溯到20世纪80年代的好地方。从知情的角度来看,再发明有时是最好的,但并不总是最好的。对于如何计算玩家时间切片的想法,你可以看看一些现有的相关项目的来源。例如: 扰流板: -
此项目具有 ; 自2005年以来一直掌握在社区手中,并积极 保持。源代码是java。基本阅读imo.
-
这是一种javascript风格 并且在网上工作。因此,这对你的生活会有很大的帮助 你的在线蟒蛇方法。该网站现在似乎已关闭 商业/封闭来源。然而,你可以看到 为github 2012游戏提交的原始来源。在 最起码,这可能会提供如何展示您的 向全世界公布最终游戏内容:)
(顺便说一句,fightcode获得亚军!)
你的第一条询盘就到此为止了。然而: 最便宜的(从任何意义上讲)选择是
chroot
监狱。下一个最便宜的选择是这样的。虽然我没有使用此软件的经验,但性能显然接近本机。否则,是的,完全虚拟化使用或任何东西
意见:
完全虚拟化会带来头痛和不必要的开销
如果(并且只有)你很小心,你可以用一个简单的chroot
jail
- 把监狱仅仅作为一个一次性的“竞技场”来运行代码。确保它以完成工作所需的最低资源和权限运行
- 将您的web应用程序与监狱完全分离(例如,监狱不需要网络访问等)
python
。在这种情况下,为了避免破坏系统,您可能希望从源代码构建所需的任何Python版本
下面是我在Centos上安装Python2.7的方法(假设您已经安装了jailkit)
首先,包括创建专用用户在内的更正式的jailkit方法可能是:
# Once-only set-up:
# as root user:
## get, build and alt-install required python onto host OS
mkdir -p /usr/local/src/python
cd /usr/local/src/python
wget http://www.python.org/ftp/python/2.7/Python-2.7.tgz
tar -vxzf Python-2.7.tgz
cd Python-2.7
./configure #default ${prefix}="/usr/local"
make
make altinstall #don't clobber systems' python; everythin installed under /urs/local and comes with 2.7 postfix.
## set-up a jailkit config for python 2.7 (& optionally to support some minimal devs)
cat <<OOOK >> /etc/jailkit/jk_init.ini
[python2.7]
comment = python 2.7 interpreter and libraries
paths = python2.7, /usr/local/lib/python2.7, /usr/local/include/python2.7, /etc/ld.so.conf
devices = /dev/null, /dev/zero, /dev/random, /dev/urandom
OOOK
这里有一个不推荐的,更特别的方法
# Once-only set-up:
# as root user:
## get and build required python
mkdir -p /usr/local/src/python
cd /usr/local/src/python
wget http://www.python.org/ftp/python/2.7/Python-2.7.tgz
tar -vxzf Python-2.7.tgz
cd Python-2.7
./configure --prefix="/usr" # optionally override default ${prefix} ~ we don't really need /local/ indirection for our jail
make
## find out minimal python lib dependencies so we can add them to the jail - see jk_cp -j below..
ldd /home/jail_py/usr/bin/python
注意:根据您的要求,您可能还需要安装
/proc
。例如,如果未*装入/proc
,则运行类似的操作将失败
cat <<OOOK | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7 -
#thx: https://raw.github.com/pixelb/ps_mem/master/ps_mem.py
import os
import sys
import errno
class Proc:
def __init__(self):
uname = os.uname()
if uname[0] == "FreeBSD":
self.proc = '/compat/linux/proc'
else:
self.proc = '/proc'
def path(self, *args):
return os.path.join(self.proc, *(str(a) for a in args))
def open(self, *args):
try:
return open(self.path(*args))
except (IOError, OSError):
val = sys.exc_info()[1]
if (val.errno == errno.ENOENT or # kernel thread or process gone
val.errno == errno.EPERM):
raise LookupError
raise
def meminfo(self):
fd=self.open("meminfo")
for next in iter(fd.readline, ""):
print next.replace('\n', '')
Proc().meminfo()
OOOK
cat这是一个Python平台即服务(platform-as-a-service),这意味着我们代表用户运行大量不可信的代码——Python.org首页上的新交互式控制台是我们的,它的约束条件可能与您的不太远
我建议使用操作系统级虚拟化;语言层面的任何东西都可能不那么安全。出于历史原因,我们使用chroot和cgroup,但是如果我们开始
# Ad-infinitum:
# as root user:
## create a user
useradd -M -s /sbin/nologin prisoner
passwd prisoner
## manually create a jail
mkdir -p /home/jail_py
## deploy python into jail
# IMPORTANT: be sure to export DESTDIR to avoid stomping on your system python ;)
cd /usr/local/src/python/Python-2.7
export DESTDIR="/home/jail_py" # point install to /home/jail_py/${prefix}
make install # no need for altinstall since we're deploying directly to the jail
cd /home
## provision jail with a copy of /etc/ld.so.conf to prevent jk_cp form chucking out warnings
jk_cp -j /home/jail_py /etc/ld.so.conf
## copy minimal python lib dependencies to the jail - see ldd above
jk_cp -j /home/jail_py /lib/libpthread.so.0 /lib/libdl.so.2 /lib/libutil.so.1 /lib/libm.so.6 /lib/libc.so.6 /lib/ld-linux.so.2
## quick sanity-check for setuids
find /home/jail_py -perm -4000 -exec ls -ldb {} \;
## test running jailed python as user 'prisoner'
echo "import sys; print sys.version" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
echo "import os; print 'cwd:{} uid:{}'.format(os.getcwd(),os.getuid())" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
## optional, if we need /proc
mkdir -p /home/jail_py/proc
mount -t proc /proc /home/jail_py/proc
#optional, if we need some /dev/x
jk_cp -j /home/jail_py /dev/null
#nuke everything
umount /home/jail_py/proc
rm -fr /home/jail_py
userdel prisoner
cat <<OOOK | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7 -
#thx: https://raw.github.com/pixelb/ps_mem/master/ps_mem.py
import os
import sys
import errno
class Proc:
def __init__(self):
uname = os.uname()
if uname[0] == "FreeBSD":
self.proc = '/compat/linux/proc'
else:
self.proc = '/proc'
def path(self, *args):
return os.path.join(self.proc, *(str(a) for a in args))
def open(self, *args):
try:
return open(self.path(*args))
except (IOError, OSError):
val = sys.exc_info()[1]
if (val.errno == errno.ENOENT or # kernel thread or process gone
val.errno == errno.EPERM):
raise LookupError
raise
def meminfo(self):
fd=self.open("meminfo")
for next in iter(fd.readline, ""):
print next.replace('\n', '')
Proc().meminfo()
OOOK