tcproxy 使用介绍

来源:互联网 发布:华林证券软件 编辑:程序博客网 时间:2024/06/07 15:04

最近看到一个基于c语言开发的tcp代理开源项目 地址:https://github.com/dccmx/tcproxy
因为在现有的项目引用到 做下简单的记录     
这里面主要是应用到了epoll 处理监听网络客户端,代理端口转发到本地服务,可以实现过滤黑名单,很小巧的程序


</pre><pre name="code" class="cpp">int main(int argc, char **argv) {  int i, listen_fd;
</pre><pre name="code" class="cpp">
  struct sigaction sig_action;  ParseArgs(argc, argv);  if (run_daemonize) Daemonize();  sig_action.sa_handler = SignalHandler;  sig_action.sa_flags = SA_RESTART;  sigemptyset(&sig_action.sa_mask);  sigaction(SIGINT, &sig_action, NULL);  sigaction(SIGTERM, &sig_action, NULL);  sigaction(SIGPIPE, &sig_action, NULL);  if ((policy->listen.addr == NULL) || !strcmp(policy->listen.addr, "any")) {    free(policy->listen.addr);    policy->listen.addr = strdup("0.0.0.0");  } else if (!strcmp(policy->listen.addr, "localhost")) {    free(policy->listen.addr);    policy->listen.addr = strdup("127.0.0.1");  }  listen_fd = anetTcpServer(error_, policy->listen.port, policy->listen.addr);  el = aeCreateEventLoop(65536);  if (listen_fd < 0 || aeCreateFileEvent(el, listen_fd, AE_READABLE, AcceptTcpHandler, NULL) == AE_ERR) {    LogFatal("listen failed: %s", strerror(errno));  }  LogInfo("listenning on %s:%d", (policy->listen.addr? policy->listen.addr : "any"), policy->listen.port);  for (i = 0; i < policy->nhost; i++) {    if (policy->hosts[i].addr == NULL) policy->hosts[i].addr = strdup("127.0.0.1");    LogInfo("proxy to %s:%d", policy->hosts[i].addr, policy->hosts[i].port);  }  aeMain(el);  aeDeleteEventLoop(el);  FreePolicy(policy);  return 0;}
ParseArgs 判断命令行参数 

policy = ParsePolicy(argv[i]);   这个函数用了加密算法 把端口地址体会成代理地址端口映射

接下来整个程序围绕 

policy这个结构体来操作   listen_fd = anetTcpServer(error_, policy->listen.port, policy->listen.addr);  创建一个socket连接bind 地址 listen 开始监听 

el = aeCreateEventLoop(65536); 创建el 事件循环

接下来这步比较重要了 

  if (listen_fd < 0 || aeCreateFileEvent(el, listen_fd, AE_READABLE, AcceptTcpHandler, NULL) == AE_ERR) {
    LogFatal("listen failed: %s", strerror(errno));
  }

回调函数 AcceptTcpHandler  里面accept 接受客户端连接  

aeCreateFileEvent(el, cfd, AE_READABLE, ReadIncome, c)  

读写数据 在readincome里面 接受客户端信息

void ReadIncome(aeEventLoop *el, int fd, void *privdata, int mask) {  LogDebug("read in come");  Client *c = (Client*)privdata;  Client *r = c->remote;  char *buf;  int len, nread = 0;  while (1) {    buf = BufferListGetSpace(r->blist, &len);    if (buf == NULL) break;    nread = recv(fd, buf, len, 0);    if (nread == -1) {      if (errno == EAGAIN) {        // no data        nread = 0;      } else {        // connection error        goto ERROR;      }    } else if (nread == 0) {      // connection closed      LogInfo("connection closed");      goto ERROR;    }    if (nread) {      BufferListPush(r->blist, nread);      SetWriteEvent(r);      LogDebug("set write");    } else {      break;    }  }  return;ERROR:  c->OnError(c);}
循环接受客户端数据的同时 触发SetWriteEvent 写事件  

前面说的是原理:

       一、要增加黑名单  可以在ReadIncome 这个函数加限制判断  读取的buf 内容 判断是否是给它通过 

       二、在ParseArgs函数可以做一些改动 包括加密密码等内容 




0 0
原创粉丝点击