`
tower
  • 浏览: 243977 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

收藏的一个linux下proxy实现的源码

阅读更多

/****************************************************************************
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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#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() */

extern int errno; /* defined by libc.a */
/*extern char *sys_errlist[];  defined by libc.a */


void parse_args (int argc, char **argv);
void daemonize (int servfd);
void do_proxy (int usersockfd);
void reap_status (void);
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.
****************************************************************************/

main (argc,argv)
int argc;
char **argv;
{
 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) {
  fputs("failed to create server socket",stderr);
  exit(1);
 }

 /* ...and bind our address and port to it */
 if (bind(sockfd,(struct sockaddr *) (&servaddr),sizeof(servaddr)) < 0) { 
  fputs("faild to bind server socket to specified port",stderr);
  exit(1);
 }

 /* get ready to accept with at most 5 clients waiting to connect */
 listen(sockfd,5);

 /* turn ourselves into a daemon */
 daemonize(sockfd);

 /* 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);
  }
  
  /* if fork() failed, the connection is silently dropped -- oops! */
  
  close(newsockfd);
 }
}

/****************************************************************************
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 (argc,argv)
int argc;
char **argv;
{
 int i;
 struct hostent *hostp;
 struct servent *servp;
 unsigned long inaddr;
 struct {
  char proxy_port [16];
  char isolated_host [64];
  char service_name [32];
 } pargs;


 if (argc < 4) {
  printf("usage: %s ",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)
  bcopy(&inaddr,&hostaddr.sin_addr,sizeof(inaddr));
 else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL)
  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 (servfd)
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) {
  fputs("failed to fork first child",stderr);
  exit(1);
 }
 else if (childpid > 0)
  exit(0); /* terminate parent, continue in child */

 /* dissociate from process group */
 if (setpgrp(0,getpid()) < 0) {
  fputs("failed to become process group leader",stderr);
  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(SIGCLD,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 (usersockfd)
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,sys_errlist[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 (msg)
char *msg;
{
 FILE *console;

 console = fopen("/dev/console","a");
 fprintf(console,"proxyd: %s",msg);
 fclose(console);
 exit(1);
}

/****************************************************************************
function: reap_status
description: handle a SIGCLD 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 pid;
 union wait status;

 while ((pid = wait3(&status,WNOHANG,NULL)) > 0); /* loop while there are more dead children */
}

分享到:
评论

相关推荐

    tcp proxy源码 linux c

    一个基于linux环境开发的简单的proxy源码。经过测试,ssh telnet rdp 都可以使用

    ftpproxy-1.2.3.rar_Linux c proxy_ftpproxy_ftp代理_linux ftp_proxy-

    proxy源代码,linux下的ftp 代理的源代码,大家多多支持啊

    Proxy源代码分析--谈谈如何学习linux网络编程

    通过以上分析,我们可以看到《Proxy源代码分析——谈谈如何学习Linux网络编程》这篇文章不仅提供了一个很好的学习案例,还涵盖了Linux网络编程的多个方面,非常适合初学者作为入门指南。希望每位读者都能从中受益,...

    Proxy源代码分析(包括源码分析和可在Linux下运行的源码)

    这段代码虽然只是描述了最简单的proxy操作,但它的确是经典,它不仅清晰地描述了客户机/服务器系统的概念,而且几乎包括了Linux网络编程的方方面面,非常适合Linux网络编程的初学者学习。  这段Proxy程序的用法是...

    proxylab-handoutV1.0_linux网络编程_linuxhttpgetpost_connect_源码

    本资源"proxylab-handoutV1.0_linux网络编程_linuxhttpgetpost_connect_源码"提供了一个简洁高效的HTTP/HTTPS代理程序,它支持GET、PUT、POST、HEAD和CONNECT等多种HTTP协议指令。这个代理程序对于学习和开发相关...

    zabbix源码编译一键部署(包含proxy)

    本教程将详细介绍如何在Red Hat 7或CentOS 7及其以上版本上,通过源码编译的方式,一键部署Zabbix包括Proxy组件,并集成LNMP(Linux + Nginx + MySQL + PHP)环境。这种方式的好处在于能够灵活地定制配置,适应特定...

    AOA Linux实现 ,含TCP转发

    通过分析这个项目的源码,我们可以深入学习TCP转发的具体实现,包括如何处理并发连接、数据流控制、异常处理等。 总的来说,AOA Linux实现结合TCP转发的项目涵盖了Linux系统编程、网络协议、并发处理等多个IT领域的...

    Proxy源代码分析

    Proxy源代码分析可以帮助我们深入了解网络通信的原理以及如何在Linux环境下实现客户端-服务器模型。以下是对Proxy源代码及其涉及的关键知识点的详细说明: 1. **套接字(socket)**:在Linux网络编程中,套接字是进程...

    linux下TOMCAT集群(proxy)安装文档.pdf

    完成以上步骤后,你的Linux系统上将有一个基于Apache的TOMCAT集群,通过反向代理实现负载均衡。记得在实际部署时,根据你的网络环境和需求调整配置参数,确保所有组件能够正常通信,同时监控集群性能以优化设置。

    proxy源代码分析

    linux下的proxy软件源码 经典~

    webrtc源码的下载-对应ios-android-linux-mac-window等平台的编译文档

    webrtc源码的下载-对应ios-android-linux-mac-window等平台的编译文档 举例mac端 //直接连外网代理,如何有连外面vpn就不需要,下面的连接是例子不能直接连改自己IP和端口 export ...

    SS5 Linux 下开源的 Socket5 代理软件

    SS5在Linux环境下是一款广泛应用的开源Socket5代理软件。Socket5协议是一种通用的代理协议,它不仅支持TCP连接,还支持UDP数据包的传输,因此SS5被广泛用于网络访问控制、网络安全、数据转发等场景。本文将详细介绍...

    charles-proxy 抓包工具 v4.2 Win + Mac + Linux全平台破解文件

    下载正版原版程序: ...Windows 平台,将下载的charles.jar文件覆盖到安装目录下的lib文件夹下即可完成破解! Mac 平台,将下载的charles.jar文件右键 Charles.app 显示包内容,覆盖到Content-&gt;Java下即可完成破解!

    安装mysql-proxy所需工具

    6. **获取MySQL Proxy源码**: 你可以从MySQL官方网站或者GitHub上下载MySQL Proxy的源代码。下载后解压,进入源码目录,然后执行`./configure`检查依赖项,再运行`make`和`make install`进行编译和安装。 7. **...

    基于Proxy模式的分布式MySQL数据库中间件设计源码

    MySQL数据库中间件:基于C语言开发,包含59个文件,包括22个C源文件、9个C头文件、5个Linux配置文件、2个Markdown文档、2个PNG图像文件、1个.gitignore文件、1个AUTHORS文件、1个ChangeLog-CN文件、1个LICENSE文件和...

    proxyd.rar_proxy_proxyd linux_proxyd.rar

    linux 下实现网络代理功能的源码

    linux下Nginx+tomcat整合的安装与配置

    本文将详细解析在Linux环境下如何安装和配置Nginx与Tomcat的整合,帮助读者实现高效的Web服务部署。 #### 安装Nginx 首先,我们需要在Linux系统上安装Nginx。以下步骤以上传的`nginx-0.7.63.tar.gz`为例,进行详细...

    IGMP proxy源代码

    然而,对于大型网络环境,尤其是那些跨越多个物理网络的多播部署,IGMP Proxy成为一种有效工具,它能简化网络架构并优化多播流量的转发。 IGMP Proxy是一种在网络设备上实现的机制,用于在不同子网之间代理IGMP通信...

Global site tag (gtag.js) - Google Analytics