LINUX용 ROAMSWITCH · 작동 참조
CLI/헤드리스 운영 가이드
GUI 없이 Linux용 RoamSwitch를 작동하는 방법 — 클라우드 VPS 인스턴스, SSH, cron, 모니터링 스크립트 및 프로그래밍 방식 AI 에이전트(MCP)에서.
- 클라이언트 에디션(
roamswitch): 노트북, 모바일 워크스테이션 및 개발자 장치용으로 설계되었습니다. 연결된 네트워크의 신뢰 수준에 따라 nftables 방화벽 프로필을 자동으로 전환합니다. 이 가이드는 주로 Client Edition의 헤드리스/CLI 관리에 중점을 둡니다. - Server Edition(
roamswitch-server): 클라우드 VPS 인스턴스(AWS, GCP, DigitalOcean, Linode 등) 및 인터넷에 직접 노출되는 온프레미스 서버용으로 설계되었습니다. 인바운드 기본 삭제 필터링, SSH 잠금 방지, 중요 경로 파일 무결성 모니터링(FIM), eBPF/Falco 런타임 통합 및 즉시 알림(Telegram/LINE/Webhooks) 기능을 제공합니다. 전체 설치 및 관리 지침은 RoamSwitch Server Edition Operations Manual 및 Server Security Whitepaper. 을 참조하세요.
1. 구성품
| 구성 요소 | 다음으로 실행 | 역할 |
|---|---|---|
roamswitch-daemon (클라이언트) |
루트(시스템 Type=notify) |
모든 클라이언트 권한 작업: nftables 제어, 네트워크 탐지, 랜섬웨어/맬웨어 모니터링, fanotify, ARP/NDP 고정, DNS 시행. TCP/UDP 청취 소켓을 열지 않습니다. |
roamswitch-server-daemon (서버) |
루트(시스템 Type=notify) |
서버 특권 처리 전부. 인바운드 기본 전체 폐기, SSH/관리 IP 예외 보호, FIM(150개 이상의 중요 파일과 디렉터리 집합의 변조 감지), Falco eBPF UNIX 소켓 수신·프로세스 동결(SIGSTOP), 실행(exec) 레코더, 이벤트 전달(옵트인), 알림 전송 |
roamswitch(CLI) |
로그인 사용자(일부 작업에는 sudo가 필요함) | 씬 클라이언트가 데몬 상태를 읽고 있습니다. Client Edition에서 /run/roamswitch/roamswitch.sock IPC를 사용하거나 Server Edition에서 --server, server, fim 및 emergency-restore 하위 명령을 제공합니다. |
roamswitch-mcp |
AI 클라이언트에 의해 생성됨 | AI 에이전트의 프로그래밍 방식 상태 검색을 위한 읽기 전용 MCP 서버(stdio/JSON-RPC)입니다. MCP 설정을 참조하세요. |
roamswitch-ransomware-rollback |
root(watch는 systemd의 roamswitch-ransomware-rollback-watch.service) |
랜섬웨어 복구 도구. btrfs 서브볼륨과 LVM 논리 볼륨의 스냅샷을 만들고 필요한 파일만 꺼냅니다. 클라이언트 패키지에 포함되며 GUI의 '침해 대응' 탭에서도 사용할 수 있습니다 |
roamswitch-app |
로그인 사용자 | GTK GUI(클라이언트 에디션에만 해당). 헤드리스 환경에서는 필요하지 않습니다. |
A 헤드리스 배포는 데몬 + roamswitch CLI(원하는 경우 roamswitch-mcp 추가)에서 실행됩니다. 모든 자율 방어 메커니즘은 GUI 없이 작동합니다.
roamswitch)과 Server Edition(roamswitch-server)은 상호 배타적인 패키지(Conflicts)입니다. 서버 환경에 roamswitch-server을 배포합니다.2. 데몬(시스템 서비스)
클라이언트 에디션
sudo systemctl status roamswitch.service # 가동 상태
sudo systemctl enable roamswitch.service # 부팅 시 자동 시작(설치 시 활성화)
sudo systemctl restart roamswitch.service # 재시작
journalctl -u roamswitch.service -f # 로그 추적
journalctl -u roamswitch.service --since "1h ago"
클라이언트 데몬이 시작 시 및 매 주기(3초)마다 자율적으로 수행하는 작업은 다음과 같습니다.
- 연결된 게이트웨이 MAC을 식별하고
trusted_networks에 대해 nftables 프로필(open/balanced/lockdown)을 적용합니다. - 행동 기반 랜섬웨어 탐지(fanotify + Shannon 엔트로피 + 카나리아)
- 온액세스 악성 코드 검사(fanotify, 선택적으로 ClamAV)
- ARP 스푸핑 모니터링 및 신뢰할 수 없는 네트워크에 대한 예방 게이트웨이 ARP/NDP 고정
- 프로필당 커널 강화(sysctl / Yama / 코어 덤프 /
/tmpnoexec) - 위협 방지 DNS 적용(
dns_enabled+dns_scope) - 피싱 차단을 위한 링크 가드(NFQUEUE)
/run/roamswitch/state.json에 대한 런타임 상태 출력
서버 에디션
sudo systemctl status roamswitch-server.service # 가동 상태
sudo systemctl restart roamswitch-server.service # 재시작
journalctl -u roamswitch-server.service -f # 로그 추적
3. CLI 명령 참조
기본 구문: roamswitch <command> [options]. 인수 없이 실행하면 기본값은 status입니다. 출력 언어는 자동으로 OS 로케일(LC_ALL / LC_MESSAGES / LANG)을 따릅니다.
| 명령 | 권한 | 설명 |
|---|---|---|
status [--server](별칭 report / server-status) |
사용자 | 보안 건전성 진단(보통 27개 항목, --server 지정 시 서버판 34개 항목), 점수(0–100), 등급, 개선 조언. --json으로 동일한 내용을 기계 판독 가능한 JSON으로 표준 출력에 출력 |
server [status|config|setup|tui|test-notify|restart|ack|ebpf|bans|unban|allowlist] |
사용자/루트 | Server Edition 관리. config는 설정의 표시·변경, setup은 대화형 마법사, tui는 모든 기능의 TUI(roamswitch-server-tui. root로 모든 작업, 일반 사용자는 읽기 전용), test-notify는 알림 테스트, restart는 서비스 재시작(설정 리로드는 지원하지 않습니다). ack는 현재의 긴급 격리를 확인 응답합니다(FULL 격리 중에는 엄격한 격리를 유지하고, 축소 모드 중에는 해제. §3의 격리 정책 참조). ebpf(별칭 incidents)는 eBPF 런타임 가드의 현재 격리 상태와 탐지된 인시던트 이력을 표시. allowlist [list|add <rule> <process> [--exe <절대 경로>]|remove]는 오탐의 영구 허용 목록을 관리하며, --exe로 실행 파일에 묶으면 프로세스 이름 위장으로는 회피할 수 없습니다. bans [--json]는 SSH 무차별 대입 가드의 상태와 차단 중인 접속 출처(목록은 root만 읽을 수 있음)를, unban <IP|IPv6 /64|--all>는 차단 해제(root)를 수행합니다 |
fim [verify|update] |
사용자/루트 | 중요 경로 파일 무결성 모니터링 확인(verify) 및 기준 해시 데이터베이스 업데이트(update) |
bans [--json] |
사용자/루트 | SSH 무차별 대입 가드의 상태(차단/탐지만/정지 중과 그 이유), 지금 차단 중인 접속 출처와 남은 시간, 최근 기록을 표시합니다. 차단 목록은 root만 읽을 수 있으므로 sudo를 붙입니다. --json 지원. 서버 버전의 server bans와 같습니다 |
unban <IP | IPv6 /64 | --all> |
뿌리 | SSH 무차별 대입 가드의 차단을 해제하고 그 접속 출처의 실패 횟수도 지웁니다. --all로 모두 해제합니다. 서버 버전의 server unban과 같습니다 |
emergency-restore |
뿌리 | 모든 긴급 eBPF/방화벽 격리를 해제하고 네트워크 기준을 복원합니다. |
ports [-a|--all] |
사용자 | 0.0.0.0, 인증되지 않은 DB 및 개발 서버의 수신 포트입니다. -a에는 루프백 전용 포트가 포함됩니다. |
guards |
사용자 | 자동 방어 가드 상태(포트 이상, ARP, USB 저장소, 다운로드, DNS 위협, 카나리아, 개발 서버 격리기, Bluetooth) |
wifi |
사용자 | Wi-Fi 암호화 강도(개방형/WEP/WPA/유선) 및 SSID |
sharing [status|on|off] |
사용자 | 신뢰할 수 없는 네트워크에서 SSH/Samba/RDP 자동 중지/복원(신뢰할 수 없는 경우 on은 활성 SSH 연결을 끊음) |
audit-url <URL> |
사용자 | 로컬 피드 + 휴리스틱을 통해 URL 피싱 및 위협 위험 검사(대상을 가져오지 않음) |
audit-secrets <text|path|directory> |
사용자 | 텍스트・파일・디렉터리(재귀적, .git/node_modules 등 제외)에서 API 키, 개인 키 및 토큰을 감지합니다(데이터를 전송하지 않음). |
audit-logs [hours] |
사용자 | 지난 N시간 동안의 시스템 저널/인증 로그를 집계하고 분류합니다(기본값 24). API 키나 토큰은 자동으로 마스킹됩니다. 로그 패턴 이상 탐지 결과(신규 패턴 및 통계적 빈도 급증)도 표시합니다. |
canary |
사용자 | 랜섬웨어 카나리아 미끼 파일 상태 및 무결성, 감지된 인시던트 기록(최근 50건까지) |
port-anomaly(별칭 port-guard) |
일반 | 미확인 포트 노출 가드의 기준선 확보 상태, 현재 자동 차단된 포트, 감지된 인시던트 기록(최근 50건까지) |
quarantine [list] |
사용자 | 악성코드 격리 저장소의 내용(샘플, 원본 경로, 위협 이름, 날짜) |
knowledge [query](별칭 faq) |
사용자 | 오프라인 지식 베이스 검색 |
airgap [enable|disable] |
사용자/루트 | Air-Gap 긴급 차단의 발동 / 해제(클라이언트판 전용). enable은 모든 외부 통신을 drop(이미 확립되어 있던 연결도 끊음), disable로 복구. 자동 해제 구조는 아래의 「격리(Air-Gap) 정책」을 참조 |
help (--help / -h) |
사용자 | 도움말 표시(하위 명령 도움말의 경우 roamswitch <command> --help) |
scan-packages [폴더...] |
일반 | 설치된 OS 패키지(dpkg/pacman/dnf/zypper 자동 판별)를 알려진 CVE 맵과 대조합니다. 폴더 인자를 전달하면 해당 프로젝트의 종속성(npm/PyPI/crates.io 등 7개 에코시스템) 잠금 파일도 대상에 추가됩니다. Ubuntu(20.04·22.04·24.04·26.04)에서는 Ubuntu 전용 데이터로, Ubuntu가 수정 버전을 이미 공개한 CVSS 7.0 이상의 CVE만 대조합니다('해당 없음'은 알려진 CVE가 없다는 뜻이 아닙니다). Ubuntu 파생판과 지원하지 않는 버전은 '대상 외'로 표시하며 Debian 데이터로 바꾸지 않습니다. 네트워크 활동은 전혀 발생하지 않습니다 |
scan-vulns [--confirm] |
일반 | active_vuln_scan_enabled: true(기본 OFF)인 경우에만 127.0.0.1 한정으로 Redis/Memcached/MongoDB/dockerd의 무인증 도달 확인, 감지된 개발 서버에 대한 CORS 설정 오류·경로 탐색·오픈 리다이렉트·SSRF 진단, SMTP 오픈 릴레이 진단, Telnet/FTP/SSH 실증형 노출 진단을 실행합니다. --confirm 없이는 드라이런입니다 |
vuln-status |
일반 | scan-vulns --confirm이 기록한 각 프로브의 최근 결과와 경과 일수(pass_age)를 표시합니다. 판정은 취약함/안전/판정 불가의 3가지 상태이며, 경과 일수는 “오늘”, “N일 전”, “알 수 없음”(미실행) 중 하나로 표시됩니다. 스캔을 한 번도 실행하지 않은 경우 scan-vulns --confirm 실행을 안내하고 종료합니다(예약 실행 기능은 아직 없으므로 경과 일수는 실제로 수동 실행한 빈도에 따라 달라집니다). 동일한 데이터는 GUI(ports 탭)와 MCP 도구 get_vulnerability_scan_history에서도 확인할 수 있습니다 |
notifications(별칭 notification-history) |
사용자 | RoamSwitch가 전송한 알림(로그 감사 이상, ClickFix 탐지 등)의 이력(최근 1주일, 최신순). --json으로 JSON 배열, --export <파일>로 JSON Lines를 출력 |
frozen [list|resume <PID>|resume all] |
사용자/root | 각 가드(랜섬웨어 고속 암호화 탐지·카나리아 변조·커널 취약점 공격 탐지·eBPF 가드의 핀포인트 차단)가 SIGSTOP으로 동결 중인 프로세스를 목록으로 표시하고, 오탐이었을 경우 해제(SIGCONT). 동결은 강제 종료가 아니므로 해제하면 멈춘 지점부터 그대로 재개됩니다. resume all로 전체 해제. root 소유 프로세스의 해제에는 sudo가 필요 |
resource-guard (별칭 leak-guard) |
사용자 | 리소스 고갈·프로세스 이상 탐지 가드(Server Edition 전용)의 탐지 인시던트 이력. 네트워크 공개 서비스의 지속적인 RSS 증가(메모리 누수/DoS)나 크래시 루프를 신뢰도 등급과 함께 표시 |
timeline (별칭 incident-timeline) |
사용자 | 링크 가드(ARP 스푸핑)·랜섬웨어 카나리아·eBPF 런타임 가드·리소스 가드의 탐지를 하나의 시계열로 통합. 프로세스 계보와 MITRE ATT&CK 태그 포함(실험적). --json으로 전체를 JSON 배열로 표준 출력에, --export <파일>로 JSON Lines(1행 1건)를 파일에 기록 |
xdp-gate [status|enable|disable] |
사용자/root | XDP 부팅 시 게이트(실험적)의 상태 표시 및 활성화·비활성화. status는 roamswitch-xdp-gate.service의 활성 여부와 현재 프로그램 상태를 표시. 기본값은 비활성 |
sensor [key|list|pair|repin|unpair|request-audit|results] |
일반/root | 별도 리포지토리의 범용 기기에 설치하는 네트워크 센서 「RoamSwitch Sensor」와의 페어링 코드 방식 상호 신뢰. pair --addr <IP> --code <코드> --fingerprint <SHA-256>로 Sensor 측이 발급한 코드를 사용해 페어링(Sensor는 고정 IP로 운용되는 것을 전제. 핑거프린트는 Sensor 화면 / roamswitch-sensor pairing show에 표시되는 값이며, TLS 1.3으로 통신하는 인증서를 핀 고정합니다. 네트워크에서는 가져오지 않으며 평문으로의 폴백도 하지 않습니다), repin으로 Sensor가 인증서를 재생성한 후의 새 핑거프린트를 다시 입력, key로 자신 단말의 공개 키/주소를 표시, unpair로 페어링 해제, request-audit로 Sensor에 능동적 취약점 감사를 요청(결과는 results로 취득). sensor_pairing_enabled: true(기본값 OFF)가 필요합니다. 자세한 내용은 Sensor 운영 매뉴얼을 참조하십시오 |
port-scan (alias portscan) |
일반 | 착신 포트 스캔 탐지 가드의 탐지 이력(송신 IP, 자동 차단 여부·지속 시간)을 표시합니다. 신규 미지 포트 「노출」을 탐지하는 port-anomaly와는 별개의 기능입니다 |
lockfile-fim [verify|update] [--quiet|-q] |
뿌리 | 의존성 잠금 파일의 변조 감시 검증(verify)과 베이스라인 갱신(update). root 권한이 필요. 감시 대상은 프로젝트 폴더(서버판은 lockfile_watch_dirs) |
scan-scripts <FOLDER...> |
사용자 | 지정한 프로젝트 폴더 하위의 node_modules에서 package.json의 preinstall / install / postinstall / prepare 스크립트를 정적으로 열거(인벤토리이며 위협 판정이 아님. 네트워크 연결 없음) |
scan-typosquat <FOLDER...> |
사용자 | package.json의 의존성 이름을 유명한 npm 패키지 이름의 내장 목록과 편집 거리 1~2로 대조하여 타이포스쿼팅 의심을 제시(참고 정보. 네트워크 연결 없음) |
web-scan [FOLDER...] [--quarantine] [--json] |
사용자/루트 | PHP·JavaScript·JSP·ASP 웹 셸, 주입된 악성 코드, 이미지로 위장한 PHP, .htaccess 악용을 웹 애플리케이션 계층 탐지 규칙(내장, 서명된 일일 피드, /etc/roamswitch/rules.d의 사용자 규칙)으로 검사합니다. 폴더를 생략하면 웹 서버 설정의 문서 루트를 검사합니다. 기본은 확인만 하며 --quarantine(root)으로 격리합니다. 종료 코드: 0 = 탐지 없음, 2 = critical 또는 high 있음, 1 = 실행 불가 |
web-rules [status|list|validate <file.json>|locked|unlock-account <user>|example] |
사용자/루트 | 웹 애플리케이션 계층 규칙의 상태(버전, 배포된 버전, 사용자 규칙 위치, 격리 수준, 계정 조치, 탐지 후 훅) 표시(status), 불러온 규칙 목록(list), 사용자 규칙 파일 검증(validate), 계정 조치로 비활성화한 로그인 셸 확인(locked)과 복원(unlock-account, root), 설정과 훅의 예시(example) |
kernel-modules [--json] [--apply [MODULE...]] [--remove] |
사용자/루트 | Copy Fail·Dirty Frag·act_pedit의 경로가 된 커널 모듈(algif_aead·esp4·esp6·rxrpc·act_pedit)을 불러올 수 있는지 파일 읽기만으로 확인합니다(통신 없음). --apply(root)는 쓰지 않는 모듈에만 modprobe.d에 install … /bin/false를 쓰고, --remove로 되돌립니다. 진단 점수에는 들어가지 않습니다 |
audit-agent-setup [FOLDER...] [--json] |
사용자/루트 | AI 에이전트에게 읽히는 지시 파일·스킬(~/.claude, ~/.codex, ~/.cursor, ~/.gemini, ~/.agents, ~/.openclaw 및 패키지 CVE 대조에 등록한 프로젝트 폴더(와 지정한 FOLDER)의 CLAUDE.md, AGENTS.md 등)과 OpenClaw의 openclaw.json을 읽기 전용으로 점검합니다(통신하지 않음). 보이지 않는 Unicode 문자, 지시 덮어쓰기, 내려받아 그대로 실행, 비밀 파일 참조와 외부 전송, 스킬 안의 컴파일된 코드, OpenClaw 인증 꺼짐이나 짧은 토큰 등을 지적하며 HTML 주석 안의 내용은 더 높게 평가합니다. 파일 본문과 비밀 정보는 출력하지 않습니다. 일치는 "사람이 읽어 볼 곳"일 뿐 악의를 단정하는 것이 아닙니다. --json은 JSON 출력 |
bluetooth-audit [--json] |
사용자 | BlueZ 설정(/etc/bluetooth/input.conf, main.conf)에 페어링 전 기기의 키보드 연결을 허용하는 항목이 없는지 확인하고, 연결된 Bluetooth 키보드·마우스를 나열합니다(읽기 전용) |
audit-npm-signatures <DIR> [--confirm] |
사용자 | npm audit signatures로 설치된 패키지의 서명·provenance를 검증(RoamSwitch에서 npmjs.com과 통신하는 유일한 명령. --confirm 없이는 드라이런. 서버판은 npm_audit_signatures_enabled의 활성화도 필요) |
install [--pm npm|pnpm] [--yes] |
사용자 | npm / pnpm의 install을 래핑하여 라이프사이클 스크립트의 실행만 bwrap 샌드박스에 가둠(패키지 다운로드는 평소처럼 네트워크에 연결하여 수행) |
forward status|test|queue (alias event-forward) |
사용자/루트 | 이벤트 전달(syslog RFC 5424 / CEF, JSON Lines, HMAC 서명 구조화 웹훅)의 상태 확인(status)·연결 테스트(test)·재전송 큐 표시(queue). 옵트인이며 기본값 꺼짐, 설정한 대상에만 전송(서버판 운영 매뉴얼 §16) |
events search|tree|export|verify|status (alias exec-events) |
뿌리 | 로컬 실행(exec) 레코더의 로그를 검색(search: --since 2h --pid N --exe S --user U --parent P --text S --json)·프로세스 트리 표시(tree <pid>)·내보내기(export)·해시 체인 검증(verify. 변조 감지이며 방지가 아님)·상태 표시(status). 로그는 root 전용이므로 보통 sudo가 필요(서버판 운영 매뉴얼 §15) |
격리(Air-Gap) 정책
고정 타이머만으로 해제하면 기다리기만 하는 공격자에게 돌파당하므로, 격리의 트리거는 신뢰도로 분류됩니다(클라이언트판·서버판 공통).
- 저신뢰도(수동 Air-Gap, 범용 이상, eBPF의 Error / Warning 이하 등): 짧은 타이머 후에 전체 복구합니다(클라이언트:
airgap_low_confidence_secs, 기본값 600초. 서버:guard.yaml의safety_timer_secs, 기본값 300초.0으로 타이머 비활성). - 고신뢰도(카나리아 변조, 랜섬웨어성 대량 덮어쓰기, lockdown 중의 ARP 스푸핑, eBPF의 Critical / Emergency / Alert, 동일 규칙의 반복 등): 조용히 복구하지 않습니다. 타이머 이후에는 원인(동결한 PID·카나리아·ARP·규칙의 재발화)을 재확인하고, 원인이 사라진 것을 확인했을 때만 알림과 함께 해제합니다. 확인하지 못한 채 ack도 없이 상한(클라이언트:
airgap_hard_cap_secs, 서버:server.conf의isolation_hard_cap_secs. 기본값은 둘 다 3600초,0= 상한 없음)에 도달하면 축소(DEGRADED) 모드로 전환됩니다. - 축소 모드는 시간 경과만으로는 절대 자동으로 열리지 않습니다(클라이언트는 루프백만 허용, 서버는 유지보수 SSH와 화이트리스트 IP의 관리 경로만 허용). 해제는 원인 소멸의 재확인, 명시적인 확인 응답(서버:
roamswitch server ack), 또는 수동 해제(GUI의 해제 버튼 /roamswitch emergency-restore)뿐입니다. 클라이언트의 축소 모드에서는airgap_degraded_lift_rfkill을true로 하지 않는 한 Wi-Fi의 rfkill도 해제되지 않습니다. - 관리 경로 이외의 확립된 연결은 끊깁니다(서버: 유지보수 SSH 포트와 화이트리스트 IP 이외. 공격자가 이미 맺어 둔 C2나 리버스 셸도 차단). 수동 Air-Gap은 경고 없는 메뉴 / GUI /
roamswitch airgap enable이라면 저신뢰도이지만, ARP 스푸핑 경고의 「지금 바로 차단」에서 발동한 경우에는 그 경고의 신뢰도(높음)를 이어받으며, 게이트웨이의 MAC이 신뢰된 MAC과 연속으로 일치하는지를 네트워크 송신 없이 재확인합니다(arp_recheck_consecutive회·arp_recheck_min_secs초 이상). 각 전환은 인시던트 타임라인에 기록됩니다.
랜섬웨어 복구(스냅샷 및 파일 단위 복원)
다음 명령은 roamswitch-ransomware-rollback의 것입니다(roamswitch의 하위 명령이 아닙니다). 상태는 /var/lib/roamswitch에 저장됩니다.
| 명령 | 권한 | 설명 |
|---|---|---|
roamswitch-ransomware-rollback snapshot [--path PATH] [--label TEXT] |
root | 대상(기본값 $HOME)의 스냅샷을 지금 만듭니다. 대상은 btrfs 서브볼륨 또는 LVM 논리 볼륨 |
roamswitch-ransomware-rollback watch [--path PATH] [--periodic-interval-secs N] |
root | 상주 감시. 짧은 시간에 파일이 대량으로 덮어써지거나 다른 방어 기능이 기록한 Critical 이벤트가 발생하면 스냅샷을 자동으로 만듭니다. 사전 스냅샷도 정기적으로 만듭니다(기본 6시간마다, btrfs는 4세대, LVM은 2세대 보관. 탐지 시점 스냅샷 이후에는 정기 생성을 기본 7일간 멈춤) |
roamswitch-ransomware-rollback list [--path PATH] [--json] |
root | 이 도구가 만든 스냅샷 목록(종류, 실체 존재 여부, 권장 사전 스냅샷). --json으로 기계 판독용 출력 |
roamswitch-ransomware-rollback restore-files <ID> <PATH> [--dest DIR] |
root | 스냅샷에서 지정한 파일이나 디렉터리만 현재 상태를 덮어쓰지 않고 다른 위치로 꺼냅니다(기본값 <대상>/RoamSwitch-Recovered/<ID>/). 복구의 첫 번째 선택지 |
roamswitch-ransomware-rollback mount-for-browsing <ID> / unmount-browse <MOUNT_POINT> |
root | restore-files에 넘길 경로를 고르기 위해 스냅샷의 내용을 볼 수 있게 합니다(btrfs는 그대로, LVM은 읽기 전용 임시 마운트). 끝나면 unmount-browse로 해제합니다 |
roamswitch-ransomware-rollback config get|set --periodic-interval-secs N |
root | 사전 스냅샷 간격(초. 0이면 끄기, 그 외에는 300 이상). 실행 중인 watch에 재시작 없이 반영됩니다. 탐지 시점 스냅샷을 끄는 설정은 없습니다 |
roamswitch-ransomware-rollback restore <ID> [--yes] [--accept-tampered] |
root | 대상 전체를 스냅샷 상태로 되돌립니다(파괴적). 탐지 시점 스냅샷은 이미 암호화된 파일을 포함하므로 --accept-tampered가 없으면 거부됩니다. 먼저 restore-files를 시도하세요 |
예
sudo roamswitch status # 클라이언트 종합 진단(27개 항목)
sudo roamswitch status --server # 서버판 종합 진단(34개 항목)
sudo roamswitch ports -a # 전체 리스닝 포트
roamswitch guards # 가드 가동 상태
roamswitch audit-url https://examp1e-login.com
roamswitch audit-secrets ./deploy.env
roamswitch audit-secrets . # 현재 디렉터리 재귀 스캔
roamswitch audit-logs 72 # 최근 72시간 로그 분석
sudo roamswitch sharing on # 미신뢰 네트워크에서 SSH/Samba/RDP 자동 중지
sudo roamswitch fim verify # FIM 파일 무결성 검증
sudo roamswitch fim update # FIM 기준선 업데이트
sudo roamswitch emergency-restore # 긴급 차단 전체 해제 및 복구
sudo roamswitch airgap enable # 긴급 차단
sudo roamswitch airgap disable # 해제
sudo roamswitch server ack # 긴급 격리를 확인 응답(FULL 격리 중에는 엄격한 격리를 유지, 축소 모드 중에는 해제)
roamswitch canary # 카나리아 인시던트 기록
roamswitch vuln-status # 최근 스캔 결과와 경과 일수(pass_age)를 표시
roamswitch port-anomaly # 미확인 포트 노출 가드 인시던트 기록
roamswitch server ebpf # eBPF 가드의 격리 상태와 인시던트 기록
roamswitch server bans # SSH 무차별 대입 가드의 상태와 차단 중인 접속 출처 목록
sudo roamswitch server unban 203.0.113.9 # SSH 무차별 대입 가드의 차단 해제(root 필요)
roamswitch notifications # 최근 1주일간의 알림 기록
roamswitch frozen # 동결 중인 프로세스 목록
sudo roamswitch frozen resume 12345 # 오탐 프로세스를 해제
sudo roamswitch sensor pair --addr 192.168.1.50 --code AB3DFGH2 --fingerprint 3F:45:89:E1:...:36:10 # 페어링 코드로 Sensor와 페어링
sudo roamswitch sensor key # 자신의 공개 키/주소를 표시
roamswitch port-scan # 포트 스캔 탐지 이력
roamswitch timeline --json # all incident-timeline records as JSON
roamswitch notifications --export n.jsonl # JSON Lines
sudo roamswitch events search --since 2h --exe curl
sudo roamswitch forward status
sudo roamswitch server allowlist add "<rule>" mytool --exe /usr/local/bin/mytool
sudo roamswitch sensor repin <PUBLIC_KEY> --fingerprint <NEW_FINGERPRINT>
sudo roamswitch server tui
서버 에디션 데몬은 root 권한으로 실행되므로, nftables 규칙 세트를 읽거나 프로세스 소유자를 확인해야 하는 명령(status / status --server / ports -a)은 sudo 없이 실행하면 부정확한 결과(잘못된 '비활성' 판정이나 프로세스 정보 누락)를 반환합니다. 설정을 변경하는 명령(sharing / fim update / airgap / emergency-restore 등)도 마찬가지로 sudo가 필요합니다. 그 외의 읽기 전용 명령은 sudo 없이도 정확하게 동작합니다.
- 하위 명령별
--help(예:roamswitch ports --help)를 지원합니다. - 기계 판독 가능한 취득은
status --json,timeline/notifications의--json(JSON 배열)과--export <파일>(JSON Lines),events search --json, MCP(§6), 또는/run/roamswitch/state.json(§5)을 사용하십시오. - 클라이언트판에서 CLI로 프로파일을 직접 전환하는 명령은 없습니다(데몬이 자율 판정). 강제하고 싶다면
config.json의manual_override를 설정하거나 IPC의set_security_level을 직접 호출합니다(§5). status는 진단 결과와 관계없이 exit code 0을 반환합니다. 모니터링에 사용할 경우에는 출력의 점수 행을 파싱하십시오(예시는 §7).
4. 구성 파일
클라이언트 에디션(~/.config/roamswitch/config.json)
데몬은 루트로 실행되며 찾은 첫 번째 유효한 파일(또는 루트 전용 환경에서는 /root/.config/roamswitch/config.json)을 사용하여 /home/*/.config/roamswitch/config.json을 검색합니다.
| 열쇠 | 유형 / 기본값 | 설명 |
|---|---|---|
language | 문자열 / OS 로케일 | UI 및 CLI 언어(ja / en / ko / zh-Hans / zh-Hant / de / fr / es / it / pt-PT) |
trusted_networks | [{name, mac, level}] | 신뢰할 수 있는 네트워크 mac은 게이트웨이 MAC이고, level은 open / balanced / lockdown입니다. |
away_protection_level | 문자열 / lockdown | 알 수 없는 네트워크의 기본 프로필 |
manual_override | 문자열 / 널 | 강제 open / balanced / lockdown(자동의 경우 null) |
dns_enabled | 부울 / true | 위협 방지 DNS 시행 |
dns_provider | 문자열 / quad9 | quad9 / cloudflare / adguard / cleanBrowsing |
dns_scope | 문자열 / untrusted_only | untrusted_only / always_on |
arp_spoof_guard_enabled | 부울 / true | ARP 스푸핑 모니터링 |
gateway_arp_lock_enabled | 부울 / true | 신뢰할 수 없는 네트워크에 대한 예방적 게이트웨이 ARP/NDP 잠금 |
port_anomaly_guard_enabled | 부울 / true | 새로운 청취 포트 자동 차단 |
system_wide_fanotify_enabled | 부울 / true | 시스템 전반에 걸친 fanotify 악성 코드 가드 |
pre_exec_blocking_enabled | 부울 / true | 사전 실행 차단(FAN_DENY) |
mount_hardening_enabled | 부울 / true | /tmp 및 /dev/shm의 noexec(비공개 프로필에 적용됨) |
yama_memory_protect_enabled | 부울 / true | Yama ptrace 제한 사항 |
usb_storage_guard_enabled / usb_keyboard_guard_enabled | 부울 / false | USB 저장소/BadUSB 키보드 가드(기본적으로 꺼져 있음) |
usb_zero_trust_enabled | 부울 / false | USB 버스 authenticate_default=0 |
bluetooth_guard_enabled | bool / true | 신뢰할 수 없는 네트워크에서 Bluetooth의 「검색 가능」을 끔(기본값 ON. 전원은 끄지 않으며 연결된 기기는 그대로 유지) |
sharing_service_control_enabled | 부울 / true | SSH / Samba / RDP 자동 중지/복원 |
scan_exclusions | [string] | 검사에서 제외된 절대 경로 |
link_guard | 물체 | {enabled, mode: "off"|"warn"|"block", allowlist, blocklist_extra, use_threat_dns} |
vpn_on_untrusted_enabled | 부울 / false | 신뢰할 수 없는 네트워크에서 VPN 터널 자동 시작 |
vpn_backend | 문자열 / wireguard | wireguard / tailscale |
active_vuln_scan_enabled | bool / false | scan-vulns 실행을 허용합니다(기본 OFF). 127.0.0.1 한정 도달 확인 프로브를 전송하므로 명시적인 옵트인이 필요합니다 |
pkgcve_watched_folders | [string] | GUI판의 종속성 대조가 대상으로 하는 프로젝트 폴더 목록(절대 경로). CLI의 scan-packages는 이 설정을 참조하지 않고 명령줄 인자로 전달된 폴더만 대상으로 합니다 |
sensor_pairing_enabled | bool / false | RoamSwitch Sensor와의 페어링 코드 방식 상호 신뢰를 허가합니다(기본 OFF). sensor 명령 사용에 필수 |
port_scan_detect_enabled | bool / true | 착신 포트 스캔 탐지 가드 |
port_scan_detect_min_distinct_ports | int / 15 | 탐지 윈도우 내에서 이 수 이상의 서로 다른 포트에 접속한 송신자를 스캔으로 판정 |
port_scan_detect_window_secs | int / 300 | 스캔 판정 집계 윈도우(초) |
port_scan_block_enabled | bool / true | 탐지된 스캔 발신 IP의 자동 차단 |
port_scan_block_duration_secs | int / 600 | 자동 차단의 지속 시간(초) |
airgap_low_confidence_secs | int / 600 | 저신뢰도 Air-Gap이 자동으로 전체 복구되기까지의 초 수(0 = 자동 해제하지 않음). 고신뢰도 격리에는 적용되지 않음(§3 「격리(Air-Gap) 정책」) |
airgap_hard_cap_secs | int / 3600 | 고신뢰도 격리가 축소(DEGRADED) 모드로 전환되기까지의 초 수(0 = 상한 없음). 축소 모드는 시간 경과로는 열리지 않음 |
airgap_degraded_lift_rfkill | bool / false | 축소 모드에서 Wi-Fi의 rfkill도 해제할지 여부(기본값에서는 해제하지 않음) |
airgapAutoRfkill | bool / true | Air-Gap 중에 Wi-Fi 무선을 rfkill로 차단할지 여부(해제 시 원래대로 되돌림) |
arp_recheck_consecutive | int / 3 | ARP 스푸핑으로 인한 격리의 원인이 사라졌다고 간주하는 데 필요한 게이트웨이 MAC의 연속 일치 확인 횟수(1 이상) |
arp_recheck_min_secs | int / 60 | 위의 연속 일치가 지속되어야 하는 최소 초 수 |
arp_recheck_active_probe | bool / true | ARP 기반 격리에서 게이트웨이의 이웃 캐시 항목이 없을 때(링크가 살아 있는 경우), ARP 요청을 직접 1회 보내 게이트웨이 MAC을 확인할지 여부. 신뢰 MAC 이외의 MAC이 응답에 하나라도 있으면 불일치. 20초에 최대 1회 |
credential_access_watch_enabled | bool / true | 예상 밖의 프로세스가 자격 증명 파일(~/.ssh의 개인 키, ~/.aws/credentials, ~/.config/gcloud, 브라우저 자격 증명 저장소)을 열면 알림(알림 전용, 기본값 ON. 백업 도구와 인덱서는 처음부터 제외, 그 밖은 credential_access_watch_allow로 제외. 설정은 약 30초 안에 반영. cat이나 head 같은 아주 짧은 읽기로, RoamSwitch가 실행 파일을 특정하기 전에 프로그램이 종료된 경우에는 알림이 나오지 않을 수 있음) |
ssh_guard_* | — | SSH 무차별 대입 가드의 설정입니다. 10개 키와 기본값은 서버 버전(server.conf)과 같습니다. ssh_guard_enabled(true), ssh_guard_block_enabled(true), ssh_guard_max_failures(6), ssh_guard_window_secs(600), ssh_guard_ban_secs(3600), ssh_guard_ban_max_secs(604800), ssh_guard_allow(비어 있음. IP / CIDR 배열 또는 쉼표로 구분한 문자열), ssh_guard_log_source(auto), ssh_guard_yield_to_fail2ban(true), ssh_guard_trust_key_days(30). sshd가 동작 중일 때만 작동합니다. 범위를 벗어난 값은 기본값으로 돌아갑니다. 약 1분 안에 반영됩니다(재시작 불필요). 목록 확인과 해제는 roamswitch bans와 roamswitch unban입니다 |
fim_intrusion_context_enabled | bool / true | 파일 변조(FIM)와 락파일 변조 알림에, 쓴 프로세스의 계정·실행 파일과 그 프로세스가 속한 SSH 로그인(접속 출처·시각·인증 방식)을 덧붙입니다. 인증 정보 파일 알림에는 SSH 로그인에 속할 때만 덧붙입니다. 데몬을 재시작한 뒤 반영됩니다. 외부로는 아무것도 보내지 않습니다 |
forward_* | — | 이벤트 전달(syslog / JSON Lines / 서명 웹훅)의 설정. 옵트인이며 기본값 꺼짐. 키는 forward_enabled·forward_syslog_url·forward_syslog_format·forward_syslog_framing·forward_tls_ca_file·forward_file_path·forward_file_max_mb·forward_file_keep·forward_webhook_url·forward_webhook_secret·forward_webhook_secret_file·forward_min_severity·forward_queue_max_mb·forward_queue_max_age_hours(형식과 기본값은 서버판 운영 매뉴얼 §18) |
exec_recorder_* / exec_rule* | — | 로컬 실행(exec) 레코더와 알림 전용 상관관계 규칙 EXR-001~007의 설정. 기본값은 활성(메모리 1 GiB 미만의 호스트에서는 비활성. 명시적 설정이 우선). 키는 exec_recorder_enabled·exec_recorder_retention_mb·exec_recorder_retention_days·exec_recorder_hash_chain·exec_recorder_hash_exe·exec_recorder_cpu_budget_pct·exec_rules_enabled·exec_rules_disabled·exec_rule_service_users·exec_rule_window_secs·exec_rules_isolation_optin(기본값 false. true로 한 경우에만 심각도가 높은 규칙이 격리의 트리거가 됨) |
sharing_service_control_enabled: true을(를) 사용하면 신뢰할 수 없는 네트워크에 연결하면 활성 SSH 세션의 연결이 끊어집니다. 헤드리스 서버에서는 비활성화된 상태로 둡니다.서버 에디션(/etc/roamswitch/server.conf)
서버판은 INI 형식의 설정 파일을 사용하며, 퍼미션 0600(root 전용)으로 보호됩니다. 모든 키의 형식·가능한 값·기본값·재시작 필요 여부는 서버판 운영 매뉴얼 §18에 있습니다. roamswitch server config show|get|set로 변경할 수 있으며, roamswitch server tui의 설정 편집기(server.conf와 guard.yaml의 전체 146개 키)에서도 편집할 수 있습니다. 서버판은 설정 리로드를 지원하지 않으므로, 변경 후에는 sudo roamswitch server restart로 반영합니다.
공유 기기용: 관리자 전용 모드
여러 사람이 함께 쓰는 기기에서는 sudo touch /etc/roamswitch/admin-only로 '관리자 전용' 모드를 켤 수 있습니다. 방화벽, DNS, VPN, USB, 커널과 마운트 강화, 무선, Sensor 신뢰처럼 기기 전체에 영향을 주는 변경이 root 또는 sudo / wheel / roamswitch 그룹의 사용자로 제한됩니다. 자신의 파일이나 프로세스에 묶인 작업(격리, kill, freeze, 스캔)은 이전과 같습니다. /etc/roamswitch/admin-only는 root 소유이고 다른 사용자가 쓸 수 없을 때만 유효합니다(사용자가 직접 만들어 전환할 수 없습니다). 기본값은 꺼짐(파일 없음)입니다.
5. 로그 및 런타임 상태 파일
| 경로 | 대상 | 설명 |
|---|---|---|
journalctl -u roamswitch.service | 클라이언트 | 클라이언트 데몬 로그(프로필 스위치, 감지, 오류) |
journalctl -u roamswitch-server.service | 서버 | 서버 데몬 로그(FIM 이벤트, Falco 감지, 격리) |
/run/roamswitch/roamswitch.sock | 클라이언트 | 클라이언트 데몬 IPC Unix 도메인 소켓 |
/run/roamswitch/events.sock | 서버 | Falco / Tetragon eBPF 연동 소켓(root:root, mode 0600. Falco도 root로 동작하므로 추가 권한 설정은 필요 없음) |
/run/roamswitch/state.json | 클라이언트 | 주기 상태: {active_level, network_trusted, fanotify_ready} |
/run/roamswitch/alerts.json | 클라이언트 | 최근 경고 대기열 |
/run/roamswitch/approvals.json | 클라이언트 | 승인 대기 중인 대기열 |
/run/roamswitch/fanotify.ready | 클라이언트 | fanotify 가드가 실행 중임을 나타내는 플래그 파일 |
/var/lib/roamswitch/fim.db | 서버 | FIM SHA-256 기준 해시 데이터베이스 |
~/.local/share/roamswitch/quarantine/ | 둘 다 | 검역소(0700, 샘플 0400) + .metadata.json |
/var/lib/roamswitch/exec_log/ | 둘 다 | 실행(exec) 레코더의 해시 체인 포함 JSON Lines(root 전용, 0600). roamswitch events로 검색·검증 |
/run/roamswitch/airgap_isolation.json / host_isolation.json | 둘 다 | 격리(Air-Gap) 상태(FULL / 축소)와 트리거의 기록. 데몬을 재시작해도 격리가 계속 유지됨 |
IPC 직접 호출(고급)
데몬은 /run/roamswitch/roamswitch.sock에서 줄 바꿈으로 구분된 JSON을 허용합니다.
# 프로파일 강제 전환(클라이언트판)
printf '{"id":1,"method":"set_security_level","params":{"level":"lockdown"}}\n' \
| sudo socat - UNIX-CONNECT:/run/roamswitch/roamswitch.sock
# 게이트웨이 ARP 고정 즉시 재확인
printf '{"id":1,"method":"reconcile_gateway_lock","params":null}\n' \
| sudo socat - UNIX-CONNECT:/run/roamswitch/roamswitch.sock
6. 프로그래밍 상태(MCP)
roamswitch-mcp은 stdio(get_security_report / verify_security_findings / get_exposed_ports / get_guard_status / audit_url_safety / audit_secrets / audit_security_logs / audit_mcp_configs / audit_agent_setup / get_app_help / get_quarantine_status / get_file_scan_guard_status / verify_fim / get_port_anomaly_incidents / get_ebpf_incidents / get_resource_guard_incidents / get_port_scan_incidents / get_ssh_guard_incidents / get_canary_status / get_vulnerability_scan_history / get_notification_history / search_exec_events / get_process_tree / get_incident_timeline / get_fleet_status / get_vpn_status / get_link_guard_status / get_air_gap_status / get_sharing_services_status / get_bluetooth_guard_status / get_usb_guard_status / run_active_vuln_scan / run_package_cve_scan / run_package_cve_scan_languages / run_package_lifecycle_script_scan / run_typosquat_scan / run_npm_audit_signatures / get_sensor_audit_results)에서 JSON-RPC를 통해 읽기 전용 도구를 노출합니다.
외부 호스트에는 연결하지 않고 로컬로 데몬 소켓에 연결하거나 roamswitch-core를 직접 호출합니다. get_security_report와 verify_security_findings는 LAN에도 아무것도 보내지 않습니다(게이트웨이 확인은 ARP 캐시 등을 참조할 뿐입니다). MCP 설정 가이드를 참조하세요.
7. 자동화 레시피
일일 크론 상태 확인 → 점수가 임계값 미만으로 떨어지면 이메일을 보냅니다.
#!/usr/bin/env bash
# /etc/cron.daily/roamswitch-health
out=$(runuser -u "$SUDO_USER" -- roamswitch status 2>&1)
score=$(printf '%s\n' "$out" | grep -oE '[0-9]+/100' | head -1 | cut -d/ -f1)
if [ -n "$score" ] && [ "$score" -lt 80 ]; then
printf '%s\n' "$out" | mail -s "RoamSwitch health: ${score}/100" root
fi
경고 대기열 모니터링(poll Alerts.json)
#!/usr/bin/env bash
last=0
while :; do
ts=$(jq -r 'max_by(.timestamp).timestamp // 0' /run/roamswitch/alerts.json 2>/dev/null || echo 0)
if [ "$ts" -gt "$last" ]; then
jq -c ".[] | select(.timestamp > $last)" /run/roamswitch/alerts.json | logger -t roamswitch-alert
last=$ts
fi
sleep 10
done
fanotify 가드 상태 확인(state.json)
jq -e '.fanotify_ready == true' /run/roamswitch/state.json >/dev/null \
|| echo "WARNING: fanotify guard is not running" >&2
8. 문제 해결
| 증상 | 해상도 |
|---|---|
roamswitch은 "roamswitch-mcp가 설치되어 있는지 확인"하고 종료됩니다. |
데몬이 실행되고 있지 않습니다 → sudo systemctl start roamswitch.service(또는 roamswitch-server.service). 소켓이 있는지 확인 |
roamswitch status은(는) fanotify 🔴를 보여줍니다. "가드가 멈췄어요" |
일시적인 fs.fanotify.max_user_groups 피로. sudo systemctl restart roamswitch.service으로 다시 시작하고 저널에서 확인 |
프로필은 balanced에 유지되며 open에 도달하지 않습니다. |
게이트웨이 MAC가 level: open을(를) 사용하여 trusted_networks에 등록되어 있는지 확인하세요. |
| SSH 연결이 예기치 않게 끊어졌습니다. | 클라이언트 버전에는 신뢰할 수 없는 네트워크에 sharing_service_control_enabled: true이 있습니다. roamswitch sharing off을 통해 비활성화 |
| 구성 변경 사항이 적용되지 않습니다. | The client daemon reads the first of /home/*/.config/…; apply with systemctl restart roamswitch.service. For the server edition, edit /etc/roamswitch/server.conf then run sudo roamswitch server restart (no reload). |
| 서버 통신이 실수로 차단됨 | 클라우드 콘솔(VNC/직렬)에 액세스하고 sudo roamswitch emergency-restore을 실행합니다. |