MyScanner는 Nmap 스캔 결과(XML) 를 인벤토리에 반영하고, 포트 노출에 대한 Triage(검토/소명) → Remediation(조치/예외) 흐름을 웹 UI로 관리하는 솔루션입니다.
해당 솔루션은 정기적인 포트스캔을 내/외부자 관점으로 진행할 때, 이력과 포트에 대한 조치사항을 관리 목적으로 사용합니다.
-
주 이용자 : 취약점 담당 인력 & IT 방화벽을 담당하는 인력
-
Backend: FastAPI + SQLAlchemy + PostgreSQL
-
Frontend: Jinja2 템플릿(서버사이드 렌더링)
-
Scan engine: Nmap (XML 출력 기반)
-
Security: 서버사이드 세션 + MFA(TOTP) + 임시 비밀번호/강제 변경
- 최근 스캔/인벤토리 요약
- Scan Run 목록(실행 로그 확인, Ingest, 삭제)
- 대상/포트 범위/옵션으로 Nmap 실행(스캔허용 ip는 docker-compose.yml 내 ALLOWED_TARGETS 참고)
- 방화벽 차단/허용 상태를 통해 스캔 진행 시 방화벽을 허용절차를 거치고 수행했는지(내부망 스캔),- 방화벽 차단을 유지한 상태로 스캔(공격자 관점 스캔)으로 진행하였는지 표기 가능
- 실행 로그 tail/stream 확인
- 스캔 종료 시
Ingest버튼 클릭으로 XML을 Inventory에 반영 - Ingest 성공(SUCCESS) 후 스캔 아티팩트(xml/log)를 자동 삭제(로그 무한 누적 방지)
- IP/Port 기준 포트 인벤토리 관리
- FW 프로필(Y/N) 포함 데이터가 존재하더라도 (IP,Port)는 동일 단위로 상태/미탐 카운트를 동기화(중복/불일치 방지)
- Excel Export 지원
- 상태(Status)와 Reviewed에 따라 데이터가 Triage Queue와 Remediated 메뉴로 자동 분리됩니다.
- 중복입력 방지 정책
- FW(방화벽)플래그가 다른 동일 IP/PORT의 경우 데이터가 중첩되어 생길 수 있습니다.(IP/PORT 당 최대 2개 데이터)
- 동일한 IP/PORT에 대한 내용의 중복적인 기입을 방지하기 위해 이미 동일한 IP/PORT로 기입된 정보가 있으면, 새로 생기는 데이터 또한 동일한 내용이 입력되도록 설계하였습니다.
- 휴먼에러 방지 정책
REMEDIATED/IGNORED로 바꾸면 Reviewed가 자동으로 Y 처리되어 실수로 Reviewed를 안 올려도 “사라짐”이 발생하지 않도록 설계DENIED는 Triage Queue에 유지(추가 검토 대상)하며 Reviewed는 강제로 NREMEDIATED/DENIED/IGNORED → ACTIVE로 되돌리면 Reviewed=N으로 초기화되어 Triage Queue에 다시 표시
- INACTIVE(미탐 2회) 상태가 되면 휴먼에러 방지를 위해 Status/Reviewed 수정이 금지됩니다.
- 이후 스캔에서 다시 탐지(open)되면 INACTIVE 해제 + Reviewed 초기화로 Triage로 복귀
- 스캔시, open된 포트를 보유한이력이 있는 IP를 목록으로 관리하는 기능입니다.
- 주요 작업(스캔/반영/계정관리/상태변경 등) 감사 로그
- 날짜 필터는 KST(Asia/Seoul) 기준으로 동작하도록 UTC 저장 시간을 변환해 조회
- 역할(Role):
admin,operator- admin: 스캔 실행/중지/삭제/ingest, 사용자 관리, 감사로그 접근
- operator: 조회 및 제한된 운영(설정에 따라 조정 가능)
- 비밀번호 정책(회원가입): 8자 이상 + 대문자/소문자/숫자/특수문자 각각 1개 이상
- MFA(TOTP): google authenticator app 지원,첫 로그인 시 등록 강제 → 이후 로그인 시 항상 코드 요구
- Reset PW: 정책을 만족하는 랜덤 임시 비밀번호 발급 +
must_change_password=True - 임시 비밀번호로 로그인 시 강제 비밀번호 변경 페이지(/change_password) 로만 접근 가능
- Reset MFA / Force Logout / Delete user: Users(admin) 메뉴에서 관리
1. operator role 로 웹 회원가입
2. DB에 직접 role 변경
docker compose exec db psql -U myscanner -d myscanner -c "UPDATE users SET role = 'admin' WHERE user_id = '<id>';"
- Python 3.12+
- PostgreSQL 16+
- Nmap 설치
- Ubuntu 예:
sudo apt-get update && sudo apt-get install -y nmap
- Ubuntu 예:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt환경변수(예시):
export DATABASE_URL="postgresql+psycopg2://myscanner:myscanner@localhost:5432/myscanner"
export LOG_DIR="/var/MyScanner/log"
export ALLOWED_TARGETS="192.168.0.0/16,10.0.0.0/8"
export DEFAULT_TCP_ARGS="-sT -sV -Pn -T3 -vv"
export TZ="Asia/Seoul"로그 디렉터리:
sudo mkdir -p /var/MyScanner/log
sudo chown -R $(whoami):$(whoami) /var/MyScanner/log서버 실행:
uvicorn app.main:app --host 0.0.0.0 --port 8000저장소의
docker-compose.yml은 환경에 따라 수정이 필요할 수 있습니다(경로/볼륨/로그 디렉터리). 아래는 가장 일반적인 예시입니다.
- Postgres는
pgdata볼륨 사용 - 앱은
LOG_DIR을 컨테이너/호스트에 마운트
services:
db:
image: postgres:16
environment:
POSTGRES_DB: myscanner
POSTGRES_USER: myscanner
POSTGRES_PASSWORD: myscanner
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myscanner -d myscanner"]
interval: 3s
timeout: 3s
retries: 30
web:
build: .
environment:
DATABASE_URL: postgresql+psycopg2://myscanner:myscanner@db:5432/myscanner
SESSION_SECRET: "change-me-in-prod"
LOG_DIR: "/var/MyScanner/log"
ALLOWED_TARGETS: "192.168.0.0/16,10.0.0.0/8"
DEFAULT_NMAP_ARGS: "-sT -sV -Pn -T3 -vv"
TZ: "Asia/Seoul"
volumes:
- /var/MyScanner/log:/var/MyScanner/log
depends_on:
db:
condition: service_healthy
ports:
- "8000:8000"
volumes:
pgdata:
운영 환경에서는 Nginx(또는 Caddy) 뒤에 두고 HTTPS를 권장합니다.
Ingest 성공 후 xml/log를 자동 삭제하도록 되어 있어 디스크 누수를 방지합니다. 감사/분석 목적으로 보관이 필요하면 해당 정책을 변경하거나, 별도 아카이빙(압축/보관 디렉터리 이동)을 권장합니다.
- PostgreSQL:
pg_dump또는 볼륨 스냅샷 - 로그/아티팩트: 필요 시만 백업(운영 정책에 따라)
(사용자가 추가) MIT © 2025 AndrewAhn