사전 SNMP
프로토콜

SNMP

gabury1고친 사람 github-actions[bot]

SNMP 는 망에 붙은 장비에게 지금 상태가 어떠냐고 물어보고 그 답을 받아 옵니다. 장비 종류가 달라도 물어보는 방법은 같습니다. 장비마다 다른 관리 화면에 들어갈 필요 없이 한 곳에서 수백 대의 값을 긁어 옵니다. 장비 쪽에서 먼저 이상을 알려 오는 길도 따로 열어 둡니다.

쉽고 빠른 이해

SNMP 는 망 장비에 상태를 물어 값을 받아 오는 프로토콜입니다. 스위치 열두 대의 포트마다 바이트가 얼마나 지나갔는지를 한 곳에서 같은 방법으로 읽어 오는 것이 대표적인 쓰임입니다.

이게 없으면 장비마다 다른 화면에 들어가 눈으로 읽어야 합니다. 제조사가 다르면 값의 이름도 읽는 방법도 다릅니다. 장비가 백 대로 늘어나면 사람이 따라갈 수 없습니다.

어떻게 도는가:

  1. 값마다 숫자로 된 주소가 미리 정해져 있습니다. 어느 제조사의 장비든 같은 주소에 같은 뜻의 값이 들어 있습니다
  2. 감시하는 쪽이 그 주소를 적어 보내면, 장비 안에 상주하는 프로그램이 해당 값을 찾아 답장에 실어 보냅니다
  3. 장비가 알릴 일이 생기면 물음을 기다리지 않고 감시하는 쪽으로 알림을 먼저 쏩니다

대가도 있습니다. 감시하는 쪽이 주기적으로 물어야 하므로 그사이에 잠깐 났다 사라진 문제는 못 봅니다. 알림은 답장을 요구하지 않는 방식이라 가는 길에 없어져도 아무도 모릅니다.

상세

SNMP(Simple Network Management Protocol, 간이 망 관리 프로토콜)는 망 장비가 들고 있는 상태 값을 떨어진 곳에서 읽고 바꾸려고 만든 프로토콜입니다. 이 절은 묻는 쪽과 답하는 쪽이 어떻게 갈리는지, 값마다 붙은 주소가 어떤 모양인지, 한 왕복에 무엇이 오가는지를 차례로 봅니다.

건물 관리인이 층마다 붙은 계량기를 도는 일과 비슷합니다. 계량기가 어디에 붙어 있고 눈금이 무엇을 뜻하는지를 미리 적어 두면 관리인이 바뀌어도 같은 방법으로 읽을 수 있습니다. SNMP 가 정한 것도 그 둘입니다. 값에 붙일 주소와, 묻고 답하는 절차입니다.

관리자와 에이전트

SNMP 에는 역할이 둘 있습니다. 값을 묻고 모으는 쪽을 관리자, 장비 안에서 그 물음에 답하는 쪽을 에이전트라고 부릅니다. 관리자는 사람이 보는 감시 서버에서 돌고, 에이전트는 감시받는 장비 안에서 돕니다.

에이전트는 장비의 운영체제 안에 늘 떠 있는 작은 프로그램입니다. 장비가 원래 세고 있던 값을 SNMP 가 정한 모양으로 바꿔 내놓는 일만 합니다. 켜진 지 얼마나 됐는지, 어느 포트로 몇 바이트가 지나갔는지 같은 값입니다.

flowchart TD
    subgraph G1["감시하는 쪽"]
        M["관리자 · 값을 묻고 모은다"]
    end
    subgraph G2["감시받는 쪽"]
        A1["라우터의 에이전트"]
        A2["스위치의 에이전트"]
        A3["프린터의 에이전트"]
    end
    M --> A1
    M --> A2
    M --> A3

관리자 하나가 에이전트 여럿을 봅니다. 감시할 장비가 늘어도 관리자 쪽 프로그램은 그대로고 물어볼 주소 목록만 길어집니다. 이렇게 관리자가 정해진 간격으로 되풀이해 물어보는 것을 폴링이라고 부릅니다.

값에 붙은 숫자 주소

관리자가 "포트 3 번으로 들어온 바이트 수"를 물으려면 그 값을 가리킬 이름이 있어야 합니다. 제조사마다 이름을 다르게 지으면 관리자가 장비마다 다른 말을 배워야 합니다.

그 대신 값마다 점으로 이은 숫자 주소를 붙였습니다. 이 주소를 OID(Object Identifier, 객체 식별자)라고 부릅니다. 어느 주소에 어떤 값이 들어 있고 그 값이 무엇을 뜻하는지 적어 둔 명세서가 MIB(Management Information Base, 관리 정보 베이스)입니다.

flowchart TD
    R["1.3.6.1 · 인터넷"]
    R --> M2["1.3.6.1.2.1 · 표준 관리 정보"]
    M2 --> S["1.3.6.1.2.1.1 · 시스템 정보"]
    M2 --> I["1.3.6.1.2.1.2 · 인터페이스 정보"]
    S --> S3["1.3.6.1.2.1.1.3 · 켜진 뒤 흐른 시간"]
    I --> I10["1.3.6.1.2.1.2.2.1.10 · 들어온 바이트 수"]

주소는 위에서 아래로 가지를 치며 좁혀집니다. 맨 위 1.3.6.1 이 인터넷 구역이고, 그 아래 1.3.6.1.2.1 부터가 어느 장비에나 있는 표준 관리 정보입니다. 거기서 다시 시스템 정보와 인터페이스 정보로 갈라지고, 뒤로 갈수록 개별 값에 가까워집니다. 가지가 갈라질 때마다 숫자가 하나씩 붙습니다.

가지 끝의 값에는 사람이 읽을 이름도 함께 붙어 있습니다. 1.3.6.1.2.1.1.3 에는 sysUpTime, 1.3.6.1.2.1.2.2.1.10 에는 ifInOctets 라는 이름이 붙습니다. 사람은 이름으로 말하고 패킷에는 숫자가 실립니다.

한 왕복에 오가는 것

관리자가 주소를 적어 보내면 에이전트가 그 주소와 값을 함께 적어 돌려보냅니다. 왕복은 이 한 번으로 끝납니다. 다음 물음은 새 왕복입니다.

sequenceDiagram
    participant 관리자
    participant 에이전트
    관리자->>에이전트: GetRequest · 주소 1.3.6.1.2.1.1.3
    Note over 에이전트: 그 주소에 담긴 값을 찾는다
    에이전트-->>관리자: Response · 그 주소의 값 1425300
    Note over 관리자: 값을 적어 두고 왕복이 끝난다

응답에는 물어본 주소가 그대로 다시 실립니다. 한 번에 주소를 여럿 물을 수 있기 때문입니다. 관리자는 어느 값이 어느 주소의 것인지 짝지어야 합니다.

돌아오는 것은 숫자뿐이고 단위나 뜻은 붙어 오지 않습니다. 위의 1425300 이 시간인지 바이트인지는 그 주소를 적어 둔 MIB 를 봐야 압니다.

메시지 종류는 일곱입니다. 관리자가 먼저 보내는 것 넷과 에이전트가 내놓는 것 셋으로 갈립니다.

메시지 보내는 쪽 하는 일
GetRequest 관리자 주소를 대고 값을 묻는다
GetNextRequest 관리자 이 주소 다음 주소의 값을 묻는다
GetBulkRequest 관리자 다음 주소 여러 개를 한 번에 묻는다
SetRequest 관리자 값을 바꾸라고 시킨다
Response(GetResponse) 에이전트 물어본 주소와 값을 돌려준다
Trap 에이전트 묻지 않아도 먼저 알린다
InformRequest 에이전트 먼저 알리되 받았다는 답을 요구한다

주소를 모르는 표를 훑는 방법

앞 그림에서 잎이던 ifInOctets 는 값 하나가 아니라 포트마다 하나씩 있는 열입니다. 주소 끝에 포트 번호가 더 붙습니다.

그러니 포트마다 재는 값은 표처럼 놓입니다. 줄 하나가 포트 하나입니다. 열 하나는 "들어온 바이트 수"처럼 포트마다 똑같이 재는 항목입니다.

아래는 포트가 둘인 장비에서 열 두 개만 잘라 본 것입니다. 화살표는 주소가 늘어선 순서입니다.

flowchart TD
    subgraph C1["열 · ifInOctets"]
        A1["ifInOctets.1 · 포트 1"]
        A2["ifInOctets.2 · 포트 2"]
    end
    subgraph C2["열 · ifInUcastPkts"]
        B1["ifInUcastPkts.1 · 포트 1"]
        B2["ifInUcastPkts.2 · 포트 2"]
    end
    A1 --> A2
    A2 --> B1
    B1 --> B2

한 열을 끝까지 내려간 다음에 옆 열의 첫 줄로 넘어갑니다. 훑는 순서가 이 화살표를 그대로 따라갑니다.

그런데 장비의 포트가 몇 개인지는 장비마다 다릅니다. 관리자는 물어보기 전에는 줄 수를 모르니 있는 주소를 미리 다 적어 둘 수 없습니다.

그래서 "이 주소 다음"을 묻는 메시지가 따로 있습니다. 관리자는 표의 머리 주소를 대고 다음을 묻고, 답으로 받은 주소로 또 다음을 묻습니다. 표 밖으로 넘어간 주소가 돌아오면 거기서 멈춥니다.

물음  ifInOctets 다음
답    ifInOctets.1 = 980      // 포트 1
물음  ifInOctets.1 다음
답    ifInOctets.2 = 412      // 포트 2
물음  ifInOctets.2 다음
답    ifInUcastPkts.1 = 61    // 다음 열이다

마지막 답이 다른 열의 주소를 돌려주었으므로 이 열은 두 줄로 끝납니다. 포트가 둘뿐인 장비였다는 뜻입니다.

이렇게 한 줄씩 훑으면 왕복이 줄 수만큼 납니다. 포트가 수백 개인 장비에서는 그 왕복이 감시 서버와 장비 양쪽을 모두 붙잡습니다. 그래서 다음 주소 여러 개를 한 답장에 몰아 받는 메시지(GetBulkRequest)가 나중에 더해졌습니다.

장비가 먼저 말을 거는 길

관리자가 5분마다 묻는다면 그사이 30초 동안 났다 사라진 장애는 안 보입니다. 물어보는 방법만으로는 놓치는 사건이 있습니다.

이 빈틈을 메우려고 에이전트가 먼저 보내는 알림이 있습니다. 링크가 끊겼다거나 장비가 다시 켜졌다는 사건이 생기면 에이전트가 관리자 쪽으로 트랩을 쏩니다. 관리자는 그것을 받으려고 포트 하나를 열어 두고 기다립니다.

트랩은 답장을 요구하지 않습니다. 가는 길에 없어지면 보낸 에이전트도 관리자도 모릅니다. 그게 곤란한 알림에는 받았다는 답을 요구하는 갈래(InformRequest)를 씁니다. 답이 안 오면 에이전트가 다시 보냅니다.

아래 그림은 앞의 두 그림과 화살표 방향이 반대입니다. 에이전트에서 시작합니다.

sequenceDiagram
    participant 에이전트
    participant 관리자
    에이전트->>관리자: Trap · 링크가 끊겼다
    Note over 에이전트,관리자: 트랩은 여기서 끝난다. 없어져도 아무도 모른다
    에이전트->>관리자: InformRequest · 같은 사건
    관리자-->>에이전트: 받았다는 답
    Note over 에이전트: 답이 안 오면 다시 보낸다

같은 사건을 알리는 두 방법이 이렇게 갈립니다. 트랩은 한 번 쏘고 잊습니다. InformRequest 는 답을 받을 때까지 붙잡습니다.

UDP 위에 얹은 이유와 그 대가

SNMP 메시지는 UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜) 위에 실립니다. UDP 는 연결을 맺지 않고 한 덩이씩 그냥 보내는 방식입니다. 관리자가 묻는 메시지는 161 번 포트로 가고, 에이전트가 쏘는 알림은 162 번 포트로 갑니다.

연결을 맺지 않는 쪽을 고른 이유는 둘입니다. 하나는 물음과 답이 각각 한 덩이로 끝나서 연결을 이어 둘 이유가 없다는 것입니다. 다른 하나는 장비가 힘들 때도 답을 내보낼 수 있어야 한다는 것입니다. 연결을 맺는 방식은 상대마다 상태를 기억해야 해서, 메모리가 넉넉하지 않은 장비에서 먼저 무너집니다.

대가는 메시지가 없어지는 것입니다. 물음이든 답이든 도중에 사라져도 아무도 알려 주지 않습니다. 그래서 관리자가 스스로 시간을 재다가 답이 안 오면 다시 묻습니다. 얼마나 기다리고 몇 번 다시 물을지는 관리자 쪽이 정합니다.

판 셋과 그 사이의 차이

지금 쓰이는 판은 셋입니다. 셋 다 같은 주소 체계를 쓰고 메시지 모양도 크게 다르지 않습니다. 갈리는 것은 주로 상대가 누구인지 확인하는 방법입니다.

판 상대를 확인하는 방법 더해진 것
v1 약속한 문자열 하나를 평문으로 실어 보낸다 —
v2c v1 과 같다 여러 값을 한 번에 받는 메시지(GetBulkRequest) · 쉽게 한 바퀴 돌지 않는 64비트 카운터(아래 카운터 절)
v3 사용자마다 열쇠를 두고 서명과 암호를 건다 누가 어느 값을 읽을 수 있는지 정하는 규칙

v1 과 v2c 가 쓰는 그 문자열을 커뮤니티 스트링이라고 부릅니다. 암호 구실을 하지만 암호로 감싸지 않은 채 실려 갑니다. 같은 망을 들여다볼 수 있는 사람은 그 문자열을 그대로 읽습니다. v2c 이름 끝의 c 가 이 문자열 방식을 그대로 물려받았다는 표시입니다.

v3 은 그 문자열을 사용자 이름과 열쇠로 바꿨습니다. 메시지에 서명을 붙여 내용이 도중에 바뀌지 않았음을 확인합니다. 필요하면 본문을 암호로 감쌉니다. 읽기를 허용할 주소 범위를 사용자마다 따로 정하는 규칙도 이 판에서 생겼습니다.

한 망 안에서 판이 섞여 도는 것은 흔합니다. 오래된 장비는 v1 만 알아듣기도 합니다. 물음은 v3 으로 받고 알림은 v2c 로 쏘는 장비도 있습니다.

값을 바꾸는 메시지를 대개 닫아 두는 이유

SNMP 는 읽기만 하는 프로토콜이 아닙니다. 값을 바꾸라고 시키는 메시지가 있어서 포트를 내리거나 설정을 고치는 데도 쓸 수 있습니다.

그런데 이 기능을 꺼 두는 운영자가 많습니다. v1 과 v2c 에서는 문자열 하나만 알면 누구나 바꿀 수 있기 때문입니다. 읽기용과 쓰기용 문자열을 따로 두더라도 둘 다 암호 없이 오갑니다.

그 탓에 SNMP 는 실무에서 읽기 전용으로 쓰이는 일이 많습니다. 설정을 바꾸는 일은 장비에 직접 접속하거나 설정 전용 프로토콜로 넘깁니다.

카운터를 두 번 읽어야 하는 까닭

에이전트가 돌려주는 값 가운데 상당수는 계속 커지기만 하는 카운터입니다. 포트로 지나간 바이트 수가 그렇습니다. 장비가 켜진 뒤로 쌓인 총합이지 지금 속도가 아닙니다.

그래서 속도를 알고 싶으면 두 번 읽어 차이를 내야 합니다. 1분 간격으로 읽어 그 차이를 60 으로 나누면 초당 바이트가 나옵니다.

10:00:00  ifInOctets 1200000  // 1차
10:01:00  ifInOctets 1530000  // 2차
차이 330000 ÷ 60초            // 초당 5500

카운터는 담을 수 있는 최대값에 닿으면 0 으로 돌아갑니다. 32비트 카운터는 대역이 넓은 회선에서 금방 한 바퀴를 돕니다.

아래는 폴링 세 번과 네 번 사이에 그 한 바퀴가 낀 경우입니다. 세로축은 카운터 값이고 맨 위가 담을 수 있는 최대값입니다.

xychart-beta
    x-axis ["0분", "1분", "2분", "3분", "4분"]
    y-axis "카운터 값" 0 --> 100
    line [20, 50, 80, 10, 40]

3분 값이 2분 값보다 작습니다. 그대로 빼면 차이가 음수가 되어 속도가 엉뚱하게 나옵니다. 폴링 간격이 길수록 이런 되감김이 두 폴링 사이에 낄 확률이 높아집니다. 64비트 카운터가 나중 판에서 더해진 까닭입니다.

SNMP 를 고를 때와 안 고를 때

망 장비의 상태를 읽는 일에서는 아직 SNMP 가 기본입니다. 스위치·라우터·무정전 전원 장치처럼 남의 코드를 심을 수 없는 장비도 에이전트를 이미 달고 나오기 때문입니다.

직접 만든 서버 응용에는 잘 안 씁니다. 응용 안쪽 값을 SNMP 로 내보내려면 주소 체계부터 새로 정의해야 합니다. 값을 이름과 함께 그냥 밀어 보내는 방식이 훨씬 적은 품으로 끝납니다.

짧게 났다 사라지는 사건이나 초보다 촘촘한 값에도 안 맞습니다. 묻고 답하는 방식이라 묻는 간격보다 짧은 일은 안 보입니다. 장비 쪽이 스스로 값을 계속 밀어 보내는 스트리밍 텔레메트리가 그 빈틈을 겨냥합니다.

관련 항목

SNMP 가 주고받는 메시지 종류

GetRequest · GetNextRequest · GetBulkRequest · SetRequest · GetResponse · Trap · InformRequest

SNMP 에 관여하는 역할·참여자

망 관리 스테이션 · SNMP 에이전트 · 관리 대상 객체 · 프록시 에이전트 · 서브에이전트

SNMP 가 값에 이름을 붙이는 데 쓰는 체계

MIB · OID · MIB-II · SMI · ASN.1 · BER · 엔터프라이즈 MIB

SNMP 로 실제로 읽어 오는 장비 상태 값

sysUpTime · ifInOctets · ifOperStatus · 인터페이스 카운터 · 게이지 · 카운터 랩어라운드

SNMP 메시지를 실어 나르는 하위 프로토콜

UDP · IP · 포트 번호 · 데이터그램 · TCP

SNMP 판마다 갈리는 인증·암호 수단

커뮤니티 스트링 · USM · VACM · HMAC · AES · SNMPv3

SNMP 를 구현하거나 값을 긁어 오는 프로그램

Net-SNMP · snmpd · snmpwalk · Zabbix · Nagios · LibreNMS · Cacti · SNMP Exporter

SNMP 대신 쓸 수 있는 다른 수집 방식

스트리밍 텔레메트리 · NETCONF · gNMI · IPFIX · NetFlow · sFlow · syslog · OpenTelemetry

SNMP 가 감시 대상으로 삼는 장비

라우터 · 스위치 · 방화벽 · 로드 밸런서 · 무정전 전원 장치 · 프린터 · 네트워크 인터페이스

SNMP 를 노리는 공격과 그 대비

SNMP 증폭 공격 · UDP 반사 공격 · IP 스푸핑 · 접근 제어 목록 · 관리 전용 망

SNMP 를 정의하는 표준 문서

RFC 1157 · RFC 1213 · RFC 3411 · RFC 3416 · STD 62 · IETF · IANA

SNMP 로 모은 값을 다루는 감시 개념

모니터링 · 폴링 · 풀 모델 · 메트릭 · 시계열 · 임계값 경보 · 텔레메트리

다른 이름: Simple Network Management Protocol · 간이 망 관리 프로토콜