在线判题系统hustoj的搭建

摘要:ACM/ICPC程序设计竞赛,愈来愈受到各个高校的重视,是程序设计竞赛中的奥林匹克。Hustoj是搭建在linux系统上的判题系统。可以判断代码的正确性。会及时返回经过或者不经过,若是不经过会返回具体缘由。因此这个系统很适合ACM队员在上面作一些练习。每一个学校有必要有本身的OJhustoj虽然说是开源,有搭建教程。可是在搭建过程当中仍是会有一些问题。因此针对这些问题,给出了个人解决办法。php

ACM/ ICPC programming competition, more and more attention by variouscolleges and universities, is the design competition in the OlympicGames. Hustoj is built on the linux system on the problem system.Able to determine the correctness of the code. Will be returned intime or not through, if not passed will return to specific reasons.So this system is very suitable for ACM players in the above to dosome practice. Each school need to have their own OJ, hustoj althoughit is open source, there are structures tutorial. But in the processof building or there will be some problems. So for these questions,given my solution.css


关键字:在线判题系统hustoj搭建OJlinux搭建OJhtml


引言前端


ACM比赛愈来愈受到高校重视,这是一个可以提升大学生编程能力的好平台。各个学校的ACM队员都须要在本身的OJ上刷题,作练习,还须要出题,由于出题可以很好的锻炼一我的,思惟能力。若是你能出题说明你对这个知识点理解比较透彻,而不是直接敲的模板(照着代码抄上去的)。除此以外,每一个高校也会不按期的举办校赛,什么的,举办校赛,不少比赛广泛用的是PC^2,对于用过PC^2的人来说,还能够。不过这个用软件容易不当心交错文件。在线判题系统这类问题会相对比较少,其次,在线判题系统的搭建过程也比PC2简单一点。流程少,若是懂一点php还能够添加一些小功能。Hustoj是开源项目。举办比赛是没什么问题的。大型比赛也没什么问题。由于他有远程判题,多台机器进行判题任务。虽然说网上博客也不少,可是实际在弄的过程也会出现不少问题。因此本文主要说说搭建hustoj过程,以及常见问题。以及简单的说说如何使用。让学校举办比赛变得容易一点。目前没找到hustoj的开发文档,这样不利于二次开发,说一说该项目结构,一边后人开发有所参考。java



  1. 安装流程

1.1系统要求

该项目是运行在linux系统上的,因此必要的环境是须要一台linux电脑。对于没有linux电脑的,能够将一台windows装成ubuntu系统,具体如何装能够参考百度上面的教程,推荐使用hustoj的镜像,方便易用。装系统就很少说了,网上教程不少。随便找一个。mysql

1.2软件环境须要

到此,假设系统已经装好了。如今须要安装一些hustoj的一些必须的软件。由于hustoj的开发者是使用php+mysql,因此这些环境是必须须要的。因为linux文件的权限比较安全,若是是新手会遇到不少问题,若是只是短时间比赛,局域网的比赛那么用root帐户是没什么大问题的。若是是搭建公网上面的OJ,仍是建议将用户的文件权限设置好,文件的所属用户设置好,解决安全性的问题。linux

下面以ubuntu14.04为例,服务能够选择apache或者nginxnginx

首先切换到root帐户,若是root没有设置,请用你装系统时用的帐户修改密码c++

sudopasswd rootgit

根据提示修改密码后


suroot

切换到root,安装相应软件

apt-getinstall update

apt-getinstall php5.0

apt-getinstall apache2

apt-getinstall mysql-server

apt-getinstall mysql-client

apt-get-f install

咱们装好了必要的软件。

1.3下载项目

github上找到hustoj下载下来。

下载地址https://github.com/zhblue/hustoj[1]

解压后或获得几个文件

                                       图1


解压后文件如图1Wiki是该项目的说明。咱们须要的文件是trunk这个文件夹里面的。进入文件夹trunk会有图3这些东西。Install里面是安装的脚本,core是判题服务的代码,web是前端的文件。


1.4web配置


由于咱们装的是apache,因此咱们把web文件夹里面的东西放到/var/www/html/                                          

因此,咱们进入删除 html目录                                   

                         2

rm-r /var/www/html/

mvweb/ /var/www/html

chown-R www-data:www-data /var/www/html/                                           

用浏览器进入看看web是否安装成功。若是如图2所示就表明前端安装成功了。

3

下面就是修改配置文件,配置文件在/var/www/html/include/db_info.inc.php

vim打开他修改它对应的信息。


static$DB_HOST="localhost";数据库的服务器地址

static$DB_NAME="jol";数据库名

static$DB_USER="root";数据库用户名

static$DB_PASS="root";数据库密码//connect db

static$OJ_NAME="HUSTOJ";OJ的名字,将取代页面标题等位置HUSTOJ字样。

static$OJ_HOME="./";OJ的首页地址

static$OJ_ADMIN="root@localhost";管理员email

static$OJ_DATA="/home/judge/data";测试数据所在目录,实际位置。

static$OJ_BBS="discuss";//"bbs"论坛的形式,discuss为自带的简单论坛,bbs为外挂论坛,参考bbs.php代码。

static$OJ_ONLINE=false;是否使用在线监控,须要消耗必定的内存和计算,所以若是并发大建议关闭

static$OJ_LANG="cn";默认的语言,中文为cn

static$OJ_SIM=true;是否显示类似度检测的结果。

static$OJ_DICT=false;是否启用在线英字典

static$OJ_LANGMASK=1008;//1mC2mCPP 4mPascal 8mJava 16mRuby 32mBash 1008 for security reason tomask all other language 用掩码表示的OJ接受的提交语言,能够被比赛设定覆盖。

static$OJ_EDITE_AREA=true;//是否启用高亮语法显示的提交界面,能够在线编程,无须IDE

static$OJ_AUTO_SHARE=false;//true:自动分享代码,启用的话,作出一道题就能够在该题的Status中看其余人的答案。

static$OJ_CSS="hoj.css";默认的css,能够选择dark.cssgcode.css,具备有限的界面制定效果。

static$OJ_SAE=false;//是不是在新浪的云平台运行web部分

static$OJ_VCODE=true;是否启用图形登陆、注册验证码。

static$OJ_APPENDCODE=false;是否启用自动添加代码,启用的话,提交时会参考$OJ_DATA对应目录里是否有append.c一类的文件,有的话会把其中代码附加到对应语言的答案以后,巧妙使用能够指定main函数而要求学生编写main部分调用的函数。

static$OJ_MEMCACHE=false;是否使用memcache做为页面缓存,若是不启用则用/cache目录

static$OJ_MEMSERVER="127.0.0.1";memcached的服务器地址

static$OJ_MEMPORT=11211;memcached的端口

static$OJ_RANK_LOCK_PERCENT=0;//比赛封榜时间的比率,如5小时比赛设为0.2则最后1小时封榜。

static$OJ_SHOW_DIFF=false;//显示WrongAnswer时的对比[2]



1.5判题服务的搭建

进入图3core目录里面,找到make.sh。首先chmod+x make.sh 而后运行这个文件.接着编译好后会出现两个可执行程序分别把这两个程序放在/usr/bin里面。

#!/bin/bash

#beforeinstall check DB setting in

# judge.conf

# hustoj-read-only/web/include/db_info.inc.php

# and downhere

#and runthis with root


#CENTOS/REDHAT/FEDORAWEBBASE=/var/www/html APACHEUSER=apache

WEBBASE=/var/www/html

APACHEUSER=www-data

DBUSER=root

DBPASS=root


#try installtools

sudo apt-getinstall make flex g++ clang libmysql++-dev php5 apache2 mysql-serverphp5-mysql php5-gd php5-cli mono-gmcs subversion

sudo/etc/init.d/mysql start


sudo yum -yupdate

sudo yum -yinstall php httpd php-mysql mysql-server php-xml php-gd gcc-c++ mysql-devel php-mbstring glibc-static flex

sudo/etc/init.d/mysqld start


sudo svncheckout https://github.com/zhblue/hustoj/trunk/trunkhustoj-read-only


#create userand homedir

sudo /usr/sbin/useradd -m -u 1536 judge




#compile andinstall the core

cdhustoj-read-only/core/

sudo./make.sh

cd ../..

#install weband db

sudo cp -Rhustoj-read-only/web $WEBBASE/JudgeOnline

sudo chmod-R 771 $WEBBASE/JudgeOnline

sudo chown-R $APACHEUSER $WEBBASE/JudgeOnline

sudo mysql-h localhost -u$DBUSER -p$DBPASS < db.sql


#create workdir set default conf

sudo   mkdir /home/judge

sudo   mkdir /home/judge/etc

sudo   mkdir /home/judge/data

sudo   mkdir /home/judge/log

sudo   mkdir /home/judge/run0

sudo   mkdir /home/judge/run1

sudo   mkdir /home/judge/run2

sudo   mkdir /home/judge/run3

sudo cpjava0.policy  judge.conf /home/judge/etc

sudo chown-R judge /home/judge

sudo chgrp-R $APACHEUSER /home/judge/data

sudo chgrp-R root /home/judge/etc /home/judge/run?

sudo chmod775 /home/judge /home/judge/data /home/judge/etc /home/judge/run?


#boot upjudged

sudo cpjudged /etc/init.d/judged

sudo chmod+x  /etc/init.d/judged

sudo ln -s/etc/init.d/judged /etc/rc3.d/S93judged

sudo ln -s/etc/init.d/judged /etc/rc2.d/S93judged

sudo/etc/init.d/judged start

sudo/etc/init.d/apache2 restart

sudo/etc/init.d/httpd restart


执行完这些语句,重启以后就能够了。

1.6添加超级管理员


而后在浏览器上进入注册界面。注册一个帐户,以后进入数据库修改数据库,添加超级管理员。意思就是将那个用户插入到表privilege。图4是表privilege的结构。在数据库执行执行插入sql语句。

insert intoprivilege(user_id,rightstr) values('admin','administrator');

4

若是一切正常这就表明你的OJ搭建好了。可是在搭建的过程当中总不是一路顺风的。


2搭建过程当中常见问题

2.1搭建好web后在浏览器不能访问

首先有多是apache没有正常运行,或者没有给web正确的文件权限。看看web配置文件是否修改正确。打开配置文件看看,常常填错的数据库用户名和数据库名,再或者就是将配置文件改坏了,好比删掉了双引号,致使代码编译错误。这些问题解决办法,很简单我就再也不多说了。因此在安装apache的时候咱们能够一个一个排除问题。先看看apache是否在正常运行。多是apache没有正常打开用命令查看apache是否正常运行。

/etc/init.d/apache2status

若是出问题了就得去apache官网查查帮助文档。解决了这个问题,看看phpapache有没有弄好,看看apache能不能解析运行php代码。能够在/var/www/html/index.php写上一段测试代码,试试能不能输出helloworld,若是不能说明apache没有加载php模块。

问题一个一个排除,这几个问题排除以后还不能运行,就极可能文件在下载或者解压的过程当中文件有所损坏。

2.2不判题可能缘由

首先看看判题机的配置文件写好了没,配置文件

目录为:/home/judge/etc/judge.conf


OJ_HOST_NAME=127.0.0.1若是用mysql链接读取数据库,数据库的主机地址

OJ_USER_NAME=root数据库账号

OJ_PASSWORD=root数据库密码

OJ_DB_NAME=jol数据库名称

OJ_PORT_NUMBER=3306数据库端口

OJ_RUNNING=4judged会启动judge_client判题,这里规定最多同时运行几个judge_client

OJ_SLEEP_TIME=5judged经过轮询数据库发现新任务,轮询间隔的休息时间,单位秒

OJ_TOTAL=1老式并发处理中总的judged数量

OJ_MOD=0老式并发处理中,本judged负责处理solution_id按照TOTAL取模后余数为几的任务。

OJ_JAVA_TIME_BONUS=2Java等虚拟机语言得到的额外运行时间。

OJ_JAVA_MEMORY_BONUS=512Java等虚拟机语言得到的额外内存。

OJ_SIM_ENABLE=0是否使用sim进行代码类似度的检测

OJ_HTTP_JUDGE=0是否使用HTTP方式链接数据库,若是启用,则前面的HOST_NAME等设置忽略。

OJ_HTTP_BASEURL=http://127.0.0.1/JudgeOnline使用HTTP方式链接数据库的基础地址,就是OJ的首页地址。

OJ_HTTP_USERNAME=admin使用HTTP方式所用的用户账号(HTTP_JUDGE权限),该账号登陆时不能启用VCODE图形验证码,但能够登陆成功后启用。

OJ_HTTP_PASSWORD=admin密码

OJ_OI_MODE=0是否启用OI模式,即不管是否出错都继续判剩余的数据,在ACM比赛中一旦出错就中止运行。

OJ_SHM_RUN=0是否使用/dev/shm的共享内存虚拟磁盘来运行答案,若是启用能提升判题速度,但须要较多内存。

OJ_USE_MAX_TIME=1是否使用全部测试数据中最大的运行时间做为最后运行时间,若是不启用则以全部测试数据的总时间做为超时判断依据。[3]


这个是配置文件的注释,按照你想要的,数据库密码正确填写,这里写配置文件不须要添加引号.重启判题机,因为有不少依赖kill命令不可以干掉这个进程,因此须要用到-9这个参数。题目的测试数据若是不可以上传,多是/home/judge/data/这个目录文件读写权限有点问题,咱们能够直接把他设为777

chmod -R 777/home/judge/data/


 

3 hustoj的文件结构

3.1前台文件结构

                                      图5

后台管理的相关文件admin,管理的相关php文件;

bbs是讨论版的相关代码;

template是前台的一些模板,flat-ui,bs,bs3

其余是一些插件的包含文件。

3.2判题部分的文件结构

data  etc log  run0  run1  run2  run3

判题部分,文件,data是放测试数据的文件夹,里面仍是文件夹,文件夹名字是题目的id,每一个题目一个文件夹,文件夹里面是输入输出,能够是多组测试数据。多组测试数据文件名字相同的看的是后缀.in是输入文件。一样的文件名对应的.out文件是输出文件。若是不是特判就是简单对比文件是否同样,若是是特判,那么特判须要本身写一个特判的规则,放在当前的文件夹。etc/文件夹是放判题的配置文件以及判题的服务程序,和主程序。Run0~3 对应的文件夹是编译用户提交代码并运行的地方。里面是一个小的linux环境,边沟编译运行代码。



4.OJ安全性问题

评测鸡的实现,已经有了不少不考虑安全问题的版本。所以这里只讨论安全问题。


我大概把评测攻击分为两部分:编译时攻击、运行时攻击。


编译时攻击


编译时攻击是不少评测鸡并无防范的。例以下面几种攻击状况:


编译超时


#include</dev/random>      # Linux

#include<CON>              # Windows


这种攻击方式的原理是,让编译器读一个永远也读不完的文件,把评测鸡卡死在编译阶段。BZOJ已经被这段代码卡掉不少次了。


示例:提交记录#3019- PYOJ

解决办法:设置编译的时间限制,或者用vfk的办法,把编译器监控起来。


输出巨大文件


咱们在作数论题的时候玩过这种事情:inta[10000000]={1,0},这样编译出来的文件会特别大。在个人机器上,它的大小是39MB


咱们想到,让编译器生成一个极大的文件。下面是一个针对gcc的编译炸弹,从wikicoding.org蒯来的。全文以下:


main[-1u]={1};

编译这段代码以后,会生成16GB的文件。


示例:提交记录#2912- PYOJ

解决办法:设置编译出来的可执行文件的大小限制。


include攻击

include攻击同时被vfleaking(UOJ)和李扬(QDUOJ)描述。向二位致敬。


include攻击是指:用C/C++代码include网站的配置文件,而后经过返回的编译错误信息,读取密码。


例如。对于hustoj,能够采用下面的代码:


#include"/var/www/JudgeOnline/include/db_info.inc.php"


这份代码将会include数据库的配置文件。上交这份代码,将会返回以下的编译信息:



事发后,hustoj的这个漏洞已经在一年前修复。


示例:提交记录#3020- PYOJ

个人解决方法:


评测鸡和服务鸡必须隔离。

设置好文件权限(hustoj就是这样修复漏洞的)。

最好不要告诉用户编译错误的信息。

vfk的解决办法:把编译器监视起来。


另外riteme提出了另外一种鬼畜的解决办法。见[漏洞报告]include攻击&middot;Issue #14 &middot; hzxie/voj 


须要注意的一点:不要想着用检查用户代码的形式规避攻击。C/C++define功能能够轻易绕过这些检查。



运行时攻击


运行时攻击,已经有比较好并且通用的解决方案。解决这个问题难度并不大。


运行系统指令


system("shutdownnow");


这种攻击方式很早就被解决了。


示例:提交记录#3021- PYOJ

解决方法:用沙箱跑评测,能够采用ptrace。可是我准备用一种更暴力的方案。直接把程序扔进docker里面跑,它爱玩成什么样就玩成什么样吧233


fork炸弹

曾经有OJ被选手程序不停地fork()搞炸了。


我没有拿到代码,所以这里无法分析。


故意运行超时


while(1):pass

而后忽然交一大堆这种程序,以达到相似DDOS的效果&hellip;&hellip;


这种东西很没技术含量。下面是一份针对hustoj的脚本:


https://gist.github.com/Ruanxingzhi/9f0caba5e2d8a690ae1e89bcfb92abba

效果是用1000个帐号,每一个帐号提交10次,每一个帐号在提交以后休息11s

体现为:两分钟内,OJ上面多了一万份提交。


解决方法:注册的时候设置验证码,若是一个帐号短期内屡次提交,在这个帐号下一次提交的时候也须要验证码。


请注意,注册的时候,只用邮箱验证,不用验证码是不行的!

总结


我玩了这么久的OJ,一共也就发现这几种攻击方式&hellip;&hellip;

可是好像不少OJ对编译时攻击防范并很差。

点蜡烛。但愿OJ作得愈来愈好吧。[4]

以上是知乎大神总结的,还有就是经过插件的漏洞进行攻击,好比kindedit以前的漏洞,能够绕过cookie上传文件。对了,最好把配置文件弄成judge用户不能够操做的权限。这样数据库密码省得泄露了。


时间、资源的限制:

内存:我使用了rlimit进行控制,同时也方便在运行结束后得到内存使用状况的数据,不过有一个&ldquo;缺点&rdquo;就是若是是声明了一个超大的空间但从未访问使用就不会被统计进来(通过观察发现不少ACM或者OI比赛也都是这么处理的,因此应该不算是一个问题)。

时间:首先一样也是使用rlimit进行CPU时间控制。注意它只能控制CPU时间,不能控制实际运行时间,因此像是sleep或者IO阻塞之类的状况是没有办法的,因此还在额外添加了一个alarm来进行实际时间的限制。按照大部分比赛的管理,最终统计的时间是CPU时间。

文件句柄:一样能够经过rlimit来实现,以保证程序不要打开太多文件。不过其实文件这一块问题是比较多的,若是可行的话最好仍是使用stdio而后管道重定向,彻底禁止程序的文件IO操做。

访问控制:

经过chroot创建一个jail,将程序限制在指定目录中运行。因为是比赛程序,使用的动态连接库颇有限,因此直接静态编译,从而使得运行目录中连.so都不须要。

进行必要的权限控制,例如将输入文件和程序文件自己设置为程序的运行用户只读不可写。

权限控制:

监控程序使用root权限运行,完成必要准备后 fork并切换为受限用户(好比nobody)来运行程序。

rlimit 设置的都是hardlimit ,非root没法修改。

正确设置运行用户以后,以前由root创造的jail受限用户是没法逃出的。

系统调用控制:

上面这些(尤为是第一步)是有很大问题,就算不是root,也还能作到不少事情。且不说fork之类的,光是那个alarm,就能够很轻松的把计时器取消了或者干脆主动接收这个信号。因此最根本的仍是须要使用ptrace之类的调试器附着上程序,监控全部的系统调用,进行白名单+计数器(好比execopen)过滤。这一步实际上是最麻烦的(不一样平台的系统调用号不同,咱们使用的是strace项目里头整理的调用号)。

更进一步:

若是你对操做系统更熟悉,那么还有一些更有趣的事情能够作。好比Linux下的seccomp功能(seccomp- Wikipedia ChromeLinux 版就在沙盒中使用了这个技术),尤为是后期加入了seccomp-bpf以后变得更加易用。还好比SELinux也能够做为defend-by-depth的一环。另外,cgroup其实也能够用得上。

结束语

搭建了hustoj,只会这些还不够,最好本身写一下判题机什么的,要深刻了解学习才有收获。若是只是按照教程弄一下,并不会有很大的收获。做为了名ACM理解判题原理是颇有用的,这样对解题也是颇有用的。学无止境。


参考文献

[1]ZHBLUE,HUSTOJWIKI,https://github.com/zhblue/

[2]LIUXINGDEBLOG,hustoj永久等待或编译并评判解决方法hustoj,https://www.myvary.cn/index.php/2016/05/11/hustoj-ing/,2016-05-11

[3]OMG_BY,linuxubuntu搭建hustOJ系统,http://www.cnblogs.com/OMG-By/p/5978831.html

[4]RUANXINGZHI,OJ技术思考:评测安全,https://zhuanlan.zhihu.com/p/26984739

相关文章
相关标签/搜索