proxyd.c
/**************************************************************************** * program: proxyd * module: proxyd.c * summary: provides proxy tcp service for a host on an isolated network. * * programmer: Carl Harris (ceharris@vt.edu) * date: 22 Feb 94 * * description: * This code implements a daemon process which listens for tcp connec- * tions on a specified port number. When a connection is established, * a child is forked to handle the new client. The child then estab- * lishes a tcp connection to a port on the isolated host. The child * then falls into a loop in which it writes data to the isolated host * for the client and vice-versa. Once a child has been forked, the * parent resumes listening for additional connections. * * The name of the isolated host and the port to serve as proxy for, * as well as the port number the server listen on are specified as * command line arguments. * ****************************************************************************/ #include #include #include #include #include #include #include #include <sys/stat.h> #include #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include #include <sys/ioctl.h> #include <sys/resource.h> #include <sys/wait.h> #define TCP_PROTO "tcp" int proxy_port; /* port to listen for proxy connections on */ struct sockaddr_in hostaddr; /* host addr assembled from gethostbyname() */ void parse_args(int argc, char **argv); void daemonize(int servfd); void do_proxy(int usersockfd); void reap_status(int sig); void errorout(char *msg); /**************************************************************************** * function: main * description: Main level driver. After daemonizing the process, a socket * is opened to listen for connections on the proxy port, * connections are accepted and children are spawned to handle * each new connection. * arguments: * argc,argv you know what those are. * * return value: none. * calls: parse_args, do_proxy. * globals: reads proxy_port. * ****************************************************************************/ int main(int argc, char *argv[]) { unsigned int clilen; int childpid; int sockfd, newsockfd; struct sockaddr_in servaddr, cliaddr; parse_args(argc,argv); /* prepare an address struct to listen for connections */ bzero((char *) &servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = proxy_port; /* get a socket... */ if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("failed to create server socket"); exit(1); } int on=1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))==-1) { perror("setsockopt()"); exit(1); } /* ...and bind our address and port to it */ if (bind(sockfd,(struct sockaddr *)(&servaddr),sizeof(servaddr)) < 0) { perror("faild to bind server socket to specified port"); exit(1); } /* get ready to accept with at most 5 clients waiting to connect */ listen(sockfd, 5); /* turn ourselves into a daemon */ daemonize(sockfd); signal(SIGCHLD,reap_status); /* fall into a loop to accept new connections and spawn children */ while (1) { /* accept the next connection */ clilen = sizeof(struct sockaddr_in); newsockfd = accept(sockfd, (struct sockaddr*)(&cliaddr), &clilen); if (newsockfd < 0 && errno == EINTR) continue; /* a signal might interrupt our accept() call */ else if (newsockfd < 0) /* something quite amiss -- kill the server */ errorout("failed to accept connection"); /* fork a child to handle this connection */ if ((childpid = fork()) == 0) { close(sockfd); do_proxy(newsockfd); exit(0); }else if (childpid < 0) { errorout("fork"); } /* if fork() failed, the connection is silently dropped -- oops! */ close(newsockfd); } return 0; } /**************************************************************************** * function: parse_args * description: parse the command line args. * arguments: * argc,argv you know what these are. * * return value: none. * calls: none. * globals: writes proxy_port, writes hostaddr. * ****************************************************************************/ void parse_args(int argc, char *argv[]) { int i; struct hostent *hostp; struct servent *servp; in_addr_t inaddr; struct { char proxy_port[16]; char isolated_host[64]; char service_name[32]; }pargs; if (argc < 4) { printf("usage: %s args",argv[0]); exit(1); } strcpy(pargs.proxy_port,argv[1]); strcpy(pargs.isolated_host,argv[2]); strcpy(pargs.service_name,argv[3]); for (i = 0; i < strlen(pargs.proxy_port); i++) if (!isdigit(pargs.proxy_port[i])) break; if (i == strlen(pargs.proxy_port)) proxy_port = htons(atoi(pargs.proxy_port)); else { printf("%s: invalid proxy port",pargs.proxy_port); exit(0); } bzero(&hostaddr,sizeof(hostaddr)); hostaddr.sin_family = AF_INET; if ((inaddr = inet_addr(pargs.isolated_host)) != INADDR_NONE) { hostaddr.sin_addr.s_addr = inaddr; }else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL) { //hostaddr.sin_addr = *((struct in_addr *)hostp->h_addr); bcopy(hostp->h_addr,&hostaddr.sin_addr,hostp->h_length); }else { printf("%s: unknown host",pargs.isolated_host); exit(1); } if ((servp = getservbyname(pargs.service_name,TCP_PROTO)) != NULL) hostaddr.sin_port = servp->s_port; else if (atoi(pargs.service_name) > 0) hostaddr.sin_port = htons(atoi(pargs.service_name)); else { printf("%s: invalid/unknown service name or port number",pargs.service_name); exit(1); } } /**************************************************************************** * function: daemonize * description: detach the server process from the current context, * creating a pristine, predictable environment in which it * will execute. * arguments: * servfd file descriptor in use by server. * * return value: none. * calls: none. * globals: none. * ****************************************************************************/ void daemonize(int servfd) { int childpid, fd, fdtablesize; /* ignore terminal I/O, stop signals */ signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGTSTP,SIG_IGN); /* fork to put us in the background (whether or not the user * specified '&' on the command line */ if ((childpid = fork()) < 0) { perror("failed to fork first child"); exit(1); }else if (childpid > 0) exit(0); /* terminate parent, continue in child */ /* dissociate from process group */ if (setpgid(0,getpid()) < 0) { perror("failed to become process group leader"); exit(1); } /* lose controlling terminal */ if ((fd = open("/dev/tty",O_RDWR)) >= 0) { ioctl(fd,TIOCNOTTY,NULL); close(fd); } /* close any open file descriptors */ for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++) { if (fd != servfd) close(fd); } /* set working directory to / to allow filesystems to be unmounted */ chdir("/"); /* clear the inherited umask */ umask(0); /* setup zombie prevention */ signal(SIGCHLD,reap_status); } /**************************************************************************** * function: do_proxy * description: does the actual work of virtually connecting a client to * the telnet service on the isolated host. * arguments: * usersockfd socket to which the client is connected. * * return value: none. * calls: none. * globals: reads hostaddr. * ****************************************************************************/ void do_proxy(int usersockfd) { int isosockfd; fd_set rdfdset; int connstat; int iolen; char buf[2048]; /* open a socket to connect to the isolated host */ if ((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) errorout("failed to create socket to host"); /* attempt a connection */ connstat = connect(isosockfd,(struct sockaddr *)&hostaddr,sizeof(hostaddr)); switch (connstat) { case 0: break; case ETIMEDOUT: case ECONNREFUSED: case ENETUNREACH: strcpy(buf,strerror(errno)); strcat(buf,""); write(usersockfd,buf,strlen(buf)); close(usersockfd); exit(1); /* die peacefully if we can't establish a connection */ break; default: errorout("failed to connect to host"); } /* now we're connected, serve fall into the data echo loop */ while (1) { /* Select for readability on either of our two sockets */ FD_ZERO(&rdfdset); FD_SET(usersockfd,&rdfdset); FD_SET(isosockfd,&rdfdset); if (select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL) < 0) errorout("select failed"); /* is the client sending data? */ if (FD_ISSET(usersockfd,&rdfdset)) { if ((iolen = read(usersockfd,buf,sizeof(buf))) <= 0) break; /* zero length means the client disconnected */ write(isosockfd,buf,iolen); /* copy to host -- blocking semantics */ } /* is the host sending data? */ if (FD_ISSET(isosockfd,&rdfdset)) { if ((iolen = read(isosockfd,buf,sizeof(buf))) <= 0) break; /* zero length means the host disconnected */ write(usersockfd,buf,iolen); /* copy to client -- blocking semantics */ } } /* we're done with the sockets */ close(isosockfd); close(usersockfd); } /**************************************************************************** * function: errorout * description: displays an error message on the console and kills the * current process. * arguments: * msg message to be displayed. * * return value: none -- does not return. * calls: none. * globals: none. * ****************************************************************************/ void errorout(char *msg) { FILE *console; console = fopen("/dev/console","a"); fprintf(console,"proxyd: %s",msg); fclose(console); exit(1); } /**************************************************************************** * function: reap_status * description: handle a SIGCHLD signal by reaping the exit status of the * perished child, and discarding it. * arguments: none. * return value: none. * calls: none. * globals: none. * ****************************************************************************/ void reap_status(int sig) { int pid; int status; while ((pid = waitpid(0, &status, WNOHANG)) > 0); /* loop while there are more dead children */ }
proxyd.c的更多相关文章
- sniffer 和 debug flow
sniffer 和 debug flow sniffer 和 debug flow 复制模板,直接修改IP即可使用: diagnose sys session filter clear diagnos ...
- Proxy源代码分析——谈谈如何学习Linux网络编程
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...
- Linux网络编程:一个简单的正向代理服务器的实现
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...
- Proxy模式(代理[延迟]模式)
Proxy?? Proxy是"代理人"的意思,它指的是代替别人进行工作的人.代理实际上就是使用委托的机制,在代理的过程中你可以做点其他的事情,然后再来执行被代理对象的代码. 知识储 ...
- Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u014530704/article/de ...
- Proxy源代码分析--谈谈如何学习Linux网络编程
http://blog.csdn.net/cloudtech/article/details/1823531 Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux ...
随机推荐
- form表单提交路径action="" 时的一种特殊情况
一.说明: 当页面的form表达的action=""时,表示表单会提交到当前页面,但是如果当前页面的URL里已经带有一个参数了,每次提交表达时这个参数依然存在,不管form表单里有 ...
- java中的数据类型
通常情况下,为了方便物品的存储,我们会规定每个盒子可以存放的物品种类,就好比在"放臭袜子的盒子"里我们是不会放"面包"的!同理,变量的存储也讲究"分门 ...
- x-requested-with 请求头 区分ajax请求还是普通请求(转)
在服务器端判断request来自Ajax请求(异步)还是传统请求(同步): 两种请求在请求的Header不同,Ajax 异步请求比传统的同步请求多了一个头参数 1.传统同步请求参数 accept t ...
- 寻找子域名的IP段
校网网络安全检测,第一步,我们做的工作是找出学校所有的IP段. 当然,期间我们可以利用软件帮助我们扫描,但是一款软件往往是不够的,因为它全面,所以我们用了IISPutScanner,subDomai ...
- JavaScript 对象的创建和对6种继承模式的理解和遐想
JS中总共有六种继承模式,包括原型链.借用构造函数.组合继承.原型式继承寄生式继承和寄生组合式继承.为了便于理解记忆,我遐想了一个过程,对6中模式进行了简单的阐述. 很长的一个故事,姑且起个名字叫 ...
- SVN 集中式版本控制软件
简介: 目前流行的版本控制软件中,SVN ( 集中式版本控制 ) 算是使用范围更广.且使用时间更早的一款了,现在 git ( 分布式版本控制 ) 更火爆一点. 一.安装svn [root@localh ...
- PHP从mysqli中获取的资源$result是不是不能while($row = $result->fetch_assoc())这样两次?【坑】
PHP从mysqli中获取的资源$result是不是不能while($row = $result->fetch_assoc())这样两次? 因为我这样做,结果后面的查询结果就无法显示了,目前尚不 ...
- Robot Framework入门学习2 创建第一个测试用例
本文章部分内容引自以下网址,感谢作者的辛苦分享 http://www.cnblogs.com/fnng/p/3871712.html http://blog.csdn.net/tulituqi/art ...
- 详解C语言的类型转换
1.自动类型转换 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255( ...
- filter之排除个别过滤
1.jsp 篇 一般拦截器设置都是拦截*.action.*.jsp等,如此我们可以扩展后缀名,逃过拦截: jsp的话,可以改成.jspf后缀. ( 把一个JSP文件命名为jspf扩展名,然后inclu ...