실측 결과
Hostveil이 고친 뒤에 Hostveil의 점수가 올라가는 것은 아무것도 증명하지 않습니다. 무엇이 발견 항목인지, 고친다는 것이 무엇인지, 그러고 나면 숫자가 몇이어야 하는지를 전부 같은 코드가 정하기 때문입니다. 그래서 이 페이지는 다른 사람들이 만든 도구가 같은 호스트를 수정 전후로 보고 무엇을 말했는지를 싣습니다 — 움직이지 않은 계측기까지, 그리고 잘못된 이유로 움직인 것 하나까지. 아래의 모든 수치는 저장소에 커밋된 실행 결과에서 나오며, 직접 재현할 수 있습니다.
점수만으로는 근거가 되지 않는 이유
자기 자신과만 일관된 스캐너는 만들기 쉽고 아무 쓸모가 없습니다. Hostveil이 어떤 포트 바인딩을 발견 항목이라고 선언하고, Compose 파일을 고치고, 방금 자기가 쓴 그 파일을 다시 읽고, 스스로에게 점수를 준다면, 그 고리의 어느 단계도 서버의 보안에 닿지 않습니다. 모든 단계가 내부적으로 옳으면서도 전체가 연극일 수 있습니다.
빠져나올 방법은 하나뿐입니다. 우리가 만들지 않았고 우리의 견해를 공유하지 않는 계측기를 쓰는 것입니다. 아래 넷 중 셋은 다른 사람이 다른 목적으로 만든 것이고, 나머지 하나는 커널이 직접 답하는 리스닝 소켓 목록이라 견해라는 것 자체가 없습니다.
아래는 일부러 잘못 설정한 호스트 하나에 대한 한 번의 실행입니다. 벤치마크가 아니라 증거입니다. 인용하기 전에 이 결과가 보여주지 않는 것을 먼저 읽어 주세요.
측정한 호스트
셀프호스터가 실제로 굴리는 잘못된 설정을 심어 둔 서버입니다. 서비스는 흉내가 아니라 실제로 돕니다. Compose 스택 3개 — Nextcloud+PostgreSQL, Jellyfin+Redis, Portainer+Watchtower — 가 모든 포트를 0.0.0.0에 공개하고 no-new-privileges도 재시작 정책도 메모리 제한도 없으며, 빈 비밀번호와 root 로그인과 비밀번호 인증을 허용하는 SSH 드롭인, 설치돼 있지만 꺼져 있는 ufw, 꺼져 있는 자동 보안 업데이트, 0.0.0.0에 바인딩된 네이티브 Redis, UID 0인 두 번째 계정, 모두가 읽을 수 있는 /etc/shadow, API 키 옆에 설정 파일이 놓인 AI 에이전트 런타임 2개, 디버깅·프로파일링 가이드가 흔히 풀라고 시키는 대로 완화한 뒤 재부팅에도 살아남게 /etc/sysctl.d에 남겨 둔 sysctl 값 2개, 그리고 systemd의 샌드박스 지시자를 하나도 설정하지 않은 손수 작성 백업 유닛까지 있습니다.
| 운영체제 | Ubuntu 24.04.4 LTS |
| 아키텍처 | x86_64 |
| 커널 | 6.8.0-134-generic |
| Hostveil | hostveil v3-dev |
| 측정 시각 | 2026-08-18T23:36:39+00:00 |
| 수정 전 발견 항목 | 실행된 13개 도메인에서 140건. 그중 13개만 자기 범위를 전부 봤습니다 |
계측기
| 계측기 | 만든 곳 | 볼 수 있는 것 |
|---|---|---|
Hostveil scan --json | 우리 | 자기 측정. 나머지와 함께 놓는 이유는 이들이 같이 움직이는지를 독자가 직접 보게 하기 위해서입니다. |
| Lynis | CISOfy | 자기 규칙 집합을 가진 호스트 감사 도구. 대표 수치는 264개 테스트에 대한 0–100 하드닝 지수입니다. |
| docker-bench-security | Docker | CIS Docker Benchmark. 이미지·컨테이너 런타임 섹션만 실행합니다 — 실행 중인 컨테이너에 대한 44개 점검. |
| 외부 TCP 스캔 | — | Docker 브리지 위의 컨테이너에서 호스트로 되짚어 connect합니다. 0.0.0.0에 붙은 것에는 닿고 루프백에 붙은 것에는 닿지 않습니다. 응답·거부·무응답 세 가지로 구분합니다. |
| 리스닝 소켓 | 커널 | ss -ltn을 와일드카드/라우팅 가능 주소와 루프백 전용으로 나눈 것. 우리 것이든 남의 것이든 규칙 집합이 개입하지 않습니다. |
다섯 단계, 그리고 그중 셋을 나눠 놓은 이유
Hostveil이 적용하는 Auto 수정은 전부 파일 편집입니다. 그것이 되돌릴 수 있는 이유이고, 동시에 적용한 순간에는 아무것도 발효되지 않는 이유입니다. 실행 중인 컨테이너는 생성될 때의 포트 매핑을 그대로 들고 있고, 데몬은 이미 읽어 둔 설정으로 계속 서빙합니다.
그래서 호스트를 다섯 번 잽니다.
| 단계 | 호스트 상태 |
|---|---|
| before | 심어 둔 그대로. |
| after | hostveil fix --all --yes 실행 직후. 파일은 바뀌었고 아무것도 재시작하지 않았습니다. |
| restarted | 스택마다 docker compose up -d. 서비스가 새 파일을 읽었습니다. |
| reviewed | hostveil fix --all --review --yes까지 실행한 뒤 — Hostveil이 할 수는 있지만 무인으로는 하지 않는 Review 수정들. 운영자가 실제로 밟는 경로입니다. |
| restored | 모든 체크포인트를 롤백하고, 서비스를 다시 되돌려 재시작한 뒤. |
after만 싣는다면 독립 계측기가 아무것도 보지 못했다고 말하게 되는데, 그것은 사실이지만 수정이 아무 일도 하지 않은 것처럼 읽힙니다. restarted만 싣는다면 Hostveil이 하지 않는 — 그리고 일부러 Auto로 제공하지 않는 — 재시작의 공을 슬그머니 가져가게 됩니다. 서비스 재시작은 되돌릴 수 없고 체크포인트를 남길 수 없습니다. 두 열 사이의 간극이 이 페이지에서 가장 쓸모 있는 한 가지입니다.
그리고 무인 수정만 재면 도구의 절반만 재는 것입니다. fix --all은 Auto만 적용하는데, SSH 강화 항목은 전부 Review입니다 — root 로그인이나 비밀번호 인증을 끄는 일은 그 명령을 내리고 있는 세션 자체를 끊을 수 있으니까요. reviewed 열은 그걸 읽고 수락한 운영자가 얻는 결과이고, SSH 도메인이 비로소 움직이는 곳입니다.
결과
| 측정 항목 | before | after | restarted | reviewed | restored |
|---|---|---|---|---|---|
| Hostveil 점수 | 29 | 37 | 41 | 60 | 34 |
| Hostveil 발견 항목 | 140 | 98 | 83 | 50 | 119 |
| Lynis 하드닝 지수 | 57 | 63 | 66 | 80 | 68 |
| Lynis 제안 | 37 | 33 | 33 | 20 | 29 |
| CIS Docker PASS | 16 | 16 | 19 | 20 | 16 |
| CIS Docker WARN | 16 | 16 | 13 | 12 | 16 |
| 와일드카드/라우팅 가능 바인딩 포트 | 7 | 7 | 2 | 2 | 7 |
| 호스트 밖에서 응답하는 포트 | 7 | 7 | 2 | 1 | 6 |
hostveil fix --all --yes가 55건을 적용했고 실패는 없었습니다. 이어서 fix --all --review --yes가 42건을 더 제안했고, 그중 24건이 체크포인트를 남겼으며 18건은 남기지 않았습니다 — 파일 편집이 아닌 것들로, Hostveil이 자신의 히스토리에 각각 [not reversible]로 표시하고 아래의 롤백으로도 되돌아가지 않습니다.
움직인 것
호스트 밖에서 응답하던 것들. 서비스를 재시작하자 다른 네트워크 네임스페이스에서 오는 TCP 연결에 포트 네 개가 응답을 멈췄습니다. 5432, 6380, 8080, 8096, 9000, 각각 PostgreSQL, Jellyfin 옆에 공개돼 있던 Redis, Nextcloud, 그리고 Jellyfin입니다. 이 페이지에서 가장 논쟁의 여지가 없는 결과입니다. 해석한 것이 없고, 바인드 주소가 바뀌었고, 서비스가 닿지 않게 됐습니다.
Review 수정을 수락하자 두 개가 더 닫혔는데, 그쪽이 흥미롭습니다. 아직 응답하는 것은 22뿐입니다. 조용해진 둘은 2375번, 즉 Docker 데몬 자신의 API — 닿을 수 있는 사람에게는 인증 없는 root입니다 — 와 6379번, 직접 설치한 Redis입니다. 뒤쪽은 Hostveil이 보고하고도 고치기를 거절한 항목입니다. 그것을 루프백에 묶으려면 데이터스토어마다 경로와 문법이 다른 설정 파일을 편집해야 하고, 발견 항목은 그 경로를 들고 있지 않기 때문입니다. 둘 다 파일을 고쳐서 닫은 것이 아닙니다. Hostveil이 방화벽을 켰고, 거절한 수정이 해낸 수정으로 해소됐습니다.
그래서 커널과 스캐너의 말이 여기서 갈리는데, 그 어긋남이 가치 있습니다. Review 수정 뒤에도 라우팅 가능한 주소에 묶여 있는 소켓은 2개이고, 그중 호스트 밖에서 응답하는 것은 1개입니다. 바인드 주소와 패킷 필터는 포트에 대한 서로 다른 주장이고 둘 다 참입니다. 이 페이지는 듣기 좋은 쪽을 고르는 대신 둘 다 적습니다.
CIS Docker 벤치마크. 재시작 시점에 세 항목이 통과로 바뀌고 — 5.14, 5.26, 5.3 — Review 수정까지 수락하자 네 번째가 통과했습니다: 5.11, 컨테이너의 메모리 사용량이 제한되어 있는가, 즉 compose.ds010입니다. 5.14는 컨테이너 인바운드 트래픽이 특정 호스트 인터페이스에 바인딩되어 있는가, 5.26은 컨테이너가 추가 권한을 획득하지 못하도록 제한되어 있는가 — 각각 포트 바인딩과 no-new-privileges이고, Hostveil을 한 번도 들어본 적 없는 도구가 확인해 준 것입니다. 5.3은 사정이 다릅니다. 아래를 보세요.
SSH, 다만 Review 경로에서만. Hostveil의 SSH 영역은 무인 수정으로 10 → 31, Review 수정까지 수락하면 10 → 100이 됩니다. 이 간극이 reviewed 열이 존재하는 이유 전부입니다. root 로그인과 비밀번호 인증은 가장 중요한 두 항목이면서, 지켜보지 않는 사이 Hostveil이 끄지 않는 두 항목이기도 합니다. 잘못 끄면 그 명령을 내리고 있는 세션 자체가 끊기기 때문입니다.
Lynis도 마침내. 하드닝 지수가 57 → 80이 됐는데, 목록은 그대로입니다. 시작할 때와 같은 경고 3건, 제안 20건으로 끝납니다. Lynis의 지수는 통과한 하드닝 시험 수를 세는 것이지 지워진 항목 수를 세는 것이 아니어서, 오른 3점은 어느 제안 하나가 이름 붙일 수 없는 시험들에 흩어져 있습니다. 무인 경로만 보면 같은 지수가 1점 움직입니다. 그 경로만 재던 것이 이 페이지의 이전 판이 "Lynis는 움직이지 않는다"고 보고했던 이유입니다.
움직이지 않은 것
Hostveil의 컨테이너 축은 100점 만점에 0 → 2였습니다. Compose 파일에 대해 가진 수정을 전부 적용했는데도 바닥에 머물렀습니다. 남은 것이 설계상 Manual이기 때문입니다 — Portainer와 Watchtower에 마운트된 Docker 소켓, 호스트 네트워킹, 환경 변수 속 비밀값. 소켓 마운트를 떼면 그것을 필요로 하는 두 도구가 망가지고, Hostveil은 그 판단을 대신 하지 않습니다.
Lynis 경고 3건 중 2건은 Hostveil이 찾아놓고 거절한 항목입니다. AUTH-9204는 UID가 0인 사용자 확인, AUTH-9208은 passwd의 중복 계정 확인 — 둘 다 심어 둔 두 번째 root이고, Hostveil은 이를 accounts.uid0으로 보고하고 손대지 않습니다. 계정 삭제는 체크포인트로 되돌릴 수 없습니다. userdel은 계정과 그룹과 메일 스풀을 가져가고, 그 계정이 소유하던 모든 파일을 UID 고아로 남깁니다. 두 도구가 겹치는 땅은 실재하고, Hostveil은 그것을 취하지 않기로 택한 것입니다.
CVE 축은 아예 움직이지 않았습니다. 16 → 16입니다. 여기서 수락한 Review 수정에는 이미지 갱신도 들어 있는데, 최신 태그를 받아 온다고 축이 올라가지는 않습니다. 더 새로운 이미지가 패치된 이미지는 아니고, 최신 태그에도 각자 공개된 취약점이 있기 때문입니다. 같은 씨앗으로 돌린 이전 실행에서는 바로 그 이유로 이 축이 내려가는 것을 봤습니다. 여기 적는 이유는 좋은 쪽으로 움직인 수치만 보여 주는 페이지야말로 이 페이지가 반대하는 그것이기 때문입니다.
AI 에이전트 축은 0 → 13이었습니다. 파일 권한 관련 두 건은 고쳐졌고, 설정 자체에 관한 항목은 전부 고쳐지지 않았습니다. 모두 같은 이유로 의도적 미수정 목록에 있습니다. OpenClaw의 설정은 JSON5이고 사용자들이 주석을 많이 답니다. Hostveil에는 왕복 보존 인코더가 없어서 다시 인코딩하면 그 주석을 조용히 지우게 됩니다. 컨테이너 다음으로 이 호스트에서 가장 많은 점수를 깎는 영역이고, Hostveil이 탐지는 하되 아직 고치지 못하는 지점을 가장 분명하게 보여 줍니다.
after 열에서는 Hostveil 자신의 숫자 외에 아무것도 움직이지 않았습니다. 수정 55건이 적용됐고 디스크의 파일 28개가 바뀌었는데, CIS Docker 벤치마크도 외부 스캔도 커널의 소켓 목록도 동일한 호스트를 보고했습니다. 이것이 파일을 편집하는 수정 도구의 정직한 모습이고, 재시작 열이 존재하는 이유입니다.
CIS 5.3은 해당한다면 SELinux 보안 옵션이 설정되어 있는가인데, 이것이 해소되었습니다. SELinux는 설정되지 않았습니다. docker-bench가 이 점검을 HostConfig.SecurityOpt가 비어 있지 않은지로 구현하는데, no-new-privileges가 바로 그 필드에 들어가기 때문입니다. 그래서 실제 개선 하나가 — 서비스마다 MEDIUM 항목 하나씩 해소한 compose.ds006 — SELinux가 없는 호스트에서 SELinux 점검 통과로 둔갑했습니다.
이것을 싣는 이유는 이 페이지가 다루는 실패 양식이 우리 쪽이 아니라 독립 계측기 쪽 문으로 들어온 사례이기 때문입니다. 외부 숫자가 움직였다는 것이 그 밑의 성질이 바뀌었다는 증명은 아닙니다. 여기 네 계측기 중 셋은 일관되었고, 넷째는 읽어 보면 무너지는 이유로 동의했습니다.
남이 한 하드닝에도 점수가 움직이는가?
위의 모든 것은 Hostveil이 호스트를 고치고, 독립적인 계측기들이 무언가 바뀌었다고 동의한 기록입니다. 그런데 가장 날카로운 질문 하나가 남습니다. Hostveil 자신의 수정에만 반응하는 숫자는 보안 점수가 아닙니다. 백분율이 붙은 할 일 목록일 뿐입니다.
그래서 두 번째 실험이 있고, 3.21 전까지 이 페이지에 없던 것이 바로 이것입니다. scripts/measure/control.sh는 같은 시드 호스트를 CIS 벤치마크와 Lynis 자신의 제안에 따라 하드닝합니다. sshd 설정, 커널 파라미터, 파일 모드, 두 번째 root 계정, Docker 데몬입니다. 그리고 Hostveil은 아무것도 적용하지 않습니다. 모든 변경은 남의 기준으로 거슬러 올라가고, 그중 어느 것도 Hostveil의 수정 레지스트리를 보고 고른 것이 아닙니다. 그다음 Hostveil이 스캔하고, 질문은 그것이 알아챘느냐입니다.
| 측정 항목 | 시드 직후 | control.sh 이후 |
|---|---|---|
| Hostveil 점수 | 29 | 44 |
| Hostveil SSH 축 | 18 | 100 |
| Hostveil 계정 위생 축 | 22 | 44 |
| Hostveil 파일 권한 축 | 50 | 100 |
| Lynis 하드닝 지수 | 57 | 62 |
| Lynis 경고 | 4 | 2 |
| CIS Docker 통과 | 16 | 17 |
| 호스트 밖에서 응답하는 포트 | 8 | 3 |
움직였고, 움직여야 할 이유로 움직였습니다. 축 세 개가 올랐고 Hostveil은 그중 어느 것에도 관여하지 않았습니다. SSH는 CIS 드롭인이 root 로그인과 비밀번호 인증을 껐기 때문이고, 계정 위생은 시드해 둔 두 번째 root 계정이 삭제됐기 때문이며, 파일 권한은 /etc/shadow와 SSH 호스트 키의 모드가 조여졌기 때문입니다. Hostveil은 그 뒤에 호스트를 읽고, 찾은 것을 점수로 매겼습니다.
바깥에서 본 Lynis도 같은 말을 하는데, 구체적으로 같은 말을 합니다. 사라진 경고 둘은 AUTH-9204, AUTH-9208이고, 둘 다 그 두 번째 root 계정입니다. Hostveil이 보고를 멈춘 바로 그 계정을, Hostveil을 한 번도 들어본 적 없는 도구가 찾아낸 것입니다.
움직이지 않은 것이 답의 나머지 절반입니다. 방화벽 축은 50에 그대로인데 control.sh가 방화벽을 켜지 않기 때문이고, 컨테이너 축은 0에 그대로인데 그 축을 바닥에 붙들고 있는 것이 CIS Docker 절이 건드리지 않는 Manual 항목들이기 때문입니다. Portainer에 마운트된 소켓, 호스트 네트워킹, 환경 변수 속 비밀값이 그렇습니다. 응답을 멈춘 포트 다섯 개는 외부 스캐너와 docker-bench에는 보이지만, 그 축을 바닥에서 들어 올리지는 못합니다. 호스트에 무엇을 했든 모든 축이 오르는 점수라면 그쪽이 더 의심스러운 결과일 것입니다.
control.sh는 작성돼 있었지만 한 번도 실행된 적이 없었습니다. 계정 단계는 “removing UID 0 account breakglass”라고 찍고, 아무것도 지우지 않고, 0으로 종료했습니다. userdel은 계정이 사용 중인지를 uid로 판단하는데 UID 0 쌍둥이는 root와 uid를 공유하므로, pid 1을 발견하고 거절합니다. 이건 지금까지 존재한 모든 호스트에서 참이고, 따라서 한 번도 성공할 수 없었던 단계였습니다. 그것을 가린 것이 2>/dev/null || true였습니다.
대조군은 계정 위생 절반을 조용히 빼먹고 있었고, 그것을 찾아낸 실행이 그것을 고친 실행입니다. 단계를 조용히 건너뛰는 대조군은 실패하는 대조군보다 나쁩니다. 그렇게 나온 숫자도 여전히 측정처럼 보이기 때문입니다.
롤백 복원율
보안 측정이 아니라 복구 계층에 대한 주장이며, 나머지가 의미를 가지려면 먼저 성립해야 하는 것입니다. Hostveil은 운영자에게 서버의 파일을 편집하게 해 달라고 요청하고, "되돌릴 수 있다"가 그 요청이 합당한 이유의 전부입니다.
| 감시한 경로 | 60 |
| 수정이 바꾼 경로 | 28 |
| 바이트 단위로 복원된 경로 | 27 |
| 롤백한 체크포인트 | 79 |
| 복원율 | 96% |
복원되지 않은 유일한 경로는 /etc/shadow이고, 체크포인트가 실패한 게 아닙니다. reviewed 단계는 Hostveil 스스로 되돌릴 수 없다고 표시한 픽스 18건을 적용하는데, 그중에는 apt-get dist-upgrade 전체 업그레이드와 rkhunter·fail2ban·auditd를 포함해 호스트에 없던 하드닝 도구 다섯 개를 설치하는 픽스들이 있습니다. 패키지를 설치하는 일에는 체크포인트로 잡을 파일이 없습니다 — 픽스가 말한 그대로 동작한 것이지, 하겠다는 일을 못 한 것이 아닙니다. 그중 하나가 새 시스템 계정을 만들면서 /etc/shadow를 부수적으로 다시 썼고, rkhunter의 의존성 체인은 컴파일러 도구 모음을 다시 설치했습니다 — 컴파일러 바이너리 두 개에 이전 상태가 기록되지 않은 이유도 이것입니다. before 스캔이 돌 때는 아직 존재하지 않았던 파일이었습니다. 되돌릴 수 있던 스물일곱 건은 모두 바이트 단위로 정확히 복원됐고, 스물여덟 번째는 애초에 되돌릴 수 없는 것이었으며 Hostveil은 적용하기 전에 이미 그렇게 말해 두었습니다.
해시는 일부러 체크포인트를 기준으로 잡지 않습니다. 체크포인트는 Hostveil이 백업했다고 믿는 내용이므로, 복원된 파일을 거기에 견주는 것은 Hostveil이 자기 자신과 일치하는지를 묻는 일일 뿐입니다. 후보 경로는 스캔에서 나옵니다 — 발견 항목이 가리키는 모든 파일, 그리고 /etc/sysctl.d의 모든 항목. 파일을 만드는 수정은 존재하는 것만 나열하는 이전 상태에서는 보이지 않기 때문입니다. 그리고 그 경로들을 아무것도 적용하기 전에 살아 있는 파일시스템에서 해싱합니다. 롤백이 재현해야 하는 것이 바로 그 상태입니다.
결과 표의 restored 열은 같은 주장을 해시가 아니라 계측기로 한 번 더 잰 것이자, 파일 롤백이 덮지 못하는 것을 보여 주는 열입니다. Hostveil 자신의 점수는 29에서 34로 정확히 돌아옵니다. 외부 스캔은 그렇지 않습니다. 전에는 포트 7개가 응답했고 지금은 6개가 응답합니다.
이 차이는 롤백 실패가 아니고, 자세히 읽을 값어치가 있습니다. 방화벽을 켜는 것은 파일 편집이 아니라 체크포인트가 없으므로, 나머지가 전부 제자리로 돌아간 뒤에도 ufw는 계속 돌고 있습니다. 그것이 아직 막고 있는 두 포트는 어느 컨테이너도 공개하지 않는 포트입니다. 2375번과 6379번이고, 거부(refused)가 아니라 차단(filtered)으로 보고됩니다. 아무것도 듣고 있지 않은 것이 아니라 패킷 필터가 떨어뜨리고 있다는 뜻입니다.
그리고 다시 응답하는 다섯 개는 그 방화벽을 통과해서 응답합니다. Docker는 컨테이너 포트를 공개할 때 자기 규칙을 ufw보다 앞에 씁니다. 그래서 Compose 파일을 되돌리자 그 바인딩이 0.0.0.0으로 돌아왔고 방화벽은 그것을 보지도 못했습니다. 이것이 firewall.docker-bypass입니다 — 두 가지 해결책이 서로 무관해 운영자만 고를 수 있기 때문에 Hostveil이 보고하고 고치기를 거절하는 항목이, 내려오는 길에, 그것을 한 번도 들어본 적 없는 계측기 안에서 스스로를 증명한 셈입니다.
이 결과가 보여주지 않는 것
호스트 하나, 설정 하나입니다. 표본 조사가 아니라 심어 둔 컨테이너 한 대입니다. 여기서 무슨 일이 있었는지를 말할 뿐, 다른 호스트에서 무슨 일이 있을지는 말하지 않습니다.
Auto 수정만 적용했습니다. fix --all은 Auto로 분류된 수정만 적용합니다. Review와 Manual 항목 — PermitRootLogin, 방화벽, Docker TCP 소켓, 두 번째 root 계정 — 은 전부 그대로 남았고, 그 하나하나가 위에서 잰 어떤 것보다도 큰 변화입니다. 이 수치는 천장이 아니라 바닥입니다.
모든 영역이 실행됐습니다. CVE와 AI 에이전트 런타임을 포함해 열세 개 전부입니다. 그중 sysctl과 systemd 두 영역은 한동안 조용히 100점을 받았는데, 호스트가 잘 다져져서가 아니라 시드가 그 두 영역에 물어볼 거리 자체를 심어 두지 않았기 때문입니다. 채점할 운영자 작성 systemd 유닛도, 걸릴 sysctl 값도 없었습니다. 이제 시드에 둘 다 들어갑니다 — 하드닝 지시자가 하나도 없는 백업 유닛, 그리고 “gdb: Operation not permitted” 같은 가이드마다 풀라고 하는 sysctl 값 두 개. 그래서 영역 수는 열한 개에서, 에이전트 경로를 고친 뒤 열두 개로, 지금은 열세 개로 늘었습니다. 시드는 이제 저장소에 있고, 그 경로들은 체커와 테스트로 대조됩니다.
스캔은 인터넷이 아니라 Docker 브리지에서 옵니다. 다른 네트워크 네임스페이스에서 0.0.0.0에 묶인 것에 닿으므로 재려는 속성은 정확히 잽니다. 다만 클라우드 제공자의 보안 그룹까지 통과하지는 않습니다. 여기서 응답하는 포트라도 기계 밖에서는 닿지 않을 수 있고, 여기서 거절된 포트는 누구에게나 거절됩니다.
여기 어떤 것도 침해 여부를 재지 않습니다. 우리 것을 포함해 이 페이지의 모든 계측기는 설정을 잽니다. 파일을 읽는 스캐너가 주장할 수 있는 정직한 한계가 거기까지입니다.
직접 재현하기
양쪽 다 저장소에 있습니다. 호스트를 만드는 스크립트와, 그것을 재는 하네스입니다. 둘 다 실행되는 호스트를 되돌릴 수 없게 편집하니, 컨테이너나 버려도 되는 VM에 겨누세요. 본인 머신에는 절대 겨누지 마세요. seed.sh는 그렇게 보이지 않는 곳에서는 실행을 거부합니다.
git clone https://github.com/seolcu/hostveil && cd hostveil
go build -o /usr/local/bin/hostveil ./cmd/hostveil
# 위 수치를 전부 잰 그 프로필로 호스트를 만들고, 계기 세 개를 설치합니다.
# root SSH 로그인을 허용하고, UID 0 계정을 하나 더 만들고,
# 데이터베이스를 0.0.0.0에 공개합니다.
sudo scripts/measure/seed.sh
sudo scripts/measure/run.sh -c -p seeded /tmp/measurement.json시드는 원래 저장소 밖에 있었고, 그래서 이 안내는 가장 중요한 지점에서 불완전했습니다. 재라고만 하고 호스트는 알아서 맞추라는 셈이었으니까요. 게다가 픽스처가 제품과 어긋나도 아무도 알아채지 못했습니다. 그 사본 하나는 OpenClaw 설정을 ~/.config/openclaw/에 썼는데, 에이전트 체커가 보지 않는 경로입니다. 그래서 런타임 두 개를 심어 둔 호스트에 대해 "런타임 없음"이라고 보고했습니다. 이제 시드가 쓰는 모든 경로는 체커 자신의 표와 테스트로 대조됩니다.
같은 씨앗인데 점수가 예전보다 낮아졌고, 그게 핵심입니다. 직전에 커밋된 실행은 수정 전 이 호스트를 40으로 봤고, 이번 실행은 29로 봅니다. 호스트가 나빠진 것이 아닙니다. Hostveil이 더 많이 찾아냈고 — 그때 83건, 지금 140건입니다 — 기록만 되고 아직 발효되지 않은 수정을 자기 공으로 세는 것을 그만뒀습니다. 3.20.1 이전 모든 실행의 after 열을 부풀리고 있던 것입니다. 채점이 엄격해져서 내려간 점수는, 공개할 값어치가 있는 유일한 종류의 후퇴입니다.
위 실행은 같은 바이너리로, 따로 시드한 호스트들에서 여러 번 반복했습니다. 호스트를 설명하는 수치는 매번 같게 나왔습니다. 같은 점수, 재시작 단계에서 해소된 CIS 점검 ID 3개와 Review 단계의 네 번째도 같고, 포트도, 복원된 파일도 같습니다. 실행 사이에 달라진 것은 호스트가 아니라 재는 쪽과 심어 둔 쪽이었습니다. Trivy가 없는 호스트는 CVE 축을 N/A로 보고했고 그만큼 총점이 높게 나왔습니다. 제외된 축은 0점을 받는 대신 분모에서 빠지기 때문입니다. 에이전트 설정이 엉뚱한 경로로 간 호스트도 그 영역에서 똑같은 일이 벌어졌습니다. 시드를 저장소에 커밋하고 테스트로 묶은 이유가 이것이고, 이전 실행이 열한 개, 그다음 열두 개였던 영역이 이번에 열세 개인 이유도 이것입니다. 커밋된 실행 결과는 docs/measurements/에 있고, 이 페이지의 모든 수치는 그중 최신 것과 테스트로 대조됩니다 — 여기 낡은 숫자가 남아 있으면 빌드가 깨지며, 독자가 알아채야 할 일이 아닙니다. -c를 붙이면 출력 중 관측이 아니라 약속에 해당하는 두 가지에 대해 0이 아닌 종료 코드로 실패합니다. 롤백이 바뀐 파일을 전부 정확히 복원했다는 것, 그리고 Hostveil 자신의 점수가 어쨌든 움직였다는 것. 그 밖에는 아무것도 단언하지 않습니다. 이 페이지의 나머지 숫자는 Hostveil의 변경과 무관한 이유로도 움직이기 때문입니다.