\documentclass{ictlab} \errorcontextlines=99 \RCS $Revision: 1.17 $ \usepackage{verbatim,key,alltt,subfigure} \usepackage[hang,bf,nooneline]{caption2} \ifx\pdftexversion\undefined \else \usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref} \fi \newcommand*{\labTitle}{SNMP Agent, the Set Operation, Traps and Notifications}% \providecommand*{\SNMP}{\acro{SNMP}\xspace} \providecommand*{\MIB}{\acro{MIB}\xspace} \providecommand*{\ID}{\acro{ID}\xspace} \providecommand*{\OID}{\acro{OID}\xspace} \providecommand*{\FAQ}{\acro{FAQ}\xspace} \providecommand*{\EGP}{\acro{EGP}\xspace} \providecommand*{\RPM}{\acro{RPM}\xspace} \providecommand*{\VACM}{\acro{VACM}\xspace} \renewcommand{\floatpagefraction}{0.75} % default is .5, to increase % density. \renewcommand*{\bottomfraction}{0.6} % default is 0.3 \renewcommand*{\topfraction}{0.85} % default is 0.7 \renewcommand*{\textfraction}{0.1} % default is 0.2 \begin{document} \tableofcontents % \Large \section{Background} Before you do this exercise, you will need a Linux installation on your hard disk. To see how to do this, refer to the document \url{http://nicku.org/snm/lab/install-linux/install-linux.pdf}. You will then need to configure \texttt{sudo} as described in \url{http://nicku.org/ossi/lab/sudo/sudo.pdf}. You then need to configure your \SNMP agent to allow \texttt{set-request} and \texttt{get-request} operations as described below. For this exercise, you will set a simple \emph{community string} for read and another for read-write operations. The agent is called \texttt{snmpd}. The configuration for the agent is in the file \texttt{/etc\allowbreak/snmp\allowbreak/snmpd.conf}. \subsection{Traps and Inform Requests} \label{sec:traps-and-notifications} \begin{figure}[htb] \centering% \mbox{% \subfigure[Traps]% {\label{sbf:trap}\includegraphics[height=0.2\linewidth]{trap}}% \qquad% \subfigure[Notification]% {\label{sbf:inform}\includegraphics[height=0.2\linewidth]{inform}} }% \caption{Traps get no response, while an \SNMP{}v2 inform requires a response. The agent may resend the inform-request after a timeout period during which it gets no response.} \label{fig:traps-and-notifications} \end{figure} All versions of \SNMP support a mechanism called a \emph{trap} or \emph{inform request}. A \emph{trap} or \emph{inform request} is like an interrupt from the agent to the manager. There is no response to a trap, as seen in figure~\vref{sbf:trap}, whereas inform requests have responses, as shown in figure~\ref{sbf:inform}. A trap usually indicates something is wrong, allowing the manager software to take actions such as flag the problem with a red symbol, and perhaps send email and perhaps a short message to the management team. The Net-\SNMP tools provide the \texttt{snmptrap} command to send traps and notifications, and the \texttt{snmptrapd} program to receive them. \subsection{SNMPv1 traps} \label{sec:snmpv1-traps} Traps in \SNMP version 1 come with seven ``generic traps'' as shown in table~\vref{tab:generic-traps}. \begin{table}[htb] \begin{tabularx}{\linewidth}[t]{@{}>{\ttfamily}lX@{}} \toprule% \textnormal{\textbf{Generic trap name}}& \\[-0.5ex] \textnormal{\textbf{and number}} & \textbf{Definition}\\ \midrule% coldStart(0) & Shows the agent has been restarted.\\ warmStart(1) & Indicates that the agent has reinitialised itself. None of the management variables have been reset.\\ linkDown(2) & Sent when an interface on the device has gone down. The first variable binding indicates which interface went down.\\ linkUp(3) & Sent when an interface on the device comes back up. The first variable binding indicates which interface came up.\\ authenticationFailure(4) & Indicates someone used the wrong community string to access your agent. Useful to detect if someone is attacking your device using \SNMP.\\ egpNeighborLoss(5) & Indicates that an \emph{Exterior Gateway Protocol} (\EGP) neighbour has gone down.\\ enterpriseSpecific(6) & Indicates that the trap is enterprise specific. Devices from vendors often come with their own \SNMP traps under the vendor's branch under the private-enterprise node of the \MIB tree. To process this, the \NMS needs to decode the trap number from the \SNMP message. You can implement your own traps. See the example below, where a trap \MIB module defines a trap.\\ \bottomrule \end{tabularx} \caption{Generic traps in \SNMP version 1.} \label{tab:generic-traps} \end{table} You can define your own \MIB for your own specific traps. See the exercises in section~\vref{sec:traps-exercises}. \subsection{Using \texttt{snmptrap} to send traps} \label{sec:snmptrap} The syntax of the program \texttt{snmptrap} for sending \SNMP{}\,v1 traps is: \begin{alltt} $ \textbf{snmptrap -v 1 -c \meta{community-string} \meta{hostname} \meta{enterprise-oid} \meta{agent} \bs \meta{generic-trap} \meta{specific-trap} \meta{uptime} \textmd{[}\meta{OID} \meta{type} \meta{value}\textmd{]}\ldots} \end{alltt}%$ \begin{table}[htb] \begin{tabularx}{\linewidth}{@{}lX@{}} \toprule% \textbf{Argument} & \textbf{Meaning}\\ \midrule% \meta{hostname} & the hostname of the manager to which you are sending the trap.\\ \meta{enterprise-oid} & the \OID under which a number of different enterprise traps may be defined. In the example below, this is \texttt{TRAP-TEST-MIB::demotraps}.\\ \meta{agent} & the hostname or \IP address of the agent. If you leave this as \texttt{""}, then it will be set to the address of the current machine. This may seem pointless, but it is important when you use a proxy.\\ \meta{generic-trap} & the number from table~\vref{tab:generic-traps}, which is in the range 0\ldots6. \\ \meta{specific-trap} & the number of the trap defined under the \MIB object \meta{enterprise-oid}. In the example below, this is 17, corresponding to \texttt{TRAP-TEST-MIB::demo-trap}. \\ \meta{uptime} & normally an empty string; that means use the local value of \texttt{sysUpTime} on this agent.\\ \meta{OID} & there may be one or more variable values sent with the trap to indicate what is happening. You provide them in a group of \meta{OID} \meta{type} \meta{value}\\ \meta{type} & The data type of the value sent. Usually \texttt{i} for integer, or \texttt{s} for string. \texttt{man snmptrap} for all the types.\\ \meta{value} & the value of the variable that is sent in the trap.\\ \bottomrule \end{tabularx} \caption{The required arguments for an \SNMP{}v1 trap with the format: \texttt{snmptrap -v 1 -c \meta{community-string} \meta{hostname} \meta{enterprise-oid} \meta{agent} \meta{generic-trap} \meta{specific-trap} \meta{uptime} {[{\meta{OID} \meta{type} \meta{value}}]}\ldots}} \label{tab:snmpv1-arguments} \end{table} \subsection{SNMPv2c Notifications} \label{sec:snmpv2c-notifications} In \SNMP{}v2c and v3, the agent sends \emph{notifications}. Notification is a macro which sends either a trap or an inform request. An inform request is like a trap with an acknowledgment. A trap is simpler; it has no generic numbers, specific numbers or enterprise \OID{}s. As with \SNMP{}v1 traps, you will use \texttt{''} to indicate the current system uptime. The syntax for generating an \SNMP{}v2 notification is \begin{alltt} $ \textbf{snmptrap -v 2c -c \meta{community-string} \meta{hostname} \meta{uptime} \meta{trapOID} \bs \textmd{[}\meta{OID} \meta{type} \meta{value}\textmd{]}\ldots} \end{alltt}%$ The meaning of each argument is the same as for \SNMP{}v1 traps, except for the \meta{trapOID}, which is the \OID of a complete \MIB object which must be defined for the notification. \section{Procedure} \subsection{Installing and Configuring the Agent} \label{sec:Configuring the Agent} I took the \texttt{net-snmp} source \RPM software package from Fedora Core 1 and compiled it on Red Hat 9. I did this because it provides better support for Perl \SNMP programming. We will install the resulting binary software packages from an \NFS directory on our server. \begin{enumerate} \item Change to the network directory: \begin{alltt} $ \textbf{cd /home/nfs/snmp} \end{alltt}%$ \item Now install the software packages: \begin{alltt} $ \textbf{sudo rpm -Uhv net-snmp-*5.0.9-2.i386.rpm} \end{alltt}%$ \begin{explanation} Note the asterisk `\texttt{*}'. I suggest press the \key{Tab} key to complete the file name, then add the asterisk afterwards, to reduce typing mistakes. \end{explanation} %% \item Verify that the agent is installed: %% \begin{alltt} %% $ \textbf{rpm -qa | grep net-snmp} %% net-snmp-devel-5.0.6-17 %% net-snmp-5.0.6-17 %% net-snmp-utils-5.0.6-17 %% \end{alltt}%$ %% \begin{explanation} %% See the note further down about the \RPM package manager. Here we %% are listing all the software packages installed on the system, and %% just looking for those with the string ``\texttt{net-snmp}'' in %% the name. %% \end{explanation} %% If not, then install it like this: %% \begin{enumerate} %% \item Use \texttt{yum}: %% \begin{alltt} %% $ \textbf{sudo yum install net-snmp\bs*} %% \end{alltt}%$ %% %% \item mount the network drive from %% %% \texttt{ictlab\allowbreak.tyict\allowbreak.vtc\allowbreak.edu\allowbreak.hk:\allowbreak/var\allowbreak/ftp\allowbreak/pub} %% %% on some convenient directory: %% %% \begin{alltt} %% %% $ \textbf{sudo mkdir /mnt/nfs} %% %% $ \textbf{sudo mount nicku.org:/var/ftp/pub /mnt/nfs} %% %% \end{alltt} %% \item OR if \texttt{yum} is not set up properly on your machine, %% install them manually: %% \begin{enumerate} %% \item Change to directory containing the software: %% \begin{alltt} %% $ \textbf{cd /home/nfs/rh-9.0-updated/RedHat/RPMS} %% \end{alltt}%$ %% \item \dots and install the software. %% \begin{enumerate} %% \item If no packages are installed, then do this: %% \begin{alltt} %% $ \textbf{sudo rpm -Uhv net-snmp-*.rpm} %% \end{alltt}%$ %% \item Otherwise install only the ones that are missing. %% \end{enumerate} %% \end{enumerate} %% \end{enumerate} \item Edit the configuration for the \SNMP agent: \begin{alltt} $ \textbf{xhost +localhost} $ \textbf{sudo -v} $ \textbf{sudo emacs /etc/snmp/snmpd.conf &} \end{alltt}%$ \begin{explanation} The first line allows users other than your own account (such as the user root) to display graphical objects on your local X server. The second line starts a new five-minute password free period for \texttt{sudo}. If the five-minute period has expired, then the editor cannot start in the background; \texttt{sudo} will wait for you to bring it to the foreground by typing \texttt{fg}, so that you can enter your password. Typing \texttt{sudo -v} simply avoids this inconvenience. \end{explanation} %% \item Comment out the section on \texttt{Access Control} by selecting %% it with your mouse, and then press %% \key{Alt-x}\allowbreak\,\texttt{comment-region}, or go through and %% comment each line out by hand. Note that %% \key{Alt-x}\allowbreak\,\texttt{comment-region} will work if you are %% logged into your \LDAP account, where you have my nice %% \texttt{.emacs} macro file. %% \begin{explanation} %% Note that this is a large section of the configuration file: there %% are about five lines in mine that start with options %% \texttt{com2sec}, \texttt{group}, \texttt{view} and %% \texttt{access}. These need to be commented out, since they %% impose too tight an access control for our exercises here. %% \end{explanation} % #### % # First, map the community name "public" into a "security name" % # sec.name source community % # com2sec notConfigUser default public % # #### % # # Second, map the security name into a group name: % # # groupName securityModel securityName % # group notConfigGroup v1 notConfigUser % # group notConfigGroup v2c notConfigUser % # #### % # # Third, create a view for us to let the group have rights to: % # # name incl/excl subtree mask(optional) % # view systemview included system % # #### % # # Finally, grant the group read-only access to the systemview view. % # # group context sec.model sec.level prefix read write notif % # access notConfigGroup "" any noauth exact systemview none none \item Configure two community strings in the \texttt{snmpd.conf} file, as in the following patch.\label{ste:community-strings} Note that we are using \VACM commands here; we could just use \texttt{rocommunity} and \texttt{rwcommunity} instead (see \texttt{man snmpd.conf}), but we are learning about \VACM. {\footnotesize \begin{verbatim} --- snmpd.conf~ 2003-11-28 16:25:40.000000000 +0800 +++ snmpd.conf 2003-12-01 11:47:49.000000000 +0800 @@ -39,13 +39,16 @@ # sec.name source community com2sec notConfigUser default public +com2sec RWUser default private #### # Second, map the security name into a group name: # groupName securityModel securityName -group notConfigGroup v1 notConfigUser +group notConfigGroup v1 notConfigUser group notConfigGroup v2c notConfigUser +group RWGroup v1 RWUser +group RWGroup v2c RWUser #### # Third, create a view for us to let the group have rights to: @@ -54,12 +57,15 @@ # name incl/excl subtree mask(optional) view systemview included .1.3.6.1.2.1.1 view systemview included .1.3.6.1.2.1.25.1.1 +view all included .1 #### # Finally, grant the group read-only access to the systemview view. # group context sec.model sec.level prefix read write notif -access notConfigGroup "" any noauth exact systemview none none +#access notConfigGroup "" any noauth exact systemview none none +access notConfigGroup "" any noauth exact all none none +access RWGroup "" any noauth exact all all all # ----------------------------------------------------------------------------- \end{verbatim}% } \begin{explanation} You can see all the options that the agent can understand in its configuration file \texttt{snmpd.conf} by typing \texttt{snmpd~-H}, and of course, from the man page: \texttt{man snmpd.conf}. Another good source of information about the Net-\SNMP tools is the Net-\SNMP \FAQ: \url{http://net-snmp.sourceforge.net/FAQ.html}, and also the Net-\SNMP tutorials: \url{http://net-snmp.sourceforge.net/tutorial/}. Note that ``in real life,'' these passwords are sensitive, and should be selected as you would any other password. \end{explanation} \item Start the agent: \begin{alltt} $ \textbf{sudo /sbin/service snmpd start} \end{alltt}%$ \item Enable the agent to always start when the computer boots: \begin{alltt} $ \textbf{sudo /sbin/chkconfig snmpd on} $ \textbf{/sbin/chkconfig snmpd --list} \end{alltt} \begin{explanation} The first command ensures that the next time a computer boots on your hard disk, it will start the agent \texttt{snmpd} whenever it moves into runlevels 3, 4 or 5. The second command lists which runlevels \texttt{snmpd} will start at, to confirm to yourself that the previous command worked. Note: you may wish to add the directories \texttt{/sbin} and \texttt{/usr/sbin} to your \texttt{PATH} in your login script, $\sim$\texttt{/.bash\_profile}. The line you would want to add is: \begin{verbatim} export PATH=$PATH:/sbin:/usr/sbin \end{verbatim}%$ \end{explanation} \item Note that any time you change the configuration for the agent (by editing \texttt{/etc\allowbreak/snmp\allowbreak/snmpd.conf}), you will need to restart the agent to get it to read the new configuration with: \begin{alltt} $ \textbf{sudo /sbin/service snmpd restart} \end{alltt}%$ \end{enumerate} \subsection{The MIB Files} \label{sec:The MIB Files} \begin{enumerate} \item Identify the list of \MIB files installed on your computer: \begin{alltt} $ \textbf{rpm -ql net-snmp | grep mibs} \end{alltt}%$ \begin{explanation} The \acro{RPM} package manager manages software packages on your computer. It maintains a database of all the software packages installed, all the files within each package, and checksums on each file, as well as plenty of other information that you can query. For more about this, read the chapter on \RPM in the Red Hat Reference Guide (download from the Red Hat web site---it's a really well-written manual, worth reading). The command \texttt{rpm -ql net-snmp} is a \textbf{q}uery to \textbf{l}ist the files in the \texttt{net-snmp} package. We are just \texttt{grep}ping here for the \MIB files. \end{explanation} \item Examine the file \texttt{SNMPv2-MIB.txt}. \begin{explanation} \item This is one of the \MIB files on your computer. They are text files, written using Abstract Syntax Notation One (\ASN.1). The \MIB files are like the schema for a database: they determine what type of data each \MIB variable can carry, and provide a name and \OID for each \MIB variable (managed object). They also show the exact location of each \MIB variable in the \MIB tree. \end{explanation} \item Identify some \MIB objects that have a \texttt{MAX-ACCESS} of \texttt{read-write}. These are variables that you can change with a \texttt{set-request} \SNMP operation. \begin{explanation} Note that the manual page for the agent configuration file, \texttt{snmpd.conf}, shows that if \texttt{/etc\allowbreak/snmp\allowbreak/snmpd.conf} has a value for \texttt{syslocation}, \texttt{syscontact} or \texttt{sysname}, then the \MIB variables \texttt{sysLocation}, \texttt{sysContact} and \texttt{sysName} respectively will become read only, so only try to set these \MIB variables if you comment out the corresponding value in \texttt{/etc\allowbreak/snmp\allowbreak/snmpd.conf}. \end{explanation} \end{enumerate} \subsection{Setting Managed Objects} \label{sec:Setting Managed Objects} \begin{enumerate} \item Identify some managed objects that you can set. \item Read their original values with \texttt{snmpgetnext}. \item Change their value with \texttt{snmpset}. \begin{explanation} You can refer to the man page for \texttt{snmpset}. There is also a simple tutorial on \texttt{snmpset} at \url{http://net-snmp.sourceforge.net/tutorial-5/commands/snmpset.html}. \end{explanation} \item You can use \texttt{snmpset} like this: \begin{alltt} $ \textbf{snmpset -v 2c -c \meta{rw community string} \meta{hostname} \bs \meta{OID} \meta{type} \meta{value} \textmd{[}\meta{OID} \meta{type} \meta{value}\textmd{]}\ldots} \end{alltt}%$ \begin{explanation} Just in case you are wondering what the value of \meta{rw community string} might be, you set it in your agent back in step~\vref{ste:community-strings}. The value of \meta{type} is shown on the \texttt{snmpset} manual page. It is a single letter, such as \texttt{s} for string, or \texttt{i} for integer. \end{explanation} \item Verify that the value has or has not changed. Note that the \texttt{SYNTAX} determines that type of data that you may put into that managed object. The syntax values are what we have discussed in the lectures. \end{enumerate} \subsection{Sending Traps} \label{sec:Traps} Now read the Net-SNMP tutorial on traps at \url{http://net-snmp.sourceforge.net/tutorial-5/commands/snmptrap.html}. Using this as a guide, working with a partner if possible, send your partner a trap using \texttt{snmptrap}, and also receive a trap from your partner using \texttt{snmptrapd}. If you have no partner available, then you can send and receive the trap on the same machine. \subsubsection{Exercises with Traps and Notifications} \label{sec:traps-exercises} We begin by installing two \MIB files, one for an enterprise \OID for an \SNMP{}v1 trap, and another for a notification \MIB object for an \SNMP{}v2c notification. We install the \MIB files as described in the Net-\SNMP \FAQ at \url{http://net-snmp.sourceforge.net/FAQ.html#How_do_I_add_a_MIB_}. \begin{enumerate} \item Download the two \MIB files from the subject web site, at \url{http://nicku.org/snm/lab/snmp-set-trap/TRAP-TEST-MIB.txt} and \url{http://nicku.org/snm/lab/snmp-set-trap/NOTIFICATION-TEST-MIB.txt}. These are from the Net-\SNMP Trap tutorial. Here is the file \texttt{TRAP-TEST-MIB.txt} \begin{verbatim} TRAP-TEST-MIB DEFINITIONS ::= BEGIN IMPORTS ucdExperimental FROM Net-SNMP-MIB; demotraps OBJECT IDENTIFIER ::= { ucdExperimental 990 } demo-trap TRAP-TYPE STATUS current ENTERPRISE demotraps VARIABLES { sysLocation } DESCRIPTION "This is just a demo" ::= 17 END \end{verbatim} And here is \texttt{NOTIFICATION-TEST-MIB.txt} \begin{verbatim} NOTIFICATION-TEST-MIB DEFINITIONS ::= BEGIN IMPORTS ucdavis FROM Net-SNMP-MIB; demonotifs OBJECT IDENTIFIER ::= { ucdavis 991 } demo-notif NOTIFICATION-TYPE STATUS current OBJECTS { sysLocation } DESCRIPTION "Just a test notification" ::= { demonotifs 17 } END \end{verbatim} \item Create a directory in your home directory to put these \MIB files': \begin{alltt} $ \textbf{mkdir -p \(\sim\)/.snmp/mibs} \end{alltt}%$ Notice the dot in the directory name. \item Copy the two \MIB files into this directory: \begin{alltt} $ \textbf{cp NOTIFICATION-TEST-MIB.txt TRAP-TEST-MIB \(\sim\)/.snmp/mibs} \end{alltt}%$ \item Now start the \texttt{snmptrapd} service: \begin{alltt} $ \textbf{sudo /sbin/service snmptrapd start} \end{alltt}%$ and optionally set the service to always start on boot: \begin{alltt} $ \textbf{sudo chkconfig snmptrapd on} \end{alltt}%$ \ldots then verify that it is on: \begin{alltt} $ \textbf{sudo chkconfig snmptrapd --list} \end{alltt}%$ \item Open another terminal window to watch the main log: \begin{alltt} $ \textbf{sudo tail -f /var/log/messages} \end{alltt}%$ \item Now send some traps while watching the log window. This first example is an \SNMP{}v1 trap. \begin{alltt} $ \textbf{snmptrap -c public localhost TRAP-TEST-MIB::demotraps \bs '' 6 17 '' SNMPv2-MIB::sysLocation.0 s "Just here"} \end{alltt}%$ \begin{explanation} See section~\vref{sec:snmptrap} for a more detailed explanation of what is happening here. \end{explanation} \item This other example from the tutorial is an \SNMP{}v2c notification. \begin{alltt} $ \textbf{snmptrap -v 2c -c public localhost '' \bs NOTIFICATION-TEST-MIB::demo-notif \bs SNMPv2-MIB::sysLocation.0 s "just here"} \end{alltt}%$ \end{enumerate} \begin{explanation} See section~\vref{sec:snmpv2c-notifications} for an explanation of the parameters. For the \SNMP version 1 example, we are using the enterprise specific trap (see table~\vref{tab:generic-traps}). The \MIB file \texttt{TRAP-TEST-MIB.txt} defines a trap (\texttt{demo-trap}) with numeric \OID of \texttt{.1.3.6.1.4.1.2021.13.990.0.17}. Go ahead: try this after installing the two \MIB files: \begin{alltt} $ \textbf{snmptranslate -On TRAP-TEST-MIB::demo-trap} .1.3.6.1.4.1.2021.13.990.0.17 $ \textbf{snmptranslate -On NOTIFICATION-TEST-MIB::demo-notif} .1.3.6.1.4.1.2021.991.17 \end{alltt}%$ \end{explanation} \end{document}