vortmax has asked for the wisdom of the Perl Monks concerning the following question:

I am writing a heartbeat script to test whether or not our remote systems are up and running. The system consists of a firewall with two public IP's and a server behind the firewall. I need to be able to determine the status of each connection and if the server behind the firewall is responsive. Since the firewall is set to drop ICMP packets I had to get a little creative with the check. So I used the Net::Ping module to 'ping' the firewall by attempting a connection to the firewall's management website over https. If the connection is refused, the connection is up (vs no reply = down). I attempted this same thing using http, which should be forwarded through the firewall to the server, but this always came back as alive, even on connections I know are down. Since I also use SNMP to monitor the server, I thought I'd just have try to pull a simple OID from the server. If it works, the server is responsive, if not then it isn't. The problem I'm hitting is that because of a limitation with the firewall, I can't pass udp packets over port 161 through the firewall, so I have to use port 163 then nat them over to 161 on the backside of the firewall. This is all well and good, but I can't seem to get Net::SNMP to use port 163, or if it is, It's just not working. Here is my code:
#!/usr/bin/perl use warnings; use strict; use SNMP; use Socket; my $host = 'xxx.xxx.xxx.xxx'; my $oid = '1.3.6.1.2.1.1.4'; my $sver = '1'; my $comm = 'secret'; my $session; my $reply; &SNMP::initMib(); my %snmpparms; $snmpparms{Community} = $comm; $snmpparms{DestHost} = inet_ntoa(inet_aton($host)); $snmpparms{Version} = $sver; $snmpparms{UseSprintValue} = '1'; $snmpparms{RemotePort} = '163'; $session = new SNMP::Session(%snmpparms); $reply = $session->get($oid); if ($session->{ErrorNum}) { die "DOOM!: ".$session->{ErrorStr}."\n"; } print "$reply\n";
running this gives:
DOOM!: Timeout
I know the server is reachable over port 163, as I'm running other monitoring software and I've been able to get this to work in php. So I guess my question is two-fold. How do I get snmp to work over port 163 and is there a better way to approach this? Possibly make a socket connection with the server over port 80, send some headers and check the reply?

Replies are listed 'Best First'.
Re: SNMP RemotePort
by superfrink (Curate) on Apr 10, 2008 at 19:23 UTC
    Update: I did not realize SNMP is a front end for Net::SNMP. The code below probably won't help.

    Run tcpdump on the machine running the SNMP server to see if the NAT is really working and that the traffic really is getting through to port 161.

    Check that snmpd is listening and allowing connections from outside localhost. (On Ubuntu/Debian check /etc/default/snmp to see what IP it is binding to. Also check snmpd.conf.)

    Original post:

    If you can do it just open UDP port 161 on the firewall from the IP of the server doing the monitoring.

    I have not tried using a different port but Net::SNMP has functionality to specify the port number. Code I have run (based on the docs as I recall) is below.
    use strict; use Data::Dumper; use Net::SNMP; my ($session, $error) = Net::SNMP->session( -hostname => shift || 'localhost', -community => shift || 'public', -port => shift || 161 ); if (!defined($session)) { printf("ERROR: %s.\n", $error); exit 1; } my $sysUpTime = '1.3.6.1.2.1.1.3.0'; my $result = $session->get_request( -varbindlist => [$sysUpTime] ); if (!defined($result)) { printf("ERROR: %s.\n", $session->error); $session->close; exit 1; } printf("sysUpTime for host '%s' is %s\n", $session->hostname, $result->{$sysUpTime} ); #print Dumper($result); $session->close; exit 0;
    Example output is:
    $ ./snmp-uptime.pl 172.19.1.2 my_community_string sysUpTime for host '172.19.1.2' is 263 days, 14:47:49.58
      okay...it works now. sorry. I tested it with tcpdump, which showed that it was in fact sending packets on port 163 but the response was timing out. So on a hunch, I moved the script over to a different server (no edits) and tried it again... and it worked. So it must be an issue with how something on my dev machine is installed/configured. thanks for your help