The OpenVOS architecture makes use of several independent systems; the NIO for X25 communication, the fiber channel disk array controllers, UPS for power, the RSN Internet Console Server for RSN over IP and the maintenance network Ethernet switches that allow all these systems to communicate over a private Ethernet/IP network. These systems are monitored by various OpenVOS processes to make sure that they are running correctly. But some events like user logins are not monitored. The RSN console and the network switches have the option to send a message to a logging server whenever someone logs in or tries to login. Since the network switches are only connected to the Stratus module it makes sense to have a logging server run on the Stratus module. To that end I have created a very simple logging server, it simply writes the message that it receives along with a date-time stamp and the IP address of the host that sent the message to standard output. By running the server as a started process the messages can be saved to the process’s out file.

Examples from the network switches
It is possible that someone who was authorized was just having problems typing the root password when logging into the network switch as root, then again maybe they are just really good at guessing passwords.


2011-10-02 11:55:39 : 10.10.1.75 : >%AAA-W-REJECT: New telnet connection for use
+r root, source 10.10.1.1 destination 10.10.1.75  REJECTED

2011-10-02 11:56:03 : 10.10.1.75 : >%AAA-W-REJECT: New telnet connection for use
+r root, source 10.10.1.1 destination 10.10.1.75  REJECTED

2011-10-02 11:56:08 : 10.10.1.75 : >%AAA-I-CONNECT: User CLI session for user ro
+ot over telnet , source 10.10.1.1 destination  10.10.1.75 ACCEPTED

Here is someone guessing system administrator user IDs


2011-10-02 12:03:13 : 10.10.1.75 : >%AAA-W-REJECT: New telnet connection for use
+r admin, source 10.10.1.1 destination 10.10.1.75  REJECTED

2011-10-02 12:03:30 : 10.10.1.75 : >%AAA-W-REJECT: New telnet connection for use
+r sysadmin, source 10.10.1.1 destination 10.10.1.75  REJECTED

2011-10-02 12:04:39 : 10.10.1.75 : >%AAA-W-REJECT: New telnet connection for use
+r Administrator, source 10.10.1.1 destination 10.10.1.75  REJECTED

Besides user logins the network switches will report when the configuration has been changed


2011-10-02 15:16:29 : 10.10.1.75 : >%COPY-I-FILECPY: Files Copy - source URL run
+ning-config destination URL flash://startup-config

2011-10-02 15:16:43 : 10.10.1.75 : >%COPY-N-TRAP: The copy operation was complet
+ed successfully

And it will also report link up and down messages which can be very useful when troubleshooting communication problems.


2011-10-02 15:49:17 : 10.10.1.75 : >%LINK-W-Down:  2/e24

2011-10-02 15:49:20 : 10.10.1.75 : >%LINK-I-Up:  2/e24
  Examples from the RSN Internet Console Server
Someone from the module connected to the RSN console and logged in as root, after typing the password incorrectly twice.


2011-10-02 12:11:03 : 10.10.1.200 : in.telnetd[2942]: connect from 10.10.1.1 (10
+.10.1.1)
2011-10-02 12:11:03 : 10.10.1.200 : telnetd[2942]: doit: getaddrinfo: Temporary
+failure in name resolution
2011-10-02 12:11:07 : 10.10.1.200 : login[2943]: invalid password for `root' on
+`ttyp0' from `10.10.1.1'
2011-10-02 12:11:15 : 10.10.1.200 : login[2943]: invalid password for `root' on
+`ttyp0' from `10.10.1.1'
2011-10-02 12:11:35 : 10.10.1.200 : login[2945]: root login  on `ttyp0' from `10
+.10.1.1'

Note that the RSN console will report a user ID of UNKNOWN if an attempt is made with an invalid user ID.


2011-10-02 12:12:31 : 10.10.1.200 : in.telnetd[2946]: connect from 10.10.1.1 (10
+.10.1.1)
2011-10-02 12:12:32 : 10.10.1.200 : telnetd[2946]: doit: getaddrinfo: Temporary
+failure in name resolution
2011-10-02 12:12:37 : 10.10.1.200 : login[2947]: invalid password for `UNKNOWN'
+on `ttyp0' from `10.10.1.1'
2011-10-02 12:12:45 : 10.10.1.200 : login[2947]: invalid password for `UNKNOWN'
+on `ttyp0' from `10.10.1.1'
2011-10-02 12:12:54 : 10.10.1.200 : login[2947]: invalid password for `UNKNOWN'
+on `ttyp0' from `10.10.1.1'

The RSN console will not report when the valid user ID rsn_admin is used to login. However, you will still see the connection. The rsn_admin user ID does not have access to change any of the system configuration files. If the rsn_admin user tries to change to root with the su command it will be logged.


2011-10-02 12:15:37 : 10.10.1.200 : in.telnetd[2957]: connect from 10.10.1.1 (10
+.10.1.1)
2011-10-02 12:15:38 : 10.10.1.200 : telnetd[2957]: doit: getaddrinfo: Temporary
+failure in name resolution
2011-10-02 12:15:54 : 10.10.1.200 : su[2959]: + ttyp0 rsn_admin-root
2011-10-02 12:15:54 : 10.10.1.200 : PAM_unix[2959]: (su) session opened for user
+ root by rsn_admin(uid=500)

As will attempts that fail.


2011-10-02 12:19:50 : 10.10.1.200 : PAM_unix[2972]: authentication failure; rsn_
+admin(uid=500) -> root for su service
2011-10-02 12:19:52 : 10.10.1.200 : su[2972]: pam_authenticate: Authentication f
+ailure
2011-10-02 12:19:52 : 10.10.1.200 : su[2972]: - ttyp0 rsn_admin-root

 

To configure the network switch to send log messages to the OpenVOS module you need to log into the switch as root, execute the logging command and then save the new configuration:

telnet 10.10.1.75                                       
Trying...
Connected to 10.10.1.75.
Escape character is '^]'.

User Name:root
Password:******

console# config
console(config)# logging 10.10.1.1
console(config)#

console# copy running-config startup-config

 

To configure the RSN console to send log messages to the OpenVOS module you need to log into the console as root and start the syslogd process with the command “syslogd –R 10.10.1.1:514”. To make sure that the syslogd process is started after a reboot the /etc/tc.d/rc.local file must be changed.

telnet 10.10.1.200
Trying...
Connected to 10.10.1.200.
Escape character is '^]'.

Moxa Embedded Linux, Professional Edition
Linux/armv5teb 2.4.18_mvl30-ixdp425

azvos login: root
Password:
Welcome to

    ___  _____  __        _______    _____                   __
   / _ / __/ |/ / ____  /  _/ _   / ___/__  ___  ___ ___  / /__
  / , _/ /    / /___/ _/ // ___/ / /__/ _ / _ (_-</ _ / / -_)
 /_/|_/___/_/|_/       /___/_/     ___/___/_//_/___/___/_/__/ 

 Authorized Users Only!

root@azvos:~# syslogd -R 10.10.1.1:514
root@azvos:~# 
root@azvos:~# 
root@azvos:~# 
root@azvos:~# cd /etc/rc.d
root@azvos:/etc/rc.d# cp rc.local rc.local.bak
root@azvos:/etc/rc.d# echo syslogd -R 10.10.1.1:514 >> rc.local
root@azvos:/etc/rc.d# tail rc.local
fi
/etc/init.d/ssh start
/etc/init.d/apache stop
/etc/init.d/portmap stop
rm -f /rsn/call.log
/rsn/callhome &
lcmmessage -c -m "   Welcome to   " -l
lcmmessage -m " RSN-IP Console " -l
cat /etc/motd
syslogd -R 10.10.1.1:514
root@azvos:/etc/rc.d#

 

Assuming you get the same output as shown above you can delete the rc.local.bak file with “rm rc.local.bak”.

Once logging has been set up on the devices you need to run the logd program on the Stratus module.  I suggest starting the program with the following command macro. The log file will be named logd.(date).(time).out. If for some reason a file will that name already exists it is be renamed to logd.(date).(time).old.out. If there is already a file with the .old.out suffix it is deleted. Given that the time stamp is to the second this is unlikely. The out file has implicit locking set so the file may be read at any time. Note that the out file will grow forever so some maintenance on your part will be needed or you can modify the program to make it smarter about handling the output.



& start_logd.cm begins here
&
& Version 1.00 11-11-02
& noah.davids@stratus.com
&
& This script creates a log file, sets implicit locking and starts the logd
& process. The process will not normally terminate and the log file has the
& potential to grow very large.
&
&
& This software is provided on an "AS IS" basis, WITHOUT ANY WARRANTY OR
& ANY SUPPORT OF ANY KIND. The AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED
& WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE.
& This disclaimer applies, despite any verbal representations of any
& kind provided by the author or anyone else.
&
&set DT (date).(time)
&if (exists logd.&DT&.out)
&then !rename logd.&DT&.out logd.&DT&.old.out -delete
!create_file logd.&DT&.out
!set_implicit_locking logd.&DT&.out
start_process logd -output_path logd.&DT&.out -privileged -process_name logd
&
& start_logd.cm ends here

 

Any finally here is the program.



/* logd.c starts here

   Version 1.00 11-11-02
   noah.davids@stratus.com

   This software is provided on an "AS IS" basis, WITHOUT ANY WARRANTY OR
   ANY SUPPORT OF ANY KIND. The AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED
   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE.
   This disclaimer applies, despite any verbal representations of any
   kind provided by the author or anyone else.
*/

#define _POSIX_SOURCE

#include <sys/select.h>
#include <prototypes/inet_proto.h>
#include <stdlib.h>
#include <string.h>
#include <c_utilities.h>
#include <errno.h>
#include <time.h>

#define BUFFERLEN 10000
#define bzero(s, len)             memset((char *)(s), 0, len)

int errno;

getCurrentDateTime (char * szDT)
{
time_t tTime;
struct tm *tmLT;

tTime = time ((time_t *) 0);
tmLT = localtime (&tTime);

sprintf (szDT, "%4ld-%02ld-%02ld %02ld:%02ld:%02ld",
          tmLT -> tm_year+1900,
          tmLT -> tm_mon,
          tmLT -> tm_mday,
          tmLT -> tm_hour,
          tmLT -> tm_min,
          tmLT -> tm_sec);
}

main (argc, argv)
int    argc;
char   *argv [];

{
 struct sockaddr_in serv_addr;
 struct sockaddr_in cli_addr;
 int clilen = sizeof (cli_addr);

 int zeroCount = 0;
 int socks0;
 int recvBytes;

 char szSender [16];
 char  szDateTime [32];
 char szMessage [BUFFERLEN];
 short portNumber;

 if (argc == 1)  /* no arguments - use the default of 514 */
    {
    portNumber = 514;
    }
 else
 if (argc == 2) /* one argument, must be the expected port number */
    {
    portNumber = atoi (argv [1]);
    if (portNumber == 0)
       {
       printf ("nn%s argument was not the expected port number", argv [1]);
       printf ("nUsage: logd [port number, default = 514]n");
       exit (-1);
       }
    }
 else /* more than one argument gets a usage message */
    {
    printf ("nnToo many arguments");
    printf ("nUsage: logd [port number, default = 514]n");
    exit (-1);
    }

/* Leting you know what argument values will actually be used */

 printf ("logd %dnn", portNumber);

 if ((socks0 = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    {
    perror ("logd: can't create dgram socket");
    exit (errno);
    }

/* build a sockaddr structure holding the address we will bind to. The IP
   address is INADDR_ANY meaning we will listen on all active IP addresses */

 bzero ( (char *) &serv_addr, sizeof (serv_addr));
 serv_addr.sin_family        = AF_INET;
 serv_addr.sin_addr.s_addr   = htonl (INADDR_ANY);
 serv_addr.sin_port          = htons (portNumber);

/* now bind to the address and port */

 if (bind (socks0, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
    {
    perror ("logd: can't bind local address");
    exit (errno);
    }

/* main loop just does a recv, blocking until something is available to read.
   Assuming we receive at least 1 byte we get the current date-time,
   convert the senders IP address to a printable string and print the
   date-time, address and message starting at the 5th character position.
   The first four characters of a syslog message are <NN> where NN is a
   severity and facility code. These can be used for message filtering. Since
   this program doesn't do any filtering I just skip them. */
 while (1)
   {
    recvBytes=recvfrom(socks0,szMessage, BUFFERLEN, 0,
          (struct sockaddr *) &cli_addr, &clilen);
    if (recvBytes > 0)
       {
       getCurrentDateTime ((char *) &szDateTime);
       strcpy (szSender, inet_ntoa ((struct in_addr) cli_addr.sin_addr));
       szMessage [recvBytes] = 0;
       printf ("%s : %s : %sn", szDateTime, szSender, &szMessage[4]);
       zeroCount = 0;
       }
    else
    if (recvBytes < 0) /* in the event of an error report it and exit */
       {
       getCurrentDateTime ((char *) &szDateTime);
       printf ("%s : Error %d returned - exitingn", szDateTime, errno);
       exit (errno);
       }
    else  /* I can't think of any reason we would be getting null messages */
       {  /* but if we get a stream of them we would silently loop. This */
       zeroCount++;          /* forces out a message if we get 100 null */
       if (zeroCount > 99)   /* messages in a row */
          {
          getCurrentDateTime ((char *) &szDateTime);
          strcpy (szSender, inet_ntoa ((struct in_addr) cli_addr.sin_addr));
          printf ("%s : %s %sn", szDateTime,
               "We have received 100 null messages, the last one from",
               szSender);
          zeroCount = 0;
          }
       }
   }
}

/* logd.c ends here */