← 인프라·격리

BluePy - SSH로 KISA 보안 점검을 규칙 단위로 돌리는 CLI

규칙 133개를 쌓은 서버 보안 점검 도구가 v0.1에서 검증된 다섯 규칙만 기본으로 열기까지

목차
  1. 무엇인가
  2. 왜 만들었나
  3. 어떻게 동작하나
  4. 써 보니
  5. 실패와 고친 것
  6. 지금 상태

무엇인가

2025년에 들어간 BluePy 커밋 중 74개가 닷새 사이에 몰렸다.
그해 11월 README는 진행률을 98%로 적었다.
이듬해 6월에 나온 v0.1이 기본 스캔에서 여는 검증된 점검은 다섯 규칙이다.

BluePy는 리눅스·macOS 서버에 SSH(암호화된 원격 접속)로 접속해
KISA(한국인터넷진흥원) 기준 보안 점검을 규칙 하나씩 돌리고
규칙마다 PASS·FAIL·MANUAL을 돌려주는 CLI(명령줄 도구)다.
서버 설정을 점검하려는 사람은 리포를 내려받은 뒤,
리포 루트에서 파이썬 패키지 관리자 uv로 scan 명령을 실행한다.
설치형 패키지는 없다.

왜 만들었나

출발점은 2017년에 작성됐다고 내가 말한 옛 점검 프로젝트다.
2025년 10월, 나는
Claude Code에 이 코드를 분석해 달라고 맡기며 이렇게 적었다.
"지금 포트폴리오 재구성 설계중이야. 2017년에 작성돼서 오래된 프로젝트긴한데"
리포에 처음 들어온 분석 문서는 원형을 Python 2와 C++(Qt),
리눅스 전용, KISA 기준 73개 항목, 소켓 통신, Excel 보고서로 정리했다.

방향은 이튿날 새벽에 바로잡았다.
내려받아 쓰는 진단 도구를 만들되, 쓰는 사람은 일반 사용자라고 정정했다.
"일반 사용자 누구라도 그냥 프로그램 더블클릭하면 진단 할 수 있게끔 만드는거라고 정정할게."
같은 날 오전에는 비전공자도 GUI(그래픽 화면)에서
진단하고 고칠 수 있게 하겠다며 화면까지 정했다.
구성 제안은 에이전트에게 넘기면서
"프로그램 개발 프로젝트는 처음이니까"라는 단서를 달았다.

어떻게 동작하나

스캔 한 번은 규칙을 하나씩 차례로 실행하는 반복 과정이다.
명령줄 도구가 SSH로 서버에 접속해 플랫폼별 규칙 파일을 읽고
실험 규칙을 거른다. 스캐너는 규칙에 적힌 점검 명령을 원격에서 실행해
출력을 모으고 그 출력을 규칙이 가리키는 파이썬 검사 함수에 넘겨
PASS·FAIL·MANUAL 중 하나와 메시지를 받는다.
규칙 하나는 YAML(설정 파일 형식) 파일 하나와 검사 함수 하나로 이뤄진다.

결과는 규칙 ID별로 모여 개수와 점수로 집계된다.
점수는 PASS 1점, MANUAL 0.5점, FAIL 0점을 합쳐
전체 개수로 나눈 백분율이다. 종료 코드는 도구가 제대로 돌았는지만 알려 준다.
스캔을 마치면 FAIL이 몇 개든 0이고, 연결 실패는 2, 규칙 로드 실패는 3이다.
점검 결과는 --json 출력의 7개 키에 담긴다.

기본 스캔의 범위는 규칙 로더의 기본값이 정한다.
로더는 규칙 파일에 experimental 키가 없으면 실험 규칙으로 읽고
기본 스캔은 실험 규칙을 거른다. experimental: false 표시를 단 규칙은
리눅스 U-18·U-19와 macOS M-01·M-02·M-05 다섯 개뿐이다.
--include-experimental 옵션을 주면 실험 규칙도 함께 돈다.
v0.1 트리에 있는 규칙은 실험 규칙까지 합쳐 리눅스 71개, macOS 10개, 윈도우 49개다.

발행 카탈로그는 내 역할을 원형과 방향으로 적었다.
2025년 10~11월에 이 프로젝트의 Claude Code로 보낸 내 입력은
403행(슬래시 명령을 빼면 157행)이다.
커밋의 작성자 이름과 메시지 줄만으로는 누가 코드를 썼는지 알 수 없다.

옛 코드를 새 구조로 옮기는 방식은 변환 스크립트였다. 스크립트 머리말은 파이썬 2 코드를
3.12로 바꾸고 규칙 파일과 검사 함수의 뼈대를 자동으로 만든다고
적었고, 점검 함수 73개를 한 번에 옮기는 사용 예를 실었다.
리눅스 검사 함수 73개는
밤 10시 넘어 시작한 단계별 커밋으로 3시간 24분 만에 채워졌다.
계획표의 2~4주차에 해당하는 스캐너, GUI·데이터베이스, Excel 보고서는
이어진 새벽 한 시간 남짓 동안 커밋 세 개로 들어갔다.
그 뒤 사흘 사이에 macOS 규칙, 자동 수정 엔진, 윈도우 규칙이 추가됐고
11월 시점의 규칙 파일은 모두 133개였다.

이듬해 6월 GJC 세션에서 나는 공개를 전제로 계획을 다시 세워야 하는지 물었고
도커를 권하는 계획에는 이렇게 되물었다.
"oss 계획에 도커를 권장하는건 너무 무거운것 같은데. 도커가 필요한 이유는 뭐지?"

2026-06-23 v0.1 커밋의 README는 도커를 라이브 합격 시험에만 쓰고
설치 요건에는 넣지 않았다.
설치에 필요한 것은 uv와 의존성 셋(pydantic, pyyaml, asyncssh)이 전부다.

써 보니

이 글을 위한 조사가 확인한 스캔 실행은 이 조사가 직접 돌린 도커 합격 시험뿐이다. 내 기록에서
실제 서버에 scan을 돌린 입력이나 보고는 찾지 못했다.
v0.1 커밋 트리를 받아 도커 하니스를 돌리면 우분투 컨테이너에 SSH로 접속한다.
/etc/shadow 권한이 400이라 U-19는 PASS,
/etc/passwd 권한이 644라 U-18은 FAIL이 나오고 종료 코드는 0이다.
컨테이너 시작 스크립트는 시작할 때마다 두 파일의 권한을 다시 설정하고,
스크립트 주석은 이것이 결과를 우연이 아닌 인과로 만든다고 적었다. 출력 마지막 줄은 이렇다.

[acceptance] PASS: {"U-19": "PASS", "U-18": "FAIL", "total": 2, "passed": 1, "failed": 1, "manual": 0, "cli_counts_match": true}

macOS 쪽 증거는 분기 단위 테스트와 실제 명령 출력 캡처, 두 가지다.
고정물로 둔 출력은 SIP(시스템 무결성 보호) 점검의
"System Integrity Protection status: enabled."와
FileVault 점검의 "FileVault is Off."다.
README는 라이브 SSH 확인을 수동으로 했다고 적었다.

그전의 테스트 숫자는 커밋 제목에 남아 있다.
2025년 10월 18~19일 커밋 제목에 적힌 숫자는 165/165 통과, 271/272 통과,
테스트 340개(커버리지 63%)로 늘었다.
11월 README는 "테스트 354개 통과 (100% 통과율)"을 성과로 적었다.
모두 커밋과 문서에 적힌 값이고, 이 조사에서 그 시점의 테스트를 돌려 다시 센 값은 아니다.
그달 말 나는 다른 리포를 작업하다가 BluePy 테스트를 아직 로컬에서만 돌려 봤다고 적었다.

실패와 고친 것

v0.1이 지운 거짓 PASS 검사기 셋은
검사기 셋을 지우고 줄여서 닫은 기록에 따로 적었다.

2025년 트리의 연결 코드는 SSH 호스트 키 검증을 꺼 두었다.
known_hosts 값이 None이었고,
주석은 프로덕션에서는 이 검증을 쓰라고 권장한다고 적었다.
v0.1은 엄격 검증을 기본으로 두고 --insecure 옵션을 줄 때만
검증을 끄면서 경고를 로그에 남긴다. README에 적힌 이유는 한 줄이다.
"BluePy is a security tool, so it must not undermine its own transport"

명령줄 도구도 같은 시점에는 이름만 있었다.
2025년 11월 트리의 프로젝트 설정은 bluepy-cli 진입점을 선언했지만,
그 트리에는 CLI 코드 폴더가 없었다.
v0.1은 scan 하위 명령 하나로 명령줄 도구를 새로 만들었고,
--json 출력의 7키 구조를 바꾸지 말라고 기여 규칙에 못 박았다.

v0.1에서 고쳐지지 않은 채 기본 스캔에서 빠진 것도 있다.
v0.1 트리의 리눅스 규칙 71개 중 29개는 점검 명령이 비어 있다
(U-41~U-49, U-51~U-59, U-61~U-69, U-71, U-72).
로더는 명령이 없으면 echo 'No commands (manual check)' 한 줄로 채운다.
이 29개는 experimental 키가 없어서 로더 기본값에 따라 실험으로 분류됐고
기본 스캔에는 포함되지 않는다.

문서와 실물이 어긋난 곳은 표로 모았다.

무엇문서가 적은 것실물
라이선스 (2025년 11월)README 배지가 MIT를 표시그 시점 트리에 라이선스 파일이 없음. 지금 리포는 MIT
실험 표시 (v0.1)미검증 점검은 experimental: true 표시를 단다그 값을 적은 규칙 파일 0개. 로더 기본값이 실험으로 분류
--insecure (v0.1)라이브 시험 하니스는 쓰지 않는다하니스의 CLI 호출 단계는 이 옵션을 넣는다. 엄격 경로는 앞 단계의 프로세스 안 스캔이 증명한다고 주석에 적힘

지금 상태

발행 카탈로그는 BluePy의 상태를 보관으로 적었다.
"블루파이만 푸시."라는 입력 직후 v0.1 커밋이
v0.1.0 태그와 함께 GitHub에 올라갔다.
그 뒤로는 커밋도, 열린 이슈도 없다(2026-10-19 확인 기준).
리포는 공개이고 MIT 라이선스이며 GitHub의 보관 설정은 아니다.
스타 1개와 포크·이슈·풀 리퀘스트 0건이다(2026-10-19 확인 기준). 스타는 내가 단 것이다.

v0.1 README에 적힌 보류 목록은 다섯 가지다.
윈도우 트랙 노출과 자동 수정 노출(둘 다 엔진은 있다),
터미널 UI(v0.2 예정), PySide6 GUI, 뒤섞인 옛 KISA 매핑의 전면 수리가 그것이다.
v0.1에는 설치형 wheel이나 단독 실행 파일이 없다.