Pull to refresh

A Quick Guide to Setting Up SNMPv3

Reading time7 min
Views699
Original author: Vadim Rybalko

Setting up a v3 user on the server-side agent for the default Linux snmpd (net-snmp package).
Out of scope: SNMP traps and read-write (rw) users.

SNMP version 3 allows packet transmission in encrypted form, making it safe to transfer telemetry over public networks without the risk of exposing either authentication information (analogous to a community string) or the data stream itself, which is encrypted using a symmetric algorithm with a shared key.

A Reminder: How v1/v2c Is Configured

In SNMP v1/v2c, the concept of a community is used. This is essentially a passphrase that the agent receives from the client. If the community matches access settings (for example, if the client’s IP address is within the allowed range), the agent returns the telemetry. Everything is transmitted in plaintext, including both the community string and the requested telemetry.

Example requests in tcpdump (with community comminity_name):

tcpdump: listening on br0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:28:09.382435 IP (tos 0x48, ttl 44, id 25108, offset 0, flags [DF], proto UDP (17), length 74)
    192.158.1.38.46214 > 198.51.100.1.161:  { SNMPv2c C="comminity_name" { GetNextRequest(25) R=1193096294  .1.3.6.1.2.1 } } 
20:28:09.414940 IP (tos 0x48, ttl 44, id 25112, offset 0, flags [DF], proto UDP (17), length 77)
    192.158.1.38.46214 > 198.51.100.1.161:  { SNMPv2c C="comminity_name" { GetNextRequest(28) R=1193096295  .1.3.6.1.2.1.1.1.0 } } 
20:28:09.447385 IP (tos 0x48, ttl 44, id 25117, offset 0, flags [DF], proto UDP (17), length 77)
    192.158.1.38.46214 > 198.51.100.1.161:  { SNMPv2c C="comminity_name" { GetNextRequest(28) R=1193096296  .1.3.6.1.2.1.1.2.0 } } 
20:28:09.479880 IP (tos 0x48, ttl 44, id 25125, offset 0, flags [DF], proto UDP (17), length 77)
    192.158.1.38.46214 > 198.51.100.1.161:  { SNMPv2c C="comminity_name" { GetNextRequest(28) R=1193096297  .1.3.6.1.2.1.1.3.0 } } 
20:28:09.512357 IP (tos 0x48, ttl 44, id 25128, offset 0, flags [DF], proto UDP (17), length 77)
...

NB: In tcpdump here and below, only requests are shown—responses are omitted.

To configure v2 community, add a line to /etc/snmp/snmpd.conf with the following syntax:

rocommunity[6] communityname [access] [-V view]

Where:

  • 6 (optional) – enables IPv6 (separate from IPv4)

  • communityname – the name of the community, effectively a shared password

  • access (optional) – access control options: default, hostname, network/bits

  • -V view (optional) – limits visibility to a specific OID subtree (configured separately; out of scope here)

A basic example:

rocommunity  comminity_name
rocommunity6 comminity_name

This sets up a single read-only community called comminity_name for both IPv4 and IPv6 with no additional access restrictions.

That should be enough to understand the basics.

Authentication in SNMPv3

Version 3 drops the term community. Or rather, it’s been reworked, but the term itself is no longer used. Now there’s encryption for both the stream and the authentication data. What’s used instead?

  • A username

  • An authentication password

  • An encryption password

So instead of a familiar “login/password” pair, we get a less intuitive “login/two passwords” model. Each password also requires an associated algorithm:

  • The authentication password uses a hashing algorithm—traditionally MD5 or SHA (with SHA variants introduced in later versions)

  • The encryption password uses a symmetric encryption algorithm—traditionally DES or AES (again, later AES variants exist)

A sample v3 request in tcpdump looks like this:

tcpdump: listening on br0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23:28:39.753314 IP (tos 0x48, ttl 44, id 62294, offset 0, flags [DF], proto UDP (17), length 92)
    192.158.1.38.48116 > 198.51.100.1.161:  { SNMPv3 { F=r } { USM B=0 T=0 U="" } { ScopedPDU E= C="" { GetRequest(14) R=30306933  } } } 
23:28:39.785927 IP (tos 0x48, ttl 44, id 62301, offset 0, flags [DF], proto UDP (17), length 171)
    192.158.1.38.48116 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=9 T=330 U="user_name" } { ScopedPDU [!scoped PDU]8f_6f_9f_0a_aa_3b_69_8c_02_30_66_48_52_7d_52_2b_9e_b0_a2_84_cc_60_8a_9e_d5_67_30_52_26_88_0e_68_a7_89_5d_df_78_a4_9b_4e_62_dc_f6_54_f8_16_00_02_ba_f7} } 
23:28:39.818831 IP (tos 0x48, ttl 44, id 62308, offset 0, flags [DF], proto UDP (17), length 174)
    192.158.1.38.48116 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=9 T=330 U="user_name" } { ScopedPDU [!scoped PDU]f1_46_7e_ec_3a_d4_38_94_69_38_14_73_20_71_de_1a_24_b2_61_56_d9_a2_c3_20_b2_6b_6e_11_5f_23_25_f7_56_ba_09_df_09_82_79_54_ec_22_7a_f5_81_60_52_59_83_65_40_09_ac} } 
23:28:39.851664 IP (tos 0x48, ttl 44, id 62310, offset 0, flags [DF], proto UDP (17), length 174)
    192.158.1.38.48116 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=9 T=330 U="user_name" } { ScopedPDU [!scoped PDU]43_30_e9_c9_7c_e2_07_9e_41_74_53_98_51_79_ff_7b_26_51_93_b2_fe_35_db_8e_a4_67_58_87_3e_de_8c_f6_5a_3e_1d_a4_47_d7_3d_f9_c8_b1_ac_2f_d2_48_3a_57_d0_f4_a8_45_9c} } 
23:28:39.884478 IP (tos 0x48, ttl 44, id 62316, offset 0, flags [DF], proto UDP (17), length 174)
    192.158.1.38.48116 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=9 T=330 U="user_name" } { ScopedPDU [!scoped PDU]a0_35_d4_83_cb_6a_82_f1_bd_d7_16_58_00_ff_d7_5e_03_3a_01_c8_be_2e_6d_e5_bf_eb_7c_ce_07_12_76_fc_ee_6e_61_dc_18_d3_4b_7e_dd_f7_bc_f1_3e_de_ad_52_a2_2e_22_ea_74} } 
...

Note that the username is not encrypted, so be careful not to leak anything unnecessary in transit.

Configuration is a bit more involved. You can’t just drop a pre-written line into the config (with caveats), because authentication data is generated when the user is created. This complicates deployment using common tools like Ansible.

Both the agent and client must share the following (besides the agent hostname):

  • Username

  • Authentication password (CLI option -a for net-snmp)

  • Authentication algorithm (-A)

  • Encryption password (-x)

  • Encryption algorithm (-X)

In addition to the main config /etc/snmp/snmpd.conf, there are at least two other files for dynamic user creation and auth data storage:

  • /var/lib/snmp/snmpd.conf

  • /usr/share/snmp/snmpd.conf

The snmpd daemon writes the necessary lines on startup. So before creating a user, the process must be stopped. If not, the built-in script will refuse to create a user, since it overwrites one of these files in-memory at startup.

To create a user on the agent, use:

net-snmp-create-v3-user -ro -a 'auth_pass' -A SHA -x 'priv_pass' -X AES user_name

This creates a read-only user named user_name with:

  • auth_pass (SHA)

  • priv_pass (AES)

The script writes lines to the two mentioned config files:

  • /var/lib/snmp/snmpd.conf:
    createUser user_name SHA "auth_pass" AES "priv_pass"

  • /usr/share/snmp/snmpd.conf:
    rouser user_name

But that’s not all. On startup, snmpd modifies /var/lib/snmp/snmpd.conf: all createUser lines are removed and replaced with something like:

usmUser 1 3 0x80001f888052e226409c42d06300000000 "user_name" "user_name" NULL .1.3.6.1.6.3.10.1.1.3 0x018a3bb9c17caafed74347e50d918963e37e70d7 .1.3.6.1.6.3.10.1.2.4 0xcfdecd0e1bc6bf08eb7ae90e68bdb414 ""

The /usr/share/snmp/snmpd.conf file remains unchanged. You can manage these usmUser lines with the CLI utility snmpusm (see man).

SNMPv3 Security Levels

Let’s briefly touch on SNMPv3 security levels. Common levels include:

  • noAuthNoPriv — no authentication, no encryption

  • authNoPriv — authenticated but unencrypted

  • authPriv — authenticated and encrypted

The first is rarely used; let’s focus on authNoPriv and authPriv.

Sample tcpdump output for authNoPriv:

10:50:58.534839 IP (tos 0x48, ttl 44, id 54935, offset 0, flags [DF], proto UDP (17), length 92)
    192.158.1.38.20723 > 198.51.100.1.161:  { SNMPv3 { F=r } { USM B=0 T=0 U="" } { ScopedPDU E= C="" { GetRequest(14) R=1808634162  } } } 
10:50:58.567563 IP (tos 0x48, ttl 44, id 54937, offset 0, flags [DF], proto UDP (17), length 162)
    192.158.1.38.20723 > 198.51.100.1.161:  { SNMPv3 { F=ar } { USM B=10 T=39805 U="user_name" } { ScopedPDU E=_80_00_1f_88_80_52_e2_26_40_9c_42_d0_63_00_00_00_00 C="" { GetNextRequest(25) R=1808634161  .1.3.6.1.2.1 } } } 
10:50:58.600457 IP (tos 0x48, ttl 44, id 54945, offset 0, flags [DF], proto UDP (17), length 165)
    192.158.1.38.20723 > 198.51.100.1.161:  { SNMPv3 { F=ar } { USM B=10 T=39805 U="user_name" } { ScopedPDU E=_80_00_1f_88_80_52_e2_26_40_9c_42_d0_63_00_00_00_00 C="" { GetNextRequest(28) R=1808634163  .1.3.6.1.2.1.1.1.0 } } } 
...

And for authPriv:

10:51:47.463848 IP (tos 0x48, ttl 44, id 61280, offset 0, flags [DF], proto UDP (17), length 92)
    192.158.1.38.54277 > 198.51.100.1.161:  { SNMPv3 { F=r } { USM B=0 T=0 U="" } { ScopedPDU E= C="" { GetRequest(14) R=1901099838  } } } 
10:51:47.496541 IP (tos 0x48, ttl 44, id 61282, offset 0, flags [DF], proto UDP (17), length 172)
    192.158.1.38.54277 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=10 T=39854 U="user_name" } { ScopedPDU [!scoped PDU]f2_87_ea_15_87_25_a7_b8_44_b4_38_62_15_86_d4_4e_1a_99_34_9e_6c_4d_6a_39_ea_1c_d7_1c_6e_f6_1f_76_c0_e2_ba_91_4d_8e_d5_9c_e7_06_29_c1_47_6e_a2_9a_2b_5c} } 
10:51:47.529402 IP (tos 0x48, ttl 44, id 61290, offset 0, flags [DF], proto UDP (17), length 175)
    192.158.1.38.54277 > 198.51.100.1.161:  { SNMPv3 { F=apr } { USM B=10 T=39854 U="user_name" } { ScopedPDU [!scoped PDU]da_e4_d6_48_f1_ea_28_7f_bf_ce_d6_e0_ef_f7_95_06_0c_d7_79_7c_f1_4b_78_75_4f_1a_e2_00_a6_83_d5_e6_c2_82_55_0f_09_a4_7d_f1_e1_f2_a0_64_d3_c3_d7_13_c3_ae_95_8b_db} } 
...

You can see that in authNoPriv, only the authentication part is encrypted—requested OIDs are visible. In authPriv, the entire payload is encrypted, increasing the packet size slightly. While this adds some CPU overhead, it’s negligible today given the speed of symmetric encryption with a shared key.

Configuring the Client

You can test whether SNMP is working using the built-in snmpwalk tool.

For SNMP v2c (community-based):

snmpwalk -v 2c -c communityname hostname

Where:

  • communityname — the community name

  • hostname — the agent’s hostname

For SNMP v3 with authPriv encryption:

snmpwalk -v 3 -a SHA -A auth_pass -x AES -X priv_pass -l authPriv -u user_name hostname

Where:

  • SHA — authentication algorithm

  • auth_pass — authentication password

  • AES — encryption algorithm

  • priv_pass — encryption password

  • authPriv — "authenticated + encrypted" security level

  • user_name — the username

  • hostname — the agent’s hostname

If that works, just fill in the corresponding values in your monitoring software.

CC BY-SA, Vadim Rybalko. SNMPv3 Configuration in LibreNMS.
CC BY-SA, Vadim Rybalko. SNMPv3 Configuration in LibreNMS.

If something isn’t working, check firewall rules on both ends. Try running snmpwalk from the monitoring host and inspect the traffic with tcpdump. Also test SNMP access from the agent host itself, using both the external IP and loopback addresses like 127.0.0.1 or ::1.

Tags:
Hubs:
0
Comments0

Articles