AccessScope 사용 설명서
서버의 액세스 로그에서 공격 시도를 찾아 근거가 된 로그 행과 함께 보여 주는 진단 도구의 사용법입니다. 화면에서 진단하는 순서를 먼저 설명하고, 명령어로 사용하는 방법은 8장에 모았습니다.
1. AccessScope 소개
AccessScope는 웹 서버나 SSH 서버가 이미 남기고 있는 로그를 읽어서 공격 시도를 찾는 진단 도구입니다. 찾아낸 항목에는 근거가 된 로그 행을 함께 보여 줍니다. 직접 서버를 운영하면서 로그에 수상한 접근이 남아 있지 않은지 확인하고 싶은 분에게 알맞습니다.
로그는 읽기만 합니다. 로그를 변경하거나 삭제하지 않고, 통신을 차단하지도, 권한을 올리지도 않습니다. 진단 자체에는 LLM도 네트워크도 사용하지 않습니다.
| 환경 | 사용할 수 있는 것 |
|---|---|
| Mac(macOS 12 이상) | 화면 앱과 명령어 |
| Linux 클라이언트판 | 화면 앱과 명령어 |
| Linux Server Edition 패키지 | 명령어만 |
Mac은 RoamSwitch의 DMG에, Linux는 RoamSwitch의 deb / rpm / tarball에 들어 있습니다. RoamSwitch와는 별개의 도구이며 라이선스는 Apache License 2.0입니다. 실행할 때는 Mac에서는 앱 아이콘을, Linux에서는 앱 목록의 'AccessScope'를 선택합니다.
저장되는 파일
AccessScope가 자동으로 저장하는 것은 설정, 찾아낸 로그 목록, 제외 규칙, 이전 진단과의 비교 기록입니다. 모두 ~/.config/accessscope/ 아래에 본인만 읽고 쓸 수 있는 권한으로 놓입니다.
업데이트
Mac에서는 설정의 '업데이트'에서 '업데이트 확인'을 눌렀을 때만 lafine.net에 접속합니다. 이 컴퓨터나 로그의 정보는 보내지 않으며, 내려받은 파일은 서명을 확인한 뒤에 설치합니다. Linux에는 앱 안의 업데이트가 없으므로 패키지 업데이트로 갱신합니다.
2. 처음 하는 진단
- 로그를 고릅니다. 가장 간단한 방법은 '이 컴퓨터의 로그 찾기'입니다. nginx, Apache, SSH 등의 로그를 자동으로 찾아서 '이 컴퓨터에서 찾은 로그'에 나열합니다. 위치를 알고 있을 때는 '파일 선택'이나 '폴더 선택'으로 고르거나, 창 위에 파일이나 폴더를 끌어다 놓습니다.
- '기간'을 고릅니다. 기본값은 '최근 7일'이며, '최근 24시간', '최근 30일', '전체'로 바꿀 수 있습니다. 기간은 지금부터 거슬러 세므로, 오래된 로그를 진단하고 싶을 때는 '전체'를 고릅니다.
- '진단 실행'을 누릅니다. '로그를 읽는 중', '분석하는 중'으로 진행 상황이 표시되고, 끝나면 결과가 열립니다.
3. 읽을 수 있는 로그와 찾는 위치
로그의 종류는 내용을 보고 자동으로 판별합니다. gzip으로 압축된 순환(rotate) 로그도 그대로 읽을 수 있습니다. 폴더를 고르면 그 안에 있는 로그처럼 보이는 파일을 한꺼번에 읽습니다.
| 종류 | 읽을 수 있는 것 |
|---|---|
| 웹 서버 | Apache, nginx, Caddy, Traefik, HAProxy, AWS ALB와 CloudFront(로그를 내려받아 '파일 선택'으로 고릅니다) |
| SSH와 인증 | sshd, sudo, su, PAM. Linux는 auth.log와 secure 외에 journald도, Mac은 macOS 통합 로그도 읽을 수 있습니다 |
| 그 밖의 것 | fail2ban, 메일(Postfix, Dovecot), 데이터베이스(MySQL, MariaDB, PostgreSQL), Docker 컨테이너의 로그 |
'이 컴퓨터의 로그 찾기'는 표준 위치와 웹 서버 설정 파일이 가리키는 로그 위치를 조사합니다. 목록에 나오는 것은 로그로 읽을 수 있다고 확인된 것뿐입니다.
Docker 컨테이너
'Docker 컨테이너도 확인'에 체크하면 이 컴퓨터의 Docker 로그도 대상으로 삼을 수 있습니다. 진단 전에 실행할 명령과 대상 컨테이너가 확인 화면에 표시되고, '동의하고 진단'을 눌렀을 때만 읽습니다. 읽기만 하며 권한은 올리지 않습니다.
LLM으로 로그 찾기(선택)
찾지 못했을 때는 'LLM으로도 찾기'로 LLM에게 위치를 찾게 할 수도 있습니다. 전달하는 것은 실행 중인 서버의 이름이나 /var/log 등에 있는 파일의 이름 같은 환경의 사실뿐이며, 파일의 내용은 전달하지 않습니다. 제안은 읽을 수 있는지 확인한 뒤에 체크가 해제된 상태로 나옵니다. 설정은 7장을 보세요.
4. 결과 보는 법
진단이 끝나면 4개의 탭에서 결과를 확인할 수 있습니다.
| 탭 | 볼 수 있는 것 |
|---|---|
| 대시보드 | 종합 위험도(없음, 낮음, 중간, 높음), 심각도별과 분류별 탐지 건수, 시간대별 추이, 요청이 많은 IP와 경로 |
| 탐지 | 찾아낸 탐지의 목록입니다. 심각도로 좁히거나 제목으로 검색할 수 있습니다 |
| 입력 로그 | 어느 로그를 몇 행 읽었는지. 읽지 못한 로그와 그 이유 |
| LLM으로 분석 | LLM에게 보고서 문장을 쓰게 합니다(7장) |
탐지 보는 법
탐지는 'SQL 인젝션 시도'처럼 이름으로 표시되고, 심각도(높음, 중간, 낮음)와 확신도가 붙습니다. 확신도는 로그만으로 어디까지 말할 수 있는지를 나타냅니다.
- 확정은 로그만으로 말할 수 있는 것입니다.
- 유력은 그 시도가 있었을 가능성이 높은 것입니다.
- 가설은 로그만으로는 확인할 수 없는 것입니다.
'근거 로그 행'을 열면 그 탐지의 바탕이 된 로그 행을 그대로 볼 수 있습니다. 평소에는 닫혀 있으니, 먼저 이름과 이유를 읽고 궁금한 것만 열어 보세요.
종합 위험도(0에서 100)는 심각도와 확신도로 가중치를 준 참고용 값입니다. 건수가 많다는 것만으로는 커지지 않고, 심각도가 높음인 탐지가 하나도 없으면 '높음'이 되지 않습니다. 확률이 아니므로 참고 값으로 봐 주세요.
5. 확인할 건수 줄이기
제외 규칙
자사 사무실의 IP, 상태 감시, 자사 취약점 진단처럼 나올 것을 이미 알고 있는 탐지는 보고에서 뺄 수 있습니다. 뺀 탐지는 버리지 않고 이유와 함께 건수를 남깁니다.
- '탐지' 탭에서 탐지의 IP 옆에 있는 '이 IP 제외…'를 누릅니다.
- 이유를 입력하고 '제외 규칙에 추가'를 누릅니다. 이유는 보고에 남습니다.
- 확인 대화상자에서 내용을 확인하고 승인합니다. 다음 진단부터 적용됩니다.
설정의 '제외 규칙'에는 지금 유효한 규칙이 목록으로 표시됩니다. 표시 전용이며 여기서는 편집할 수 없습니다. 세부 조건이 있는 규칙은 설정 폴더에 두는 파일(suppress.toml)에 씁니다. 쓰는 법은 8장에 있습니다. 심각도가 '높음'인 탐지는 제외해도 빠지지 않고 보고에 남습니다.
이전 진단과의 비교
같은 로그 조합을 계속 진단하면 이전 기록과 비교해서 새로 나타난 탐지에 '신규' 표시가 붙습니다. '탐지' 탭의 '신규만'에 체크하면 신규만 좁혀서 볼 수 있습니다. 첫 진단에서는 모두 신규로 다룹니다. 기록에 들어가는 것은 탐지의 지문(해시), 종류, 심각도, 건수, 시각뿐이며 로그의 문자열은 들어가지 않습니다.
6. 결과 내보내기
결과 화면 위에 있는 버튼으로 결과를 밖으로 가져갈 수 있습니다.
| 버튼 | 할 수 있는 것 |
|---|---|
| 보고서 저장(Markdown) | 진단 보고서를 Markdown 파일로 저장합니다 |
| 요약 복사 | 요약을 클립보드에 복사합니다 |
| 내보내기… | 차단 목록(IP 목록)이나 탐지 목록을 내보냅니다 |
'내보내기…'에서는 차단 목록의 형식으로 fail2ban-ip, nftables, ipset, nginx-deny, apache-require, csv를 고를 수 있습니다. 탐지 목록은 CSV, SARIF, JSON으로 내보낼 수 있습니다.
차단 목록은 '포함할 조건'을 '기본', '엄격', '넓게' 중에서 고를 수 있고, 내보낼 IP의 수는 저장하기 전에 표시됩니다. 공식 크롤러의 IP와 제외 규칙의 대상인 IP는 항상 들어가지 않습니다.
7. LLM을 이용한 분석(선택)
진단 결과를 LLM에게 문장으로 정리하게 하는 기능입니다. 기본 상태에서는 꺼져 있습니다. 사용하려면 설정의 'LLM 연동'에서 'LLM 분석 사용'에 체크하고, '사용할 LLM'을 고른 뒤 '저장'을 누릅니다. 고를 수 있는 것은 claude, opencode, codex, agy 중에서 그 컴퓨터에 명령이 설치되어 있는 것입니다.
전송하는 내용
- 원본 로그는 보내지 않습니다. 보내는 것은 통계와 탐지의 사실, 탐지마다 최대 3행의 근거 로그 행(1행에 300자까지)입니다.
- 키, 토큰, 비밀번호 같은 비밀과 이메일 주소는 보내기 전에 가립니다.
- IP는
203[.]0[.]113[.]9처럼 무해화한 형태로 전달합니다. '실제 IP를 전달하지 않음(가명으로 바꿈)'에 체크하면ip-001같은 가명으로 바꿉니다.
'LLM으로 분석' 탭에서 '전송할 내용 확인'을 누르면 보낼 전문을 볼 수 있습니다. 이 동작으로는 아무것도 보내지 않습니다. 'LLM으로 분석'을 눌렀을 때 비로소 보냅니다.
- 로그의 내용은 공격자가 쓸 수 있습니다. AccessScope는 AI에 대한 지시처럼 보이는 문자열을 탐지로 보고하고, LLM의 출력은 신뢰할 수 없는 인용으로 표시합니다. LLM이 탐지를 실제보다 심각하게 읽는 일도 있으므로, 결론은 근거 로그 행으로 확인하세요.
- claude와 opencode는 AccessScope가 도구(명령 실행과 파일 읽기)를 막은 상태로 실행합니다. codex와 agy는 도구를 막을 수 없으므로 설정에 표시되는 확인에 체크해야 합니다. root에서도 LLM 분석을 사용할 수 있지만 LLM이 root 권한으로 동작하므로 권한 없는 사용자로 실행하기를 권합니다(root로 실행 중일 때 설정에 주의 문구가 표시됩니다).
8. 명령어로 사용하기
Server Edition처럼 명령어만 있는 환경이나 cron으로 정기적으로 돌리고 싶을 때는 accessscope 명령을 사용합니다. 화면과 같은 엔진이므로 찾아내는 탐지도 같습니다.
accessscope discover
accessscope scan --auto --since 7d --report report.md
accessscope scan /var/log/nginx/access.log /var/log/auth.log
| 옵션 | 동작 |
|---|---|
--auto | 표준 위치 등에서 로그를 찾아 진단합니다. --since 7d로 기간을 좁힐 수 있습니다 |
--report FILE | Markdown 보고서를 씁니다 |
--format json|csv|sarif | 표준 출력의 형식을 바꿉니다 |
--export-blocklist FORMAT[:FILE] | 차단 목록을 내보냅니다 |
--fail-on high|medium|low | 그 심각도 이상의 탐지가 있으면 종료 코드 3으로 끝납니다 |
--since-last、--new-only | 이전과 비교해서 신규 탐지만 표시합니다 |
--llm NAME、--show-prompt | LLM에게 분석하게 합니다. --show-prompt는 보낼 전문을 표시하고 끝납니다(아무것도 보내지 않습니다) |
cron으로 매일 돌리기
accessscope scan --auto --since 24h --since-last --new-only --fail-on medium
이전 실행에 없던 탐지만 표시하고, 신규 탐지가 중간 이상일 때만 종료 코드 3이 됩니다. --llm 없는 진단은 root에서도 동작합니다.
suppress.toml 쓰는 법
제외 규칙은 ~/.config/accessscope/suppress.toml에 씁니다. 이 파일이 있으면 자동으로 읽습니다.
[[rule]]
reason = "office"
ip = ["203.0.113.0/28"]
expires = 2027-03-31
[[rule]]
reason = "uptime monitor"
ua_prefix = ["Mozilla/5.0 (compatible; UptimeRobot"]
path_prefix = ["/healthz"]
- 규칙은 쓴 모든 항목에 일치한 요청에 적용됩니다.
reason은 필수이며 모든 보고에 표시됩니다.expires가 지난 규칙은 적용되지 않습니다. - 심각도가 '높음'인 탐지는 규칙에
allow_high = true가 없으면 제외되지 않습니다. - User-Agent와 경로는 클라이언트가 쓸 수 있는 값입니다. IP를 쓰지 않고 그것들만으로 지정한 규칙은 공격, 인증, 웹셸 등의 탐지를 제외할 수 없습니다.
9. 할 수 없는 것
- 볼 수 있는 것은 로그에 남은 사실뿐입니다. 요청의 본문, 응답의 내용, 애플리케이션의 내부 상태, 순환되어 사라진 기간은 알 수 없습니다. 탐지가 없다는 것이 안전하다는 증명은 아닙니다.
- 탐지는 '시도가 있었다'는 뜻이며, 성공했다는 증거가 아닙니다. User-Agent는 자기 신고이며 위장할 수 있습니다.
- 여러 로그에 걸친 연쇄는 주소가 같다는 사실만을 근거로 합니다. NAT나 프록시 뒤에서는 관계없는 사람이 같은 주소로 보입니다. 내부 주소(리버스 프록시나 Docker 게이트웨이)는 많은 클라이언트를 한데 모은 것이므로 연쇄에 넣지 않습니다. 성공한 징후가 없는 연쇄는 심각도가 낮음이 됩니다.
- '낯선 접속 위치에서의 로그인'은 그 로그에 낯설다는 뜻이며 부정이라고는 할 수 없습니다. '평소와의 차이'는 변화를 나타낼 뿐이며 공격이라고는 할 수 없습니다.
- AWS ALB와 CloudFront의 로그는 AWS 문서의 정의에 맞춰 만든 행으로 시험했으며, 실제 AWS의 출력으로는 시험하지 않았습니다.
10. 문제가 생겼을 때
'지금은 읽을 수 없는 로그'에 나온다
권한이 부족할 때의 표시입니다. AccessScope는 권한을 올려서 읽지 않습니다. 다음 중 하나로 대처하세요.
- 파일 로그는 권한이 있는 사용자로 실행하거나, 로그의 복사본을 '파일 선택'으로 고릅니다.
- Linux의 journald는 root, 또는 adm, systemd-journal, wheel 그룹의 사용자로 실행합니다.
- macOS 통합 로그는 admin 그룹의 사용자로 실행합니다.
'이 컴퓨터에서 진단할 수 있는 로그를 찾지 못했습니다'라고 나온다
이유가 문장으로 표시됩니다. 예를 들면 '웹 서버(Apache, nginx 등)의 로그가 없습니다'처럼 나옵니다. Mac에서는 SSH 기록이 없을 때 '원격 로그인(SSH)이 꺼져 있을 수 있습니다'라고 나옵니다. 표시되는 '파일 선택', 'LLM으로 찾기', '다른 위치 지정'으로 다음 방법을 시도할 수 있습니다. 어디를 조사했는지는 닫혀 있는 '자세한 탐색 결과'를 열면 알 수 있습니다.
'Docker 로그를 읽지 못했습니다'라고 나온다
Docker가 실행 중이 아니거나, Docker를 찾을 수 없거나, 권한이 없거나, Docker가 오류를 반환한 경우 중 하나입니다. 권한이 없을 때는 Docker를 사용할 수 있는 사용자로 AccessScope를 실행하세요. AccessScope는 권한을 올려서 다시 읽지 않으며, docker 그룹에 참여하라고 요구하거나 권하지도 않습니다. docker 그룹의 권한은 호스트의 root와 같기 때문입니다.
'로그로 읽을 수 없음'이라고 나온다
고른 파일에서 한 행도 해석하지 못했을 때의 표시입니다. 그 파일은 진단 대상이 되지 않으며 어디로도 전송되지 않습니다. 지원하는 로그 종류인지 확인한 뒤 다시 골라 주세요.
'LLM으로 분석'을 누를 수 없다
버튼 근처에 이유가 표시됩니다. 'LLM 연동이 꺼져 있습니다'라고 나오면 설정에서 활성화합니다. '사용할 LLM이 선택되어 있지 않습니다'라고 나오면 설정에서 고릅니다. root로 실행 중일 때나 사용할 LLM의 명령이 컴퓨터에 설치되어 있지 않을 때도 사용할 수 없습니다.
접속 출처가 프록시 IP뿐이다
리버스 프록시나 CDN 뒤에 있는 로그에서는 접속 출처가 프록시의 IP가 될 수 있습니다. 기본값인 '자동'에서는 기록된 접속 출처가 내부 주소(리버스 프록시나 Docker 게이트웨이 등)인 행에 한해서만 X-Forwarded-For로 클라이언트 IP를 정합니다. 외부에서 직접 온 행은 기록된 접속 출처 그대로입니다. 헤더 값은 위조할 수 있으므로 이 방법으로 정한 IP는 확인된 크롤러로 취급하지 않습니다. 끄고 싶을 때는 설정의 '분석'에서 '사용 안 함'을 고릅니다. 오른쪽부터 세어 신뢰할 수 있는 중계가 아닌 첫 주소를 쓰는 방법과 가장 왼쪽 주소를 쓰는 방법도 고를 수 있지만, 이 값은 클라이언트가 바꿀 수 있으므로 직접 관리하는 신뢰할 수 있는 중계 뒤에서만 사용하세요. 다음 진단부터 유효해집니다.