// CTF 문제 인스턴스 클라우드

Bad CTF 소리, 이제 그만.

참가 팀마다 전용 microVM을 한 대씩 할당하고 그 안에서 docker-compose.yml을 고치지 않고 그대로 실행합니다. 서버는 서울·도쿄·프랑크푸르트·애틀랜타에 두고 저희가 직접 운영합니다.

격리
팀당 VM 1대
과금
10분 단위
연동
CTFd, REST API
tail -f /var/log/chall.run/spawn.log 415 실행 중
예시 로그 · 09:00, 대회가 열리고 서버가 넘어가는 시간

01 대회 시작 직후

문제 서버가 죽는 건대부분 대회 시작 직후입니다.

여러 대회 후기와 저희가 직접 겪은 일을 섞어 만든 가상의 타임라인입니다. 팀별 인스턴스를 서버 한 대로 버티면 보통 이렇게 됩니다.

  1. 운영진이 #announcements에 "good luck, have fun" 공지
  2. 문제 공개. 812팀이 같은 초에 "인스턴스 시작" 클릭
  3. 하나뿐인 docker 호스트 load average 97. SSH 먹통
  4. OOM killer가 하필 web/blog-v2의 postgres를 골라 죽임
  5. #general: "문제 서버 터졌나요?" ×140
  6. 결국 서버 재부팅. 돌던 인스턴스도, 반쯤 짠 익스플로잇도 전부 증발
  7. CTFtime 리뷰 1등 댓글: "bad ctf, infra died". 웨이트 투표 결과는 생략

$ diff bad-ctf.yml chall.run.yml

+팀마다 microVM 1대

한 팀 인스턴스에서 fork bomb이 터져도 다른 팀은 멀쩡합니다. VM마다 커널이 따로 있고 cgroup으로 자원 상한을 걸며 docker 소켓도 공유하지 않습니다.

+대회 시간에 맞춘 자원 예약

Reserved 플랜으로 예약하면 대회 시작 시각에 맞춰 전용 서버의 메모리와 vCPU를 비워 둡니다. 그 서버에는 다른 고객의 인스턴스가 올라가지 않습니다.

+몰리면 줄을 세웁니다

자원이 모자라면 요청을 실패시키지 않고 대기열에 넣습니다. 대기 순번과 예상 시간은 CTFd 화면에서 볼 수 있습니다.

+TTL과 자동 정리

인스턴스 수명은 문제마다 운영진이 정합니다. 10분짜리 짧은 문제도, 몇 시간씩 붙잡는 문제도 되고 참가자 연장 허용 여부도 고를 수 있습니다. 시간이 다 된 인스턴스는 알아서 정리되니 새벽 3시까지 메모리를 붙잡고 있을 일은 없습니다.

+VM별 트래픽 제한

한 팀이 브루트포스를 돌려도 나머지 811팀의 회선은 멀쩡합니다.

02 동작 방식

compose 파일과 CTFd는지금 쓰는 그대로 씁니다.

  1. 01

    이미지 올리기

    challrun push 한 번이면 이미지를 빌드해서 고른 리전에 배포합니다. 로컬에서 테스트한 compose 파일 그대로입니다.

  2. 02

    플랫폼 연동

    CTFd는 플러그인만 설치하면 되고 다른 플랫폼은 REST API를 호출하면 됩니다. rCTF든 직접 만든 대회 사이트든 HTTP 요청만 보낼 수 있으면 붙일 수 있습니다.

  3. 03

    대회 당일

    참가자가 인스턴스를 켤 때마다 새 microVM이 뜨고 팀별 플래그가 들어갑니다. 서버 모니터링과 장애 대응은 저희가 맡습니다.

# sits next to your docker-compose.yml, nothing else changes
name: web/blog-v2
compose: ./docker-compose.yml
expose:
  - service: app
    port: 8080
    as: https   # https://<team>.blog-v2.inst.chall.run
  - service: pwnbox
    port: 31337
    as: tcp     # nc icn1.chall.run 40213
resources:
  memory: 512Mi
  cpu: 0.5
ttl: 45m
flag:
  env: FLAG       # unique per team, injected at spawn
  format: "acme{%s}"
team -- https / nc --> edge.icn1   sni + port map
                          |
          +---------------+---------------+
          v                               v
   host epyc-07                    host epyc-11
   |- fc-7f3a  b4ckd00r          |- fc-c0de  r3kt
   |  `- compose: app, db          |  `- compose: pwnbox
   |- fc-91ab  null_ptr          `- fc-0b5e  0xfe
   `- ...                             `- ...

03 요금

요금은 크레딧으로,10분 단위로 계산합니다.

쓴 만큼 10분 단위로 크레딧이 차감됩니다. 1크레딧은 $0.002이고 $10를 충전하면 5,000크레딧입니다. 기본료나 플랫폼 이용료는 따로 없고 On-demand는 최소 결제 금액도 없습니다.

요금표

항목기준크레딧
메모리256 MiB · 10분1
vCPU (공유)0.25 vCPU · 10분1
디스크인스턴스당 2 GiB까지무료
초과분 48 GiB · 10분1
아웃바운드 트래픽대회당 20 GB까지무료
초과분 GB당리전별 차등
이미지 저장 공간10 GiB까지무료
초과분 20 GiB · 10분1
인바운드 트래픽, IPv4, TLS, DDoS 방어무료

10분 단위로 올림해서 과금하므로 1분만 써도 10분 요금이 나갑니다. 예를 들어 프랑크푸르트 리전의 512 MiB / 0.5 vCPU 인스턴스는 10분에 4크레딧($0.008)입니다.

리전

리전요금 배율트래픽 (크레딧/GB)
fra1프랑크푸르트 ×1.002
ams1암스테르담 ×1.002
atl1애틀랜타 ×0.952
icn1서울 ×1.1517
nrt1도쿄 ×1.156
sin1싱가포르 ×1.156
gru1상파울루 준비 중×1.40미정

On-demand와 Reserved

두 플랜은 단가가 같습니다. Reserved는 대회 시간 동안 자원을 확실히 잡아 두는 대신 예약한 만큼은 쓰지 않아도 요금이 나갑니다.

On-demand Reserved
단가 동일 동일
자원 남는 자원으로 제공, 몰리면 대기 대회 시간 동안 전용 서버 확보
약정 없음 최소 24시간, 25,000크레딧($50) 이상
신청 바로 사용 대회 72시간 전까지
안 쓴 자원 과금 없음 과금
예약보다 더 쓰면 — 넘는 만큼 On-demand 요금
취소 — 대회 72시간 전까지 무료

04 비용 계산

대회 규모를 넣으면예상 비용이 나옵니다.

예시
인스턴스당 메모리
인스턴스당 vCPU

예상 비용 icn1 · On-demand

인스턴스 실행 횟수
4,500
10분 구간 수
27,000
10분당 크레딧
4 × 1.15
CPU·메모리
124,200 cr
트래픽
340 cr
합계 $249

124,540 크레딧 · 1 cr = $0.002

평균 94개, 시작 직후에는 많게는 282개가 동시에 돌아갑니다.

시작 후 몇 시간은 141 GiB / 141 vCPU 정도를 Reserved로 잡아 두면 안전합니다.

인스턴스는 대회 초반에 몰려서 켜지므로 피크를 평균의 3배로 잡은 대략적인 계산입니다. 대회 중 실제 사용량은 대시보드에서 볼 수 있습니다.

05 커뮤니티 지원

작은 대회는비용을 지원합니다.

학생이나 자원봉사자가 여는 대회는 서버비를 운영진이 직접 내는 경우가 많습니다. 아래 조건에 맞으면 스폰서 후원금과 chall.run 예산으로 모은 크레딧 풀에서 인스턴스 비용을 지원해 드립니다. 한도는 대회당 125,000크레딧($250)으로 계산기의 중형 예선 예시를 돌릴 수 있는 양입니다.

상금
현금 상금 총액 US$2,000 이하 또는 상금 없음
주최
학교 동아리, 대학, 비영리단체, 자원봉사 팀
참가
참가비 없이 누구나 등록 가능
조건
chall.run이 제공하는 스폰서용 인스턴스 플러그인 사용. 인스턴스 실행 버튼 아래에 크레딧 풀 후원사 로고가 작게 표시될 수 있습니다.
지원 신청 →
스폰서-->크레딧 풀-->커뮤니티 대회

후원금은 전부 커뮤니티 대회 인스턴스 비용으로 씁니다. 지원받은 대회에서는 스폰서용 인스턴스 플러그인의 실행 버튼 아래에 후원사 로고가 작게 들어갑니다.

  • supporter $500 교내 CTF 25개 정도
  • backer $2,500 중형 예선 10개 정도
  • founding $10,000+ 1년 치 풀 운영, 지원 심사 참여
후원사 01모집 중
후원사 02모집 중
후원사 03모집 중
후원사 04모집 중
후원사 05모집 중
후원사 06모집 중
후원 문의 →

06 자주 묻는 질문

왜 컨테이너가 아니라 microVM인가요?

CTF 참가자는 원래 샌드박스를 탈출하려는 사람들입니다. 컨테이너는 같은 서버의 다른 팀과 커널을 함께 쓰지만 microVM은 팀마다 커널이 따로 있습니다. VM이 1초 안에 부팅되기 때문에 격리를 높여도 참가자가 기다릴 일은 거의 없습니다.

기존 문제를 고쳐야 하나요?

대부분은 고칠 필요가 없습니다. 로컬에서 docker compose up으로 돌아가는 문제라면 여기서도 그대로 돌아갑니다. 다만 privileged 컨테이너와 host 네트워크 모드는 쓸 수 없습니다.

CTFd를 안 써도 연동할 수 있나요?

REST API로 붙이면 됩니다. 시작·연장·중지·상태 조회 엔드포인트 네 개가 전부이고 CTFd 플러그인도 같은 API를 씁니다.

대회 중에 크레딧이 떨어지면요?

잔액이 얼마 남지 않으면 알림을 보내 드립니다. 크레딧이 모두 소진되어도 인스턴스가 바로 중지되지는 않습니다. 비용은 나중이고, 일단 대회는 운영되어야 하니까요.

참가자가 인프라를 공격하면요?

VM마다 트래픽 제한이 걸려 있고 다른 팀 VM이나 컨트롤 플레인으로 가는 경로는 막혀 있습니다. VM 탈출 같은 취약점을 찾으면 알려 주세요. 제대로 된 제보에는 사례합니다.

사전 신청 일시 중단문의는 메일로 부탁드립니다.

$ 문의

베타를 준비하는 동안 사전 신청은 받지 않고 있습니다. 대회 일정이나 궁금한 점은 아래 주소로 메일 보내 주세요.

support@quickmetal.kr 메일 보내기 →