요약

  • RFC 3014는 로컬 로그를 만들어, 애플리케이션이 알림 경로에서 수신하지 못했을 수 있는 SNMP Trap 또는 Inform의 내용을 복구할 수 있게 했다.
  • 이 대체 경로는 진실의 기록 보관소가 아니었다. 필터, 접근 규칙, 용량, 시간 경과, 자원 압박, 재시작 에포크, 그리고 다른 관리자들이 기록이 읽히기 전에 증거를 지워버릴 수 있었다.
  • 기록·폐기 카운터, 로그별 인덱스,sysUpTime불연속성은 일부 손실을 가시화할 수 있었지만, 제외되거나 삭제된 기록을 복원할 수는 없었다.

SNMP 알림은 관리자가 요청할 때까지 기다리지 않고 관리 정보를 전달하도록 설계되었다. 장치는 Trap을 발생시킬 수 있고, Inform은 확인 응답과 재전송을 더할 수 있었다. 그러나 어느 쪽도 경로를 불멸로 만들지는 못했다. 재전송은 전달되기 전에 멈출 수 있었고, 수신자가 사용 불가능할 수도 있었으며, 수집기는 일시적 상태가 지나간 뒤에야 격차를 발견할 수도 있었다.

RFC 3014는 2000년 11월 제안 표준(Proposed Standard)으로 발표되며, 로컬 알림 로그 MIB로 이에 응답했다. 이 로그는 사라진 Trap이나 Inform에 대한 보험 장치였다. 관리 애플리케이션은 이를 폴링하고, 마지막으로 수집한 항목부터 이어받아, 보존된 변수 바인딩으로부터 알림 PDU를 재구성할 수 있었다.

겉보기에 단순한 이 조치는 증거 구조를 바꾸었다. 알림은 더 이상 발신자에서 수신자까지 단 하나의 경로만 갖지 않았다. 나중의 판독자가 회수할 수 있는 로컬 기록도 남길 수 있었다. 비동기 경로와 내구성 있어 보이는 경로는 하나의 관리 행위에 대한 두 명의 증인이 된 것이다.

그러나 RFC 3014는 두 번째 증인이 완전하다고 가장하지 않았다. 구성 섹션은 무엇이 들어올 수 있고 얼마나 남을 수 있는지를 통제했다. 통계는 기록된 항목과 폐기된 항목을 세었다. 로그는 살아남은 알림을 담았다. 따라서 이 표준은 단순한 기억이 아니라, 기억을 둘러싼 정책과 희소성을 기술했다.

수용(admission)이 먼저였다. 이름 있는 로그는 SNMP 알림 MIB의 필터를 참조했다. 항목은 알림이 그 필터와 적용 가능한 접근 제어를 통과한 후에만 나타났다. 규격의 예제는linkUp과linkDown만 수용하는 로그를 만들었다. 그 로그에서 다른 부분의 침묵은 다른 알림이 발생하지 않았다는 증거가 아니라, 그것들이 선택된 시야 밖에 있었다는 뜻이었다.

보안은 이 시야를 더 좁혔다. 이름 있는 로그는 자신의 생성자의 보안 자격 증명을 보존했다. 로컬에서 생성된 알림의 경우, 시스템은 보호된 객체를 그 로그에 넣기 전에 알림 발신자(Notification Originator)가 사용하는 것과 동일한 접근 검사를 적용해야 했다. 자원이 적은 장치는 기본값인 이름 없는(null) 로그만 노출할 수 있었고, 이 로그는 수용을 위한 암묵적 생성자 자격 증명을 갖지 않았다.

이 구분은 한 사용자의 로그가 그 사용자가 읽을 수 없는 객체의 우발적 채널이 되는 것을 막았다. 동시에, 승인된 두 관찰자가 같은 장치에서 서로 다른 이력을 받을 수 있음을 의미했다. 완전성은 결코 추상적인 “그 로그”의 속성이 아니었다. 그것은 로그 이름, 필터, 생성자 자격 증명, 엔진, 관리 컨텍스트에 상대적인 것이었다.

출발 컨텍스트가 중요했던 이유는 여러 SNMP 엔진이 독립적으로 동작할 수 있고, 각 엔진이 여러 이름 있는 관리 컨텍스트를 노출할 수 있기 때문이다. RFC 3014는 발신 엔진 식별자와 컨텍스트를 저장했다. 이 좌표 없는linkDown은 어느 관리되는 세계가 바뀌었는지에 대한 완전한 진술이 아니었다.

이어서 용량이 두 번째 경계를 부과했다.nlmConfigGlobalEntryLimit는 모든 이름 있는 로그를 함께 제한했다.nlmConfigLogEntryLimit는 개별 로그를 제한했다.nlmConfigGlobalAgeOut은 항목이 자동 제거되기 전에 유지되어야 할 분수를 정했다. 0은 설정된 한도가 없거나 시간 경과 없음을 의미할 수 있었지만, 무한한 기억을 만들지는 않았다.

표준은 이를 직접 밝혔다. 특정 한도가 그만큼의 데이터를 실제로 보유할 수 있음을 보장하지는 않는다. 실현은 여전히 구현 자원에 좌우된다. 항목 추가가 전역 한도나 가용 자원을 초과하면, 어느 로그에서든 가장 오래된 항목이 제거될 수 있었다. 이름 있는 로그가 자체 한도를 초과하면 그 로그의 가장 오래된 항목이 물러날 수 있었다.

전역 한도는 시간과 로그별 약속보다 우선했다. 항목이 존재하는 동안 관리자가 전역 한도를 낮추면, 시스템은 새 한도가 충족될 때까지 가장 오래된 기록을 폐기해야 했다. 심지어 그 기록들이 시간 경과 값보다 최신이고 각자의 로그가 자체 한도 이내에 있는 경우에도 그러했다.

이것은 단순한 캐시 기계를 넘어섰다. 이것은 누가 다른 관찰자의 증거 창을 줄일 수 있는지를 정의했다. RFC 3014는 여러 애플리케이션이 공유 한도를 서로 다른 값으로 설정하면 서로의 신뢰성과 완전성을 해칠 수 있다고 경고했다. 한 애플리케이션이 다른 쪽이 볼 기회 전에 알림을 삭제할 수 있었다. 문서는 이 가능성을 서비스 거부(denial-of-service) 공격으로 명명하고, 대응책은 추후 연구에 남겼다.

불신뢰한 전달 경로로부터 증거를 구하려던 로그는 그 결과 자체의 제어면 공격 표면을 갖게 되었다. Trap은 전송 중 사라질 수 있었다. 보존된 복사본은 필터에 의해 제외될 수 있었다. 수용된 행은 용량에 의해 퇴거될 수 있었다. 아직 최신인 행은 새 전역 설정 이후 사라질 수 있었다. 장치는 재시작할 수 있었다. 각 실패는 서로 다른 잔재를 남겼다.

바로 그 잔재가 중요했기에 RFC 3014는 카운터를 제공했다. 전역 통계는 기록된 알림과 폐기된 알림을 구분했다. 로그별 통계는 각 이름 있는 로그에 대해 동일한 구분을 했다. 폐기 카운터가 증가하면 운영자에게 보존된 이력이 자원 또는 용량 압박으로 항목을 잃고 있음을 알려 주었다.

그러나 카운터는 사라진 기록이 아니었다. 카운터는 어떤 카운터 에포크 내에서 손실이 발생했음을 입증할 수 있었지만, 지워진 알림 식별자, 변수 바인딩 또는 운영적 의미를 복원하지는 못했다. 열 개의 항목이 폐기되었다면, 숫자 10은 그것들이 일상적인 링크 플랩인지, 팬 고장인지, 서비스 중단 직전의 유일한 경고였는지를 드러내지 않았다.

폴링에도 에포크가 필요했다. 보존된 각 행은 자신의 이름 있는 로그 내에서 단조 증가하는 인덱스를 받았다. 수집기는 회수한 최고 인덱스를 기억하고 다음 폴링에서 그 지점부터 시작할 수 있었다. 또한 인덱스를 초기화하고 항목을 잃을 수 있는sysUpTime의 불연속성을 검사해야 했다.

인덱스 연속성이 답하는 질문은 좁았다. 현재 관리 시스템 에포크에서 수집기가 보존된 순서를 끝까지 진행했는가? 그것은 생성된 모든 알림이 필터를 통과하고, 접근 제어를 살아남고, 가용 자원에 맞고, 폴링 시까지 남아 있었음을 증명하지 못했다. 격차는 삭제를 드러낼 수 있었지만, 격차의 부재는 수용되지 않은 것을 드러내지 못했다.

초기화는 이 경계를 가시화했다. 관리 시스템 재시작 후에 행이 살아남는지는 구현에 따른 사항이었으며, RFC는 일반적으로 그렇지 않을 것이라 예상한다고 밝혔다. 구현이 그것들을 보존한다면, 재시작된sysUpTime에 기반한 타임스탬프는 모호해지므로, 재시작 이전 항목은nlmLogTime을 0으로 노출해야 했다. 행은 살아남을 수 있지만, 그 원래의 상대 시계는 살아남지 못할 수 있었다.

로그는 또한 시스템에 그 능력이 있을 때에만 로컬 날짜·시간을 저장했다. 달력 타임스탬프, 상대 업타임, 증가 인덱스는 서로 다른 좌표였다. 그중 어느 하나만으로는 재시작, 시계 변경, 여러 엔진에 걸친 신뢰할 수 있는 연대기를 만들 수 없었다.

보존된 항목에 대해 이 모델은 표현에 신중했다. 각 변수 바인딩은 인덱스와 SNMP 데이터 타입에 적합한 값 객체와 함께 저장되었다. 애플리케이션은 알림 PDU를 재구성할 수 있었다. 이것은 유의미한 수령 증명이었다. 이 형식화된 필드들이 로그된 메시지에 존재했다는 것이다.

그러나 그것은 메시지 뒤에 있는 물리적·논리적 조건이 실제로 참임을 증명하지 않았다. 에이전트는 잘못 감지할 수 있었다. 카운터는 이미 랩되었거나 초기화되었을 수 있었다. 원격 알림은 인증되지 않았거나 잘못된 컨텍스트 아래 해석되었을 수 있었다. 메시지 재구성은 주장을 보존할 뿐, 그 주장을 그것이 서술하는 세계로 승격시키지 않았다.

이 구분은 인간의 행동에 대해서도 경계를 그었다. 보존된linkDown항목을 읽은 수집기는 그 행의 재독입(readback)을 증명할 수 있었다. 그러나 여전히 운영자가 그것을 보았는지, 올바른 인터페이스를 상호 연관시켰는지, 인시던트를 열었는지, 변경을 승인했는지, 서비스를 복구했는지, 사용자 결과를 측정했는지는 증명할 수 없었다.

주변의 SNMP 프레임워크는 진화했다.RFC 1905는 SNMPv2 프로토콜 동작과 InformRequest 컨텍스트를 제공했다.RFC 2573과RFC 2575는 RFC 3014가 사용하는 애플리케이션과 뷰 기반 접근 제어를 기술했으며, 이후RFC 3413과RFC 3415가 그 프레임워크 문서들을 대체했다. 이 계보는 주변 모듈을 바꾸었지만, 수용과 재독입에는 각자의 수령 증명이 필요하다는 증거 규칙 자체를 바꾸지는 않았다.

이후 규격들은 알림 로그를 재사용 가능한 인프라로 다루었다.RFC 3877의 Alarm MIB는 알람 이력에서 적용 가능한 알림 로그 행을 가리킬 수 있었다.RFC 5676의 SYSLOG-MSG-MIB는 이 일반 메커니즘을 사용하여 syslog 메시지를 SNMP로 표현했다. 이러한 참조는 구조적 재사용을 보여줄 뿐, 배포, 완전성 또는 성공적인 인시던트 대응을 입증하지 않는다.

Lu Heng의 최소 초기 규격(minimum-initial-specification) 관점은 원래 설계의 강점을 설명해 준다. RFC 3014는 하나의 보편적 보존 예산을 선언하는 대신, 구성, 통계, 출발 좌표, 인덱스, 형식화된 값이라는 작은 공통 객체 집합을 표준화했다. 운영자와 구현은 로컬 자원 결정을 유지했다.

그 자유에는 대가가 따랐다. 보존 수치는 실행이 관찰되어야 하는 로컬 약속이었다. 러닝 코드 우주(running-code primacy)는 다음을 묻는다. 필터가 설치되어 있었는가, 행이 수용되었는가, 용량이 변하지 않았는가, 카운터 에포크가 연속이었는가, 수집기가 실제로 그 항목을 읽었는가? MIB 정의만으로는 어떤 이름 있는 장치에서 그 사실들 중 하나도 증명되지 않는다.

현실 계층(Reality Layers)이 마지막 규율을 제공한다. 사건, 알림, 수용된 행, 보존된 행, 수집기의 읽기, 분석가의 해석, 승인된 행동, 서비스 결과는 서로 연관되어 있지만 서로 교환 가능하지 않았다. 로그는 운영 시스템 안의 증거 시스템이었지, 현실의 투명한 복제본이 아니었다.

따라서 RFC 3014의 가장 지속적인 기여는 “경보를 저장하라”가 아니었다. 그것은 백업 증거에도 자신만의 필터, 소유자, 할당량, 에포크가 있음을 명시적으로 인정한 것이다. 사라진 알림은 로그에서 발견될 수 있었다. 사라진 로그 항목은 때때로 카운터나 불연속성으로부터 추론될 수 있었다. 그 경계 너머에서, 정직한 시스템은 자신이 더 이상 알지 못하는 것을 말해야 했다.

출처