為你的QQ造一個SOCKS5 PROXY(Gcc篇)之三

本文以QQ为对象,介绍如何编写一个SOCKS5 PROXY。详细阐述了SOCKS5 UDP封包结构,给出Launch_UDP()函数的源代码,该代码实现了UDP代理功能。最后完成整个PROXY并使用QQ进行测试,还可截留数据去除广告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本文以QQ為對像,教你如何寫一個SOCKS5 PROXY
本章主要介紹Launch_UDP()的工作原理

一、SOCKS5 UDP封包結構
===========================
順序為:
2 Bytes 保留字,一定要為0x0
1 Bytes Current fragment number
1 Bytes 地址類型
X Bytes 目的地地址
2 Bytes 目的地端口號
N Bytes 數據


二、源代碼
===========================


void Launch_UDP( int udp_proxy_port, const char *udp_proxy_ip, int clt_udp_port )
{
 //port is NOT network orders
 
 //記錄本機,客戶端,遠端服務器和封包來源地址
 struct sockaddr_in servaddr,clientaddr,remoteaddr,inaddr;
 int inlen;
 int listenfd;
 int n;
 fd_set set;
 //把接收來的數據寫在緩衝區第11個Byte之後,前10 Bytes用來存放Header
 char *thisbuf = &buf[10];
 int thissize = BUFSZ - 10;

 printf("< UDP Session - START >/n/n");

 //建立一個UDP SOCKET,注意UDP協議不需要listen, accept和conenct
 memset(&servaddr, 0, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_port = htons( udp_proxy_port );
 servaddr.sin_addr.s_addr = htonl( INADDR_ANY );

 memset(&remoteaddr, 0, sizeof(remoteaddr));
 remoteaddr.sin_family = AF_INET;
 
 listenfd = socket(AF_INET, SOCK_DGRAM, 0);
 if(listenfd < 0) {
  p_error("socket error");
  exit(-1);
 }

 if( bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
  p_error("bind error");
  exit(-1);
 }

 //使用select來監控Socket是否有資料可讀
 FD_ZERO(&set);
 FD_SET(listenfd, &set);

 while( 1 ) {

  if( select( listenfd+1, &set, NULL, NULL, NULL) < 0 ) {
   p_error("select error");
   exit(-1);
  }
  
  if( FD_ISSET( listenfd, &set ) ) {
   //UDP協議可使用recvfrom()來接收數據,並獲得來源地地址
   n = recvfrom( listenfd, thisbuf, thissize, 0, (struct sockaddr *)&inaddr, &inlen );
  
   if( n >=0 ) {
    
    debug_showip( &inaddr, "Received From", "/n" );

    //資料來自客戶端
    if( (thisbuf[0]==0x0) && (thisbuf[1]==0x0) &&
     (htons(inaddr.sin_port)==clt_udp_port) )
    {     
     //保存客戶端的地址
     memcpy( &clientaddr, &inaddr, sizeof(clientaddr) );
     
     if( thisbuf[3] != 0x1 ) {
      //如果目的地地址類型為域名,先進行解析獲得IP再發送
      struct hostent *h;
      char tmp[256];
      int seg;
     
      strncpy( tmp, &thisbuf[5], thisbuf[4] );
      tmp[ thisbuf[4] ] = 0;

      h = gethostbyname ( tmp ); //<netdb.h>
 
      if( h == NULL )
       p_error("unknown domain name/n");
      else
      {
       remoteaddr.sin_addr.s_addr = (*(struct in_addr*)h->h_addr).s_addr;
      
       seg = thisbuf[4]+1;
       memcpy( &remoteaddr.sin_port, &thisbuf[4+seg], 2 );
      
       debug_showbin( thisbuf, 4+seg+2, "RECV CLIENT [ Header ]","/n");
       debug_showbin( &thisbuf[4+seg+2], n-(4+seg+2), "RECV CLIENT [ Data ]","/n");
       debug_showip( &remoteaddr, "Send to DOMAIN", "/n/n");
       
       sendto( listenfd, &thisbuf[4+seg+2], n-(4+seg+2), 0, (struct sockaddr*)&remoteaddr,sizeof(remoteaddr));
      }
     } else {
      //目的地地址為IPv4,直接把資料發送過去
      memcpy( &remoteaddr.sin_port, &thisbuf[8], 2 );
      memcpy( &remoteaddr.sin_addr.s_addr, &thisbuf[4], 4 );
      
      debug_showbin( thisbuf, 10, "RECV CLIENT [ Header ]","/n");
      debug_showbin( &thisbuf[10], n-10, "RECV CLIENT [  Data  ]","/n");
      debug_showip( &remoteaddr, "Send to IP", "/n/n");
      
      sendto( listenfd, &thisbuf[10], n-10, 0, (struct sockaddr*)&remoteaddr,sizeof(remoteaddr));
     }
    }
    else
    { //資料來自遠端服務器
     debug_showbin(thisbuf, n, "RECV REMOTE","/n");
     debug_showip(&clientaddr, "Send to CLT","/n/n");

     //編寫Header     
     buf[0] = 0x0;
     buf[1] = 0x0;
     buf[2] = 0x0;
     buf[3] = 0x1;
     memcpy( &buf[4], &udp_proxy_ip, 4 );
     memcpy( &buf[8], &udp_proxy_port, 2 );

     //發送到客戶端
     sendto( listenfd, buf, n+10, 0, (struct sockaddr*)&clientaddr,sizeof(clientaddr));
  } } }
 }
 
 close(listenfd);
 
 printf("< UDP Session - END >/n/n");
}

 

三、測試
===================
到目前為止,整個PROXY已經完成,可以用QQ來測試一下,連接後QQ與遠端服務器之間傳輸的資料都會顯示在屏幕上,我們還可以對數據進行截留,從而把煩人的廣告全去掉:)


下載本章的源代碼 → mysocks5.c

内容概要:本文深入探讨了多种高级格兰杰因果检验方法,包括非线性格兰杰因果检验、分位数格兰杰因果检验、混频格兰杰因果检验以及频域因果检验。每种方法都有其独特之处,适用于不同类型的时间序列数据。非线性格兰杰因果检验分为非参数方法、双变量和多元检验,能够在不假设数据分布的情况下处理复杂的关系。分位数格兰杰因果检验则关注不同分位数下的因果关系,尤其适合经济数据的研究。混频格兰杰因果检验解决了不同频率数据之间的因果关系分析问题,而频域因果检验则专注于不同频率成分下的因果关系。文中还提供了具体的Python和R代码示例,帮助读者理解和应用这些方法。 适合人群:从事时间序列分析、经济学、金融学等领域研究的专业人士,尤其是对非线性因果关系感兴趣的学者和技术人员。 使用场景及目标:①研究复杂非线性时间序列数据中的因果关系;②分析不同分位数下的经济变量因果关系;③处理不同频率数据的因果关系;④识别特定频率成分下的因果关系。通过这些方法,研究人员可以获得更全面、细致的因果关系洞察。 阅读建议:由于涉及较多数学公式和编程代码,建议读者具备一定的统计学和编程基础,特别是对时间序列分析有一定了解。同时,建议结合具体案例进行实践操作,以便更好地掌握这些方法的实际应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值