Lafine Systems Design · 기술 문서

RoamSwitch Server Edition 아키텍처/보안 백서

클라우드 및 온프레미스 Linux 인프라를 위한 헤드리스 자율 네트워크 보안 & 무결성 방어 제품군입니다. 홍보성 표현은 쓰지 않으며, 기재 내용은 공식 배포 패키지의 실제 동작과 §6의 셀프 체크로 확인할 수 있도록 했습니다.

버전 v1.11.1 대상 RoamSwitch Server Edition 1.11.1(DNS 터널링 탐지/허니토큰/포렌식 증거 보전/NIST CSF·CIS Controls 매핑/서명된 커널 CVE 맵 갱신) 요구 사항 systemd + nftables 발행 2026-10-08

§1개요 및 핵심 원칙

RoamSwitch Server Edition은 클라우드 공급자(AWS, GCP, Azure, 베어메탈 VPS) 및 온프레미스 데이터 센터 전반의 Linux 서버 인프라용으로 특별히 제작된 헤드리스 상주 자율 네트워크 보안 및 무결성 보호 제품군입니다.

이동성 및 Wi-Fi 경계 적응에 초점을 맞춘 클라이언트 워크스테이션 버전과 달리 Server Edition은 인바운드 기본 삭제, 중요 경로 파일 무결성 모니터링(FIM), 선점형 커널 LPE 및 권한 에스컬레이션 강화, eBPF 런타임 위협 원격 측정 등 5가지 타협할 수 없는 원칙을 기반으로 합니다. 분리 전 긴급 경고를 통한 자율적 공극 호스트 격리.

데몬 본체에서 외부 통신 라이브러리를 완전히 배제하는 Zero Telemetry 원칙을 코드 수준에서 관철하며(기본값에서 외부로 나가는 것은 끌 수도 있는, 서명된 데이터의 수신(커널 CVE 데이터, Web 규칙, 그리고 Ubuntu 서버에서는 OS 패키지 CVE 대조에 쓰는 Ubuntu 패키지 CVE 데이터. 매니페스트는 매일 확인, CVE 데이터 본체는 약 30일에 1회)뿐이며, 그 밖의 예외는 모두 운영자가 명시적으로 옵트인한 것입니다. §1 핵심 설계 원칙), 비밀 정보(봇 토큰과 설정)는 권한 0600으로 보호됩니다.

1.1 비교: 클라이언트 에디션과 서버 에디션

차원 클라이언트 에디션(데스크탑/모바일) 서버 에디션(헤드리스/인프라)
배포 노트북, 모바일 개발자 워크스테이션 클라우드 VM, 베어메탈 노드, 컨테이너 호스트
네트워크 동작 Wi-Fi SSID/Gateway MAC 기반의 동적 프로필 전환 정적 인바운드 기본 삭제. 명시적으로 허용된 포트만 노출됩니다.
사용자 인터페이스 GTK3 데스크탑 GUI + 트레이 표시기 완전 헤드리스. CUI 명령 + 대화형 설정 마법사 + 터미널 UI(roamswitch-server-tui)
사고 알림 데스크탑 알림(libnotify) Telegram Bot, LINE Messaging API 및 Webhooks(Slack/Discord)에 직접 푸시
1차 방어 공용 Wi-Fi ARP 스푸핑, BadUSB, 랜섬웨어 문서 암호화 외부 정찰 삭제, FIM 변조 감지, 컨테이너 이스케이프, 커널 LPE(CVE-2026-53362)

1.2 핵심 아키텍처 원칙

  • Zero Telemetry(제로 텔레메트리): 기본값에서는 사용자나 환경에 관한 정보를 외부로 일절 전송하지 않습니다. 데몬 본체에는 HTTP/TLS 외부 통신 라이브러리가 없으며, 운영자가 설정한 알림·전달 때만 시스템 표준의 curl(Telegram/LINE/Webhook. 토큰이나 URL 같은 비밀은 표준 입력의 설정으로 전달하며 명령줄 인수에는 싣지 않음)과 openssl(TLS syslog 전달)을 서브프로세스로 실행합니다. 기본값에서 켜져 있는 외부 통신은 패키지 매니저의 업데이트를 제외하면 다음 하나뿐입니다. (1) cve_kernel_map_updates_enabled(기본 true)가 켜져 있는 동안 roamswitch-updater가 서명된 데이터를 lafine.net에서 익명으로 받습니다. 받는 것은 컨테이너 격리 감사용 커널 CVE 데이터, 웹 애플리케이션 계층 탐지 규칙(Web 규칙), 그리고 Ubuntu 서버에서는 OS 패키지 CVE 대조에 쓰는 Ubuntu 패키지 CVE 데이터입니다. 서명된 매니페스트와 그 서명은 매일 확인하고(GET 2회), 커널 CVE 데이터 본체와 Ubuntu 패키지 CVE 데이터는 마지막 갱신에서 약 30일이 지났을 때만 받으며(Ubuntu 데이터가 아직 없는 서버는 다음 일일 확인에서 받음), Web 규칙은 매니페스트의 버전이 새로울 때만 받습니다. 쿼리 문자열과 쿠키가 없고 소프트웨어를 나타내는 헤더가 고정된 User-Agent: RoamSwitch-Updater뿐인 HTTPS GET만 하고, Ed25519 서명을 검증할 수 있는 데이터만 채택하며, 이 호스트의 정보는 일절 보내지 않습니다. roamswitch server config set cve_kernel_map_updates_enabled false, 설정 마법사 또는 서버 TUI로 끌 수 있고, 기존 server.conf에 false가 명시되어 있으면 그대로 존중됩니다. 꺼도 감사는 내장 기준선으로 동작하지만, Ubuntu 서버의 OS 패키지 CVE 대조는 Ubuntu 데이터가 들어올 때까지 'CVE 데이터 없음'으로 표시되고 결과를 돌려주지 않습니다. 이 밖의 예외는 모두 운영자가 명시적으로 옵트인한 것입니다. (2) 이벤트 전달(forward_enabled, 기본 false)은 운영자가 설정한 syslog / JSON Lines 파일 / 서명된 Webhook 목적지로만 보냅니다. (3) npm_audit_signatures_enabled(기본 false)를 켜고 운영자가 roamswitch audit-npm-signatures <DIR> --confirm을 실행했을 때만 npm 자체가 registry.npmjs.org에 문의합니다. (4) sensor_pairing_enabled(기본 false)를 켠 경우에만 운영자가 입력한 Sensor 주소로 접속합니다(Sensor는 별개 제품이며 Zero Telemetry의 대상이 아닙니다). (5) Fleet(Business 티어)은 단말 측 코드뿐이며, 등록하지 않은 단말은 아무것도 보내지 않고 이름 해석도 하지 않습니다. 관리 서비스는 미배포·미출시이며 원격 명령 경로는 설계상 없습니다. (6) 동봉된 별도 도구 accessscope(액세스 로그 보안 진단)의 LLM 연동은 기본적으로 꺼져 있습니다. 켠 경우(명령줄에서는 --llm을 지정한 경우)에 한하여, 운영자가 선택한 LLM의 명령을 통해 진단 요약·근거 로그 행·환경 정보(로그 찾기 기능)가 외부 서비스로 전송될 수 있습니다. 데몬(roamswitch-server)은 이 통신에 관여하지 않으며, AccessScope는 root로도 LLM 분석을 실행할 수 있으며(이 경우 LLM이 root 권한으로 동작하므로 권한 없는 사용자로 실행하기를 권합니다), Zero Telemetry의 대상이 아닙니다. 동봉된 별도 도구 personalsoc(로그와 방어 상태 확인)도 마찬가지로, --llm을 지정한 경우에 한해 운영자가 선택한 LLM 명령을 통해 진단 요약이 외부 서비스로 전송될 수 있습니다(Zero Telemetry의 대상이 아닙니다). pathscope 명령은 LLM을 호출하지 않습니다. (7) clamav_enabled(기본 false)를 켰을 때만 데몬이 freshclam을 실행하여 ClamAV 시그니처를 받습니다(시그니처 데이터베이스가 아직 없을 때의 최초 1회와, clamav_scan_dirs를 지정하고 있는 동안 clamav_freshclam_interval_secs(기본 7200초)마다).
  • 인바운드 기본 거부 (Inbound Default Drop)는 허용한 포트 이외(TCP)로의 새로운 인바운드 연결을 nftables로 폐기하며, RST조차 돌려보내지 않습니다. 포트 스캔에는 허용한 포트만 보입니다(루프백, 수립된 연결, ICMP와 ICMPv6는 통과시킵니다).
  • Fail-Closed & 자가 복구는 다음과 같습니다. 기본 거부와 격리 규칙은 커널에 남아 있으므로 데몬이 중지·재시작되어도 유지됩니다(Restart=always). Docker 공개 포트 보호는 60초마다, Egress 차단 목록과 포트 스캔 차단은 300초마다 다시 확인하여 사라진 규칙을 재설치합니다. 축소 운영(DEGRADED)의 격리 규칙은 15초마다 평가하여 확인하고, 사라졌으면 재설치합니다. 기본 거부 규칙 자체를 외부에서 지운 경우에는 자동으로 다시 적용하지 않으므로, 진단 "인바운드 기본 거부"(roamswitch server status)로 확인하십시오.
  • 권한 0600에 의한 보호: 설정 파일 /etc/roamswitch/server.conf는 생성·갱신 시 자동으로 권한 0600이 강제됩니다. 토큰이나 Webhook URL 같은 비밀은 curl에 전달할 때도 표준 입력의 설정으로 전달하며, 명령줄 인수(/proc/<pid>/cmdline을 통해 다른 사용자에게 보임)에는 싣지 않습니다.

§2위협 환경 및 적대적 모델

최신 인터넷 연결 서버는 끊임없는 자동화된 스캐닝, 컨테이너 침입 벡터, 제로데이 커널 권한 상승에 직면해 있습니다.

해결된 주요 위협 벡터
  1. 자동 정찰 및 DB 노출: 의도하지 않게 노출된 내부 데이터베이스 포트를 찾는 인터넷 전체 스캐너(MySQL 3306, Redis 6379, Postgres 5432).
  2. 중요한 경로 변조 및 백도어 삽입: 핵심 인증 바이너리(/bin/login, /usr/bin/sudo, /etc/pam.d/*, /etc/shadow)를 수정하여 지속성을 구축하는 침입자.
  3. 커널 권한 에스컬레이션(CVE-2026-53362 Frag Gap): 권한 없는 공격자가 사용자 네임스페이스(unshare -U -r)를 무기화하여 커널 메모리 손상을 유발하고 루트로 에스컬레이션합니다.
  4. 컨테이너 소켓 중단: 마운트된 /var/run/docker.sock 또는 --privileged 플래그가 있는 잘못 구성된 컨테이너가 호스트 OS에서 루트 작업을 실행합니다.
  5. 프로세스 메모리 스누핑: 공격자는 개인 키 또는 자격 증명을 추출하기 위해 프로세스 전반에 걸쳐 ptrace을 연결하거나 /proc/$pid/mem을 읽습니다.

§3시스템 아키텍처

RoamSwitch Server Edition은 최소한의 메모리와 제로 CPU 오버헤드를 위해 설계된 기본 Rust 바이너리로 작동합니다.

┌─────────────────────────────────────────────────────────────┐
│  사용자 & 관리자 공간                                       │
│                                                             │
│   roamswitch (CLI)             roamswitch-mcp (AI 에이전트) │
│   · server status (34항목 진단)  · 보안 감사 도구 모음      │
│   · server config / setup      · 표준 입출력 JSON-RPC       │
│   · fim verify / update                                     │
│        │                               │                    │
└───────┼───────────────────────────────────┼─────────────────┘
         │ (CUI 명령 & 설정 반영)         │ (stdio)
┌───────▼───────────────────────────────────▼─────────────────┐
│  시스템 기반 (systemd + root 권한)                          │
│                                                             │
│   roamswitch-server-daemon                                  │
│   ├── CriticalPathFim (SHA-256 백그라운드 순회)             │
│   ├── eBPF / Falco 연동 모듈                                │
│   ├── Notifier (Telegram / LINE / Webhook 즉시 발송)        │
│   └── Air-Gap Controller (nftables 긴급 차단 규칙 전개)     │
│                                                             │
│   설정 관리: /etc/roamswitch/server.conf (권한 0600)        │
│   무결성 DB: /var/lib/roamswitch/fim.db                     │
└─────────────────────────────────────────────────────────────┘

§4핵심 방어 메커니즘

4.1 경계 보안(인바운드 기본 삭제)

nftables의 inet roamswitch_server 테이블의 input 체인에 policy drop을 적용합니다. 관리자가 지정한 포트(ssh_ports, allowed_ports)로의 새로운 TCP 인바운드 연결만 허용하고, 허용되지 않은 포트로의 통신은 타임아웃(드롭)시킵니다. 루프백, 수립된 연결, ICMP와 ICMPv6는 허용합니다.

만일 Air-Gap(긴급 격리)이 발동하더라도 유지보수용 SSH 포트(ssh_ports)와 등록된 유지보수 출발지 IP(whitelist_ips)의 관리 경로(신규·수립된 연결)만은 규칙상 유지되어, 원격 복구 작업이 불가능해지는 사태를 막습니다(preserve_ssh_on_isolation, 기본 true). 그 밖의 수립된 연결(공격자가 이미 열어 둔 C2나 리버스 셸 등)은 default-drop으로 차단됩니다. 관리 IP 지정(whitelist_ips와 guard.yaml의 허용 대상)이 비어 있으면 격리 중에도 유지보수 SSH 포트가 모든 출발지의 신규 연결을 받으므로, 서버 시작 시 경고를 출력합니다. preserve_ssh_on_isolation=false로 설정하면 SSH도 함께 차단합니다. 1.10.4 이하의 서버 에디션에는 결함이 있었습니다. 격리 규칙이 SSH 응답을 차단하여 격리 중에는 운영자의 SSH가 통하지 않았습니다. 1.10.5에서 수정되었습니다.

4.2 중요 경로 파일 무결성 모니터링(FIM)

OS 부팅·인증·네트워크·시스템 관리와 관련된 가장 중요한 파일의 SHA-256 해시 무결성을 감시합니다. 대상은 고정된 23곳(/etc/shadow·/etc/passwd·/etc/sudoers·/etc/ssh/sshd_config·/bin/login·/usr/bin/sudo·/usr/sbin/sshd·/usr/lib/systemd/systemd 등), /etc/pam.d·/etc/sudoers.d·/etc/ssh/sshd_config.d·/etc/cron.d와 /etc/cron.{hourly,daily,weekly,monthly}·/etc/systemd/system·/etc/ld.so.conf.d·/etc/profile.d·/root/.ssh의 12개 디렉터리 바로 아래 파일(새 파일의 출현도 탐지. /root/.ssh의 known_hosts와 known_hosts.old는 SSH로 접속할 때마다 다시 쓰이므로 제외합니다), RoamSwitch 자체 바이너리, 로그인 가능한 각 사용자의 authorized_keys, 그리고 존재해서는 안 되는 /etc/ld.so.preload(출현을 탐지)입니다. 정상적인 패키지 업데이트 후에는 정상 기준선이 자동으로 갱신됩니다. Debian 계열에서는 /etc/apt/apt.conf.d/99roamswitch-fim 훅(apt upgrade 등)이, RHEL 계열과 openSUSE에서는 /var/lib/rpm을 감시하는 systemd.path 유닛(roamswitch-fim-update.path)이 roamswitch fim update를 실행합니다.

침입 경로의 특정(누가, 어느 SSH 로그인으로 변경했는가)

파일 변경을 알리는 알림(Critical Path FIM과 락파일 FIM)에, 변경한 프로세스(계정·실행 파일·명령)와 그 프로세스가 속한 SSH 로그인(접속 출처의 IP와 포트·로그인 시각·인증 방식·공개 키 지문)을 덧붙입니다(기본 활성. fim_intrusion_context_enabled). 이벤트를 읽은 그 자리에서 쓴 프로세스의 /proc/<pid>(실행 파일, 사용자, loginuid, sessionid, cgroup, 부모 체인)를 촬영합니다. tee나 sed처럼 순식간에 끝나는 프로세스 때문입니다. 이미 종료되어 얻지 못한 프로세스는 실행 레코더(활성일 때)의 기록으로 보충합니다. 로그인과의 연결은 SSH 가드의 세션 표를 먼저 쓰고, 없으면 logind와 journald의 Accepted 행에서 찾습니다. SSH 가드를 꺼 두어도 동작합니다. 외부로는 아무것도 보내지 않습니다.

신뢰하는 것은 커널이 보고하는 값뿐입니다. 실행 파일은 /proc/<pid>/exe(argv[0]가 아닙니다), 로그인은 loginuid(로그인 시 한 번만 설정되며 sudo와 su를 넘어 이어집니다)와 cgroup의 session-N.scope, 그리고 부모 체인입니다. comm, 명령줄, 환경 변수처럼 프로세스 스스로 바꿀 수 있는 값은 표시만 하고 판정에는 쓰지 않습니다. sshd를 자칭할 뿐인 프로세스는 SSH 로그인으로 보지 않습니다. 알림은 세 가지를 구분해서 씁니다. 찾음(접속 출처·시각·인증 방식·키), "SSH 로그인은 찾지 못했습니다"(조사한 결과 systemd 서비스, 컨테이너, 로컬 로그인 세션, 로그인 세션에 속하지 않는 프로세스 중 하나였을 때), "로그인 경로를 확인하지 못했습니다"(프로세스가 이미 없고 실행 레코더에도 없음, logind가 응답하지 않음, 정기 검사로 찾은 변경이라 프로세스를 알 수 없음 등). 확인하지 못한 것을 로그인이 아니라고 쓰지는 않습니다. 조회에 실패해도 알림은 반드시 나갑니다.

/etc/ssh/sshd_config: modified
  프로세스: root (로그인한 계정: admin) / /usr/bin/tee / 명령: tee /etc/ssh/sshd_config (pid 4121)
  SSH 로그인: admin 계정이 2026-10-17 03:12:08에 203.0.113.25:51544에서 연 세션입니다(인증: publickey, 키 SHA256:AbCdEf0123456789)

/etc/sudoers: modified
  로그인 경로를 확인하지 못했습니다(정기 검사에서 발견한 변경이라 변경한 프로세스는 알 수 없습니다)

install, sed -i, 같은 디렉터리에서의 cp와 mv처럼 새 파일을 같은 이름 아래에 두는 편집도 탐지합니다. 파일 단위 표시는 inode에 붙기 때문에, 예전에는 이런 편집에서 이벤트가 나오지 않았습니다. 이제는 감시 대상 파일이 있는 디렉터리에도 표시를 붙이고, 같은 디렉터리에서 다른 이름의 파일이 닫히면 몇 밀리초 뒤에 이름을 다시 조회합니다. 한계: 다른 디렉터리에서 쓴 파일을 mv로 가져오는 경우는 정기 스캔(fim_check_interval_secs)이 찾을 때까지 알 수 없습니다. 그때는 쓴 프로세스를 알 수 없으며 알림에도 그렇게 적힙니다.

실측은 운영자의 접속 출처를 별도의 네트워크 네임스페이스(netns)에 둔 Ubuntu 24.04 VM에서 했습니다. sudo tee, nohup으로 분리한 프로세스(로그아웃한 뒤에도 접속 출처 IP를 특정할 수 있고 "이 세션은 이미 종료되었습니다"가 붙습니다), sudo -i 연쇄, 매우 짧게 사는 cat 모두에서 IP·사용자·인증 방식이 알림에 나왔습니다. 로컬 로그인에서는 "SSH 로그인은 찾지 못했습니다"가 나옵니다. exec -a "sshd: …"로 이름을 위장한 프로세스는 SSH로 보지 않았습니다.

기록은 알림 외에도 인시던트 타임라인(종류 fim)과 /var/lib/roamswitch/fim_intrusions.json(root 전용, 최신 100건)에 남습니다. MCP의 verify_fim에는 추가 필드 recentIntrusionContext로 나옵니다(root로 실행했을 때만). 변조 여부의 판정은 달라지지 않습니다. 한계: 실행 레코더를 끈 상태에서 쓴 프로세스가 극단적으로 짧게 살면 실행 파일을 알 수 없어, 부모 프로세스의 실행 파일과 명령줄을 대신 표시합니다. 지속성 감시(persistence_watch)의 알림에는 프로세스 정보가 없으므로 침입 경로가 붙지 않습니다. 침입 경로가 보여 주는 것은 변경한 프로세스와 로그인까지입니다. 침입의 입구 자체(공격당한 취약점이나 키가 도난된 경위)는 알 수 없습니다. 끄려면 fim_intrusion_context_enabled=false로 합니다.

4.3 커널 및 컨테이너 강화

Frag Gap(CVE-2026-53362) 완화: sysctl을 통해 user.max_user_namespaces = 0을 적용하여 LPE 벡터를 무력화합니다. Yama LSM 보호은 kernel.yama.ptrace_scope = 2을 시행하여 무단 메모리 검사를 방지합니다. 컨테이너 워크로드는 docker.sock 노출에 대해 감사됩니다. 서버 에디션에서는 비특권 네임스페이스 금지가 기본적으로 켜져 있습니다(harden_userns_enabled). rootless Podman 등이 동작하지 않게 되므로, 사용한다면 false로 하세요.

Docker의 공개 포트(-p)는 호스트의 표준 방화벽을 우회하는 알려진 문제가 있으므로, protect_docker_ports=true(기본값)에서 DNAT 이전의 목적지 포트가 허용 포트(ssh_ports·allowed_ports)에 없는 외부 인터페이스발 트래픽을 차단합니다(응답 트래픽·루프백·컨테이너 간 통신은 대상 외). iptables/iptables-nft 백엔드에서는 DOCKER-USER 체인(IPv4, Docker IPv6가 켜져 있으면 ip6tables로도)에, Docker 29 이상 등의 네이티브 nftables 백엔드(DOCKER-USER가 없는 구성)에서는 전용 inet roamswitch_docker_guard 테이블(forward 훅, 우선순위 -10)에 설치하며, 후자는 하나의 룰셋으로 IPv4와 IPv6 모두를 대상으로 합니다. 데몬은 주기적으로 다시 확인하여 사라진 규칙을 다시 설치합니다. 또한 --privileged 컨테이너의 시작이나 /var/run/docker.sock 마운트를 docker events로 실시간 탐지하여 컨테이너 탈출 위험으로 즉시 알리는 상시 가드도 갖추고 있습니다(설정 불필요, 자동 차단은 하지 않는 알림 전용). 메일 중계나 공유 폴더처럼 다른 사람에게 건네는 파일을 다루는 호스트에서는 선택적으로 켤 수 있는 File Scan Guard(내장 YARA + 선택적 ClamAV)가 정기 스캔과 자동 격리를 제공합니다.

컨테이너 실행 가드(container_exec_guard_enabled, 기본 true). 실행 중인 Docker 컨테이너의 overlay2 루트에 fanotify FAN_OPEN_EXEC(알림 클래스)를 설정하고, 실행된 파일의 내용을 내장 YARA 규칙으로 검사하여 알립니다. docker events를 구독한 뒤 docker ps로 실행 중인 컨테이너를 열거하므로 데몬 시작 시 이미 실행 중인 컨테이너도 대상이 됩니다. 실행된 파일의 내용은 fanotify가 넘겨주는 파일 디스크립터에서 읽으므로, 실행 직후 자기 삭제되어도 검사할 수 있습니다. 알림 전용이며 실행을 멈추거나 거부하지 않습니다(Server Edition에는 허가 클래스 fanotify가 존재하지 않습니다). Docker 29는 docker events 메시지에서 더 이상 권장되지 않는 Status를 제거했기 때문에, 1.11.0까지는 구독이 곧바로 실패하고 가드는 구독을 사용하지 못한 채 5초마다 재연결을 반복했습니다. 1.11.1부터 오래된 Docker에서도 같은 값을 가지는 Action을 사용하는 형식으로 바꿨습니다. 구독이 계속 실패할 때는 재연결 간격을 5초에서 최대 5분까지 두 배로 늘리고, 같은 원인의 경고는 처음 한 번만 기록합니다.

4.4 eBPF 런타임 위협 원격 측정 및 팽창 방지 조정

최신 eBPF(CO-RE/BTF) 프로브를 활용하여 권한 상승 및 컨테이너 침입 시도를 밀리초 단위로 차단합니다. Falco의 표준 문제점(로그 팽창, 디스크 소모 및 CPU 오버헤드)을 제거하기 위해 RoamSwitch는 최적화된 프로필(/etc/falco/config.d/99-roamswitch-optimized.yaml)을 표준화합니다.

  • 심각도 필터링(priority: warning): 시끄러운 운영 원격 측정(정보/알림)을 95% 억제하여 엄격하게 조치 가능한 보안 사고를 표시합니다.
  • 커널 수준 사전 삭제(drop_failed_exit: true): 실패한 syscall 종료를 커널 프로브에서 직접 삭제하여 CPU 컨텍스트 전환을 50% 이상 줄입니다.
  • 메모리 공간 최적화(cpus_for_each_buffer: 2): 링 버퍼를 8MB에서 2MB로 압축하여 메모리 사용량을 30~50MB로 엄격하게 제한합니다.
  • 직접 UNIX 소켓 IPC: 디스크 I/O를 거치지 않고 메모리상의 소켓(/run/roamswitch/events.sock)으로 즉시 연계합니다.
  • 로그 자동 상한(/etc/logrotate.d/roamswitch-falco)은 maxsize 50M과 7세대의 압축 로테이션(매일 실행)으로 Falco 로그의 비대화를 억제합니다.

eBPF 격리의 정확도와 속도(Falco의 규칙에만 맡기지 않는다)

eBPF 격리의 정확도와 속도는 센서(Falco나 Tetragon)의 규칙에 좌우됩니다. 실제로 Falco 0.45.0의 표준 규칙(29건)에는 호스트의 리버스 셸을 탐지하는 것이 없습니다. 리버스 셸용 규칙은 컨테이너 전용이고, 일부는 RoamSwitch의 priority: warning 조건에 걸려 버려집니다. RoamSwitch는 규칙의 완성도를 전제로 삼지 않고 세 가지로 보완합니다. 격리에 걸린 시간을 재는 것, 경보 경로가 살아 있는지 주기적으로 확인하는 것, 리버스 셸을 스스로도 탐지하는 것입니다.

격리 지연의 측정: eBPF 인시던트마다 Falco가 탐지한 뒤 데몬이 경보를 읽기까지(detect_to_receive_ms), 읽은 뒤 대응이 끝나기까지(receive_to_action_ms. 격리 호출이 돌아온 뒤에 잽니다. 호스트 Air-Gap은 룰셋을 다 읽어 들일 때까지), 그 합계(detect_to_action_ms)를 기록합니다. 값은 ebpf_incidents.json과 MCP의 get_ebpf_incidents에 추가 필드로 나옵니다. 프로세스를 격리했을 때의 알림에는 "탐지부터 대응까지 N밀리초" 한 줄이 붙습니다. 실측(Ubuntu 24.04 VM, Falco 0.45.0, modern eBPF)은 탐지에서 수신까지 1~2밀리초, 수신에서 프로세스 격리와 SIGKILL까지 41~62밀리초(합계 42~64밀리초), 호스트 Air-Gap은 합계 109밀리초였습니다(목표 150밀리초 이내). 값은 이 VM의 것입니다. Tetragon은 수신 시에 시각을 붙이므로 detect_to_receive_ms가 없습니다.

하트비트(ebpf_heartbeat_interval_secs. 기본 600초, 0이면 비활성, 활성화할 때는 60~86400): 패키지에는 RoamSwitch 자체의 Falco 규칙 96-roamswitch-heartbeat.yaml이 들어 있습니다. 데몬은 주기적으로 root만 쓸 수 있는 일회용 경로(/run/roamswitch/heartbeat/ 아래의 난수)를 열고, 그 규칙의 경보가 Falco의 출력으로 돌아올 때까지의 시간을 잽니다. 한 번의 왕복으로 규칙이 로드되어 있고, Falco가 동작하며, 출력 경로가 살아 있음을 한꺼번에 확인할 수 있습니다. 돌아오지 않는 확인이 2회 연속될 때(첫 번째 1분 뒤에 재확인)만 "규칙이 로드되지 않았거나 출력이 도달하지 않습니다"라는 경고를 24시간에 한 번까지 알립니다. 하트비트 행은 격리·알림·허용 목록·인시던트 기록 어디에도 넘기지 않고 버립니다. 외부로는 아무것도 보내지 않습니다. 실측 왕복은 2~6밀리초였고, 규칙을 빼자 약 164초 뒤에 경고가 나왔으며, 되돌리자 약 75초 만에 정상으로 돌아왔습니다.

상태는 /var/lib/roamswitch/ebpf_heartbeat.json에 남고, MCP get_ebpf_incidents의 heartbeat와 진단 K-04(eBPF 런타임 에이전트. 진단 항목 수는 34 그대로입니다)가 읽습니다. Falco가 동작하고 있어도 하트비트가 돌아오지 않으면 K-04는 불합격입니다. 한계: 확인하는 것은 규칙 하나(open 계열 시스템 호출)의 왕복이라, 다른 규칙이 개별적으로 망가진 것까지는 알 수 없습니다. 확인 간격(기본 10분) 사이에 망가진 것은 다음 확인까지 알 수 없습니다. Tetragon에서는 수행하지 않습니다. Falco가 동작하지 않거나 규칙 파일이 없는 호스트에서는 아무것도 확인하지 않고 아무것도 경고하지 않습니다(정지는 기존 알림이 담당합니다). Falco는 확인할 때마다 경고를 한 줄 syslog에 씁니다(기본이면 하루 144줄).

리버스 셸 탐지(RoamSwitch 자체)

Falco의 규칙에 의존하지 않고, RoamSwitch가 직접 2초마다 /proc을 읽어 표준 입력과 표준 출력이 이 호스트에서 외부 주소로 맺은 하나의 TCP 연결에 이어진 셸·인터프리터(sh·bash·python·perl·ruby·php·node 등)를 찾습니다. bash -i >& /dev/tcp/…, python, perl, nc -e, socat exec:가 대상입니다. 2회 연속으로 보인 것만 프로세스당 한 번 보고합니다. 기본은 외부 공개 주소로 향하는 것만이며, 사설 주소(RFC 1918·CGNAT·링크 로컬)는 reverse_shell_watch_include_private=true일 때만 셉니다(ssh의 ProxyCommand, 컨테이너, 로컬 개발에 정상적인 것이 많기 때문입니다). 루프백은 보지 않습니다. 밖에서 받아들인 연결(inetd나 socat TCP-LISTEN이 accept한 것)도 대상이 아닙니다. 실측(Ubuntu 24.04 VM)에서는 bash의 /dev/tcp, python, perl, nc -e, socat exec:를 연결 후 약 2.4초에 탐지했습니다. ssh, ProxyCommand가 붙은 ssh, git over ssh, nc 클라이언트는 탐지하지 않습니다.

탐지는 RoamSwitch Reverse Shell이라는 Critical eBPF 이벤트로서 Falco 경보와 같은 경로(허용 목록, 알림 쿨다운, guard.yaml의 심각도별 동작, 인시던트 기록)에 들어갑니다. 기본에서는 프로세스를 격리하고 종료(kill)합니다. root가 소유한 리버스 셸은 프로세스 단위 격리에 실패하므로, 기존 Critical 방침대로 호스트 전체의 Air-Gap까지 진행됩니다. 정상 프로그램이 잘못 탐지될까 걱정될 때의 탈출구는 둘입니다. reverse_shell_watch_notify_only=true(Warning으로 알림만 하고 격리도 kill도 하지 않음. 기본 false)와 허용 목록 등록 sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <프로세스 이름>입니다. 설정 키는 reverse_shell_watch_enabled(기본 true), reverse_shell_watch_include_private(기본 false), reverse_shell_watch_notify_only(기본 false)의 세 가지입니다.

한계: 이름(프로세스 이름과 실행 파일 이름)으로 좁히기 때문에, 셸이나 인터프리터가 아닌 이름으로 표준 입출력을 소켓에 연결한 자작 바이너리는 찾지 못합니다. 루프백을 경유하는 연결(ssh -R의 되돌림 등)과 2초보다 짧은 연결은 보지 않습니다. 호스트의 프로세스 공간에서 보이지 않는 프로세스도 볼 수 없습니다. 이 탐지는 Server Edition에만 있는 기능으로, Mac과 Linux 클라이언트 버전에는 없습니다.

4.5 분할 전 경고를 통한 비상 공극 격리

중요한 변조 시 네트워크 인터페이스를 차단하기 직전에 데몬은 Telegram, LINE 및 Webhooks에 긴급 경고를 동기식으로 발송합니다. 경고는 서버 Hostname 및 기본 IP 주소를 자동으로 추가합니다.

긴급 경보 형식(JA/EN)
🚨 [RoamSwitch IMMINENT AIR-GAP] 【긴급 경고】 네트워크를 완전히 차단(Air-Gap)합니다 (cve_2026_53362_lpe)
🚨 중대한 보안 인시던트 탐지: cve_2026_53362_lpe
호스트: production-app-01 (IP: 192.168.1.10)
대상 프로세스: exploit_payload (PID: 4921)
긴급 대응: 피해 확산을 막기 위해 호스트의 네트워크를 전면 차단(Air-Gap)합니다 (SSH 관리 포트만 유지).
경고: 이 알림의 전송이 끝나는 즉시 모든 외부 인터넷 통신이 차단됩니다.
시각: 2026-09-06 18:00:00
⚠️ 네트워크 연결은 즉시 차단됩니다.

해제 조건은 트리거의 확신도에 따라 다릅니다. 낮은 확신도의 트리거(eBPF Error 등급 이하 등)는 짧은 타이머(guard.yaml의 server_safeguards.safety_timer_secs, 기본 300초)로 전면 복구됩니다. 높은 확신도의 트리거(eBPF Critical/Emergency/Alert, 동일 규칙 반복에 의한 호스트 격리로의 에스컬레이션, 카나리아 변조 등)는 조용히 복구되지 않습니다. 짧은 타이머 이후에는 원인(동결한 PID의 생존, 규칙의 재발화 등)을 다시 확인하여 원인 소멸이 확인된 경우에만 알림과 함께 해제합니다. 확인하지 못하고 ACK도 없이 상한(isolation_hard_cap_secs, 기본 3600초, 0 = 상한 없음)에 도달하면 DEGRADED로 전환됩니다. DEGRADED는 유지보수 SSH 포트와 유지보수 출발지 IP의 관리 경로(신규·수립된 연결)를 유지하고 신규 외부 발신은 유지보수 출발지 IP로만 허용하며, 시간이 지나도 절대 자동으로 열리지 않습니다. 해제는 원인 소멸의 재확인, roamswitch server ack(DEGRADED 중의 ACK는 해제를 의미), 또는 roamswitch emergency-restore뿐입니다. ACK한 격리(FULL)는 운영자가 인계한 것으로 보아, 타이머로 복구되지도, 원인 소멸이 확인되었을 때 자동 해제되지도, DEGRADED로 전환되지도 않고 emergency-restore로 해제될 때까지 유지됩니다. 모든 전환은 인시던트 타임라인에 기록되고 알림이 전송됩니다.

프로세스 실행 레코더 & 이벤트 전달

netlink 프로세스 커넥터로 exec를 기록하는 로컬 전용 레코더가 기본값으로 활성 상태로 동작합니다(클라이언트판과 공통). 실행 파일 경로, 명령줄 인수(길이를 제한하고 제어 문자는 이스케이프), 부모 프로세스 계보, uid, 컨테이너 ID, 실행 파일의 SHA-256 등을 /var/lib/roamswitch/exec_log에 해시 체인이 붙은 JSON Lines(0600)로 저장합니다(기본 200MB / 14일). 해시 체인은 변조를 탐지할 수 있지만 방지는 할 수 없습니다(root를 탈취한 공격자는 체인 전체를 다시 쓸 수 있음). 알림 전용 상관 규칙 EXR-001~010(웹 서비스에서의 셸 기동, /tmp·memfd 실행, 공격 도구의 연쇄 등)은 단독으로는 격리하지 않습니다. 운영자가 exec_rules_isolation_optin(기본 false)을 명시적으로 켠 경우에 한해 높은 심각도의 규칙이 호스트 격리의 높은 확신도 트리거로 취급됩니다.

이벤트 전달(forward_enabled, 기본 false)은 운영자가 설정한 목적지로만 보냅니다. 목적지는 syslog(RFC 5424 또는 CEF, UDP/TCP/TLS), JSON Lines 파일, HMAC-SHA256 서명이 붙은 Webhook입니다. TLS syslog는 시스템의 openssl s_client, Webhook은 시스템의 curl(비밀은 표준 입력의 설정으로 전달하며 명령줄 인수에는 싣지 않음)로 처리하고, 데몬에는 TLS/HTTP 크레이트가 없습니다. 전송되는 것은 인시던트 타임라인과 알림 기록에 오르는 탐지 이벤트(eBPF·격리 상태의 전환·FIM·카나리아 등)와 실행 규칙 알림에 대한 호스트 이름, 이벤트 ID, 시각, 종류, 심각도, 규칙, 조치, PID, 프로세스 이름, 요약 항목과 실행 기록의 세그먼트 봉인 해시뿐입니다. 실행 기록의 원시 로그는 포함하지 않습니다.

DNS 터널링/데이터 유출 탐지

dns_tunnel_detect_enabled(기본값 true)을 활성화하면 이 호스트가 직접 보내는 DNS 쿼리(UDP/TCP 53번 포트만)를 전용 NFQUEUE 컨슈머로 감시합니다. 라벨 길이가 40바이트를 초과하고 섀넌 엔트로피가 3.8을 초과하는 경우, 또는 질의 레코드의 qtype이 TXT/NULL 중 하나인 경우(ClamAV 서명 갱신이 사용하는 clamav.net 대상 TXT만은 집계하지 않습니다)에, 그 질의를 iodine·dnscat2 같은 DNS 터널링 도구에 특징적인 "의심스러운 형태"로 집계하며, 최근 60초 동안 이러한 질의가 10건 이상에 도달했을 때만 알립니다(같은 도메인에 대한 재알림은 300초 간격을 두고, 버스트가 이어지는 동안은 600초, 1200초로 늘려 최대 1800초 간격으로 합니다). 검사 대상은 DNS(UDP/TCP 53번 포트)뿐이며 다른 트래픽은 검사하지 않습니다. 알림 전용이며 자동으로 차단하지 않습니다. 내부 nft 규칙에는 bypass가 부여되어 있어 탐지 스레드가 중단되거나 응답하지 않아도 DNS 쿼리는 그대로 통과합니다. 이름 해석이 이 기능의 오작동으로 막히는 일은 없습니다. 설정 변경을 반영하려면 roamswitch server restart를 실행해야 합니다(실시간 재적용 미지원).

알려진 한계. 하이픈으로 구분된 긴 호스트명(예: prod-us-east-1-web-server-node-0042)과, 메일 서버가 짧은 시간에 여러 다른 발신 도메인의 SPF/DKIM TXT 레코드를 검증하는 것처럼 서버 환경에서 특히 현실적인 정상 작업이, 목적지 도메인을 구분하지 않는 단일 전역 카운터로 TXT/NULL 버스트를 집계하는 방식 때문에 오탐을 유발할 수 있음을 실측으로 확인했습니다. 두 가지 모두 2026-09-23에 대응 완료했습니다. 설정 가능한 entropy 허용목록과, apex domain(QNAME 마지막 2개 레이블을 이용한 간단한 근사치로, Public Suffix List의 엄격한 구현은 아닙니다) 단위로 버스트 카운터를 분리하는 방식으로 해결했습니다. 허용목록에는 기본적으로 주요 CDN/클라우드 및 PaaS 접미사 16개(cloudfront.net·akamaiedge.net·akamaized.net·edgekey.net·edgesuite.net·fastly.net·azureedge.net·googleusercontent.com·amazonaws.com·r2.dev·workers.dev·vercel.app·netlify.app·supabase.co·firebaseapp.com·web.app)가 포함되어 있으며, 운영자는 ServerConfig.dns_tunnel_entropy_allowlist(server.conf의 쉼표 구분 키, TUI에서도 편집 가능)에 자사 내부 도메인을 추가할 수 있습니다. 허용목록이 면제하는 것은 라벨 길이+엔트로피 판정뿐이며, TXT/NULL qtype 판정은 허용목록 여부와 관계없이 항상 적용되므로 허용목록 도메인 아래에 터널을 위장하는 우회를 방지합니다(예외는 ClamAV 서명 갱신이 사용하는 clamav.net 대상 TXT뿐입니다. 제3자가 그 도메인 아래에 서브도메인을 만들 수 없으므로 집계하지 않습니다). 버스트 카운터는 apex domain 단위로 분리되어 목적지를 구분하지 않는 단일 전역 카운터로 인한 오탐은 해소되었습니다(60초 이동 윈도와 10건 임계값이라는 판정 로직 자체는 이번 대응에서 변경하지 않았습니다. 재알림 간격은 그 후, 버스트가 이어지는 동안 300초에서 최대 1800초까지 늘리는 방식으로 바꾸었습니다). iodine·dnscat2 같은 실제 악성 트래픽은 항상 공격자가 관리하는 단일 도메인 아래에서 라벨과 qtype만 바꾸므로, apex domain 단위로 좁혀도 탐지력은 떨어지지 않습니다.

SSH 무차별 대입 탐지·차단(ssh_guard)

RoamSwitch 자체의 무차별 대입 방어로, ssh_guard_enabled(기본 true)로 동작합니다. sshd 로그를 journald에서 journalctl -f로 흘려 읽고(journald가 없는 환경에서만 auth.log/secure를 추적), 접속 출처별로 실패를 집계해, 임계치(기본 600초에 6회)에 도달한 출처에 대해 inet roamswitch_sshguard 테이블에서 SSH 포트에 대한 새 연결(ct state new)만 차단합니다. 금지와 동시에, 그 접속 출처가 이미 SSH에 맺어 둔 연결도 끊습니다(conntrack 항목을 지우고 응답 방향 패킷을 버리는 규칙을 더해 끊습니다). 금지 대상은 인증된 세션도, 공개 키 로그인 성공 기록도, 면제도 없는 접속 출처뿐이며 끊기 직전에 한 번 더 확인하므로, 인증된 세션과 면제된 접속 출처는 끊지 않습니다. 차단은 1시간에서 시작해 재발할 때마다 4배, 최대 7일이며 만료는 nftables 타임아웃이 처리합니다. Air-Gap(격리)은 시작하지 않고 외부로 통신하지도 않습니다(journalctl·nft·loginctl 등을 로컬에서 실행할 뿐입니다). fail2ban(sshd jail 활성) 또는 CrowdSec(firewall bouncer 동작 중)이 이미 sshd를 지키고 있으면 차단은 양보하고 탐지와 알림만 합니다.

로그 줄에는 공격자가 정할 수 있는 문자열(사용자 이름)이 들어갑니다. 그래서 접속 출처 주소는 줄 끝의 from <IP> port <N>에서만 읽으며, 사용자 이름에 위조한 출처를 넣어도 제3자는 차단되지 않습니다. journald에서는 송신 자격 증명(_UID, _COMM)이 root의 sshd인 줄만 읽고, logger -t sshd로 쓴 줄은 읽지 않습니다. 파일(auth.log) 추적에는 송신자를 보증하는 필드가 없고 syslog를 쓸 수 있는 로컬 사용자가 줄을 위조할 수 있으므로 기본값으로 하지 않았습니다. 운영자가 차단되지 않도록 게이트웨이·DNS·자기 자신·루프백·whitelist_ips·ssh_guard_allow·인증된 SSH 세션의 접속 출처·최근 30일 안에 공개 키 인증으로 성공한 접속 출처·페어링된 Sensor는 차단하지 않습니다. 사설 주소는 면제하지 않습니다. 공개 키 실패(Failed publickey)는 집계하지 않습니다.

실측(Ubuntu 24.04 VM. 실제 journald와 systemd): 6번째 실패에서 차단까지 약 0.2초(0.17~0.24초)였습니다. 운영자의 접속 출처는 차단되지 않았고, 사용자 이름에 위조한 출처를 넣은 시도에서도 제3자는 차단되지 않았습니다. 실제 hydra(4병렬)는 6번의 실패에서 멈췄습니다. 서버 재시작 후 남은 시간과 함께 차단이 복원되는 것, 해제할 수 있는 것, fail2ban이 sshd를 지키고 있을 때 탐지와 알림만 하게 되는 것도 확인했습니다. 이 수치는 이 VM 환경의 것입니다. 연결 끊기를 더한 뒤의 실측에서, 차단 뒤에도 통과한 실패는 더하기 전 16~24건, 더한 뒤 0~4건이었습니다. conntrack 항목을 지우는 것만으로는 연결이 끊기지 않았고, 응답 방향 패킷을 버리는 규칙을 더하고서야 효과가 있었습니다.

웹 애플리케이션 계층 탐지 규칙(웹셸·삽입 코드)

Server Edition에는 쓰기를 보고 검사하는 경로가 없었고 clamav_scan_dirs의 정기 스캔뿐이었습니다. 이제 웹 서버(Apache·nginx·Caddy) 설정에서 찾은 문서 루트를 알림 전용 fanotify(FAN_CLASS_NOTIF, 다른 프로세스를 멈추게 하지 않음)로 감시하여, PHP·JavaScript·JSP·ASP 파일이 쓰이고 닫히는 즉시 웹 애플리케이션 계층 탐지 규칙(웹셸, 삽입된 난독화 코드, 이미지로 위장한 PHP, .htaccess 악용)으로 검사합니다. 놓친 이벤트와 시작 전부터 있던 파일을 위해 6시간마다 정기 스캔도 합니다. 규칙은 세 층(내장, 일일 업데이터가 서명 검증 후 설치, /etc/roamswitch/rules.d/*.json의 사용자 규칙)이며, 18개 규칙에는 실제 샘플에서 뽑은 시그니처가 없고 공개된 수법만 기술되어 있습니다.

Server Edition에서 자동 격리는 기본적으로 critical만입니다. high는 알림과 탐지 후 훅만 실행하며 운영 중인 사이트의 파일에는 손대지 않습니다. 알림(Telegram·LINE·Webhook)은 10개 언어이며 탐지마다 규칙 이름과 격리했는지 남겼는지를 표시합니다. 규칙 가져오기는 일일 업데이터와 같은 한 번의 가져오기에 포함되어 새 접속처가 늘지 않습니다. cve_kernel_map_updates_enabled를 끄면 통신이 전혀 없고 내장 규칙으로 동작합니다. 실제 fanotify에서 쓰인 웹셸이 2초 안에 격리되고 무해한 파일은 남는 것을 확인했습니다.

탐지 후에는 /etc/roamswitch/hooks/post-detection에 실행 파일을 두면 탐지 내용(JSON)이 표준 입력으로 전달됩니다(root 소유, 쓰기 불가, 상위 디렉터리도 안전한 것만 실행하며, 셸을 거치지 않고 환경 변수는 최소한이며 30초 후 중단). 선택 사항인 계정 조치(기본 꺼짐)는 격리한 파일 소유자의 로그인 셸을 해제합니다. root, UID가 account_min_uid(기본 1000) 미만인 계정, 로그인 중인 사용자, 데몬 자신의 사용자에게는 아무것도 하지 않으며, 원래 셸을 기록해 roamswitch web-rules unlock-account로 되돌릴 수 있습니다. 오탐 실측은 WordPress 본체 2,409개, phpMyAdmin 3,356개, npm 의존성 14,743개 파일에서 0건이었습니다. 한계로, 읽는 것은 앞 256 KB(쓰기·실행 시)와 4 MB(스캔)뿐이고 변수 이름 조립('ev'.'al') 같은 분할은 따라가지 못하며, 실제 샘플이 없어 알려진 악성코드의 개별 시그니처는 포함하지 않습니다.

허니토큰(자격 증명 미끼)

데몬 시작 시, 공격자와 자동화된 자격 증명 탈취 도구가 실제로 스캔하는 알려진 실제 경로(/root/.aws/credentials·/root/.ssh/id_rsa·/root/.docker/config.json·/root/.pypirc·/root/.env.backup. 데몬이 root로 실행되므로 /root 하위)에 ROAMSWITCH_HONEYTOKEN 마커가 포함된 가짜 자격 증명 파일을 멱등적으로 배치합니다(기본적으로 켜짐. honeytokens_enabled로 끌 수 있고 배치 위치는 honeytokens_home로 바꿀 수 있음). 해당 경로에 이미 실제 파일이 있으면 절대 덮어쓰지 않습니다(배치 전 항상 존재 여부를 확인). 허니토큰에 대한 실제 접근은 상한이 있는 관련 추가 미끼(추가 AWS 프로필, SSH config, kubeconfig 등)의 연쇄 배치로도 이어질 수 있습니다. 1.10.4까지의 배포 패키지에는 이 기능에 필요한 roamswitch-honeytokens이 포함되어 있지 않아, 패키지로 설치한 환경에서는 동작하지 않았습니다. 1.10.5부터 포함되었고, 서버 에디션에서 systemd 샌드박스가 /root에 대한 쓰기를 막던 문제도 1.10.5에서 고쳐졌습니다. 1.11.1부터 RoamSwitch 자체가 실행하는 docker 명령은 빈 전용 디렉터리를 DOCKER_CONFIG로 지정해 시작하므로 미끼 /root/.docker/config.json에는 반응하지 않습니다. 다른 프로그램이 읽으면 지금까지처럼 감지합니다.

백그라운드 감시 프로세스(roamswitch-honeytokens)가 알림 클래스의 fanotify(아무것도 막지 않음)로 각 미끼 파일의 읽기·열기를 감시합니다. 이벤트가 접근한 쪽의 PID를 전달하므로 그 자리에서 접근한 실행 파일을 특정할 수 있습니다(fanotify를 쓸 수 없는 환경에서는 inotify와 fuser로 전환합니다). 정상적인 프로세스가 이 파일들을 읽을 이유는 본래 없으므로, RoamSwitch 자체 바이너리와 SSH 미끼에 대한 OpenSSH 클라이언트(ssh·scp·sftp·ssh-add·ssh-agent 등. ssh-keygen은 포함하지 않음)를 제외한 접근을 침입자의 침해 이후 정찰(MITRE ATT&CK T1552, Unsecured Credentials)을 나타내는 강력한 신호로 간주하여 알립니다. 접근한 실행 파일을 특정하지 못한 접근도 허용하지 않고 탐지로 처리합니다. 알림 전용이며 접근한 프로세스의 동결이나 차단 같은 추가 대처는 하지 않습니다.

알려진 한계. /root/.ssh/id_rsa 디코이 본문은 읽을 수 있는 텍스트를 포함하고 있으며, 실제 OpenSSH 개인 키의 base64 본문으로서는 여전히 유효하지 않은 형식입니다. 다만 대부분의 시크릿 스캐너는 -----BEGIN ... PRIVATE KEY----- 헤더의 정규식 일치만으로 플래그를 지정하므로, 실제 운영 환경에서의 탐지율에 미치는 영향은 제한적이라고 판단합니다. 또한 fanotify를 쓸 수 없어 inotify로 전환된 환경에서는, 접근 프로세스 식별(fuser 호출)이 파일을 읽은 직후 즉시 종료되는 매우 짧은 수명의 프로세스에 대해서는 PID·프로세스 이름을 확보하지 못할 수 있습니다. 이 경우 알 수 없음으로만 처리될 뿐, 접근 자체의 탐지(이벤트 발생·알림)에는 영향을 주지 않습니다.

증거 보전 번들(포렌식 자동 수집)

증거 수집은 다음 경우에 실행됩니다. eBPF 런타임 위협 센서의 이벤트로 해당 프로세스의 프로세스 단위 네트워크 격리에 성공했을 때, 그 격리에 실패하여 호스트 전체 Air-Gap으로 격상되었을 때, 호스트 전체를 차단하는 Air-Gap을 실행했을 때입니다. 랜섬웨어 카나리아가 변조를 탐지하여 프로세스를 동결하고 호스트를 격리하는 경로에서도 실행됩니다. 호스트 전체를 차단하는 경로에서는 차단 전에 실행되며 차단을 지연시키지 않습니다. 1.10.4까지는 프로세스 단위 격리에 성공한 경우에만 실행되었고, 1.10.5에서 대상을 넓혔습니다. 대상 프로세스의 PID를 알 수 없으면 /proc 스냅샷은 수집하지 않습니다. roamswitch-incident-capture가 실행되어 증거 번들을 <상태 디렉터리>/incident-evidence/<타임스탬프>-<짧은 ID>/에 저장합니다. 수집 내용은 기본 라우팅 인터페이스에서 tshark로 수행하는 경계 지정 30초 패킷 캡처(tshark가 없으면 건너뜀으로 기록할 뿐)와, 대상 프로세스의 /proc/<pid> 스냅샷(status, cmdline, maps, 비밀 정보로 보이는 값을 [REDACTED]로 치환한 environ, 열려 있는 파일 디스크립터의 링크 대상 목록(내용 자체는 수집하지 않습니다), 조상 프로세스 계보)입니다. 개별 아티팩트 수집 실패는 번들 전체를 중단시키지 않고 그 사실만 기록한 뒤 나머지 수집을 계속합니다. 1.10.4까지의 배포 패키지에는 이 기능에 필요한 roamswitch-incident-capture이 포함되어 있지 않아, 패키지로 설치한 환경에서는 동작하지 않았습니다. 1.10.5부터 포함되었습니다.

수집 결과는 manifest.json에 정리되며, 번들 내 모든 아티팩트의 SHA-256 해시를 기록합니다(사후 변조 탐지를 위해). 번들은 자동으로 삭제되지 않습니다. 운영자가 sudo roamswitch-incident-capture prune [--keep-days N](기본 보존 기간 30일)을 명시적으로 실행했을 때만 오래된 번들이 삭제됩니다. 필요할 때 수동으로 수집하는 sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json] 명령도 제공됩니다.

수집된 증거는 수집 시점에는 검증되지 않습니다. 이후 변조 여부를 확인하려면 sudo roamswitch-incident-capture verify <번들 디렉터리> [--json]를 실행하십시오. 번들 내 현재 파일을 다시 해시하여 manifest.json에 기록된 값과 대조하고, 변경됨·누락·미기록(매니페스트에 없는 파일이 혼입됨) 중 하나로 각각 보고합니다.

알려진 한계. 이 검증은 manifest.json의 SHA-256을 번들 밖에 있는 기록과 대조합니다. 기록은 두 곳입니다. 번들 밖의 기록 체인(evidence_anchor.log. 각 줄이 직전 줄에 이어지며, 추가 전용 속성을 붙입니다)과 시스템 로그(태그 roamswitch-evidence)입니다. 수집 후 manifest.json을 고쳐 쓰면 verify가 실패합니다. 기록의 줄을 고치거나 지워도 체인이 끊어져 실패합니다. 다만 root 권한을 가진 공격자가 체인과 시스템 로그의 전송처를 모두 고쳐 쓸 수 있는 경우는 막지 못합니다. 시스템 로그를 다른 기기로 전송하는 운용을 권장합니다. 서명은 구현하지 않았습니다. 이 기록이 없는(이전 버전에서 수집한) 번들은 '기록 없음'으로 표시되며, 외부의 뒷받침이 없다는 뜻입니다.

§534-체크 보안 진단 스위트

Server Edition은 34가지 전문 보안 상태 감사를 실행합니다.

# 카테고리 제목 확인 표준 및 논리
1인증 및 액세스SSH 루트 로그인 및 비밀번호 인증PermitRootLogin no 검증. 비밀번호 인증도 비활성화되어 있으면 공개 키 인증만으로 보고하고, 활성화되어 있어도 root 로그인이 금지되어 있으면 합격으로 처리합니다
2인증 및 액세스빈 비밀번호 계정/etc/shadow에 빈 비밀번호 해시가 있는 사용자가 없는지 확인합니다.
3인증 및 액세스Sudoers 권한 위생/etc/sudoers와 /etc/sudoers.d에 비밀번호 없이 모든 권한을 부여하는 NOPASSWD: ALL이 없는지 감사
4네트워크인바운드 기본 거부기본 인바운드 삭제 정책에 대해 nftables을 감사합니다.
5커널 및 무결성권한이 없는 사용자 네임스페이스(Frag Gap)user.max_user_namespaces=0(또는 kernel.unprivileged_userns_clone=0)으로 LPE 공격 경로 차단
6커널 및 무결성eBPF BTF 지원/sys/kernel/btf/vmlinux을 통해 커널 BTF 유형 정보의 유효성을 검사합니다.
7커널 및 무결성eBPF LSM 활성커널 lsm= 부팅 매개변수에서 bpf을 확인합니다.
8네트워크XDP 부팅 시 게이트Link Guard의 nftables 테이블이 설치되기 전 부팅 직후의 공백을 XDP 기본 거부 게이트로 메웁니다(실험적 기능, 기본값은 로드되지 않는 옵트인 전용). 고정된(pinned) 링크의 유무를 확인하며, 로드되지 않았더라도 실패로 처리하지 않습니다
9커널 및 무결성eBPF 런타임 보안 에이전트Falco / Tetragon 등 에이전트의 동작 상태를 확인. Falco가 동작 중일 때는 RoamSwitch 자체 규칙의 경보가 돌아오는지(하트비트)도 확인하며, 돌아오지 않으면 불합격(RoamSwitch의 Falco 파일이 부족하면 그 파일 이름도 표시)
10커널 및 무결성통합 인시던트 타임라인Link Guard, Canary, eBPF Guard, Resource Guard의 인시던트를 시간순으로 통합하는 타임라인이 기록 가능한 상태(기록된 이벤트가 있거나 저장소에 쓸 수 있음)인지 확인하고, 최근 차단 소요 시간을 표시합니다
11컨테이너Docker 소켓 마운트 감사/var/run/docker.sock의 컨테이너 마운트를 감지합니다.
12컨테이너Docker 권한 컨테이너고위험 --privileged 컨테이너 워크로드에 대한 감사
13컨테이너컨테이너 런타임 격리 수준 (runc/gVisor/Kata)기본 컨테이너 런타임을 확인합니다. runc 계열(호스트 커널 공유)은 실패, gVisor(runsc) 또는 Kata Containers(컨테이너별 VM 격리)가 감지되면 통과입니다. Docker/containerd가 감지되지 않으면 해당 없음으로 처리합니다
14컨테이너Docker 방화벽 우회 방지 (DOCKER-USER)게시된 컨테이너 포트가 Docker 자체 규칙으로 방화벽 기본 거부를 우회하지 못하도록, 항상 가장 먼저 평가되는 DOCKER-USER 체인(또는 RoamSwitch 전용 Docker 가드 nftables 테이블)에 RoamSwitch의 규칙이 실제로 존재하는지 검증합니다. server.conf의 protect_docker_ports가 활성화된 경우에만 평가합니다
15커널 및 무결성ClamAV 실제 탐지 테스트 (EICAR)데몬이 시작 2분 후와 이후 6시간마다, 자신의 실행 환경(예: systemd 샌드박스 안)에서 무해한 EICAR 테스트 파일을 스캔하여 ClamAV가 실제로 탐지하는지 확인합니다. server.conf의 clamav_enabled가 활성화된 경우에만 평가합니다
16커널 및 무결성fanotify 이벤트 누락 (큐 오버플로)fanotify 이벤트 큐가 넘쳐 커널이 버린 FIM 및 컨테이너 실행 감시 이벤트가 있는지 검사합니다. 큐가 넘치는 동안의 파일 쓰기와 실행은 실시간 감시에서 빠지므로, 자주 발생하면 fs.fanotify.max_queued_events 값을 늘립니다
17커널 및 무결성실행 중인 커널의 알려진 CVE 노출실행 중인 커널 버전을 로컬의 알려진 CVE 맵(내장 기준선 또는 서명을 검증한 업데이트)과 대조합니다. 검사 자체는 외부와 통신하지 않으며, 맵 업데이트는 cve_kernel_map_updates_enabled(기본 true, 끌 수 있음)에 따라 가져옵니다. 확정할 수 없는 경우 실패가 아니라 '판정 불가'로 처리합니다
18무결성FIM(중요 경로 파일 무결성)고정된 23개의 핵심 파일과 12개 디렉터리 바로 아래 모든 파일 등의 SHA-256 해시 무결성 검증
19커널 및 무결성Yama 프로세스 보호kernel.yama.ptrace_scope가 2 또는 3인지 확인하여 메모리 도청 방지
20네트워크IP 전달 비활성화됨net.ipv4.ip_forward = 0 확인
21네트워크TCP SYN 쿠키 보호net.ipv4.tcp_syncookies = 1 확인
22네트워크역방향 경로 필터링(rp_filter)net.ipv4.conf.all.rp_filter가 1(엄격) 또는 2(완화. 멀티홈 구성용)인지 확인하여 위조 패킷 폐기
23커널 및 무결성코어 덤프 제한fs.suid_dumpable = 0을 통한 프로세스 메모리 누수 방지
24운영자동 보안 업데이트unattended-upgrades(Debian / Ubuntu)나 dnf-automatic(RHEL / Fedora) 등에 의한 패치 자동 적용 설정을 확인합니다
25운영NTP 시간 동기화chrony 또는 systemd-timesyncd을 통해 동기화를 확인합니다.
26운영SSH 무차별 대입 보호RoamSwitch 자체 SSH 가드(ssh_guard)가 동작하며 차단하는 설정일 때, 또는 fail2ban·crowdsec의 상시 가동을 확인합니다.
27커널 및 무결성권한 없는 eBPF 비활성화됨kernel.unprivileged_bpf_disabled가 1 또는 2인지 확인하여 Spectre/LPE 방지
28네트워크ICMP 리디렉션이 무시됨accept_redirects = 0을 통한 경로 오염 방지
29네트워크ICMP 에코 브로드캐스트가 무시됨스머프 증폭기 DoS 공격 완화
30커널 및 무결성공유 메모리 강화/dev/shm에 nodev·nosuid·noexec 중 하나라도 마운트 옵션이 붙어 있는지 확인합니다
31인증 및 액세스레거시 안전하지 않은 프로토콜 없음평문 수신 서비스(telnetd, rshd, tftpd 등)와 평문 클라이언트(telnet, rsh, tftp 등)가 설치되어 있지 않은지 확인합니다(서비스와 클라이언트는 따로 표시).
32커널 및 무결성SUID 프로세스 코어 덤프 제한됨SUID 바이너리 충돌 시 자격 증명 유출을 방지합니다.
33커널 및 무결성보조 프로그램(미끼·증거 수집) 설치데몬은 자격 증명 미끼(허니토큰) 프로그램과 증거 번들 프로그램을 이름으로 실행하며, 없으면 조용히 아무것도 하지 않습니다. 두 프로그램이 설치되어 있는지 확인합니다.
34네트워크웹 공개 디렉터리의 민감 파일 노출Apache / nginx / Caddy 설정에서 문서 루트를 찾아, 그 안의 .git, .env, .DS_Store, phpinfo, SQL 덤프, 백업, 개인 키가 웹 서버를 통해 실제로 읽히는지 서버 자신에 대한 요청으로 확인합니다. 응답이 디스크에 있는 파일의 앞부분과 일치할 때만 노출로 판정하므로, 모든 경로에 200을 반환하는 사이트나 이미 403으로 막은 파일은 오탐이 되지 않습니다. 파일 내용은 보고하지 않고 경로만 표시합니다. 웹 서버가 없는 환경은 해당 없음이며, 확인하지 못한 경우는 '판정 불가'로 처리해 점수를 깎지 않습니다.

34개 항목 각각에 해당하는 경우 NIST CSF 2.0의 기능/범주 식별자(예: PR.DS-01, DE.CM-09)를 부여하고, 확실하게 대응시킬 수 있는 항목에 한해 CIS Controls v8 통제 번호(예: 10.1, 4.1)도 함께 표기합니다. 대응이 모호한 항목은 억지로 부여하지 않고 미매핑 상태로 둡니다. 이 대응표는 CLI(roamswitch server status)와 MCP(get_security_report) 출력 모두에 포함되어, 컴플라이언스 대응이 필요한 운영자·감사 담당자가 각 점검 항목을 기존 프레임워크에 기계적으로 대응시킬 수 있게 합니다.

§6셀프 체크(Docker 환경에서의 재현 검증)

공식 APT 저장소에서 설치한 roamswitch-server 패키지에 대해, Docker의 별도 컨테이너를 외부 공격자로 삼아 내부·외부로부터의 공격을 모방한 셀프 체크를 실시합니다. 2026-09-07에 v1.3.2에서 측정한 결과는 전체 18개 항목 PASS였습니다. 2026-09-25에는 1.10 계열 소스로 빌드한 패키지(arm64, Docker Desktop)로 다시 실시하여 19개 검사가 PASS였습니다. 재실시에서 제품 측 결함 6건이 발견되어 모두 수정했습니다(1.10.5에 포함). 내역은 패키지에 보조 실행 파일이 포함되지 않았던 문제, FIM이 허니토큰을 새 파일로 보고하는 문제, 확인 응답(ack)이 무시되는 문제, 격리 중 관리용 SSH의 응답이 차단되어 관리자가 접속할 수 없게 되는 문제, preserve_ssh_on_isolation=false인데도 22번 포트가 열려 있던 문제, systemd 유닛의 샌드박스가 미끼의 쓰기를 막고 있던 문제입니다. 이 검증은 직접 사용하시는 머신에서도 재현할 수 있습니다. 절차와 스크립트는 아래 "직접 재현하는 방법"을 참조하세요.

# 시나리오 공격 벡터 확인 결과
PENT-S1 Nmap SYN 스텔스 스캔 포트 22, 80, 443, 3306, 8080 전반에 걸쳐 프로브 nftables Default Drop으로 허용되지 않은 3306 (MySQL)과 8080은 일절 응답하지 않고 폐기(Filtered). 100% 차단
PENT-S2 허용되지 않는 포트 검색 포트 3306 및 8080에 대한 컬 직접 연결 인바운드 기본 거부로 허용된 포트 80만 정상 응답하고, 나머지는 타임아웃으로 차단
PENT-S3 Egress / C2 차단 목록 악성 IP 피드에 등록된 주소로의 아웃바운드 연결 시도 egress_ip_blocklist_enabled(기본 true, nftables)에 따라 등록된 주소만 차단됨. 등록되지 않은 호스트로의 통신에는 영향 없음(전면 차단 아님)
PENT-S4 FIM 변조 공격 /bin/login에 백도어 페이로드 삽입 SHA-256 Critical Path FIM이 변조를 즉시 탐지. 정상 복원 후에는 기준선이 올바르게 재동기화
PENT-S5 guard.yaml 심각도별 격리 실제 프로세스를 참조하는 Falco Critical 이벤트를 주입 on_critical: isolate_process + kill_process로 해당 프로세스를 네트워크에서 격리한 뒤 SIGKILL
PENT-S6 보호 프로세스 안전장치 실제 sshd PID를 참조하는 동일한 유형의 이벤트를 주입 보호 프로세스 목록(sshd/systemd/컨테이너 런타임 등)에 의해 sshd는 계속 실행됨. 오탐으로 거부 로그만 기록
PENT-S7 안전 타이머 Air-Gap 사고를 확인 응답 없이 방치(운영자 ACK 없음) safety_timer_secs에 의해 응답이 없으면 자동 복귀. ACK 완료 시 emergency-restore까지 격리 유지
PENT-S8 커널 LPE 조각 간격 일반 사용자 권한으로 unshare -U -r 실행(실제 VM에서 확인) 제품이 없으면 허용되는 unshare -U -r가 기동 후에는 거부됨. user.max_user_namespaces와 kernel.unprivileged_userns_clone은 0, Yama의 ptrace_scope는 2, 비특권 eBPF는 비활성(2026-09-25, Ubuntu 24.04 VM, v1.10.4 공개판과 수정판 모두에서 확인)

참고: PENT-S7의 측정값은 v1.3.2 시점의 것이었습니다. 현재 버전에서는 확신도가 높은 트리거의 격리는 원인이 사라진 것이 확인되면 해제되고, 운영자가 확인 응답(ack)한 격리는 운영자가 해제할 때까지 유지됩니다(ack가 무시되던 결함은 2026-09-25 재실행에서 발견하여 수정했습니다). 확신도가 낮은 트리거는 같은 타이머로 복구됩니다. 자세한 내용은 §4를 참조하세요.

검증의 종류 — PENT-S8은 커널 기능(사용자 네임스페이스 금지)이 적용되어 있는지 확인합니다. PENT-S1·S2는 RoamSwitch가 설정한 nftables 규칙을 확인하는 것이며 실제로 패킷을 버리는 것은 커널입니다. RoamSwitch 고유의 로직을 시험한 항목은 PENT-S3(피드 적용), S4(FIM), S5·S6(격리와 보호 프로세스), S7(안전 타이머)입니다.

SSH 잠금 방지 메커니즘

preserve_ssh_on_isolation=true(기본값)는 Air-Gap(on_emergency) 중에도 관리용 SSH를 유지하도록 설계되어 있습니다. 그러나 2026-09-25 재실행에서, 1.10.4까지는 격리 규칙이 SSH 응답을 차단하여 격리 중 운영자가 접속할 수 없게 된다는 것이 확인되었습니다. 이전의 확인은 격리가 해제된 뒤에야 성공했을 뿐이었습니다. 1.10.5에서 수정되었으며, 격리 원인이 존속하는 조건에서 격리 중 SSH가 통과함을 확인했습니다.

검증 범위의 한계(정직한 공개)

검증할 수 없는 것

커널 강화(비특권 User Namespace 비활성화, Yama ptrace_scope 상향)는 컨테이너 내부에서 종단 간(end-to-end)으로 검증할 수 없습니다. 이러한 sysctl은 컨테이너 단위로 네임스페이스가 분리되지 않기 때문에, 특권 컨테이너(--privileged)에서의 쓰기는 검증용 샌드박스가 아니라 검증을 실행 중인 실제 머신 자체에 영향을 미치게 됩니다. 따라서 이 검증에서는 (읽기 전용 파일 시스템에 대해) sysctl 쓰기가 충돌 없이 올바르게 성능 저하 방식으로 동작하는지만 확인하며, 값이 실제로 반영되는지에 대한 확인은 본 제품이 원래 동작하도록 설계된 실제 머신 또는 VM에서 수행해야 합니다. 이 확인은 2026-09-25에 Ubuntu 24.04 VM에서 한 번만 수행했습니다(PENT-S8 행 참조).

직접 재현하기

위의 모든 검증 결과는 공식 지원 저장소(roamswitch-support)에 공개된 Docker 테스트 스위트를 통해 공식 배포 패키지만으로 직접 100% 재현할 수 있습니다(소스 코드 접근이나 저희를 신뢰할 필요가 전혀 없습니다).

# 검증 스위트 가져오기 및 재현 실행(공식 APT 저장소에서 roamswitch-server를 자동 설치)
git clone https://github.com/lafine1211/roamswitch-support.git
cd roamswitch-support/test/docker/server
./run.sh

Target·Attacker·C2 디코이, 총 3개의 일회용 컨테이너를 Docker의 기본 브리지 네트워크 위에 구성하여 18개 항목을 자동으로 검증하고 보고서를 출력합니다. v1.3.2에서의 실행 결과 전문은 RESULTS-PENTEST-SERVER-2026-09-07.ja.md에 공개되어 있습니다(구축 과정에서 발견하고 수정한 테스트 하네스 자체의 문제도 투명성을 위해 함께 기재). 2026-09-25 재실시 기록은 RESULTS-PENTEST-2026-09-25.ja.md에 있습니다.

§7운영, 배포 및 수명주기

7.1 헤드리스 CUI 툴링 및 설정 마법사

CLI를 통한 완전한 원격 관리:

  • roamswitch server status: 34개 항목의 진단 리포트를 출력합니다(10개 언어를 지원하며, 실행하는 사용자의 설정 또는 OS 로케일을 따릅니다).
  • roamswitch server setup: 포트 및 알림을 위한 대화형 터미널 마법사.
  • roamswitch server config show / set <key> <val>: Ansible/Terraform을 위한 스크립트 가능한 자동화입니다.
  • roamswitch server test-notify [all|telegram|line|webhook]: 엔드투엔드 알림 프로브.
  • roamswitch server config set language <ja|en|zh-Hans|zh-Hant|ko|de|fr|es|it|pt|system>: 데몬의 정기 진단 리포트(1시간마다)와 푸시 알림(Telegram/LINE/Webhook, 테스트 전송 포함)의 언어(호스트당 한 언어). system은 OS 로케일을 따르며, 판별할 수 없는 로케일은 ja가 됩니다. roamswitch server status의 표시 언어는 이 설정이 아니라 실행하는 사용자의 설정이나 OS 로케일을 따릅니다.
  • roamswitch server bans [--json] / sudo roamswitch server unban <IP|IPv6 /64|--all>: SSH 무차별 대입 가드의 상태와 차단 목록 확인·해제. MCP의 get_ssh_guard_incidents는 읽기 전용이라 해제할 수 없습니다.

Server TUI(roamswitch server tui)

SSH 너머에서 80x24, 키보드만으로 Server Edition의 기능 전체를 다루는 터미널 UI입니다(roamswitch server tui 또는 roamswitch-server-tui). 대시보드, 방어, 인시던트, 알림과 전달, Sensor, 설정, 서비스, 도구, 로그 감사, 정보와 도움말, Fleet의 11개 화면이 있습니다. 설정 편집기는 server.conf와 guard.yaml의 키 정의(스키마)에서 생성되며, 타입·범위·열거값을 검증하고, 재시작 필요 여부를 표시하고, 저장 전에 차이를 보여 주며, 타임스탬프가 붙은 백업과 원자적 쓰기로 저장합니다(토큰 등의 비밀 값은 가림 표시·입력 에코 없음). 격리 복구·ack·FIM 기준선 갱신·서비스 중지처럼 영향이 큰 작업은 효과를 명시한 확인 화면을 띄우며, 특히 영향이 큰 것은 yes 입력을 요구합니다(입력형 확인). root가 아니면 읽기 전용이며 필요한 sudo roamswitch ... 명령을 안내합니다. 설정 재로드(reload)는 없으며 반영하려면 서비스를 재시작해야 합니다. 표시는 10개 언어를 지원합니다.

7.2 포장

Debian / Ubuntu용 .deb 패키지와, RHEL / Fedora용 및 openSUSE용 .rpm 패키지로 제공됩니다.

§8결론

RoamSwitch Server Edition은 클라우드 및 엔터프라이즈 Linux 인프라에 “제로 텔레메트리(기본값의 외부 통신은 끌 수 있는, 서명된 데이터의 수신뿐)”, “인바운드 기본 거부에 의한 견고한 경계 방어”, “핵심 경로 변조의 즉시 탐지”, “커널 권한 상승의 예방적 차단”을 단일 통합 패키지로 제공합니다.

공격자가 노리는 주요 단계(초기 정찰, 침입, 권한 상승, 지속성 확보)에 대해 다층 탐지와 자율 차단(Air-Gap)을 결합한 Linux 서버용 보안 스위트입니다.

이 문서는 RoamSwitch Server Edition v1.11.1(인바운드 기본 거부/핵심 경로 FIM/guard.yaml 정책 엔진/커널 LPE 강화/eBPF 런타임 감시/Air-Gap의 단계적 해제/실행 레코더와 이벤트 전달/Server TUI/DNS 터널링 탐지/허니토큰/포렌식 증거 보전/NIST CSF·CIS Controls 매핑/서명된 커널 CVE 맵 갱신) 시점의 구현을 기준으로 합니다. 다만 §6의 셀프 체크 실측값은 v1.3.2(2026-09-07)와, 1.10 계열 소스로 빌드한 패키지(2026-09-25)의 것입니다. 항목별 변경 이력은 roamswitch-support의 CHANGELOG를 참조하세요. 최신 정보는 roamswitch.com/linux를 참조하세요.