2P by neo 2달전 | favorite | 댓글 1개

My Blog Technology

이 웹 서버는 내 블로그를 호스팅하기 위해 설계된 최소한의 웹 서버임. 처음부터 공용 인터넷에 견딜 수 있도록 견고하게 제작되었음. 리버스 프록시가 필요하지 않음. 실제 동작하는 모습을 http://playin.coz.is/index.html에서 볼 수 있음. Reddit에 해킹을 요청하여 재미있고 악의적인 요청 로그를 기가바이트 단위로 수집했음. 일부는 attempts.txt에 저장했고, 나중에 재미로 더 찾아볼 예정임.

하지만.. 왜?

나는 나만의 도구를 만드는 것을 즐기며, 모든 것이 "전투 테스트"되어야 한다는 말을 듣는 것에 지쳤음. 충돌이 발생하면 어쩔 것인가? 버그는 수정할 수 있음.

사양

  • Linux 전용
  • HTTP/1.1, 파이프라이닝, keep-alive 연결 구현
  • HTTPS 지원 (BearSSL을 사용하여 TLS 1.2까지)
  • 최소한의 종속성 (HTTPS 사용 시 libc와 BearSSL)
  • 구성 가능한 타임아웃
  • 접근 로그, 충돌 로그, 로그 회전, 디스크 사용량 제한
  • Transfer-Encoding: Chunked 없음 (411 Length Required로 응답하여 클라이언트가 Content-Length와 함께 다시 전송하도록 유도)
  • 단일 코어 (더 나은 VPS를 얻으면 변경될 예정)
  • 정적 파일 캐싱 없음 (아직)

벤치마크

이 프로젝트의 초점은 견고성에 있지만, 결코 느리지 않음. nginx와의 간단한 비교 (정적 엔드포인트, 둘 다 단일 스레드, 1K 연결 제한):

nginx 설정:

worker_processes 1;
events {
  worker_connections 1024;
}
http {
  server {
    listen 8080;
    location /hello {
      add_header Content-Type text/plain;
      return 200 "Hello, world!";
    }
  }
}

빌드 및 실행

기본적으로 서버 빌드는 HTTP 전용임:

$ make

이 명령은 serve (릴리스 빌드), serve_cov (커버리지 빌드), serve_debug (디버그 빌드) 실행 파일을 생성함. 릴리스 빌드는 포트 80에서, 디버그 빌드는 포트 8080에서 청취함.

HTTPS를 활성화하려면 BearSSL을 클론하고 빌드해야 함:

$ mkdir 3p
$ cd 3p
$ git clone https://www.bearssl.org/git/BearSSL
$ cd BearSSL
$ make -j
$ cd ../../
$ make -B HTTPS=1

동일한 실행 파일이 생성되지만, 포트 443 (릴리스) 또는 8081 (디버그)에서 보안 연결이 가능함. cert.pemkey.pem 파일을 실행 파일과 동일한 디렉토리에 배치해야 함. 이름과 위치를 변경하려면 다음을 수정:

#define HTTPS_KEY_FILE "key.pem"
#define HTTPS_CERT_FILE "cert.pem"

로컬에서 HTTPS로 테스트하려면 자체 서명된 인증서(및 개인 키)를 생성:

openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key key.pem -out cert.pem -days 365

사용법

서버는 docroot/ 폴더에서 정적 콘텐츠를 제공함. 이를 변경하려면 respond 함수를 수정:

typedef struct {
  Method method;
  string path;
  int major;
  int minor;
  int nheaders;
  Header headers[MAX_HEADERS];
  string content;
} Request;

void respond(Request request, ResponseBuilder *b) {
  if (request.major != 1 || request.minor > 1) {
    status_line(b, 505); // HTTP Version Not Supported
    return;
  }

  if (request.method != M_GET) {
    status_line(b, 405); // Method Not Allowed
    return;
  }

  if (string_match_case_insensitive(request.path, LIT("/hello"))) {
    status_line(b, 200);
    append_content_s(b, LIT("Hello, world!"));
    return;
  }

  if (serve_file_or_dir(b, LIT("/"), LIT("docroot/"), request.path, NULLSTR, false))
    return;

  status_line(b, 404);
  append_content_s(b, LIT("Nothing here :|"));
}

여기에서 request.path 필드를 전환하여 엔드포인트를 추가할 수 있음. 경로는 요청 버퍼의 슬라이스일 뿐임. URI는 파싱되지 않음.

테스트

서버를 valgrind와 sanitizers (주소, 정의되지 않음)로 정기적으로 실행하고 wrk를 사용하여 타겟팅함. 또한 HTTP/1.1 사양 준수를 확인하기 위해 tests/test.py에 자동화된 테스트를 추가하고 있음. 내 웹사이트를 호스팅하고 여기저기 게시하여 스트레스를 유지함. 인터넷에서 취약한 웹사이트를 스캔하는 모든 봇이 훌륭한 퍼저가 됨.

알려진 문제

  • 서버가 HTTP/1.0 클라이언트에 HTTP/1.1로 응답함

기여

나는 주로 DEV 브랜치에서 작업하고 가끔 MAIN으로 병합함. 풀 리퀘스트를 열 때 DEV를 타겟으로 하면 더 쉬워질 것임.

GN⁺의 정리

  • 이 프로젝트는 최소한의 종속성과 견고성을 목표로 하는 웹 서버임.
  • HTTP/1.1과 HTTPS를 지원하며, 다양한 로그 기능과 구성 가능한 타임아웃을 제공함.
  • 벤치마크 결과 nginx보다 빠른 응답 시간을 보여줌.
  • 개발자들이 자신의 도구를 만들고 버그를 수정하는 과정을 즐길 수 있도록 설계됨.
  • 비슷한 기능을 가진 프로젝트로는 Nginx와 Apache HTTP Server가 있음.
Hacker News 의견
  • 역방향 프록시 필요 없음: Jetty를 사용해 역방향 프록시 없이 앱을 인터넷에 배포해도 문제가 없었음

    • 보안이나 성능에 대한 구체적인 이유 없이 역방향 프록시를 사용하라는 의견이 많음
    • 역방향 프록시가 정말 필요한지 의문을 가짐
  • 자체 제작한 C 웹 서버: 상업용 웹사이트를 운영했던 C 웹 서버를 제작했음

    • 128MB RAM과 1 CPU로 많은 트래픽을 처리했음
    • 20년 전 인터넷 환경이 덜 적대적이었음을 언급함
    • 봇이 훌륭한 퍼저(fuzzer) 역할을 하지만 실제 퍼징도 필요함
  • 서비스 구축의 만족감: 시스템 API를 사용해 기본적인 서비스를 구축하는 것이 매우 만족스러움

    • poll() 함수가 높은 성능을 보여주는 것에 놀람
    • 연결별 함수와 관련 구조체, 배열이 nginx, redis, memcached와 유사함
    • 훌륭한 작업임
  • 작은 프로젝트 소개: 여가 시간에 시작한 재미있는 프로젝트를 소개함

  • Kore 프레임워크 추천: C 앱을 작성할 때 공개된 부분을 작성하는 것이 불편하다면 Kore 프레임워크를 추천함

    • ACME 인증서 관리, Pgsql, curl, 웹소켓 등의 기능이 내장되어 있음
    • Lua/Python과 C를 혼합하여 모듈을 빌드하고 실행할 수 있음
  • 흥미로운 링크 공유: sqlite.org의 althttpd 인스턴스가 하루에 50만 개 이상의 HTTP 요청을 처리함

    • $40/월 Linode에서 200GB의 콘텐츠를 제공함
    • HTTP 요청의 19%가 CGI를 통해 Fossil 소스 코드 저장소에 접근함
  • 자체 도구 제작의 즐거움: 모든 것이 "전투 테스트"되어야 한다는 의견에 지침

    • 버그는 수정할 수 있음
  • Chaos Communication Congress 강연: 보안 기능이 포함된 C로 작성된 블로그/웹 서버에 대한 강연을 상기시킴

    • 불변 저장소, 권한 축소, TLS 인증서 접근 불가 등의 기능이 포함됨
  • 안정적인 웹사이트: 첫 페이지에 표시되어도 크래시하지 않는 웹사이트

  • 기본으로 돌아가기: 필요한 것만 사용하여 기본으로 돌아가는 접근 방식을 좋아함

    • 소프트웨어의 불필요한 기능이 성능에 미치는 영향을 의문시함
    • 개발자에게 축하 인사를 전함