在線判題系統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

相關文章
相關標籤/搜索