By the SNMP Monitoring team · Reviewed July 2026
In SNMPv1/v2c the community string is the only thing standing between your agent and anyone who can reach it. It's a shared password sent in cleartext on every poll — so treat it like a password, not a label. This is the hardening how-to: replace the defaults, use a random read-only string, pin it to your poller's source IP, scope what it can read, and know when to stop patching v2c and move to v3. For what a community string is conceptually, see the community string explainer; this page is how to configure it safely.
Parent: setup. Deep config: snmpd.conf.
Step 1: Never keep 'public' / 'private'
The two defaults — public (read-only) and private (read-write) — are the first thing every scanner tries. Leaving them in place is equivalent to running with no password at all:
- Internet scanners sweep UDP 161 for
publicconstantly; a default-config agent is found within minutes of exposure. publicalone leaks your entire device inventory, topology, and running config to anyone who asks.privateis worse — read-write access means an attacker can change settings, not just read them.
Delete them and set your own. This is step zero of any SNMP deployment; nothing else you do matters if public is still there.
Step 2: Use a random read-only string
Replace the default with a long, random, read-only community in snmpd.conf:
rocommunity kQ8vN2pRxL7mZ4wT 10.0.0.5
Treat it like a generated secret, not a word:
- Generate it randomly — e.g.
openssl rand -base64 16— so it isn't guessable. - Use
rocommunity(read-only), neverrwcommunity, unless you truly need writes. - Make it long enough that brute-forcing is impractical (16+ characters).
- Store it in your secrets manager, not in a wiki or a committed config.
A random read-only string closes off the trivial-guess attack. It does not encrypt anything — which is why the next steps matter too.
Step 3: Restrict by source IP
The rocommunity directive takes a source argument — use it to accept the community only from your manager(s):
rocommunity kQ8vN2pRxL7mZ4wT 10.0.0.5
That trailing 10.0.0.5 means the string is honoured only when the request comes from that address; a CIDR like 10.0.0.0/24 scopes it to a subnet. For the fuller com2sec/group/access form, see snmpd.conf. The source restriction is what turns a cleartext password from "anyone who sniffs it can replay it from anywhere" into "anyone who sniffs it must also spoof a trusted source" — a meaningful hurdle, though not a substitute for encryption.
Step 4: Scope OIDs (allowlist)
Even a random, source-pinned string should only expose what your poller actually reads. Bind the community to a VACM view so a leaked string reveals a handful of subtrees, not the whole MIB:
rocommunity kQ8vN2pRxL7mZ4wT 10.0.0.5 -V monitoring
The -V monitoring limits the community to a named view. Building that view — which subtrees to allow — is covered in full on OID allowlist. This is defence in depth: if the string ever leaks, its blast radius is capped to the metrics you chose to expose.
Step 5: Avoid read-write
rwcommunity grants SetRequest — the ability to change the device over SNMP. That's a much larger risk than read access, because a leaked read-write string lets an attacker reconfigure interfaces, reboot gear, or flip PDU outlets. Most monitoring is entirely read-only, so there's rarely a reason to enable writes. If you genuinely need Sets (say, PDU outlet control), use SNMPv3 with write access scoped as tightly as possible rather than a v2c rwcommunity. When in doubt, leave read-write off.
Step 6: Prefer SNMPv3 where possible
Everything above hardens v2c, but none of it encrypts the community — a determined attacker who can capture a packet still sees the string. The real fix is SNMPv3, which authenticates with a hash and encrypts the payload, so a sniffed packet reveals neither the credential nor the data. Use v2c-with-hardening only on a trusted management segment; the moment traffic crosses anything untrusted, move to v3.
The hardening layers at a glance
None of these steps is sufficient alone — they stack. Think of them as concentric defences, each covering a gap the previous one leaves open:
| Layer | Attack it blocks | What it does NOT block |
|---|---|---|
| Random string | Default/dictionary guessing | Packet capture |
| Source-IP restriction | Use from an unknown host | Source spoofing, capture |
| OID allowlist | Full-MIB disclosure if leaked | Reading the allowed subtrees |
| Read-only (no rwcommunity) | Config changes / SetRequests | Reading data |
| SNMPv3 | Capture, spoofing, disclosure | — |
Read the table top to bottom and the pattern is clear: each v2c layer closes one door but leaves the "packet capture" door open, and only the final row — moving to v3 — shuts it. That's the honest summary of v2c hardening. It's genuinely worth doing on a trusted segment, because it raises the bar from "trivial" to "requires on-path capture and source spoofing," but it never reaches confidentiality. Treat the stack as a way to buy safety where v3 isn't yet an option, not as a permanent substitute for it. When you can run v3, the whole table collapses into one row.
Verifying
Confirm the new string works and the old one doesn't:
snmpwalk -v2c -c kQ8vN2pRxL7mZ4wT <host> system
SNMPv2-MIB::sysDescr.0 = STRING: Linux web01 5.15.0-generic x86_64
SNMPv2-MIB::sysUpTime.0 = Timeticks: (12345678) 1 day, 10:17:36.78
Then try the old default and confirm it fails:
snmpwalk -v2c -c public <host> system
Timeout: No Response from <host>
A timeout on public and data on your random string means the change took. Keep real community strings out of shell history and committed scripts.
Frequently asked questions
How do I change the SNMP community string?
Edit /etc/snmp/snmpd.conf, replace any rocommunity public (or rwcommunity private) with a random read-only string plus a source restriction — e.g. rocommunity <random> 10.0.0.5 — then restart snmpd. Verify with snmpwalk using the new string and confirm the old public no longer responds.
Is a community string encrypted?
No. In SNMPv1 and v2c the community string travels in cleartext on every request, so anyone who can capture a packet can read it. A source-IP restriction limits where it can be used but does not encrypt it. Only SNMPv3 encrypts the credential and payload.
How do I restrict who can use the community string?
Add a source argument to the rocommunity line — rocommunity <string> <IP-or-CIDR> — so the string is accepted only from your manager's address or subnet. For finer control use the com2sec/group/access chain. Combine it with an OID allowlist to also cap what the string can read.
Should I use a read-write community?
Avoid it. rwcommunity allows SetRequests that can change device configuration, which is a far bigger risk than read-only monitoring — and it travels in the same cleartext. Most monitoring needs only reads. If you truly need writes, use SNMPv3 with tightly scoped write access instead of a v2c read-write community.
Key takeaways
- The community string is a cleartext password — treat it like one.
- Delete
public/privatefirst; they're the first thing scanners try. - Use a random read-only string via
rocommunity, 16+ chars, from a secrets manager. - Pin the source IP on the
rocommunityline, and scope OIDs with-V <view>(allowlist). - Avoid
rwcommunity; use SNMPv3 if you need writes. - v2c hardening doesn't encrypt — prefer SNMPv3 off trusted segments. The ostr.io external check uses exactly this random-string-plus-allowlist pattern; see external monitoring.