Tuesday, September 29, 2015

Heartbeat – Know from Host when the Guest is Down in Virtual Machine



So, we already learnt about, how to know the ip address of host from guest and the ip address of guest from host. The next thing interesting to us is, how to know from the host when any of the guest machines is down. You might say, this is simple, we can always write a small shell script and ping the guest machines after certain time intervals. If we do not get any response of ping, that would mean that particular guest machine is down.

But, we already have discussed about few attacks like, ping flood and as a remedy we said, it is better to disable ping in servers. In fact, it is always a good practice to disable ping message in servers. And if we do that, the said method is unlikely to work.

So, what is the alternative method?

Socket programming! Yes, we can run the server script from the host and client scripts from the guests. Each guest will make connection with the host and send message after certain time interval. If the message stops arriving or the connection closes, we will know the guest is down.


So, let me give a sample code, which can make things clearer.


Here is the server side code:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main(void)
{
    int listenfd = 0,connfd = 0;
    pid_t wpid, pid;
    struct sockaddr_in *ipv4Addr;
    socklen_t size;
    struct sockaddr_in serv_addr;
    char sendBuff[1025];
    char readbuff[1025];
    int readlen;
    int numrv;
    struct sockaddr client_sockaddr;
    int ipAddr;
    char ipAddr_string[INET_ADDRSTRLEN];

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("socket retrieve success\n");
    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(sendBuff, '0', sizeof(sendBuff));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000);

    bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));

    if(listen(listenfd, 10) == -1){
        printf("Failed to listen\n");
        return -1;
    }
    while(1)
    {

        size = sizeof(client_sockaddr);
        connfd = accept(listenfd, &client_sockaddr, &size); // accept awaiting request

        if (connfd != -1) {
            pid = fork();
            if (pid > 0) {
                 close(connfd);
            } else {//child process
                ipv4Addr = (struct sockaddr_in *)&client_sockaddr;
                ipAddr = ipv4Addr->sin_addr.s_addr;
                strcpy(ipAddr_string, inet_ntop(AF_INET, &ipAddr, ipAddr_string, INET_ADDRSTRLEN));
                printf("Client IP Address: %s\n", ipAddr_string);
                while(1) {
                     strcpy(sendBuff, "Hi from server");
                     write(connfd, sendBuff, strlen(sendBuff));
                     readlen = read(connfd, readbuff, 1025);
                     readbuff[readlen]='\0';
                     printf("Received from client %s: %s\n", ipAddr_string, readbuff);
                     if (strcmp(readbuff, "alive") == 0) {
                          sleep(2);
                     } else {
                          printf("Client %s is down!\n", ipAddr_string);
                          close(connfd);
                          exit(1);
                     }
               }
          }
    }
    sleep(1);
 }
 return 0;
}



And here is the client side code:


#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr;
    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    }

    memset(recvBuff, '0',sizeof(recvBuff));

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    }

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\n Error : Connect Failed \n");
        return 1;
    }

    n = read(sockfd, recvBuff, sizeof(recvBuff)-1);
    if(n < 0)
    {
        printf("\n Read error \n");
    }

    recvBuff[n] = '\0';
    printf("Message from Server: %s\n", recvBuff);
    while (1) {
        write(sockfd, "alive", sizeof("alive"));
        sleep(2);
    }
    return 0;
}


Here, the client makes a connection with the server and sends a particular message “alive” after certain interval. When the server stops getting the “alive” message, it knows the client is down.

So, this was a very basic concept. You can always borrow this idea and write your own code and share your valuable inputs!

No comments:

Post a Comment