요약

  • RFC 3395는 RMON 프로토콜 식별자에 애플리케이션 동사를 추가했지만, 동사는 계수되는 패킷 안에 보이는 명령이 아니라 여러 패킷과 방향에 걸친 트랜잭션을 기술할 수 있었다.
  • 그럼에도 모든 패킷은 하나의 완전한 리프 카운터에 들어가야 했다. 여러 동사가 나타나면 프로브는 자체 정책에 따라 하나를 골라야 했고, 그리하여 공개된 숫자에는 트래픽과 구현 판단이 함께 담겼다.

정확히 같은 링크를 감시하는 두 모니터링 프로브를 상상해 보자. 두 프로브는 모든 바이트에 대해 일치한다. 같은 등록된 이름을 사용한다. 둘 다 표준을 준수한다. 그런데 한쪽이 다른 쪽보다 더 많은 한 애플리케이션 연산을 보고한다. RFC 3395는 겉보기에 작은 한 문장에 그 이유를 담고 있다: 패킷이 여러 동사 유형을 포함하면 에이전트는 하나를 선택해야 하며, 그 선택 방법은 구현에 따라 다르다.

2002년 9월 표준 트랙(Standards Track)으로 발행된 RFC 3395는 RFC 2895의 프로토콜 식별자 참조를 갱신했다. 그 문제는 실용적이었다. “HTTP”, “SNMP”, “FTP”에서 멈추는 모니터는 프로토콜은 구분할 수 있었지만, 그 안의 연산은 구분할 수 없었다. 연산마다 비용과 결과가 크게 다를 수 있었는데도. 이 문서는 그 애플리케이션 트랜잭션에 이름을 붙이는 표준 방법을 만들었다. 새로운 MIB 모듈이나 새 관리 객체를 만들지는 않았다.

물려받은 프로토콜 디렉터리는 이미 패킷을 캡슐화 스택으로 다루었다. 각 계층은protocolDirID에 4옥텟,protocolDirParameters에 1옥텟을 기여했다. 전체 시퀀스는 리프를 식별했다: 이더넷, IP 또는 TCP가 각각 따로가 아니라, 모니터가 인식한 계층 경로 전체였다. RFC 3395는 애플리케이션 동사를 그 시퀀스의 한 계층 더로 만들었다.

와이어 표현은 압축적이었다. 동사 계층은 4옥텟을 차지했다: 예약된 0 옥텟 뒤에 네트워크 바이트 순서의 24비트 부호 없는 열거형이 따랐다. 명시적 열거 범위는 1부터 16,777,215까지로, 부모 프로토콜 내에서 고유하고 가급적 조밀하게 배정되었다. 구조적 준수를 위해 0 파라미터 옥텟이 이 계층과 함께 갔지만, 동사 자체는 파라미터를 사용하지 않았다.

0은 이미 의미가 있었다. 모든 애플리케이션 프로토콜은 암묵적으로connect(0)를 소유했다. 다른 어떤 동사에도 속하지 않는, 설정 및 종료 트래픽을 위한 버킷이었다. 열거형은 재배정될 수 없었다. 그러나 이름은 전역 보호 단어가 아니었다: HTTP 예시는 별도로 CONNECT에 명시적connect(8)을 부여했다. 이 구분은 구현자에게, 익숙한 문자열에서 의미를 추론할 때 부모와 번호를 함께 확인하도록 경고했다.

매크로VERB-IDENTIFIER는 부모, 설명, 참조, 그리고 이름과 열거형 목록을 등록했다. 이름은 정의에서 대소문자를 구분했고 부모 내에서 고유했다. 프로토콜이 권위 있는 용어를 제공하면 레지스트리는 그것을 보존해야 했다. 등록은 두 제품이 같은 레이블을 인쇄할 수 있게 만들었다. 그러나 아직 같은 증거로 그 레이블에 도달하게 만들지는 않았다.

결정적 어려움은 시간이었다. 많은 프로토콜 계층은 파서 앞의 패킷에서 인식될 수 있다. 동사는 대화를 가로지를 수 있다. SNMP Response PDU는 Get 요청에 대한 응답인지 GetNext 요청에 대한 응답인지 말해 주지 않는다. 응답을 올바른 트랜잭션 아래에 계수하려면, 프로브는 반대 방향으로 움직이는 선행 요청을 기억하고 그 쌍을 상관시켜야 한다. RFC 3395의 SNMP 예시에서 Response와 Report는 따라서 독립된 동사가 아니며, 요청 트랜잭션을 물려받는다.

TCP는 다른 종류의 기억을 더한다. 하나의 애플리케이션 연산은 여러 세그먼트에 나뉠 수 있다. 프로브는 플로우를 따라가며, 분류가 가능해지기 전에 바이트 스트림의 충분한 부분을 재구성해야 할 수 있다. 캡처 정책이 동사에 의존한다면, 그 결정은 가장 이른 관련 패킷 이후에 도착할 수 있다. 그 패킷들은 사전 버퍼링되어 있거나, 이른바 연산별 캡처에서 손실되어 있어야 한다.

이것이 “동사”가 하나의 오프코드, 명령 토큰, PDU 유형을 뜻하지 않은 이유다. 하나의 트랜잭션이 여러 PDU 유형을 포함할 수 있었다. 심지어 프로토콜 디렉터리 항목을 넘을 수도 있었다: FTP의 제어 교환과 별도의 데이터 연결은 같은 유용한 연산에 속할 수 있다. 레이블은 모든 패킷에서 복사된 원시 필드가 아니라, 분류기가 고른 모니터링 트랜잭션을 나타냈다.

그럼에도 RMON 계수는 명확한 출력을 요구했다. 각 패킷은 하나의 완전한 리프 프로토콜 캡슐화 아래에서 한 번 계수되었다. 인식된 애플리케이션 토큰이 차지하는 몇 바이트가 아니라, 패킷의 전체 크기가 그 카운터를 증가시켰다. 모니터는 패킷이 한 종류 이상의 연산을 실었다는 이유만으로 한 패킷을 여러 동사 카운터에 나눌 수 없었다.

RFC 3395는 동점을 깨는 몇 가지 방법을 제안했다: 첫 번째 동사를 고르거나, 가장 자주 나타나는 동사, 가장 많은 옥텟을 차지하는 동사, 또는 프로토콜 지식을 통해 가장 흥미롭다고 여겨지는 동사를 고르는 것. 어느 것도 표준화하지 않았다. 각 규칙은 서로 다른 질문에 답하므로, 어느 구현도 문서를 위반하지 않은 채 동일한 패킷 트레이스가 서로 다른 분포를 낳을 수 있다.

예시들은 FTP, POP3, SNMP, HTTP, SMTP를 통해 추상을 구체화했다. 또한 벌거벗은 레이블이 얼마나 위험할 수 있는지 드러냈다. GET으로 표시된 카운터는 사람이 검색을 의도했다거나, 인가가 성공했다거나, 서버가 유용한 콘텐츠를 반환했다거나, 완전한 페이로드가 보였다는 증거가 아니다. 그것은 에이전트가 어느 정도의 맥락과 어느 정도의 로컬 정책을 가지고 그 등록된 리프 아래의 패킷을 분류했다고만 말한다.

보안 논의도 마찬가지로 정확했다. 동사 식별자 추가는 새 MIB 연산을 도입하지 않았지만, 더 정밀한 측정은 네트워크가 어떤 애플리케이션 연산을 사용 중인지 드러낼 수 있었다. 그 운영 세부 정보는 거친 프로토콜 합계보다 더 큰 보호를 요할 수 있었다. “새 연산 없음”은 “새 정보 없음”이 아니었다.

이후 RFC 4502가 RMON-2 MIB의 RFC 2021 명세를 대체했다. 그 계보는 측정 모델을 정확히 파악하는 데 도움을 주지만, 제품이 RFC 3395를 구현했거나, 같은 재구성 정책을 사용했거나, 부하 아래에서 충분한 상태를 유지했다는 증거는 아니다. 표준 지위는 검증할 계약을 제공할 뿐, 배포 증거를 제공하지 않는다.

Lu Heng의 최소 초기 명세(Minimum Initial Specification) 원리는 이 설계의 절제와 맞아떨어진다. RFC는 상호운용 가능한 명명 표면, 바이너리 계층, 예약 기본값, 기능 규칙, 일회성 계수 의무를 고정했다. 타임아웃, 버퍼, 스트림 재구성, 다중 동사 선호는 하나의 초기 규칙이 모든 프로토콜과 자원 제약을 안전하게 담을 수 없었기 때문에 로컬 엔지니어링에 남겨졌다.

이어지는 러닝 코드 우선성(Running-Code Primacy)은 카운터를 신뢰하는 방식을 바꾼다. 운영자는 숫자와 함께 프로브 버전, 활성화된 디코더, 상태 한계, 손실 통계, 재구성 동작, 동사 선택 정책을 필요로 한다. 그것이 없으면 비교는 공통 어휘를 공통 관측 과정으로 오해한다.

RFC 3395의 오래되지 않는 교훈은 모니터링이 신뢰할 수 없었다는 것이 아니다. 측정이 값을 얻기 전에 출처(provenance)를 얻었다는 것이다. 카운터는 프로브가 기억하고, 조립하고, 고른 후에야 GET이라고 말했다. 숫자는 실제였지만, 그 의미는 그것을 만들어낸 기계 안에 부분적으로 살아 있었다.

출처