Tuesday, September 29, 2015

Set the Firewalls of Guests from Host in Virtual Machine Or Execute command remotely from Host to Guest VM



So, we have already discussed about

What is Firewalls?
and

Now, the question is, if we are in guests and want the provision of setting firewalls from host, will it be possible?

We can give a try for a setup where both guests and host are Linux systems.

The basic idea is, if we run a server script in host and a client script in guest, so that, from host we will send a command to guest and guest will execute the command and return host its output, then we can make use of that to set firewalls in guest from host.

Of course, we would also need to run a shell script in guest, which will make our life of input and output redirection easier.

Does it look confusing?

Let me explain the code in details then.

Let's assume, we have a shell script running in guest:

#!/bin/bash
while :
do
      ./client HOSTIP > inputfile
       ret=`echo $?`
       if [ $ret -eq 0 ]
       then
             var=`cat inputfile`
             echo "command to execute: $var"
             `echo $var`
              `echo $var` &> outputfile
              ./client 192.168.1.116 outputfile
               var=`cat outputfile`
              echo "Output file contained $var"
              `rm outputfile`
      else
              echo "Could not connect"
              `rm inputfile`
               exit
       fi
       `rm inputfile`
done

This script will execute a code 'client' which will connect with the server. The server will send a command to client using sockets. The client will simply print the sent command in stdout. The shell script then redirect the content of stdout in a variable and execute it. The shell script will also redirect the stderr and stdout of the executed command to a file. And finally, the shell script will again invoke the client program, but this time with one more argument – the name of the file which contains the output. The client program, now, will open the file and send each line to the server. And the only job left to server is, print the output.

So, how does the server code looks like?
See below:

#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 i;
int listenfd = 0, connfd = 0;
pid_t wpid, pid;
struct sockaddr_in *ipv4Addr;
socklen_t size;
char command[1025];
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
                             command[0]='\0';
                             readbuff[0]='\0';
                             ipv4Addr = (struct sockaddr_in *)&client_sockaddr;
                             ipAddr = ipv4Addr->sin_addr.s_addr;
                              strcpy(ipAddr_string, inet_ntop(AF_INET, &ipAddr, ipAddr_string, INET_ADDRSTRLEN));
                             readbuff[0]='\0';
                             readlen = read(connfd, readbuff, 1025);
                             readbuff[readlen]='\0';
                             if (strcmp(readbuff, "input") == 0) {
                                              printf("Command to execute for client %s: ", ipAddr_string);
                                              gets(command);
                                              printf("Now client will execute: ");
                                              printf("%s\n", command);
                                              write(connfd, command, strlen(command));
                                               command[0]='\0';
                                               readbuff[0]='\0';
                                               close(connfd);
                             } else {
                                              printf("Command Output from client %s:\n\n", ipAddr_string);
                                              while(1) {
                                                              readbuff[0]='\0';
                                                              readlen = read(connfd, readbuff, 1025);
                                                              readbuff[readlen]='\0';
                                                              if (readlen > 0) {
                                                                             if (strcmp(readbuff, "done") == 0) {
                                                                                            readbuff[0]='\0';
                                                                                            break;
                                                                             }
                                                                            fflush(stdin);
                                                                            puts(readbuff);
                                                                          
                                                                            readbuff[0] = '\0';
                                                            }
                                              }
                                              close(connfd);
                          }
                          exit(1);
                  }
        }
         close(connfd);
          sleep(1);
    }
return 0;
}


This server code simply accepts the connection from the guest, takes the input command from the user and sends it to the guest. And when the guest connects again, it receives the output from the guest and prints it.


And the client code looks like :


#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[])
{
FILE *fp;
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
char command[1024];
char buf[1025];
int len;
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;
             }
             if (argc == 3) {
                          write(sockfd, "output", sizeof("output"));
                          fp = fopen(argv[2], "r");
                          while(!feof(fp)) {
                                      fgets(buf, 1024, fp);
                                     //puts(buf);
                                      write(sockfd, buf, i);
                                      buf[0]='\0';
                           }
                           write(sockfd, "done", sizeof("done"));
                           fclose(fp);
                           close(sockfd);
      } else {
                  write(sockfd, "input", sizeof("input"));
                  n = read(sockfd, recvBuff, sizeof(recvBuff)-1);
                  recvBuff[n]='\0';
                  puts(recvBuff);
     }
     close(sockfd);
     return 0;
}

The client code, as I said before, will make a connection with the host and wait for input commands. When it gets the input command it will print it to stdout, so that the command can be executed by the shell script. The shell script again invokes this program with three arguments, the third being the name of the file which contains the output of the command. The client then simply takes the output text from the file and sends it to the server.


Last but not the least, the client shell script needs to be executed using 'sudo' otherwise there will be permission problem.


So, this was basically a simple concept, to execute firewalls related commands remotely, or rather to execute any command remotely. Hope you enjoyed the basic idea, and if you have any feedback or comments, please feel free to share.



No comments:

Post a Comment