用socket编写的linux反向远程管理程序(c/s模式)

 用socket编写的linux反向远程管理程序(c/s模式)


这是我第一个正式写的linux程序,对我来说很有纪念意义。

 

程序主要是通过socket实现客户端连接到服务器端,然后服务器端可以控制客户端传递运行。

 

适用于客户端处于内网,服务器为公网的环境。其中使用了select函数实现并发连接。

 

源代码如下:

 

server.c:

 

 #include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/select.h>
#include <string.h>
#include <stdlib.h>

#define MAXLINE 2048
#define BACKLOG 20
int
main(int argc, char **argv)
{
 int   i, j,maxi, maxfd, listenfd, connfd, sockfd,len,id;
 int   nready, client[FD_SETSIZE];
 ssize_t   n;
 fd_set   rset, allset;
 char   line[MAXLINE],temp[INET_ADDRSTRLEN];
 socklen_t  clilen,templen;
 struct sockaddr_in cliaddr, servaddr,tempaddr;
 char    buf[20],cmd[20];

 if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0))<0 )
   {
     perror("socket");
   }

       bzero(&servaddr,sizeof(servaddr));
       servaddr.sin_family = AF_INET;
       servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
       servaddr.sin_port =htons(1234);

       if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)
       {
         perror("bind");
         exit(1);
        }
    /* how we can get the binded socket information */
       templen = sizeof(struct sockaddr);
      if (getsockname(listenfd, (struct sockaddr *)&tempaddr,&templen) == -1){
      perror("getsockname");
      exit(1);
      }
      printf("Server is listening on port %d/n",ntohs(tempaddr.sin_port));
       if (listen(listenfd,BACKLOG) == -1){
         perror("listen");
         exit(1);
       }


 maxfd = listenfd;   /* initialize */
 maxi = -1;    /* index into client[] array */
 for (i = 0; i < FD_SETSIZE; i++)
  client[i] = -1;   /* -1 indicates available entry */
 FD_ZERO(&allset);
 FD_SET(listenfd, &allset);
 FD_SET(0, &allset);
       //maxfd = 0;

 for ( ; ; ) {
  rset = allset;  /* structure assignment */
  nready = select(maxfd+1, &rset, NULL, NULL, NULL);
  if (nready == -1) {
                printf("exit! select error! %s", strerror(errno));
                break;
  }

  
  if (FD_ISSET(listenfd, &rset)) { /* new client connection */
   clilen = sizeof(cliaddr);
   if ( ( connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen) ) <  0)
   {
     perror("accept");
   }
   printf("A new connect from: %s, port %d/n",
     inet_ntop(AF_INET, &cliaddr.sin_addr, temp, INET_ADDRSTRLEN),ntohs(cliaddr.sin_port));
   printf("input id and cmd like: id cmd/n");

   for (i = 0; i < FD_SETSIZE; i++)
    if (client[i] < 0) {
     client[i] = connfd; /* save descriptor */
     break;
    }
   if (i == FD_SETSIZE)
    perror("too many clients");

   FD_SET(connfd, &allset); /* add new descriptor to set */
   if (connfd > maxfd)
    maxfd = connfd;   /* for select */
   if (i > maxi)
    maxi = i;    /* max index in client[] array */

   if (--nready <= 0)
    continue;    /* no more readable descriptors */
  }

  for (i = 0; i <= maxi; i++) { /* check all clients for data */
   if ( (sockfd = client[i]) < 0)
    continue;
   if (FD_ISSET(sockfd, &rset)) {
    //n = read(sockfd, line, MAXLINE);
    if ( (n = read(sockfd, line, MAXLINE)) <= 0) {
    //if(n==0){ 
     /*4connection closed by client */
     close(sockfd);
     FD_CLR(sockfd, &allset);
     client[i] = -1;
     printf("client %d exited!/n",i);
    }else  {
        printf("%s/n",line);
        printf("from ID %d/n",i);
        fflush(stdout);
    }
   
    bzero(line,MAXLINE);
    if (--nready <= 0)
     break;    /* no more readable descriptors */
   }
  }
if (FD_ISSET(0, &rset)) {
                    /* 用户按键了,则读取用户输入的内容发送出去 */
                     bzero(buf, MAXLINE + 1);
                    fgets(buf, MAXLINE, stdin);
   id=atoi(buf);
   for(j=0;buf[j+1]!='/n';j++)
    cmd[j]=buf[j+2];
   for(j=0;(j<=maxi)&&((sockfd=client[j])>=0);j++)
                     { 
       if(j==id)
       {
                           len =write(sockfd,cmd,strlen(cmd));
      //bzero(cmd,sizeof(cmd));
    if (len > 0)
                          printf("send %s command to ID %d/n",cmd, id);
                      else {
                          printf("send %s error!/n",buf);
                          break;
                     }
       bzero(cmd,sizeof(cmd));
       }
                    }


                }
 
 }
}

 

client.c:

 

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/select.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define MAXLINE 4096
char sendhead[MAXLINE];


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

{
int sockfd;

struct sockaddr_in servaddr;

char *info="client number 1 ";
char *sys_err="system error!/n";
char *first="pid/tppid/t/tcmd/n";
int   maxfdp1, stdineof;
fd_set  rset;
char  recvbuf[20],tmp[128],buffer[MAXLINE];
int             n,len,fd;
FILE   *ff;

if(argc!=3){
printf("useage:client address port ");
exit(0);
}

 

if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1  )

{
  perror("socket");
  exit(1);
}
   printf("%s connect server/n",info);
  
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family=AF_INET;
   servaddr.sin_port=htons(atoi(argv[2]));
   inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
 
   if( ( connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))  )<0)
   {
     perror("connect");
     exit(1);
   }
 write(sockfd,info,strlen(info));
 
      
 FD_ZERO(&rset);
 for ( ; ; ) {
  FD_SET(sockfd, &rset);
     maxfdp1=sockfd+1;

  if(  ( select(maxfdp1, &rset, NULL, NULL, NULL) )<0)
    {
      perror("select");
    }

  if (FD_ISSET(sockfd, &rset)) { /* socket is readable */
   bzero(recvbuf,20);
   n=read(sockfd, recvbuf, 20) ;
                      if(n<0) {
    perror("str_cli: server terminated prematurely");
   }else if(n==0)
    {
    printf("sever shutdown!");
    exit(-1);
    }

   printf("receive cmd:%s/n",recvbuf);
   write(sockfd,info,strlen(info));

   bzero(buffer,MAXLINE);  

    ff=popen(recvbuf,"r");
    fread(buffer,sizeof(char),MAXLINE,ff);
   write(sockfd,buffer,strlen(buffer));
   //printf("%s",buffer);
   bzero(buffer,MAXLINE);
  }
  }

       exit(0);
}

 

 

其实这就是个简单的telnet程序,不过是反向连接的,linux的ssh也可以实现反向连接。

方法如下:

例如一部linux在内网,一部在公网,

在内网上执行: ssh -f -N -R 8888:localhost:22 xxx@xxx.xxx.org , xxx.xxx.org可以是ip,

在公网的的电脑上执行: ssh xxxx@localhost -p 8888 就可以成功连上内网的电脑了,

上面命令里面的 8888 是任一个本地端口。

 


参考文章:

 

Linux网络编程--服务器模型:   http://fanqiang.chinaunix.net/a4/b7/20010508/112359.html

 

Linux select()详解:  http://blog.chinaunix.net/u1/55630/showart_510941.html

 

linux C编程--popen函数详解:http://blog.chinaunix.net/u1/58082/showart_498118.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值