青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 298  文章 - 377  trackbacks - 0
<2007年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(34)

隨筆分類

隨筆檔案

文章檔案

相冊

收藏夾

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

/*************************************  
    *   一個基礎的代理服務器類  
    *************************************  
    */  
  import   java.net.*;  
  import   java.io.*;  
   
  public   class   HttpProxy   extends   Thread   {  
          static   public   int   CONNECT_RETRIES=5;  
          static   public   int   CONNECT_PAUSE=5;  
          static   public   int   TIMEOUT=50;  
          static   public   int   BUFSIZ=1024;  
          static   public   boolean   logging   =   false;  
          static   public   OutputStream   log=null;  
          //   傳入數據用的Socket  
          protected   Socket   socket;  
          //   上級代理服務器,可選  
          static   private   String   parent=null;  
          static   private   int   parentPort=-1;  
          static   public   void   setParentProxy(String   name,   int   pport)   {  
  parent=name;  
  parentPort=pport;  
          }  
   
          //   在給定Socket上創建一個代理線程。  
          public   HttpProxy(Socket   s)   {   socket=s;   start();   }  
   
          public   void   writeLog(int   c,   boolean   browser)   throws   IOException   {  
  log.write(c);  
          }  
   
          public   void   writeLog(byte[]   bytes,int   offset,   int   len,   boolean   browser)   throws   IOException   {  
  for   (int   i=0;i<len;i++)   writeLog((int)bytes[offset+i],browser);  
          }  
   
   
          //   默認情況下,日志信息輸出到  
          //   標準輸出設備  
          //   派生類可以覆蓋它  
          public   String   processHostName(String   url,   String   host,   int   port,   Socket   sock)   {  
  java.text.DateFormat   cal=java.text.DateFormat.getDateTimeInstance();  
  System.out.println(cal.format(new   java.util.Date())   +   "   -   "   +   url   +   "   "    
                              +   sock.getInetAddress()+"\n");  
  return   host;  
          }  
   
   
   
          //   執行操作的線程  
          public   void   run()   {  
  String   line;  
  String   host;  
  int   port=80;  
                  Socket   outbound=null;  
  try   {  
          socket.setSoTimeout(TIMEOUT);  
          InputStream   is=socket.getInputStream();  
          OutputStream   os=null;  
          try   {  
                                  //   獲取請求行的內容  
  line="";  
  host="";  
  int   state=0;  
  boolean   space;  
  while   (true)   {  
          int   c=is.read();  
          if   (c==-1)   break;  
          if   (logging)   writeLog(c,true);  
          space=Character.isWhitespace((char)c);    
          switch   (state)   {  
          case   0:  
  if   (space)   continue;    
                  state=1;  
          case   1:  
  if   (space)   {  
          state=2;  
          continue;  
  }  
  line=line+(char)c;  
  break;  
          case   2:  
  if   (space)   continue;   //   跳過多個空白字符  
                      state=3;  
          case   3:  
  if   (space)   {  
          state=4;    
                                                          //   只取出主機名稱部分  
          String   host0=host;  
          int   n;  
          n=host.indexOf("http://");  
          if   (n!=-1)   host=host.substring(n+2);  
          n=host.indexOf('/');  
          if   (n!=-1)   host=host.substring(0,n);  
                                                          //   分析可能存在的端口號  
          n=host.indexOf(":");  
          if   (n!=-1)   {    
  port=Integer.parseInt(host.substring(n+1));  
  host=host.substring(0,n);  
          }  
          host=processHostName(host0,host,port,socket);  
          if   (parent!=null)   {  
  host=parent;  
  port=parentPort;  
          }  
          int   retry=CONNECT_RETRIES;  
          while   (retry--!=0)   {  
  try   {  
          outbound=new   Socket(host,port);  
          break;  
  }   catch   (Exception   e)   {   }  
                                                                  //   等待  
  Thread.sleep(CONNECT_PAUSE);  
          }  
          if   (outbound==null)   break;  
          outbound.setSoTimeout(TIMEOUT);  
          os=outbound.getOutputStream();  
          os.write(line.getBytes());  
          os.write('   ');  
          os.write(host0.getBytes());  
          os.write('   ');  
          pipe(is,outbound.getInputStream(),os,socket.getOutputStream());  
          break;  
  }  
  host=host+(char)c;  
  break;  
          }  
  }  
          }  
          catch   (IOException   e)   {   }  
   
          }   catch   (Exception   e)   {   }  
          finally   {  
          try   {   socket.close();}   catch   (Exception   e1)   {}  
          try   {   outbound.close();}   catch   (Exception   e2)   {}  
                }  
          }  
   
   
          void   pipe(InputStream   is0,   InputStream   is1,  
                    OutputStream   os0,     OutputStream   os1)   throws   IOException   {  
  try   {  
          int   ir;  
          byte   bytes[]=new   byte[BUFSIZ];  
          while   (true)   {  
  try   {  
          if   ((ir=is0.read(bytes))>0)   {  
  os0.write(bytes,0,ir);  
  if   (logging)   writeLog(bytes,0,ir,true);  
          }  
          else   if   (ir<0)  
  break;  
  }   catch   (InterruptedIOException   e)   {   }  
  try   {  
          if   ((ir=is1.read(bytes))>0)   {  
  os1.write(bytes,0,ir);  
  if   (logging)   writeLog(bytes,0,ir,false);  
          }  
          else   if   (ir<0)    
  break;  
  }   catch   (InterruptedIOException   e)   {   }  
          }  
  }   catch   (Exception   e0)   {  
          System.out.println("Pipe異常:   "   +   e0);  
  }  
          }  
   
   
          static   public   void   startProxy(int   port,Class   clobj)   {  
  ServerSocket   ssock;  
  Socket   sock;  
                  try   {  
          ssock=new   ServerSocket(port);  
          while   (true)   {  
  Class   []   sarg   =   new   Class[1];  
  Object   []   arg=   new   Object[1];  
  sarg[0]=Socket.class;  
  try   {  
          java.lang.reflect.Constructor   cons   =   clobj.getDeclaredConstructor(sarg);  
          arg[0]=ssock.accept();  
          cons.newInstance(arg);   //   創建HttpProxy或其派生類的實例  
  }   catch   (Exception   e)   {    
          Socket   esock   =   (Socket)arg[0];  
          try   {   esock.close();   }   catch   (Exception   ec)   {}  
  }  
          }  
  }   catch   (IOException   e)   {  
  }  
          }  
   
   
          //   測試用的簡單main方法  
          static   public   void   main(String   args[])   {  
  System.out.println("在端口808啟動代理服務器\n");  
  HttpProxy.log=System.out;  
  HttpProxy.logging=false;  
  HttpProxy.startProxy(808,HttpProxy.class);  
              }  
          }  
  //   HttpProxy的簡單派生類  
  //   不記錄主機名字  
  //   在日志輸出的每一行前面加上一個'*'  
   
  import   java.io.*;  
  import   java.net.*;  
   
  public   class   SubHttpProxy   extends   HttpProxy   {  
          static   private   boolean   first=true;  
          public   SubHttpProxy(Socket   s)   {  
  super(s);  
          }  
          public   void   writeLog(int   c,   boolean   browser)   throws   IOException   {  
  if   (first)   log.write('*');  
  first=false;  
  log.write(c);  
  if   (c=='\n')   log.write('*');  
          }  
          public   String   processHostName(String   url,   String   host,   int   port,   Socket   sock)   {  
  //   直接返回  
  return   host;  
          }  
          //   測試用的簡單main方法  
          static   public   void   main(String   args[])   {  
  System.out.println("在端口808啟動代理服務器\n");  
  HttpProxy.log=System.out;  
  HttpProxy.logging=true;  
  HttpProxy.startProxy(808,SubHttpProxy.class);  
              }  
   
   
  }  
posted on 2008-10-21 02:02 聶文龍 閱讀(7140) 評論(11)  編輯 收藏 引用

FeedBack:
# re: 代理服務器代碼 2008-10-21 02:03 聶文龍
不要心里老是想著只要拿到源代碼就可以直接去用,因為對rfc1928、rfc1929研究是必要的,因為在調試程序的時候,你一定要知道協議才可以調,我現在給一些相關的文檔給你,也許比那些代碼對你更加有用處:

用socks5進行udp發送數據的過程:

你的目的是要和服務器做UDP的數據傳送。
步驟:
1,和代理建立tcp聯接,(你已經完成)
2,向代理發送版本的請求信息,
我的實現:
void CCommunicator::SendVer ()
{
int datasize = 6;
char tempbuf[6];

tempbuf[0] = 5;
tempbuf[1] = 4;//標示后面所根的字接數
tempbuf[2] = 0;
tempbuf[3] = 1;
tempbuf[4] = 2;
tempbuf[5] = 3;
int senddatalen;
senddatalen = send(m_sock, (char *)tempbuf, 6, 0 );
}
這一步,你已經返回成功,是嗎?
如果失敗,斷開建立的tcp聯接,
如果成功,如果需要用戶驗證則進行步驟3,否則進行4,
3,如果需要用戶驗證,則
類似:
BOOL CCommunicator::SendUserTest()
{
int usernamelen=0;
int userpasslen=0;
usernamelen = m_strTestUserName.GetLength();
userpasslen = m_strTestUserPass.GetLength();
char tempbuf[100];

tempbuf[0] = 5;
tempbuf[1] = usernamelen;//標示后面所根的字接數
strcpy(&tempbuf[2],m_strTestUserName);

tempbuf[2+usernamelen] = userpasslen;
strcpy((char *)&tempbuf [3+usernamelen] ,m_strTestUserPass);

int senddatalen;
int len;
len = usernamelen +userpasslen + 3;
senddatalen = send(m_sock, (char *)tempbuf, len, 0 );
}
如果失敗,斷開建立的tcp聯接,
如果用戶返回成功,步驟4
4,發送請求的協議
類似:
void CCommunicator::SendRequestUDP ()
{

int const datasize = 10;
BYTE tempbuf[datasize];
tempbuf[0] = 5;
tempbuf[1] = 3;//標示UDP連接
tempbuf[2] = 0;
tempbuf[3] = 1;
tempbuf[4] = 0;
tempbuf[5] = 0;
tempbuf[6] = 0;
tempbuf[7] = 0;
*((SHORT*)(&(tempbuf[8]))) = m_uBindUDPPort;
//UDP在客戶端綁定的端口,就是你本地機器的做udp數據傳送的端口,調用
// socket函數后,再調用bind()來邦定一個端口。
char temp;
temp = tempbuf[8] ;
tempbuf[8] = tempbuf[9];
tempbuf[9] = temp;

int senddatalen = send(m_sock, (char *)tempbuf, datasize, 0 );
}
如果失敗,斷開建立的tcp聯接,
如果返回成功,驗證完畢!步驟5
5,真正的數據傳送,用代理傳送的時候,數據包的前面加上10個字節
類似:
void CCommunicator::CopyDataHead(BYTE * ptempbuf)
{
struct in_addr addr;
addr.s_addr = inet_addr(“202.220.33.333”);//這個ip是服務器端的ip

ptempbuf[0] = 0;
ptempbuf[1] = 0;
ptempbuf[2] = 0;
ptempbuf[3] = 1;
ptempbuf[4] = (char)addr.S_un.S_un_b.s_b1;;
ptempbuf[5] = (char)addr.S_un.S_un_b.s_b2;
ptempbuf[6] = (char)addr.S_un.S_un_b.s_b3;
ptempbuf[7] = (char)addr.S_un.S_un_b.s_b4;

*((SHORT*)(&(ptempbuf[8]))) = m_uServerUDPPort;//服務器的端口,就是你最終要發到那個服務器的端口,也就是你的qq服務器。
char temp;
temp = ptempbuf[8] ;
ptempbuf[8] = ptempbuf[9];
ptempbuf[9] = temp;
}
真正發送的時候類似:
int CCommunicator::SendBufferUDP(LPBYTE lpBuf,int nLen)
{
BYTE tempbuf[1000];
int iHeadData = 0;
struct sockaddr_in her;
her.sin_family = AF_INET;
her.sin_addr.s_addr = inet_addr(m_szProxyAddr);//代理服務器
her.sin_port = htons(m_uSocksPort);//發送請求的時候返回的代理服務器端的端口,記住,這是最重要的。
CopyDataHead(tempbuf);
iHeadData = 10;
nLen=nLen + 10;
int addr_len;
addr_len = sizeof(struct sockaddr);

CopyMemory((char *)&tempbuf[iHeadData],lpBuf,nLen);
int returndatalen = sendto(m_socket,(char *)tempbuf,nLen,0,(struct sockaddr *)&her,addr_len);

}
希望對你有幫助!  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:04 聶文龍
傳透代理服務器的編程

關鍵字 代理服務器、Socks4、Socks5、Http代理
原作者姓名 allfresh
文章原始出處 http://www.allfresh.net/program/proxy.htm
正文
在網絡程序設計過程中,我們經常要與各種類型的代理服務器打交道,比如在企業內部網通過代理去訪問Internet網上的服務器等等,一般代理服務器支持幾種常見的代理協議標準,如Socks4,Socks5,Http代理,其中Socks5需要用戶驗證,代理相對復雜。我在查閱RFC文檔和相關資料后,特總結一些TCP協議穿透代理服務器的程序片斷,希望對大家有所幫助。

//使用到的結構
struct sock4req1
{
 char VN;
 char CD;
 unsigned short Port;
 unsigned long IPAddr;
 char other[1];
};

struct sock4ans1
{
 char VN;
 char CD;
};

struct sock5req1
{
 char Ver;
 char nMethods;
 char Methods[255];
};

struct sock5ans1
{
 char Ver;
 char Method;
};

struct sock5req2
{
 char Ver;
 char Cmd;
 char Rsv;
 char Atyp;
 char other[1];
};

struct sock5ans2
{
 char Ver;
 char Rep;
 char Rsv;
 char Atyp;
 char other[1];
};

struct authreq
{
 char Ver;
 char Ulen;
 char Name[255];
 char PLen;
 char Pass[255];
};

struct authans
{
 char Ver;
 char Status;
};

//通過Socks4方式代理
if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
{
  m_sError = _T("不能連接到代理服務器!");
  ClientSock.Close();
  return FALSE;
}
char buff[100];
memset(buff,0,100);
struct sock4req1 *m_proxyreq;
m_proxyreq = (struct sock4req1 *)buff;
m_proxyreq->VN = 4;
m_proxyreq->CD = 1;
m_proxyreq->Port = ntohs(GetPort());
m_proxyreq->IPAddr = inet_addr(GetServerHostName());
ClientSock.Send(buff,9);
struct sock4ans1 *m_proxyans;
m_proxyans = (struct sock4ans1 *)buff;
memset(buff,0,100);
ClientSock.Receive(buff,100);
if(m_proxyans->VN != 0 || m_proxyans->CD != 90)
{
 m_sError = _T("通過代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}




//通過Socks5方式代理
if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
{
 m_sError = _T("不能連接到代理服務器!");
 ClientSock.Close();
 return FALSE;
}
char buff[600];
struct sock5req1 *m_proxyreq1;
m_proxyreq1 = (struct sock5req1 *)buff;
m_proxyreq1->Ver = 5;
m_proxyreq1->nMethods = 2;
m_proxyreq1->Methods[0] = 0;
m_proxyreq1->Methods[1] = 2;
ClientSock.Send(buff,4);
struct sock5ans1 *m_proxyans1;
m_proxyans1 = (struct sock5ans1 *)buff;
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(m_proxyans1->Ver != 5 || (m_proxyans1->Method!=0 && m_proxyans1->Method!=2))
{
 m_sError = _T("通過代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}
if(m_proxyans1->Method == 2)
{
 int nUserLen = strlen(g_ProxyInfo.m_strProxyUser);
 int nPassLen = strlen(g_ProxyInfo.m_strProxyPass);
 struct authreq *m_authreq;
 m_authreq = (struct authreq *)buff;
 m_authreq->Ver = 1;
 m_authreq->Ulen = nUserLen;
 strcpy(m_authreq->Name,g_ProxyInfo.m_strProxyUser);
 m_authreq->PLen = nPassLen;
 strcpy(m_authreq->Pass,g_ProxyInfo.m_strProxyPass);
 ClientSock.Send(buff,513);
 struct authans *m_authans;
 m_authans = (struct authans *)buff;
 memset(buff,0,600);
 ClientSock.Receive(buff,600);
 if(m_authans->Ver != 1 || m_authans->Status != 0)
 {
  m_sError = _T("代理服務器用戶驗證不成功!");
  ClientSock.Close();
 return FALSE;
 }
}
struct sock5req2 *m_proxyreq2;
m_proxyreq2 = (struct sock5req2 *)buff;
m_proxyreq2->Ver = 5;
m_proxyreq2->Cmd = 1;
m_proxyreq2->Rsv = 0;
m_proxyreq2->Atyp = 1;
unsigned long tmpLong = inet_addr(GetServerHostName());
unsigned short port = ntohs(GetPort());
memcpy(m_proxyreq2->other,&tmpLong,4);
memcpy(m_proxyreq2->other+4,&port,2);
ClientSock.Send(buff,sizeof(struct sock5req2)+5);
struct sock5ans2 *m_proxyans2;
memset(buff,0,600);
m_proxyans2 = (struct sock5ans2 *)buff;
ClientSock.Receive(buff,600);
if(m_proxyans2->Ver != 5 || m_proxyans2->Rep != 0)
{
 m_sError = _T("通過代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}




//通過HTTP方式代理
if( !ClientSock.Connect( g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort) )
{
 m_sError = _T("不能連接到代理服務器!");
 ClientSock.Close();
 return FALSE;
}
char buff[600];
sprintf( buff, "%s%s:%d%s","CONNECT ",GetServerHostName(),GetPort()," HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n");
ClientSock.Send(buff,strlen(buff)); //發送請求
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
{
 m_sError = _T("通過代理連接主站不成功!");
 ClientSock.Close();
 return FALSE;
}


我們一般先與代理服務器連通,然后向代理服務器發送代理驗證的用戶名和密碼(如果需要,如Socks5代理),驗證成功后,再向代理服務器發送需要連接的目的地址和端口。以上代碼僅用于TCP連接,如果在內部網偵聽或通過UDP協議發送信息,可查閱RFC1829等文檔資料。

<正文完>   回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:08 聶文龍
使用socks4 socks5 http代理的客戶端

///定義的結構
struct sock4req1
{
char VN;
char CD;
unsigned short Port;
unsigned long IPAddr;
char other[1];
};

struct sock4ans1
{
char VN;
char CD;
};

struct sock5req1
{
char Ver;
char nMethods;
char Methods[255];
};

struct sock5ans1
{
char Ver;
char Method;
};

struct sock5req2
{
char Ver;
char Cmd;
char Rsv;
char Atyp;
unsigned long IPAddr;
unsigned short Port;

// char other[1];
};

struct sock5ans2
{
char Ver;
char Rep;
char Rsv;
char Atyp;
char other[1];
};

struct authreq
{
char Ver;
char Ulen;
char Name[255];
char PLen;
char Pass[255];
};

struct authans
{
char Ver;
char Status;
};


///////////
///////////代碼片段
void CTestDlg::OnSocks4()
{
CString m_sError;
ClientSock.Create();

//Socks4代理服務器端口及地址
//if( !ClientSock.Connect( "195.65.215.38",1080) )
if( !ClientSock.Connect( "192.168.123.194",1080) )
{
m_sError = _T("不能連接到代理服務器!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}

char buff[100];
memset(buff,0,100);
struct sock4req1 *m_proxyreq;
m_proxyreq = (struct sock4req1 *)buff;
m_proxyreq->VN = 4;
m_proxyreq->CD = 1;
m_proxyreq->Port = ntohs(21);
m_proxyreq->IPAddr = inet_addr("219.201.39.50");
strcpy(m_proxyreq->other , "");
ClientSock.Send(buff,9);
struct sock4ans1 *m_proxyans;
m_proxyans = (struct sock4ans1 *)buff;
memset(buff,0,100);
ClientSock.Receive(buff,100);
if(m_proxyans->VN != 0 || m_proxyans->CD != 90)
{
m_sError = _T("通過代理連接主站不成功!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}



//連接已經建立,發送及接收數據
memset(buff,0,100);
strcpy(buff,"Hello!");
ClientSock.Send(buff,sizeof(buff));
memset(buff,0,100);
ClientSock.Receive(buff,100);
MessageBox(buff);
ClientSock.Close();

}

void CTestDlg::OnSocks5()
{
// TODO: Add your control notification handler code here
//http://my.nbip.net/homepage/nblulei/ttdl/sockdllb.htm

CString m_sError;
ClientSock.Create();
//Socks5代理服務器端口及地址
//if( !ClientSock.Connect("61.238.12.84",12654) )
if( !ClientSock.Connect("192.168.123.194",1080) )
{
m_sError = _T("不能連接到代理服務器!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}
char buff[600];
struct sock5req1 *m_proxyreq1;
m_proxyreq1 = (struct sock5req1 *)buff;
m_proxyreq1->Ver = 5;
m_proxyreq1->nMethods = 2;
m_proxyreq1->Methods[0] = 0;
m_proxyreq1->Methods[1] = 2;
ClientSock.Send(buff,4);
struct sock5ans1 *m_proxyans1;
m_proxyans1 = (struct sock5ans1 *)buff;
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(m_proxyans1->Ver != 5 || (m_proxyans1->Method!=0 && m_proxyans1->Method!=2))
{
m_sError = _T("通過代理連接主站不成功!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}
if(m_proxyans1->Method == 2)
{
int nUserLen = strlen("alon");
int nPassLen = strlen("alon");
struct authreq *m_authreq = {0};
m_authreq = (struct authreq *)buff;
m_authreq->Ver = 1;
m_authreq->Ulen = nUserLen;
strcpy(m_authreq->Name,"alon");
m_authreq->PLen = nPassLen;
strcpy(m_authreq->Pass,"alon");
ClientSock.Send(buff,513);
struct authans *m_authans;
m_authans = (struct authans *)buff;
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(m_authans->Ver != 1 || m_authans->Status != 0)
{
m_sError = _T("代理服務器用戶驗證不成功!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}
}
struct sock5req2 *m_proxyreq2;
m_proxyreq2 = (struct sock5req2 *)buff;
m_proxyreq2->Ver = 5;
m_proxyreq2->Cmd = 1;
m_proxyreq2->Rsv = 0;
m_proxyreq2->Atyp = 1;
m_proxyreq2->IPAddr = inet_addr("219.201.39.50");
m_proxyreq2->Port = ntohs(21);


ClientSock.Send(buff,sizeof(struct sock5req2));
struct sock5ans2 *m_proxyans2;
memset(buff,0,600);
m_proxyans2 = (struct sock5ans2 *)buff;
ClientSock.Receive(buff,600);
if(m_proxyans2->Ver != 5 || m_proxyans2->Rep != 0)
{
m_sError = _T("通過代理連接主站不成功!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}



//連接已經建立,發送及接收數據
memset(buff,0,600);
strcpy(buff,"Hello!");
ClientSock.Send(buff,sizeof(buff));
memset(buff,0,600);
ClientSock.Receive(buff,600);
MessageBox(buff);
ClientSock.Close();
}


void CTestDlg::OnHttp()
{
// TODO: Add your control notification handler code here
CString m_sError;
ClientSock.Create();
//if( !ClientSock.Connect("61.145.123.202",3128) )
if( !ClientSock.Connect("211.92.143.19",3128) )
//if( !ClientSock.Connect("WWW.TOM.COM",80) )
{
m_sError = _T("不能連接到代理服務器!");
ClientSock.Close();
MessageBox(m_sError);
return ;
}

char buff[600] = {0};
// sprintf( buff, "%s%s:%d%s","CONNECT ","219.201.39.50",21," HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n");
sprintf( buff, "%s%s:%d%s","CONNECT ","219.201.39.50",21," HTTP/1.1\r\nUser-Agent: CERN-LineMode/2.15 libwww/2.17b3\r\n\r\n");
// sprintf( buff, "%s%s:%d%s","CONNECT ","www.tom.com",80," HTTP/1.1\r\nUser-Agent: CERN-LineMode/2.15 libwww/2.17b3\r\n\r\n");
// sprintf( buff, "%s%s","GET ","HTTP://WWW.TOM.COM HTTP/1.1\r\n\r\n");

ClientSock.Send(buff,strlen(buff)); //發送請求
memset(buff,0,600);
ClientSock.Receive(buff,600);
if(strstr(buff, "HTTP/1.0 200 Connection established") == NULL) //連接不成功
{
m_sError = _T("通過代理連接主站不成功!");
ClientSock.Close();
return ;
}


/* if( strstr(buff, "Error 403") )
{
//return GoError(PROXYERROR_PROXYDISABLE); //代理服務器拒絕請求
}

if( strstr(buff, "407 Proxy authentication required") ) //需要身份驗證
{
//return GoError(PROXYERROR_USERNAMEORPASSWORD); //用戶身份校檢不成功
}
if( strstr(buff, "Connection refuesed") )
{
//return GoError(PROXYERROR_CONNECTHOSTSERVER); //通過代理連接主站不成功
}
if( strstr(buff, "Access Denied") )
{
//return GoError(PROXYERROR_USERNAMEORPASSWORD); //用戶身份校檢不成功
}
if(strstr(buff, "Connection refused by Remote Host") )
{
//return GoError(PROXYERROR_CONNECTHOSTSERVER); //通過代理連接主站不成功
}

ClientSock.Close();
*/




//連接已經建立,發送及接收數據
memset(buff,0,600);
strcpy(buff,"Hello!");
ClientSock.Send(buff,sizeof(buff));
memset(buff,0,600);
ClientSock.Receive(buff,600);
MessageBox(buff);
ClientSock.Close();


}


/////////
///另附一些http的請求和返回
發送一:
CONNECT 61.135.158.91:80 HTTP/1.1
User-Agent: MyApp/0.1


發送二:
CONNECT 61.135.158.91:80 HTTP/1.1
User-Agent: CERN-LineMode/2.15 libwww/2.17b3


發送三:
CONNECT 127.0.0.1:2222 HTTP/1.0
User-agent: MyApp/1.0
Proxy-authorization: enter xxxxxx


接收一:
HTTP/1.0 403 Forbidden
Server: Topproxy-2.0/
Mime-Version: 1.0
Date: Thu, 18 Nov 2004 16:37:53 GMT
Content-Type: text/html
Content-Length: 718
Expires: Thu, 18 Nov 2004 16:37:53 GMT
X-Squid-Error: ERR_ACCESS_DENIED 0
X-Cache: MISS fro


接收二:
HTTP/1.0 502 Proxy Error ( SSL port specified is not allowed. )
Via: 1.0 PROXY
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>

<head>
<meta http-equiv="Conten"


接收三:
HTTP/1.1 403 Forbidden
Date: Sat, 20 Nov 2004 14:33:13 GMT
Content-Length: 257
Content-Type: text/html
Server: NetCache appliance (NetApp/5.6R1D6)

<HTML>
<HEAD><TITLE>403 Forbidden</TITLE></HEAD>
<BODY>
<H1>Forbidden</H1>
<H4>
You were"



  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:12 聶文龍
簡單代理服務器C代碼實現(SOLARIS)

/*
** 編寫:無可非議
** 來源:WWW.20CN.NET
** 注意:請注明轉貼來源
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>

int m_MainId = 0; //主進程ID
int m_ListenSocket = 0; //偵聽套接字
char m_ConnectAddr[256] = {0}; //目標地址
char m_ConnectPort[256] = {0}; //目標端口

/*
** 函數名稱: GetListenSocket
** 函數功能: 生成偵聽套接字
** 傳入參數: Port : 偵聽端口
** 傳出參數: 無
** 引用函數: 無
** 返回值 : 偵聽套接字,為0時表示生成套接字失敗,其他為套接字句柄
** 備注 : 無
*/
int GetListenSocket(int Port)
{
struct sockaddr_in m_LisAddr = {0};
int m_Socket = 0;
int m_AddrLen = sizeof(struct sockaddr_in);

//配置端口信息
m_LisAddr.sin_family = AF_INET;
m_LisAddr.sin_port = htons(Port);
m_LisAddr.sin_addr.s_addr = INADDR_ANY;

//創建套接字
if ((m_Socket = socket(AF_INET,SOCK_STREAM,0)) < 0 )
{
//創建套接字失敗
return 0;
}

//綁定套接字
if(bind(m_Socket, (sockaddr*)&m_LisAddr , m_AddrLen) < 0 )
{
//綁定套接字失敗
close(m_Socket);
return 0;
}

//偵聽套接字
if(listen(m_Socket,5))
{
//偵聽套接字失敗
close(m_Socket);
return 0;
}

//偵聽套接字生成成功
return m_Socket;
}

/*
** 函數名稱: GetConnectSocket
** 函數功能: 生成連接套接字
** 傳入參數: pServerAddr : 連接地址 pServerPort : 連接端口
** 傳出參數: 無
** 引用函數: 無
** 返回值 : 連接套接字,為0時表示生成套接字失敗,其他為套接字句柄
** 備注 : 無
*/
int GetConnectSocket(char* pServerAddr,char* pServerPort)
{
struct sockaddr_in m_ServerAddr = {0};
int m_AddrLen = sizeof(struct sockaddr_in);
int m_Socket = 0;

//初始化連接信息
m_ServerAddr.sin_addr.S_un.S_addr = inet_addr(pServerAddr);
m_ServerAddr.sin_port = htons(atoi(pServerPort));
m_ServerAddr.sin_family = AF_INET;

//創建發送套接字
m_Socket = socket(AF_INET,SOCK_STREAM,0);
if(m_Socket <= 0)
{
//失敗
return NULL;
}

//連接客戶計算機
if(connect(m_Socket,(sockaddr*)&m_ServerAddr,m_AddrLen) < 0 )
{
close(m_Socket);
return NULL;
}

//連接成功
return m_Socket;
}

/*
** 函數名稱: TransSocket
** 函數功能: 完成套接字數據轉發
** 傳入參數: m_SendSocket : 發送套接字 m_RecvSocket : 接收套接字
** 傳出參數: 無
** 引用函數: 無
** 返回值 : 無
** 備注 : 逆反完成全雙工
*/
void TransSocket(int m_SendSocket,int m_RecvSocket)
{
char m_Buf[512 * 1024] = {0};
int ret = 0;
fd_set readset;
struct timeval tm = {0};
tm.tv_sec = 3600 * 24;

FD_ZERO(&readset);
FD_SET(m_RecvSocket,&readset);

while(1)
{
if((select(m_RecvSocket + 1,&readset,NULL,NULL,&tm)
<= 0))
{
//出錯
break;
}
if(!FD_ISSET(m_RecvSocket,&readset)) continue;

ret = recv(m_RecvSocket,m_Buf,512 * 1024 - 1,0);
if(ret < 0)
{
//出錯
break;
}
send(m_SendSocket,m_Buf,ret,0);
}
close(m_SendSocket);
close(m_RecvSocket);
}

/*
** 函數名稱: SocketTrans
** 函數功能: 工作主函數,完成數據轉發,新進程啟動
** 傳入參數: m_SendSocket : 發送套接字 m_RecvSocket : 接收套接字
** 傳出參數: 無
** 引用函數: 無
** 返回值 : 無
** 備注 : 逆反完成全雙工
*/
void SocketTrans()
{
struct sockaddr_in m_WorkAddr = {0};
int m_191Socket = 0;
int m_147socket = 0;
int m_WorkAddrLen = 0;

//開始任務執行
while(1)
{
//接受147的連接
m_WorkAddrLen = sizeof(struct sockaddr_in);
m_147socket = accept(m_ListenSocket,
(sockaddr*)&m_WorkAddr , &m_WorkAddrLen);

//檢查套接字合法性
if(m_147socket < 0) continue;

//連接191
m_191Socket = GetConnectSocket(m_ConnectAddr,m_ConnectPort);
if(m_191Socket == NULL)
{
close(m_147socket);
continue;
}

int ret = fork();
if(ret < 0)
{
//建立新進程失敗
printf("致命錯誤,無法建立新進程!\n");
fflush(stdout);
close(m_191Socket);
close(m_147socket);
break;
}
else if(ret == 0)
{
//關閉原來端口
close(m_ListenSocket);

//建立二次子進程,防止僵尸進程
ret = fork();
if(ret < 0)
{
close(m_191Socket);
close(m_147socket);
_exit(0);
}
else if(ret == 0)
{
//接收進程
TransSocket(m_191Socket,m_147socket);
_exit(0);
}
ret = fork();
if(ret < 0)
{
close(m_191Socket);
close(m_147socket);
_exit(0);
}
else if(ret == 0)
{
//發送進程
TransSocket(m_147socket,m_191Socket);
_exit(0);
}
close(m_191Socket);
close(m_147socket);
_exit(0);
}

//等待子線程結束
close(m_191Socket);
close(m_147socket);
waitpid(ret,NULL,0);
}
}

/*
** 函數名稱: sig_usr
** 函數功能: 進程信號處理函數
** 傳入參數: 無
** 傳出參數: 無
** 引用函數: 無
** 返回值 : 無
** 備注 : 處理進程終止事件
*/
static void sig_usr(int signo)
{
close(m_ListenSocket);
if(m_MainId == getpid())
kill(0,SIGKILL);
exit(0);
}

static void sig_ign(int signo)
{
fprintf(stderr,"signal %d catched ,ignoring\n",signo);
}

int daemon_init()
{
pid_t pid;
if((pid=fork())<0){
return -1;
}else if(pid!=0){
exit(0);
}
setsid();
umask(0);
return 0;
}

/*
** 函數名稱: main
** 函數功能: 進程主函數
** 傳入參數: 無
** 傳出參數: 無
** 引用函數: MakeFilePath,GetMyInitInfo,SocketTrans
** 返回值 : 無
** 備注 : 為客戶接收進程主函數
*/
int main(int argc,char* argv[])
{
//檢查參數合法性
if(argc != 4)
{
printf("格式:本地端口 目的地址 目的端口\n");
fflush(stdout);
return 0;
}

daemon_init();

//登記信號事件
signal(SIGTERM,sig_usr);
signal(SIGINT,sig_usr);
signal(SIGQUIT,sig_usr);
signal(SIGPIPE,sig_ign);
signal(SIGALRM,sig_ign);
signal(SIGQUIT,sig_ign);
signal(SIGFPE,sig_ign);
signal(SIGILL,sig_ign);
signal(SIGPIPE,sig_ign);
signal(SIGSEGV,sig_ign);
signal(SIGTRAP,sig_ign);
signal(SIGTSTP,sig_ign);

//取參數
strcpy(m_ConnectAddr,argv[2]);
strcpy(m_ConnectPort,argv[3]);

//獲取偵聽套接字
m_ListenSocket = GetListenSocket(atoi(argv[1]));
if(m_ListenSocket == 0)
{
printf("偵聽端口[%s]失敗!\n",argv[1]);
fflush(stdout);
return 0;
}

m_MainId = getpid();
//啟動文件接收偵聽線程
SocketTrans();
close(m_ListenSocket);
return 0;
}
  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:19 聶文龍
#include "stdafx.h"
#include "Proxy.h"
#include < winsock2.h > //WINSOCKET API 2。0
#include < stdlib.h >
#include < stdio.h >
#include < string.h >


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////


#define HTTP "http://"
#define FTP "ftp://"
#define PROXYPORT 5001 //Proxy 端口
#define BUFSIZE 10240 //緩沖區大小


CWinApp theApp;


using namespace std;


UINT ProxyToServer(LPVOID pParam);
UINT UserToProxyThread(void *pParam);


strUCt SocketPair{
SOCKET user_proxy; //socket : 本地機器到PROXY 服務機
SOCKET proxy_server; //socket : PROXY 服務機到遠程主機
BOOL IsUser_ProxyClosed; // 本地機器到PROXY 服務機狀態
BOOL IsProxy_ServerClosed; // PROXY 服務機到遠程主機狀態
};


struct ProxyParam{
char Address[256]; // 遠程主機地址
HANDLE User_SvrOK; // PROXY 服務機到遠程主機的聯結狀態
SocketPair *pPair; // 維護一組SOCKET的指針
int Port; // 用來聯結遠程主機的端口
}; //這個結構用來PROXY SERVER與遠程主機的信息交換.


SOCKET gListen_Socket; //用來偵聽的SOCKET。


int StartServer() //啟動服務
{
WSADATA wsaData;
sockaddr_in local;
SOCKET listen_socket;


if(::WSAStartup(0x202,&wsaData)!=0)
{printf("\nError in Startup session.\n");WSACleanup();return -1;};



local.sin_family=AF_INET;

local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons(PROXYPORT);


listen_socket=socket(AF_INET,SOCK_STREAM,0);
if(listen_socket==INVALID_SOCKET)
{printf("\nError in New a Socket.");WSACleanup();return -2;}


if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
{printf("\n Error in Binding socket."); WSACleanup();return -3; };


if(::listen(listen_socket,5)!=0)
{printf("\n Error in Listen."); WSACleanup(); return -4;}
gListen_Socket=listen_socket;
AfxBeginThread(UserToProxyThread,NULL); //啟動偵聽
return 1;
}


int CloseServer() //關閉服務
{
closesocket(gListen_Socket);
WSACleanup();
return 1;
}
//分析接收到的字符,得到遠程主機地址


int GetAddressAndPort( char * str, char *address, int * port)
{
char buf[BUFSIZE], command[512], proto[128], *p;
int j;
sscanf(str,"%s%s%s",command,buf,proto);
p=strstr(buf,HTTP);
//HTTP
if(p)
{
p+=strlen(HTTP);
for(int i=0;i< strlen(p);i++)
if( *(p+i)=='/') break;
*(p+i)=0;
strcpy(address,p);
p=strstr(str,HTTP);
for(int j=0;j< i+strlen(HTTP);j++)
*(p+j)=' '; //去掉遠程主機名: GET http://www.njust.edu.cn/ HTTP1.1 == > GET / HTTP1.1
*port=80; //缺省的 http 端口
}
else
{//FTP, 不支持, 下面的代碼可以省略.
p=strstr(buf,FTP);
if(!p) return 0;
p+=strlen(FTP);
for(int i=0;i< strlen(p);i++)
if( *(p+i)=='/') break; //Get The Remote Host
*(p+i)=0;
for(j=0;j< strlen(p);j++)
if(*(p+j)==':')
{*port=atoi(p+j+1); //Get The Port
*(p+j)=0;
}
else *port=21;



strcpy(address,p);
p=strstr(str,FTP);
for(j=0;j< i+strlen(FTP);j++)

*(p+j)=' ';
}
return 1;
}


// 取到本地的數據,發往遠程主機
UINT UserToProxyThread(void *pParam)
{
char Buffer[BUFSIZE];
int Len;
sockaddr_in from;
SOCKET msg_socket;
int fromlen,retval;
SocketPair SPair;
ProxyParam ProxyP;
CWinThread *pChildThread;
fromlen=sizeof(from);
msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
AfxBeginThread(UserToProxyThread,pParam); //啟動另一偵聽.
if( msg_socket==INVALID_SOCKET)
{ printf( "\nError in accept "); return -5;}
//讀客戶的第一行數據


SPair.IsUser_ProxyClosed=FALSE;
SPair.IsProxy_ServerClosed=TRUE;
SPair.user_proxy=msg_socket;


retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);


if(retval==SOCKET_ERROR)
{ printf("\nError Recv");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
if(retval==0)
{printf("Client Close connection\n");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
Len=retval;
#ifdef _DEBUG


Buffer[Len]=0;
printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
#endif
//
SPair.IsUser_ProxyClosed=FALSE;
SPair.IsProxy_ServerClosed=TRUE;
SPair.user_proxy=msg_socket;


ProxyP.pPair=&SPair;
ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);


GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port);


pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP);

::WaitForSingleObject(ProxyP.User_SvrOK,60000); //等待聯結
::CloseHandle(ProxyP.User_SvrOK);


while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)

{
retval=send(SPair.proxy_server,Buffer,Len,0);
if(retval==SOCKET_ERROR)
{ printf("\n send() failed:error%d\n",WSAGetLastError());
if(SPair.IsProxy_ServerClosed==FALSE)
{
closesocket(SPair.proxy_server);
SPair.IsProxy_ServerClosed=TRUE;
}
continue;
}
retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);


if(retval==SOCKET_ERROR)
{ printf("\nError Recv");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
continue;
}
if(retval==0)
{printf("Client Close connection\n");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
break;
}
Len=retval;
#ifdef _DEBUG
Buffer[Len]=0;
printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
#endif


} //End While


if(SPair.IsProxy_ServerClosed==FALSE)
{
closesocket(SPair.proxy_server);
SPair.IsProxy_ServerClosed=TRUE;
}
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
::WaitForSingleObject(pChildThread- >m_hThread,20000); //Should check the return value
return 0;
}


// 讀取遠程主機數據,并發往本地客戶機
UINT ProxyToServer(LPVOID pParam){
ProxyParam * pPar=(ProxyParam*)pParam;
char Buffer[BUFSIZE];
char *server_name= "localhost";
unsigned short port ;
int retval,Len;
unsigned int addr;

int socket_type ;
struct sockaddr_in server;
struct hostent *hp;
SOCKET conn_socket;


socket_type = SOCK_STREAM;
server_name = pPar- >Address;
port = pPar- >Port;


if (isalpha(server_name[0])) { /* server address is a name */

hp = gethostbyname(server_name);
}
else { /* Convert nnn.nnn address to a usable one */
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr,4,AF_INET);
}
if (hp == NULL ) {
fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
server_name,WSAGetLastError());
::SetEvent(pPar- >User_SvrOK);
return 0;
}


//
// Copy the resolved information into the sockaddr_in structure
//
memset(&server,0,sizeof(server));
memcpy(&(server.sin_addr),hp- >h_addr,hp- >h_length);
server.sin_family = hp- >h_addrtype;
server.sin_port = htons(port);


conn_socket = socket(AF_INET,socket_type,0); /* 打開一個 socket */
if (conn_socket < 0 ) {
fprintf(stderr,"Client: Error Opening socket: Error %d\n",
WSAGetLastError());
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
::SetEvent(pPar- >User_SvrOK);
return -1;
}


#ifdef _DEBUG
printf("Client connecting to: %s\n",hp- >h_name);
#endif
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
::SetEvent(pPar- >User_SvrOK);
return -1;
}
pPar- >pPair- >proxy_server=conn_socket;
pPar- >pPair- >IsProxy_ServerClosed=FALSE;

::SetEvent(pPar- >User_SvrOK);
// cook up a string to send
while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
{
retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
if (retval == SOCKET_ERROR ) {
fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());

closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}
Len=retval;
if (retval == 0) {
printf("Server closed connection\n");
closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}


retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
if (retval == SOCKET_ERROR) {
fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
break;
}
#ifdef _DEBUG
Buffer[Len]=0;
printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
#endif
}
if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)
{
closesocket(pPar- >pPair- >proxy_server);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
}
if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
{closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
}
return 1;
}





int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;


// 初始化SOCKET
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// 錯誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;

}
else
{
// 主程序開始.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}


return nRetCode;
}
#ifdef _DEBUG
printf("Client connecting to: %s\n",hp- >h_name);
#endif
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());

pPar- >pPair- >IsProxy_ServerClosed=TRUE;
::SetEvent(pPar- >User_SvrOK);
return -1;
}
pPar- >pPair- >proxy_server=conn_socket;
pPar- >pPair- >IsProxy_ServerClosed=FALSE;
::SetEvent(pPar- >User_SvrOK);
// cook up a string to send
while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
{
retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
if (retval == SOCKET_ERROR ) {
fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}
Len=retval;
if (retval == 0) {
printf("Server closed connection\n");
closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}


retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
if (retval == SOCKET_ERROR) {
fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
break;
}
#ifdef _DEBUG
Buffer[Len]=0;
printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
#endif
}
if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)

{
closesocket(pPar- >pPair- >proxy_server);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
}
if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
{closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
}
return 1;
}





int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;


// 初始化SOCKET
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// 錯誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;
}
else
{
// 主程序開始.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}


return nRetCode;
}
  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:22 聶文龍
打造自己的HTTP代理服務器
#include "stdafx.h"
#include "HTTPPROXY.h"
#define FD_NOEVENT 0
//
#define BACKUP 100
#define MAXDATALEN 65535
int HttpListenPort;
SOCKET HttpListenSock;
//
typedef struct _CLIENTINFO{
SOCKET clientsock;
SOCKET udpsock;
sockaddr_in clientsock_addr;
}CLIENTINFO,*LPCLIENTINFO;
CLIENTINFO HttpClientInfo;
//
typedef struct _SOCKINFO{
SOCKET sourcesock;
SOCKET destsock;
}SOCKINFO,*LPSOCKINFO;
SOCKINFO httpsockinfo;
//
extern long GetSocketEventId(SOCKET remotesock);
extern unsigned long GetLocalIp();
extern unsigned long GetDomainIp(char domainname[250]);
/*
long GetSocketEventId(SOCKET remotesock){
long EventId;
HANDLE hevent;
hevent=CreateEvent(NULL,0,0,0);
WSANETWORKEVENTS socket_events;
EventId=FD_NOEVENT;
if(WSAEventSelect(remotesock,hevent,FD_ACCEPT|FD_CONNECT|FD_
READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR) return EventId;
WSAEnumNetworkEvents(remotesock,hevent,&socket_events);
if(socket_events.lNetworkEvents!=0){
switch(socket_events.lNetworkEvents){
case FD_ACCEPT:EventId=FD_ACCEPT;break;
case FD_CONNECT:EventId=FD_CONNECT;break;
case FD_READ:EventId=FD_READ;break;
case FD_WRITE:EventId=FD_WRITE;break;
case FD_CLOSE:EventId=FD_CLOSE;break;
case FD_OOB:EventId=FD_OOB;break;
default:EventId=FD_NOEVENT;break;
}
}
else EventId=FD_NOEVENT;
return EventId;
}
//
unsigned long GetLocalIp()
{
char IP[MAX_PATH],*ip;
char pc_name[80];
struct in_addr in;
struct hostent *host;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,0);
ip=IP;
strcpy(ip,"Ip not get!");
if(WSAStartup(wVersionRequested,&wsaData)) return 0;
if(gethostname(pc_name,80)==SOCKET_ERROR){
WSACleanup();
return 0;
}
if(!(host=gethostbyname(pc_name))){
WSACleanup();
return 0;
}
in.s_addr=*((unsigned long *)host->h_addr_list[0]);
strcpy(ip,inet_ntoa(in));
WSACleanup();
return in.s_addr;
}
//
unsigned long GetDomainIp(char domainname[250])
{
char IP[MAX_PATH],*ip;
struct in_addr in;
struct hostent *host;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,0);
ip=IP;
strcpy(ip,"Ip not get!");
if(WSAStartup(wVersionRequested,&wsaData)) return 0;
if(!(host=gethostbyname(domainname))){
WSACleanup();
return 0;
}
in.s_addr=*((unsigned long *)host->h_addr_list[0]);
strcpy(ip,inet_ntoa(in));
WSACleanup();
return in.s_addr;
}
*/
//
//
UINT HttpReciveThread(LPVOID info){ //針對客戶端的接收處理線程
LPSOCKINFO psockinfo;
SOCKET sourcesock,destsock;
char data[MAXDATALEN];
long eventid;
int datalen;
psockinfo=(LPSOCKINFO)info;
sourcesock=psockinfo->sourcesock;
destsock=psockinfo->destsock;
TRACE("deail recive thread ok!\r\n");
while(true){
eventid=GetSocketEventId(sourcesock);
switch(eventid){
case FD_CLOSE:
TRACE("s fdclosed\r\n");
closesocket(destsock);
return 1;
break;
default:break;
}
eventid=GetSocketEventId(destsock);
switch(eventid){
case FD_CLOSE:
closesocket(sourcesock);
TRACE("d fdclosed\r\n");
return 1;
break;
default:break;
}
datalen=recv(sourcesock,data,sizeof(data),0);
if(datalen==0){
closesocket(sourcesock);
closesocket(destsock);
TRACE("s fdclosed\r\n");
break;
}
if(datalen>0){
while(!send(destsock,data,datalen,0));
}
Sleep(1);
}
return 1;
}
//
UINT HttpSendThread(LPVOID info){ //針對遠程端的接收處理線程
LPSOCKINFO psockinfo;
SOCKET sourcesock,destsock;
char data[MAXDATALEN];
long eventid;
int datalen;
psockinfo=(LPSOCKINFO)info;
sourcesock=psockinfo->sourcesock;
destsock=psockinfo->destsock;
TRACE("deail send thread ok!\r\n");
while(true){
eventid=GetSocketEventId(sourcesock);
switch(eventid){
case FD_CLOSE:
TRACE("s fdclosed\r\n");
closesocket(destsock);
return 1;
break;
default:break;
}
eventid=GetSocketEventId(destsock);
switch(eventid){
case FD_CLOSE:
closesocket(sourcesock);
TRACE("d fdclosed\r\n");
return 1;
break;
default:break;
}
datalen=recv(destsock,data,sizeof(data),0);
if(datalen==0){
closesocket(sourcesock);
closesocket(destsock);
TRACE("d fdclosed\r\n");
break;
}
if(datalen>0){
while(!send(sourcesock,data,datalen,0));
}
Sleep(1);
}
return 1;
}
//
//
UINT HttpProxyServerThread(LPVOID info){ //針對一次服務的線程
LPCLIENTINFO pclientinfo;
SOCKET connectsock,clientsock;
sockaddr_in remotesock_addr;
char data[MAXDATALEN],url[250],temp[250],httpurl[250],portnum[10];
int datalen,i,index_start,index_end,port;
CString HttpString,UrlString,PortString;
pclientinfo=(LPCLIENTINFO)info;
clientsock=pclientinfo->clientsock;
ZeroMemory((void *)data,sizeof(data));
datalen=recv(clientsock,data,sizeof(data),0);
if(datalen<=0){
closesocket(clientsock);
return 0;
}
HttpString.Format("%s",data);
UrlString=HttpString;
TRACE("get http string:\r\n");
TRACE(HttpString);
index_start=HttpString.Find("Host: ",0); //尋找url標記
if(index_start<=0){
closesocket(clientsock);
return 0;
}
index_end=HttpString.Find("\r\n",index_start);
if(index_end<=0){
closesocket(clientsock);
return 0;
}
UrlString=HttpString.Mid(index_start+6,index_end-index_start-6); //讀取 url字符串
TRACE("\r\n get url:");
TRACE(UrlString);
wsprintf(url,"%s",UrlString);
strcpy(temp,url);
strcat(temp,":");
datalen=strlen(temp);
if(HttpString.Find("GET",0)==0){ //判斷get命令,并處理
index_start=HttpString.Find(temp,0);
strcpy(httpurl,"http://");
if(index_start>0){
index_end=HttpString.Find("/",index_start);
if(index_end<=0){
closesocket(clientsock);
return 0;
}
PortString=HttpString.Mid(index_start+datalen,index_end-index_start-datalen);
port=atoi(PortString);
strcat(httpurl,temp);
itoa(port,portnum,sizeof(portnum));
strcat(httpurl,portnum);
strcat(httpurl,"/");
}
else{
port=80;
strcat(httpurl,url);
strcat(httpurl,"/");
}
TRACE("get http url:%s\r\n",httpurl);
HttpString.Replace(httpurl,"/");
HttpString.Replace("Proxy-","");
HttpString.Replace("HTTP/1.0","HTTP/1.1");
}
else if(HttpString.Find("CONNECT",0)==0){ //判斷connect命令并處理
index_start=HttpString.Find(temp,0);
if(index_start>0){
index_end=HttpString.Find(" ",index_start);
if(index_end<=0){
closesocket(clientsock);
return 0;
}
PortString=HttpString.Mid(index_start+datalen,index_end-index_start-datalen);
port=atoi(PortString);
}
else{
closesocket(clientsock);
return 0;
}
}
TRACE("get new http string:\r\n");
TRACE(HttpString);
remotesock_addr.sin_family=AF_INET;
remotesock_addr.sin_port=htons(port);
remotesock_addr.sin_addr.S_un.S_addr=GetDomainIp(url);
connectsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(connect(connectsock,(const sockaddr *)&remotesock_addr,sizeof(remotesock_addr))==INVALID_SOCKET){ //連接遠程主機
closesocket(clientsock);
return 0;
}
TRACE("\r\nconnect to remote ip ok\r\n");
ZeroMemory((void *)data,sizeof(data));
wsprintf(data,"%s",HttpString);
datalen=strlen(data);
if(HttpString.Find("CONNECT",0)<0) while(!send(connectsock,data,datalen,0));
else{
strcpy(data,"HTTP/1.0 200 Connection established\r\nProxy-agent: CHTTPPROXY V1.0 powered by shadow\r\n\r\n");
datalen=strlen(data);
while(!send(clientsock,data,datalen,0));
}
httpsockinfo.sourcesock=clientsock;
httpsockinfo.destsock=connectsock;
AfxBeginThread(HttpReciveThread,(LPVOID)&httpsockinfo); //拋出處理線程
AfxBeginThread(HttpSendThread,(LPVOID)&httpsockinfo); //
Sleep(100);
return 1;
}
//
UINT StartHttpProxy(LPVOID info){ //端口監聽線程
SOCKET NewSock;
int socklen;
sockaddr_in serversock,remotesock_addr;
serversock.sin_family=AF_INET;
serversock.sin_addr.S_un.S_addr=INADDR_ANY;
serversock.sin_port=htons(HttpListenPort);
HttpListenSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(HttpListenSock==INVALID_SOCKET) return 0;
if(bind(HttpListenSock,(const sockaddr *)&serversock,
sizeof(serversock))==SOCKET_ERROR) return 0;
listen(HttpListenSock,BACKUP);
socklen=sizeof(remotesock_addr);
TRACE("start http proxy thread while\r\n");
while(true){
NewSock=accept(HttpListenSock,(sockaddr *)&remotesock_addr,&socklen);
TRACE("waitting ok...\r\n");
if(NewSock==INVALID_SOCKET){
Sleep(1);
continue;
}
ZeroMemory((void *)&HttpClientInfo,sizeof(CLIENTINFO));
HttpClientInfo.clientsock=NewSock;
HttpClientInfo.clientsock_addr=remotesock_addr;
TRACE("start proxy thread\r\n");
AfxBeginThread(HttpProxyServerThread,(LPVOID)&HttpClientInfo);
Sleep(100);
}
return 1;
}
//
CHTTPPROXY::CHTTPPROXY()
{
WSADATA WsaData;
WORD wsaVer;
wsaVer=MAKEWORD(2,0);
WsaStartupOk=false;
if(WSAStartup(wsaVer,&WsaData)!=SOCKET_ERROR) WsaStartupOk=true;
}

CHTTPPROXY::~CHTTPPROXY()
{
if(WsaStartupOk){
WSACleanup();
}
}

int CHTTPPROXY::StartProxy(int listenport)
{
HttpListenPort=listenport;
AfxBeginThread(StartHttpProxy,(LPVOID)NULL);
return 1;
}


/*=========================================================
FILE:HTTPPROXY.h
==========================================================*/
class CHTTPPROXY
{
public:
int StartProxy(int listenport);
bool WsaStartupOk;
CHTTPPROXY();
virtual ~CHTTPPROXY();

};

/*==================================================
FILE:stdafx.h
===================================================*/
#include
#include
#include
#include


注:不要忘了在link選項中添加wsock32.lib和ws2_32.lib,或在文件前部加上如下語句:
#paragma comment(lib,"wsock32.lib")
#paragma comment(lib,"ws2_32.lib")

本代碼在win2k和vc6.0下編譯成功~~
用法,把這幾個文件添加到你的項目中,在WinMain()中添加如下代碼:
CHTTPPROXY httpproxy;
httpproxy.StartProxy(7890);
有問題mailto me!


  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:23 聶文龍
VC++6實現簡單的代理服務器

本文轉自CSDN的blog:http://blog.csdn.net/snaill/archive/2006/03/14/624437.aspx

#include "stdafx.h"
#include "Proxy.h"
#include < winsock2.h > //WINSOCKET API 2。0
#include < stdlib.h >
#include < stdio.h >
#include < string.h >

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////


#define HTTP "http://"
#define FTP "ftp://"
#define PROXYPORT 5001 //Proxy 端口
#define BUFSIZE 10240 //緩沖區大小


CWinApp theApp;

using namespace std;

UINT ProxyToServer(LPVOID pParam);
UINT UserToProxyThread(void *pParam);

struct SocketPair{
SOCKET user_proxy; //socket : 本地機器到PROXY 服務機
SOCKET proxy_server; //socket : PROXY 服務機到遠程主機
BOOL IsUser_ProxyClosed; // 本地機器到PROXY 服務機狀態
BOOL IsProxy_ServerClosed; // PROXY 服務機到遠程主機狀態
};


struct ProxyParam{
char Address[256]; // 遠程主機地址
HANDLE User_SvrOK; // PROXY 服務機到遠程主機的聯結狀態
SocketPair *pPair; // 維護一組SOCKET的指針
int Port; // 用來聯結遠程主機的端口
}; //這個結構用來PROXY SERVER與遠程主機的信息交換.

SOCKET gListen_Socket; //用來偵聽的SOCKET。

int StartServer() //啟動服務
{
WSADATA wsaData;
sockaddr_in local;
SOCKET listen_socket;

if(::WSAStartup(0x202,&wsaData)!=0)
{printf("\nError in Startup session.\n");WSACleanup();return -1;};

local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons(PROXYPORT);

listen_socket=socket(AF_INET,SOCK_STREAM,0);
if(listen_socket==INVALID_SOCKET)
{printf("\nError in New a Socket.");WSACleanup();return -2;}

if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
{printf("\n Error in Binding socket."); WSACleanup();return -3; };

if(::listen(listen_socket,5)!=0)
{printf("\n Error in Listen."); WSACleanup(); return -4;}
gListen_Socket=listen_socket;
AfxBeginThread(UserToProxyThread,NULL); //啟動偵聽
return 1;
}

int CloseServer() //關閉服務
{
closesocket(gListen_Socket);
WSACleanup();
return 1;
}
//分析接收到的字符,得到遠程主機地址

int GetAddressAndPort( char * str, char *address, int * port)
{
char buf[BUFSIZE], command[512], proto[128], *p;
int j;
sscanf(str,"%s%s%s",command,buf,proto);
p=strstr(buf,HTTP);
//HTTP
if(p)
{
p+=strlen(HTTP);
for(int i=0;i< strlen(p);i++)
if( *(p+i)=='/') break;
*(p+i)=0;
strcpy(address,p);
p=strstr(str,HTTP);
for(int j=0;j< i+strlen(HTTP);j++)
*(p+j)=' '; //去掉遠程主機名: GET http:/www.csdn.net/ HTTP1.1 == > GET / HTTP1.1
*port=80; //缺省的 http 端口
}
else
{//FTP, 不支持, 下面的代碼可以省略.
p=strstr(buf,FTP);
if(!p) return 0;
p+=strlen(FTP);
for(int i=0;i< strlen(p);i++)
if( *(p+i)=='/') break; //Get The Remote Host
*(p+i)=0;
for(j=0;j< strlen(p);j++)
if(*(p+j)==':')
{*port=atoi(p+j+1); //Get The Port
*(p+j)=0;
}
else *port=21;

strcpy(address,p);
p=strstr(str,FTP);
for(j=0;j< i+strlen(FTP);j++)
*(p+j)=' ';
}
return 1;
}

// 取到本地的數據,發往遠程主機
UINT UserToProxyThread(void *pParam)
{
char Buffer[BUFSIZE];
int Len;
sockaddr_in from;
SOCKET msg_socket;
int fromlen,retval;
SocketPair SPair;
ProxyParam ProxyP;
CWinThread *pChildThread;
fromlen=sizeof(from);
msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
AfxBeginThread(UserToProxyThread,pParam); //啟動另一偵聽.
if( msg_socket==INVALID_SOCKET)
{ printf( "\nError in accept "); return -5;}
//讀客戶的第一行數據

SPair.IsUser_ProxyClosed=FALSE;
SPair.IsProxy_ServerClosed=TRUE;
SPair.user_proxy=msg_socket;

retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);

if(retval==SOCKET_ERROR)
{ printf("\nError Recv");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
if(retval==0)
{printf("Client Close connection\n");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
Len=retval;
#ifdef _DEBUG

Buffer[Len]=0;
printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
#endif
//
SPair.IsUser_ProxyClosed=FALSE;
SPair.IsProxy_ServerClosed=TRUE;
SPair.user_proxy=msg_socket;

ProxyP.pPair=&SPair;
ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);

GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port);

pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP);
::WaitForSingleObject(ProxyP.User_SvrOK,60000); //等待聯結
::CloseHandle(ProxyP.User_SvrOK);

while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)
{
retval=send(SPair.proxy_server,Buffer,Len,0);
if(retval==SOCKET_ERROR)
{ printf("\n send() failed:error%d\n",WSAGetLastError());
if(SPair.IsProxy_ServerClosed==FALSE)
{
closesocket(SPair.proxy_server);
SPair.IsProxy_ServerClosed=TRUE;
}
continue;
}
retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);

if(retval==SOCKET_ERROR)
{ printf("\nError Recv");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
continue;
}
if(retval==0)
{printf("Client Close connection\n");
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
break;
}
Len=retval;
#ifdef _DEBUG
Buffer[Len]=0;
printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
#endif

} //End While

if(SPair.IsProxy_ServerClosed==FALSE)
{
closesocket(SPair.proxy_server);
SPair.IsProxy_ServerClosed=TRUE;
}
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
::WaitForSingleObject(pChildThread- >m_hThread,20000); //Should check the return value
return 0;
}
// 讀取遠程主機數據,并發往本地客戶機
UINT ProxyToServer(LPVOID pParam){
ProxyParam * pPar=(ProxyParam*)pParam;
char Buffer[BUFSIZE];
char *server_name= "localhost";
unsigned short port ;
int retval,Len;
unsigned int addr;
int socket_type ;
struct sockaddr_in server;
struct hostent *hp;
SOCKET conn_socket;

socket_type = SOCK_STREAM;
server_name = pPar- >Address;
port = pPar- >Port;

if (isalpha(server_name[0])) { /* server address is a name */
hp = gethostbyname(server_name);
}
else { /* Convert nnn.nnn address to a usable one */
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr,4,AF_INET);
}
if (hp == NULL ) {
fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
server_name,WSAGetLastError());
::SetEvent(pPar- >User_SvrOK);
return 0;
}

//
// Copy the resolved information into the sockaddr_in structure
//
memset(server,0,sizeof(server));
memcpy(&(server.sin_addr),hp- >h_addr,hp- >h_length);
server.sin_family = hp- >h_addrtype;
server.sin_port = htons(port);

conn_socket = socket(AF_INET,socket_type,0); /* 打開一個 socket */
if (conn_socket < 0 ) {
fprintf(stderr,"Client: Error Opening socket: Error %d\n",
WSAGetLastError());
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
::SetEvent(pPar- >User_SvrOK);
return -1;
}
#ifdef _DEBUG
printf("Client connecting to: %s\n",hp- >h_name);
#endif
if (connect(conn_socket,(struct sockaddr*)server,sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
::SetEvent(pPar- >User_SvrOK);
return -1;
}
pPar- >pPair- >proxy_server=conn_socket;
pPar- >pPair- >IsProxy_ServerClosed=FALSE;
::SetEvent(pPar- >User_SvrOK);
// cook up a string to send
while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair- >IsUser_ProxyClosed)
{
retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
if (retval == SOCKET_ERROR ) {
fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}
Len=retval;
if (retval == 0) {
printf("Server closed connection\n");
closesocket(conn_socket);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
break;
}

retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);
if (retval == SOCKET_ERROR) {
fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
break;
}
#ifdef _DEBUG
Buffer[Len]=0;
printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
#endif
}
if(pPar- >pPair- >IsProxy_ServerClosed==FALSE)
{
closesocket(pPar- >pPair- >proxy_server);
pPar- >pPair- >IsProxy_ServerClosed=TRUE;
}
if(pPar- >pPair- >IsUser_ProxyClosed==FALSE)
{closesocket(pPar- >pPair- >user_proxy);
pPar- >pPair- >IsUser_ProxyClosed=TRUE;
}
return 1;
}



int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;

// 初始化SOCKET
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// 錯誤處理
cerr < < _T("Fatal Error: MFC initialization failed") < < endl;
nRetCode = 1;
}
else
{
// 主程序開始.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}

return nRetCode;
}   回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:25 聶文龍
通過Socket5代理服務器訪問網絡的問題
SOCKS5

Socks5版本的協議說明參考 RFC1928,RFC1929
下面簡單地羅列程序實現,不涉及詳細的協議規范。首先對于TCP連接,然后再討論UDP傳輸。至于通過socks5的多播通訊,有興趣可以參考D. Chouinard的文章。

1、TCP:

// 建立流套接字
SOCKET m_socTCP=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 連接到代理服務器
int nRet = connect(m_socTCP,(SOCKADDR*)&m_saiProxy,sizeof(m_saiProxy));

// Step 1: 連接代理服務器成功后,馬上開始和代理協商,協商報文如下,詢問服務器,版本5,是需要驗證(0x02)還是不需要驗證(0x00)
  +------+-------------------+------------+
  |VER | Number of METHODS | METHODS |
  +------+-------------------+------------+
  | 0x05 | 0x02 (有兩個方法) | 0x00 | 0x02|
  +------+-------------------+------------+
const char reqNego[4]={(char)0x05,(char)0x02,(char)0x00,(char)0x02};
nRet = send(m_socTCP,reqNego,4,0);

// Setp 2: 代理服務器將返回兩個字節的協商結果,接收協商結果
fd_set fdread;FD_ZERO(&fdread);
FD_SET(m_socTCP,&fdread);
// Last param set to NULL for blocking operation. (struct timeval*)
if((nRet=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR){return NC_E_PROXY_SELECT_READ|WSAGetLastError();}
char resNego[2]={'\0'};
int nRcvd=0,nCount=0;
while(1)
{
if(FD_ISSET(m_socTCP,&fdread))
{
//接收sock[0]發送來的數據
do{
nRet = recv(m_socTCP, (char*)resNego+nRcvd, 2-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=2)&&(++nCount<1000));
if(nRcvd==2) break;
}
if(nCount++>=2000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
}
if(resNego[0]!=0x05 || (resNego[1]!=0x00 && resNego[1]!=0x02)){return NC_E_PROXY_PROTOCOL_VERSION|WSAGetLastError();};

// Step 3: 根據協商結果判斷是否需要驗證用戶,如果是0x02,則需要提供驗證,驗證部分參考RFC1929
if(resNego[1]==0x02)
{
// 需要密碼驗證
char reqAuth[513]={'\0'};
BYTE byLenUser = (BYTE)strlen(m_szProxyUserName);
BYTE byLenPswd = (BYTE)strlen(m_szProxyPassword);
reqAuth[0]=0x01;
reqAuth[1]=byLenUser;
sprintf(&reqAuth[2],"%s",m_szProxyUserName);
reqAuth[2+byLenUser]=byLenPswd;
sprintf(&reqAuth[3+byLenUser],"%s",m_szProxyPassword);
//Send authentication info
int len = (int)byLenUser + (int)byLenPswd + 3;
nRet=send(m_socTCP,(const char*)reqAuth,len,0);
if (nRet==SOCKET_ERROR){return NC_E_PROXY_SEND|WSAGetLastError();}
//Now : Response to the auth request
char resAuth[2]={'\0'};
int nRcvd=0,nCount=0;
do{
nRet = recv(m_socTCP,resAuth+nRcvd,2-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=2)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
if (resAuth[1]!=0) return NC_E_PROXY_AUTHORIZE;
// 密碼驗證通過了
}

// Step 4: 協商完成,開始發送連接遠程服務器請求,請求報文格式如下:
  +----+-----+-------+------+----------+----------+
  |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
  +----+-----+-------+------+----------+----------+
  | 1 |  1 | 0x00 |  1 | Variable |   2   |
  +----+-----+-------+------+----------+----------+
// CMD==0x01 表示連接, ATYP==0x01表示采用IPV4格式地址,DST.ADDR是遠程服務器地址,DST.PORT是遠程服務器端口
// 如果需要接受外來連接,則需要在連接完成之后,發送CMD==0x02綁定請求,代理將為此請求綁定一個套接字接受外部連接
char reqSubNego[10]={(char)0x05,(char)0x01,(char)0x00,(char)0x01,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00};
*(unsigned long*)&reqSubNego[4] =m_saiServerTCP.sin_addr.S_un.S_addr;
*(unsigned short*)&reqSubNego[8]=m_saiServerTCP.sin_port;
nRet=send(m_socTCP,(const char*)reqSubNego,10,0);
if (nRet==SOCKET_ERROR){return NC_E_PROXY_SEND|WSAGetLastError();}

// Step 5: 接收對請求的響應,響應包格式如下
  +----+-----+-------+------+----------+----------+
  |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
  +----+-----+-------+------+----------+----------+
  | 1 | 1 | 0x00 | 1   | Variable |   2   |
  +----+-----+-------+------+----------+----------+
// VER 必須是0x05, REP==0x00表示成功,ATYP==0x01表示地址是IPV4地址,BND.ADDR 是代理為連接遠程服務器綁定的地址,BND.PORT是這個套接字的端口
char resSubNego1[5]={'\0'};
if(FD_ISSET(m_socTCP,&fdread))
{
int nRcvd=0,nCount=0;
do{
nRet = recv(m_socTCP,resSubNego1+nRcvd,5-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=5)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
if(resSubNego1[0]!=0x05||resSubNego1[1]!=0x00){return NC_E_PROXY_PROTOCOL_VERSION_SUB|WSAGetLastError();};

switch(resSubNego1[3])
{
case 0x01:
{
// IP V4
char resSubNego2[6]={resSubNego1[4],0};
int nRet=-1;
if(FD_ISSET(m_socTCP,&fdread))
{
int nRcvd=0,nCount=0;
do{
int nRet = recv(m_socTCP,&resSubNego2[1]+nRcvd,5-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=5)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
}
// 得到代理綁定地址
unsigned long ulBINDAddr = *(unsigned long*)&resSubNego2; // SOCKS BIND ADDR
unsigned short usBINDPort = *(unsigned short*)&resSubNego2[4]; // SOCKS BIND PORT
m_saiProxyBindTCP.sin_addr.S_un.S_addr=ulBINDAddr;
m_saiProxyBindTCP.sin_port=usBINDPort;
// 得到本機綁定地址
int len = sizeof(m_saiHostTCP);
getsockname(m_socTCP,(SOCKADDR*)&m_saiHostTCP,&len);
}
break;
case 0x03:
{
// Domain name
int nLen = resSubNego1[4]+2;
char* presSubNego2 = new char[nLen];
if(FD_ISSET(m_socTCP,&fdread))
{
int nRet=0,nRcvd=0,nCount=0;
do{
nRet = recv(m_socTCP,presSubNego2+nRcvd,nLen-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=nLen)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
}
unsigned short usBINDPort = *(unsigned short*)(presSubNego2+nLen-2); // BIND PORT;
// 此時得到的是遠程主機的Domain Name
delete[] presSubNego2; presSubNego2=NULL;
}
break;
case 0x04:
{
// IPV6
AfxMessageBox("該版本不支持IPV6";
}
break;
default:
break;
}

// 至此,連接已經建立。在此套接字上可進行數據的收發。
}

2、UDP

SOCKS V5提供了對UDP的支持,它通過在代理服務器和內網主機之間建立一個UDP中繼的TCP連接,來輔助進行UDP數據包的收發。此連接有一個有效期,在此有效生命周期內,必須往代理發送UDP數據報確認連接有效,來維持此連接的有效性,否則,代理服務器超時,將會自動釋放此連接的資源。
下面簡單地羅列程序實現,不涉及詳細的協議規范。

// 客戶端為UDP中繼建立一個相關的流套接字
SOCKET m_socClientTCP_UdpAssociate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 連接代理服務器
int nRet=connect(m_socClientTCP_UdpAssociate,(SOCKADDR*)&saiProxy,sizeof(saiProxy));

// 連接成功,開始和代理服務器協商,首先發送版本標志,方法選擇報文
const char reqNego[4]={(char)0x05,(char)0x02,(char)0x00,(char)0x02};
nRet = send(m_socClientTCP_UdpAssociate,reqNego,4,0);
if( nRet==SOCKET_ERROR
{
DWORD dwError = WSAGetLastError();
if (dwError!=WSAEWOULDBLOCK) return NCM_E_WM_CREATE_PROXYREQUESTFAILED;
}

// 接收協商的響應
fd_set fdread; FD_ZERO(&fdread);
FD_SET(m_socClientTCP_UdpAssociate,&fdread);
if((nRet=select(0,&fdread,NULL,NULL,NULL))==SOCKET_ERROR) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;
char resNego[2]={0};
int nRcvd=0,nCount=0;
if(FD_ISSET(m_socClientTCP_UdpAssociate,&fdread))
{
nRcvd = recv(m_socClientTCP_UdpAssociate, (char*)resNego+nRcvd, 2,0);
if(nRcvd==SOCKET_ERROR) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;
}
if(resNego[0]!=0x05 || (resNego[1]!=0x00 && resNego[1]!=0x02)) return NCM_E_WM_CREATE_PROXYCONNECTFAILED;

// 看是否需要密碼驗證
if(resNego[1]==0x02)
{
// 需要密碼驗證
char reqAuth[513]; memset(reqAuth,0,513);
BYTE byLenUser = (BYTE)strlen(m_szProxyUserName);
BYTE byLenPswd = (BYTE)strlen(m_szProxyPassword);
reqAuth[0]=0x01;
reqAuth[1]=byLenUser;
sprintf(&reqAuth[2],"%s",m_szProxyUserName);
reqAuth[2+byLenUser]=byLenPswd;
sprintf(&reqAuth[3+byLenUser],"%s",m_szProxyPassword);
//Send authentication info
int len = (int)byLenUser + (int)byLenPswd + 3;
int ret=send(m_socClientTCP_UdpAssociate,(const char*)reqAuth,len,0);
if (ret==SOCKET_ERROR) if (GetLastError()!=WSAEWOULDBLOCK) return NCM_E_WM_CREATE_PROXYREQUESTFAILED;

//Now : Response to the auth request
char resAuth[2]={'\0'};
int nRcvd=0,nCount=0;
do{
ret = recv(m_socClientTCP_UdpAssociate,resAuth+nRcvd,2-nRcvd,0);
if(ret==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=2)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE}
if (resAuth[1]!=0) return NEM_E_WM_CREATE_PROXYAUTHFAILED;
// 密碼驗證通過了
}

// 開始發送向目標服務器的連接請求,其中DST.ADDR是目標服務器的地址,DST.PORT是目標服務器的UDP端口
char reqSubNego[10]={(char)0x05,(char)0x03,(char)0x00,(char)0x01,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0x00};
*(unsigned long*)&reqSubNego[4] =saiServerUDP.sin_addr.S_un.S_addr; // cmd: DEST.addr
*(unsigned short*)&reqSubNego[8]=saiServerUDP.sin_port; // cmd: DEST.port in network octet order
nRet=send(m_socClientTCP_UdpAssociate,(const char*)reqSubNego,10,0);
if (nRet==SOCKET_ERROR) return NEM_E_WM_CREATE_PROXYREQFAILED;

// 接收響應信息
int nRecvCount = 0;
int nRecvBufferLen = 10;
char szRecvBuf[10];
nRet = 0;
if(FD_ISSET(m_socClientTCP_UdpAssociate,&fdread))
{
int nRcvd=0,nCount=0;
do{
nRet = recv(m_socClientTCP_UdpAssociate,(char*)szRecvBuf+nRcvd,10-nRcvd,0);
if(nRet==SOCKET_ERROR){return NC_E_PROXY_RECEIVE|WSAGetLastError();}
nRcvd += nRet;
}
while((nRcvd!=10)&&(++nCount<1000));
if(nCount>=1000){return NC_E_PROXY_RECEIVE;}
if (szRecvBuf[0]!=0x05||szRecvBuf[1]!=0x00){return NC_E_PROXY_PROTOCOL_VERSION_SUB;}
}
else
{
return NCM_E_WM_CREATE_PROXYREQUESTFAILED;
}

// 代理服務器綁定udp地址BND.ADR,一般代理服務器都是多宿主機器,因此這個綁定地址是局域網地址,代理服務器綁定udp端口BND.PORT
// m_ulProxyUDPAddr 代理綁定地址
// m_usUDPAssociatePort 代理綁定端口
memmove(&m_ulProxyUDPAddr,&szRecvBuf[4],4);
memmove(&m_usUDPAssociatePort,&szRecvBuf[8],2);

m_bUDPAssociated = TRUE;
// 至此,得到了代理綁定的地址和端口,客戶端就可以通過它來收發UDP數據報了


// 客戶端收發實例
// 首先創建數據報套接字,綁定套接字,得到本地數據報套接字地址,端口
SOCKET m_socClientUDP=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN saiLocal;
memset(&saiLocal,0,sizeof(saiLocal));
saiLocal.sin_family = AF_INET;
saiLocal.sin_port = 0;
saiLocal.sin_addr.S_un.S_addr = INADDR_ANY;
// 綁定本地udp套接字地址,地址+端口由系統決定
if (bind(m_socClientUDP, (SOCKADDR *)&saiLocal, sizeof(saiLocal) == SOCKET_ERROR)
getsockname(m_socClientUDP, (sockaddr*)&saiLocal, &len);
// m_ulHostAddr 本機綁定地址
// m_usHostPortUdp 本機綁定端口
m_ulHostAddr = saiLocal.sin_addr.S_un.S_addr;
m_usHostPortUdp = saiLocal.sin_port;

// 按照格式,發送數據
SOCKADDR_IN saiProxy;
memset(&saiProxy,0,sizeof(saiProxy));
saiProxy.sin_family = AF_INET;
saiProxy.sin_addr.S_un.S_addr = m_ulProxyUDPAddr; // 代理綁定的udp地址
saiProxy.sin_port = m_usUDPAssociatePort; // 代理綁定的udp端口

// 每個UDP包必須攜帶如下所述的頭:
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
// 其中 ATYP==0x01 表示采用 IPV4 地址,那么頭長度就是10,DST.ADDR并不是服務器地址,而是本機綁定地址,DST.PORT是本機綁定端口
char buf[10+2]={'0x00','0x00','0x00','0x01','0xff'};
memmove(&buf[4],&m_ulHostAddr,4);
*(unsigned short*)&buf[8]=m_usHostPortUDP;
int nRet = sendto(m_socClientUDP,buf,12,0,(SOCKADDR*)&saiProxy,sizeof(saiProxy));

// 接收數據
int nLen = sizeof(saiProxy);
char buf=new char[MAX_UDPLEN];
nRet = recvfrom(m_socClientUDP,buf,MAX_UDPLEN,0,(SOCKADDR *)&saiProxy,&nLen);
if(nRet==SOCKET_ERROR) return SOCKET_ERROR;
BYTE flag=0xff;
if(memcmp(&buf[0],&flag,1)==0) return SOCKET_ERROR;
BYTE byProxyHead[20];
byProxyHead[0]=byProxyHead[1]=byProxyHead[2]=0;
byProxyHead[3]=1;
*(unsigned long*)&byProxyHead[4] = saiServerUDP.sin_addr.S_un.S_addr;
*(unsigned short*)&byProxyHead[8] = saiServerUDP.sin_port;
byProxyHead[10]=byProxyHead[11]=byProxyHead[12]=0;
byProxyHead[13]=1;
*(unsigned long*)&byProxyHead[14] = m_ulHostAddr;
*(unsigned short*)&byProxyHead[18] = m_usHostPortUdp;

int i=0;
BOOL bIsForMe=FALSE;
if(memcmp(&byProxyHead[0],&buf[i],4)==0)
{
unsigned long ulRetAddr = *(unsigned long*)&buf[i+4];
if(ulRetAddr==m_ulHostAddr)
{
unsigned short usRetPort = ntohs((unsigned short)(*(unsigned short*)&buf[i+8]));
if(usRetPort==m_usHostPortUdp)
{
bIsForMe=TRUE;
}
}
i+=10;
}
// 客戶端收發結束


// 服務器端發送實例
// m_ulProxyUDPAddr 代理綁定地址
// m_usUDPAssociatePort 代理綁定端口
// m_ulHostAddr 本機綁定地址
// m_usHostPortUdp 本機綁定端口
// 客戶端必須把上面的m_ulProxyUDPAddr,m_usUDPAssociatePort,m_ulHostAddr,m_usHostPortUdp告知服務器,服務器通過這兩個套接字進行數據的收發

// 服務器創建數據報套接字
SOCKET m_socUDP=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

// 代理的udp中繼地址
SOCKADDR_IN saiClient;
saiClient.sin_family = AF_INET;
saiClient.sin_addr.S_un.S_addr = m_ulProxyUDPAddr;
saiClient.sin_port = m_usUDPAssociatePort;
// 如果遠程目標在代理服務器后面,透過代理,指定遠程目標的socks信息,參照RFC1928
char buffer[10]={'\0'};
buffer[0]=buffer[1]=buffer[2]=0;
buffer[3]=1; // No Fragment, It's a dependent udp, no need for socks server to arrange udp fragments

// 目標機器的地址端口,透過代理后發向這里
*(int*)&buffer[4]=m_ulHostAddr;
*(unsigned short*)&buffer[8]=m_usHostPortUdp;
BYTE buf[DATA_BUFSIZE]={'\0'};
memmove(&buf[10],&szSendbuf[0],dwLength);
memmove(&buf[0],&buffer[0],10);
int nSent = sendto(m_socUDP, (const char*)&buf[0], dwLength+10, 0, (SOCKADDR*)&saiClient,sizeof(saiClient));
// 服務器端發送結束  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 02:29 聶文龍
關于通過http代理訪問Internet
最近在網上查了一點關于通過Socket代理或者http代理訪問internet的資料,國內的資料比較少,查到了一點英文資料,覺得講得還不錯。
When an HTTP connection is made through a proxy server the client (usually the browser) sends the request to the proxy. The proxy opens the connection to the destination, sends the request, receives the response and sends it back to the client. The HTTP protocol specifies a request method called CONNECT. The CONNECT method can be used by the client to inform the proxy server that a connection to some host on some port is required. The proxy server, if allows such connections, tries to connect to the destination address specified in the request header. If it the operation fails it sends back to the client a negative HTTP response and close the connection. If the operation succeeded then send back an HTTP positive response and the connection is consider established. After that, the proxy does not care what data is transferred between client requesting the connection and the destination. It just forwards data in both ways acting as a tunnel.

About the protocol
We are interested in CONNECT method from the HTTP protocol. After the applications opens a connection with the proxy server it must send the connect request in the form of an HTTP request:

CONNECT <destination_address>:<destination_port> <http_version><CR><LF><header_line><CR><LF><header_line><CR><LF>...<header_line><CR><LF><CR><LF>The proxy server process the request and try to make a connection to <destionation_address>:<destination_port>.

The proxy server sends back an HTTP response in the form:

<http_version> <code> <message><CR><LF><header_line><CR><LF><header_line><CR><LF>...<header_line><CR><LF><CR><LF>If it is a positive response (code=200) then after the empty line the proxy begins to acts as a tunnel and forwards data. If it is a negative response (code!=200) then connection is closed after the empty line.

The HTTPTunneling application
The application act as specified in a configuration file. An entry in the configuration file locks like this:

<Source port> <Destination address> <Destination port> <Proxy address> <Proxy port>If the application is running and an entry in the configuration files changes, the application automatically updates itself.

For every entry in the configuration file the application creates a port listener. This is a thread that opens a socket on <Source port> and waits for connection. When a request arrives on that port it tries to open a tunnel to the <Destination address>:< port>. If the <Proxy address> and <Proxy port> are missing, a direct connection is made. If the field are present it opens a connection to the proxy and sends a CONNECT request using the method specified above. The tunnel construction is made in a separate thread to let the port listener to accept immediatelly new connections. After the connection is established a tunnel object is constructed based on the opened sockets, sockets are marked as non-blocking and the object is passed to manager object. The thread that has created the tunnel is destroyed. Data transfer is made on a single thread. When one of the ends closes the connection the tunnel closes the other and the tunnel is marked as inactive. The manager finds the tunnel inactive and removes it from the list of active tunnels. By default the application generates log information in HTTPTunneling.log file. This file can be consulted to find wrong application behaviour.
  回復  更多評論
  
# re: 代理服務器代碼 2008-10-21 11:35 聶文龍
[轉載]C語言寫的Linux平臺socks5代理程序
C語言寫的Linux平臺socks5代理程序

信息來源:邪惡八進制信息安全團隊(www.eviloctal.com)

前幾天MSN老上不去,我還以為是公司做了防火墻限制。于是把去年這個時候寫得一個代理程序改了改,拿出來用。結果發現MSN是因為微軟的問題,鄙視啊……
因為寫得比較急,這個只支持TCP代理,UDP的我沒寫,因為MSN用不上。這個代碼可以隨意修改分發,不過最好能給我一份。

這是頭文件:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5代理頭文件,定義協議相關數據包結構
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1點15分,GF回家已經11天了。
// 2008年1月25日修改,今年GF一直在我身邊,哈哈
//
// 參考:
// http://www.rfc-editor.org/rfc/rfc1928.txt
// http://www.rfc-editor.org/rfc/rfc1929.txt
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef SOCKS5_H
#define SOCKS5_H

#define VERSION 0x05
#define CONNECT 0x01
#define IPV4 0x01
#define DOMAIN 0x03
#define IPV6 0x04

typedef struct _method_select_response // 協商方法服務器響應
{
char version; // 服務器支持的Socks版本,0x04或者0x05
char select_method;// 服務器選擇的方法,0x00為匿名,0x02為密碼認證
} METHOD_SELECT_RESPONSE;

typedef struct _method_select_request // 協商方法服務端請求
{
char version; // 客戶端支持的版本,0x04或者0x05
char number_methods; // 客戶端支持的方法的數量
char methods[255]; // 客戶端支持的方法類型,最多255個,0x00為匿名,0x02為密碼認證
} METHOD_SELECT_REQUEST;

typedef struct _AUTH_RESPONSE // 用戶密碼認證服務端響應
{
char version;// 版本,此處恒定為0x01
char result;// 服務端認證結果,0x00為成功,其他均為失敗
} AUTH_RESPONSE;

typedef struct _AUTH_REQUEST //用戶密碼認證客戶端請求
{
char version; // 版本,此處恒定為0x01
char name_len; // 第三個字段用戶名的長度,一個字節,最長為0xff
char name[255]; // 用戶名
char pwd_len;// 第四個字段密碼的長度,一個字節,最長為0xff
char pwd[255]; // 密碼
} AUTH_REQUEST;

typedef struct _SOCKS5_RESPONSE // 連接真實主機,Socks代理服務器響應
{
char version; // 服務器支持的Socks版本,0x04或者0x05
char reply; // 代理服務器連接真實主機的結果,0x00成功
char reserved; // 保留位,恒定位0x00
char address_type; // Socks代理服務器綁定的地址類型,IP V4為0x01,IP V6為0x04,域名為0x03
char address_port[1]; // 如果address_type為域名,此處第一字節為域名長度,其后為域名本身,無0字符結尾,域名后為Socks代理服務器綁定端口
}SOCKS5_RESPONSE;

typedef struct _SOCKS5_REQUEST // 客戶端請求連接真實主機
{
char version; // 客戶端支持的Socks版本,0x04或者0x05
char cmd; // 客戶端命令,CONNECT為0x01,BIND為0x02,UDP為0x03,一般為0x01
char reserved; // 保留位,恒定位0x00
char address_type; // 客戶端請求的真實主機的地址類型,IP V4為0x00,IP V6為0x04,域名為 0x03 char address_port[1]; // 如果address_type為域名,此處第一字節為域名長度,其后為域名本身,無0字符結尾,域名后為真實主機綁定端口

}SOCKS5_REQUEST;
#endif
主程序來了:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5程序,只支持TCP代理
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1點15分,GF回家已經11天了。
// 2008年1月25日修改,今年GF一直在我身邊,哈哈
//
// 參考:
// http://www.rfc-editor.org/rfc/rfc1928.txt
// http://www.rfc-editor.org/rfc/rfc1929.txt
//編譯:
// gcc -o socks5 -O2 Socks5.c -lpthread( RedHat AS5測試 )
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "Socks5.h"

#define MAX_USER 10
#define BUFF_SIZE 1024

#define AUTH_CODE 0x02

#define TIME_OUT 6000000

#define USER_NAME "yunshu"
#define PASS_WORD "ph4nt0m"

// Select auth method, return 0 if success, -1 if failed
int SelectMethod( int sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };
char reply_buffer[2] = { 0 };

METHOD_SELECT_REQUEST *method_request;
METHOD_SELECT_RESPONSE *method_response;

// recv METHOD_SELECT_REQUEST
int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret <= 0 )
{
perror( "recv error" );
close( sock );

return -1;
}

//printf( "SelectMethod: recv %d bytes\n", ret );

// if client request a wrong version or a wrong number_method
method_request = (METHOD_SELECT_REQUEST *)recv_buffer;
method_response = (METHOD_SELECT_RESPONSE *)reply_buffer;

method_response->version = VERSION;

// if not socks5
if( (int)method_request->version != VERSION )
{
method_response->select_method = 0xff;

send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 );
close( sock );

return -1;
}

method_response->select_method = AUTH_CODE;
if( -1 == send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 ) )
{
close( sock );
return -1;
}

return 0;
}

// test password, return 0 for success.
int AuthPassword( int sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };
char reply_buffer[BUFF_SIZE] = { 0 };

AUTH_REQUEST *auth_request;
AUTH_RESPONSE *auth_response;

// auth username and password
int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret <= 0 )
{
perror( "recv username and password error" );
close( sock );
return -1;
}
//printf( "AuthPass: recv %d bytes\n", ret );

auth_request = (AUTH_REQUEST *)recv_buffer;

memset( reply_buffer, 0, BUFF_SIZE );
auth_response = (AUTH_RESPONSE *)reply_buffer;
auth_response->version = 0x01;

char recv_name[256] = { 0 };
char recv_pass[256] = { 0 };

// auth_request->name_len is a char, max number is 0xff
char pwd_str[2] = { 0 };
strncpy( pwd_str, auth_request->name + auth_request->name_len, 1 );
int pwd_len = (int)pwd_str[0];

strncpy( recv_name, auth_request->name, auth_request->name_len );
strncpy( recv_pass, auth_request->name + auth_request->name_len + sizeof(auth_request->pwd_len), pwd_len );

//printf( "username: %s\npassword: %s\n", recv_name, recv_pass );
// check username and password
if( (strncmp( recv_name, USER_NAME, strlen(USER_NAME) ) == 0) &&
(strncmp( recv_pass, PASS_WORD, strlen(PASS_WORD) ) == 0)
)
{
auth_response->result = 0x00;
if( -1 == send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 ) )
{
close( sock );
return -1;
}
else
{
return 0;
}
}
else
{
auth_response->result = 0x01;
send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 );

close( sock );
return -1;
}
}

// parse command, and try to connect real server.
// return socket for success, -1 for failed.
int ParseCommand( int sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };
char reply_buffer[BUFF_SIZE] = { 0 };

SOCKS5_REQUEST *socks5_request;
SOCKS5_RESPONSE *socks5_response;

// recv command
int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret <= 0 )
{
perror( "recv connect command error" );

close( sock );
return -1;
}

socks5_request = (SOCKS5_REQUEST *)recv_buffer;
if( (socks5_request->version != VERSION) || (socks5_request->cmd != CONNECT) ||
(socks5_request->address_type == IPV6) )
{
//printf( "connect command error.\n" );
close( sock );
return -1;
}

// begain process connect request
struct sockaddr_in sin;

memset( (void *)&sin, 0, sizeof(struct sockaddr_in) );
sin.sin_family = AF_INET;

// get real server&#39;s ip address
if( socks5_request->address_type == IPV4 )
{
memcpy( &sin.sin_addr.s_addr, &socks5_request->address_type + sizeof(socks5_request->address_type) , 4 );
memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) + 4, 2 );

//printf( "Real Server: %s %d\n", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) );
}
else if( socks5_request->address_type == DOMAIN )
{
char domain_length = *(&socks5_request->address_type + sizeof(socks5_request->address_type));
char target_domain[ 256] = { 0 };

strncpy( target_domain, &socks5_request->address_type + 2, (unsigned int)domain_length );

//printf( "target: %s\n", target_domain );

struct hostent *phost = gethostbyname( target_domain );
if( phost == NULL )
{
//printf( "Resolve %s error!\n" , target_domain );

close( sock );
return -1;
}
memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length );

memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) +
sizeof(domain_length) + domain_length, 2 );
}

// try to connect to real server
int real_server_sock = socket( AF_INET, SOCK_STREAM, 0 );
if( real_server_sock < 0 )
{
perror( "Socket creation failed\n");

close( sock );
return -1;
}

memset( reply_buffer, 0, sizeof(BUFF_SIZE) );

socks5_response = (SOCKS5_RESPONSE *)reply_buffer;

socks5_response->version = VERSION;
socks5_response->reserved = 0x00;
socks5_response->address_type = 0x01;
memset( socks5_response + 4, 0 , 6 );

ret = connect( real_server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) );
if( ret == 0 )
{
socks5_response->reply = 0x00;
if( -1 == send( sock, socks5_response, 10, 0 ) )
{
close( sock );

return -1;
}
}
else
{
perror( "Connect to real server error" );
socks5_response->reply = 0x01;
send( sock, socks5_response, 10, 0 );

close( sock );
return -1;
}

return real_server_sock;
}

int ForwardData( int sock, int real_server_sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };

fd_set fd_read;
struct timeval time_out;

time_out.tv_sec = 0;
time_out.tv_usec = TIME_OUT;

int ret = 0;

while( 1 )
{
FD_ZERO( &fd_read );
FD_SET( sock, &fd_read );
FD_SET( real_server_sock, &fd_read );

ret = select( (sock > real_server_sock ? sock : real_server_sock) + 1, &fd_read, NULL, NULL, &time_out );
if( -1 == ret )
{
perror( "select socket error" );
break;
}
else if( 0 == ret )
{
//perror( "select time out" );
continue;
}

//printf( "[DEBUG] testing readable!\n" );
if( FD_ISSET(sock, &fd_read) )
{
//printf( "client can read!\n" );
memset( recv_buffer, 0, BUFF_SIZE );
ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret > 0 )
{
//printf( "%s", recv_buffer );
//printf( "recv %d bytes from client.\n", ret );
ret = send( real_server_sock, recv_buffer, ret, 0 );
if( ret == -1 )
{
perror( "send data to real server error" );
break;
}
//printf( "send %d bytes to client!\n", ret );
}
else if( ret == 0 )
{
//printf( "client close socket.\n" );
break;
}
else
{
//perror( "recv from client error" );
break;
}
}

else if( FD_ISSET(real_server_sock, &fd_read) )
{
//printf( "real server can read!\n" );
memset( recv_buffer, 0, BUFF_SIZE );
ret = recv( real_server_sock, recv_buffer, BUFF_SIZE, 0 );
if( ret > 0 )
{
//printf( "%s", recv_buffer );
//printf( "recv %d bytes from real server.\n", ret );
ret = send( sock, recv_buffer, ret, 0 );
if( ret == -1 )
{
perror( "send data to client error" );
break;
}
}
else if( ret == 0 )
{
//printf( "real server close socket.\n" );
break;
}
else
{
perror( "recv from real server error" );
break;
}
}
}

return 0;
}

int Socks5( void *client_sock )
{
int sock = *(int *)client_sock;

if( SelectMethod( sock ) == -1 )
{
//printf( "socks version error\n" );
return -1;
}

if( AuthPassword( sock ) == -1 )
{
//printf( "auth password error\n" );
return -1;
}

int real_server_sock = ParseCommand( sock );
if( real_server_sock == -1 )
{
//printf( "parse command error.\n" );
return -1;
}

ForwardData( sock, real_server_sock );

close( sock );
close( real_server_sock );

return 0;
}

int main( int argc, char *argv[] )
{
if( argc != 2 )
{
printf( "Socks5 proxy for test,code by YunShu\n" );
printf( "Usage: %s <proxy_port>\n", argv[0] );
printf( "Options:\n" );
printf( " <proxy_port> ---which port of this proxy server will listen.\n" );

return 1;
}

struct sockaddr_in sin;

memset( (void *)&sin, 0, sizeof( struct sockaddr_in) );
sin.sin_family = AF_INET;
sin.sin_port = htons( atoi(argv[1]) );
sin.sin_addr.s_addr = htonl(INADDR_ANY);

int listen_sock = socket( AF_INET, SOCK_STREAM, 0 );
if( listen_sock < 0 )
{
perror( "Socket creation failed\n");
return -1;
}

int opt = SO_REUSEADDR;
setsockopt( listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );

if( bind( listen_sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in) ) < 0 )
{
perror( "Bind error" );
return -1;
}

if( listen( listen_sock, MAX_USER ) < 0 )
{
perror( "Listen error" );
return -1;
}

struct sockaddr_in cin;
int client_sock;
int client_len = sizeof( struct sockaddr_in );

while( client_sock = accept( listen_sock, (struct sockaddr *)&cin, (socklen_t *)&client_len ) )
{
printf( "Connected from %s, processing......\n", inet_ntoa( cin.sin_addr ) );

pthread_t work_thread;
if( pthread_create( &work_thread, NULL, (void *)Socks5, (void *)&client_sock ) )
{
perror( "Create thread error..." );
close( client_sock );
}
else
{
pthread_detach( work_thread );
}
}
}   回復  更多評論
  
# re: 代理服務器代碼 2012-05-08 23:16 迷失
聊天記錄  回復  更多評論
  

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              欧美激情亚洲一区| 久久精品国产亚洲一区二区三区| 一区二区三区视频在线观看| 欧美人与禽性xxxxx杂性| 亚洲视频导航| 亚洲三级毛片| 韩日精品视频一区| 国产精品一二| 欧美日韩一区二区三| 欧美日韩中文字幕| 欧美va亚洲va国产综合| 久久成人一区二区| 亚洲一区二区精品| 亚洲小视频在线观看| 91久久午夜| 亚洲美女一区| 亚洲小说区图片区| 久久精品99久久香蕉国产色戒| 国产精品盗摄久久久| 欧美性大战久久久久久久蜜臀| 国产精品xxx在线观看www| 男人的天堂亚洲| 欧美久久九九| 国产午夜精品在线| 欲色影视综合吧| 亚洲一区二区3| 久久亚洲午夜电影| 亚洲高清资源| 黑人巨大精品欧美一区二区| 国外成人性视频| 99精品国产在热久久婷婷| 欧美色大人视频| 免费欧美高清视频| 亚洲激情电影在线| 午夜欧美视频| 一区二区三区视频观看| 国产精品视频自拍| 麻豆九一精品爱看视频在线观看免费 | 久久日韩粉嫩一区二区三区| 一区二区免费看| 宅男噜噜噜66一区二区66| 亚洲一区二区三区在线播放| 狠狠色噜噜狠狠狠狠色吗综合| 亚洲欧美中文另类| 一区二区三区高清不卡| 美女精品视频一区| 久久这里有精品15一区二区三区| 久久亚洲国产精品一区二区| 亚洲国产小视频在线观看| 亚洲人成欧美中文字幕| 久久精品欧洲| 欧美精品一区二区久久婷婷| 亚洲自拍偷拍视频| 久久久xxx| 欧美日韩国产综合久久| 国产欧美大片| 一区二区三区高清不卡| 欧美伊人久久久久久午夜久久久久| 久久久无码精品亚洲日韩按摩| 亚洲毛片在线免费观看| 91久久午夜| 欧美国产日本在线| 亚洲深夜影院| 欧美新色视频| 欧美一区二区三区在线视频| 欧美激情精品久久久久久久变态 | 国产伦精品一区二区三区高清版| 亚洲欧美国产视频| 国产亚洲成精品久久| 国产精品推荐精品| 亚洲欧美日韩综合| 欧美国产专区| 一区在线免费| 欧美国产亚洲视频| 久久亚洲国产成人| 精品999网站| 久久亚洲综合网| 久久久久久久激情视频| 国产婷婷色一区二区三区在线| 久久在精品线影院精品国产| 国产精品久久影院| 亚洲国产精品女人久久久| 国产精品日韩专区| 欧美一区视频在线| 国产精品久久久久aaaa樱花| 亚洲精品日韩激情在线电影| 亚洲精品欧美日韩专区| 欧美激情久久久久| 裸体一区二区三区| 欧美中文字幕视频在线观看| 美女久久网站| 性久久久久久久| 99爱精品视频| 老色鬼精品视频在线观看播放| 欧美激情精品久久久久久| 99国产精品国产精品久久| 欧美韩日视频| 99ri日韩精品视频| 亚洲一区二区四区| 欧美成人午夜77777| 日韩视频免费在线观看| 久久精品国产96久久久香蕉| 久久精品五月婷婷| 99在线|亚洲一区二区| 亚洲一区日韩在线| 欧美国产第二页| 亚洲综合色网站| 久久久久国色av免费看影院| 日韩亚洲欧美成人一区| 午夜欧美不卡精品aaaaa| 亚洲激情一区| 欧美一二三视频| 亚洲人成在线观看一区二区| 亚洲女同性videos| 亚洲精品在线看| 美女主播精品视频一二三四| 久久久久国产精品人| 亚洲国产欧美一区| 欧美成人精品| 一区二区日韩| 亚洲视频二区| 精品成人一区二区| 中文av一区二区| 久久一本综合频道| 久久午夜精品一区二区| 国产日韩精品视频一区二区三区| 日韩一级黄色片| 国产一区二区激情| 亚洲日本久久| 亚洲二区视频| 久久久久久自在自线| 久久亚洲国产精品一区二区 | 亚洲国产欧美一区二区三区丁香婷| av成人福利| 久久久久亚洲综合| 香蕉成人啪国产精品视频综合网| 亚洲欧美日韩精品久久久| 久久久久国产免费免费| 亚洲综合国产精品| 麻豆av一区二区三区| 欧美14一18处毛片| 免费不卡亚洲欧美| 欧美风情在线| 狠狠爱综合网| 欧美影院成年免费版| 国产精品日韩在线播放| 国产精品久久久久久亚洲调教| 午夜视频精品| 久久久噜噜噜久久人人看| 欧美综合二区| 欧美激情va永久在线播放| 久久精品国产一区二区三区| 亚洲在线播放| 久久综合九色九九| 欧美激情 亚洲a∨综合| 欧美福利在线| 日韩午夜免费视频| 一区二区欧美亚洲| 亚洲视频在线观看三级| 日韩视频永久免费| 在线一区二区日韩| 最新国产成人av网站网址麻豆| 国产一区二区三区在线免费观看| 亚洲人在线视频| 好看不卡的中文字幕| 亚洲欧美成人一区二区在线电影| 国产精品一卡二卡| 国产视频一区在线观看一区免费| 国产视频自拍一区| 亚洲欧美美女| 亚洲综合另类| 午夜在线视频观看日韩17c| 国产女主播一区| 国产精品区一区二区三| 亚洲精品免费在线播放| 日韩一级大片| 午夜日韩av| 女女同性女同一区二区三区91| 久久中文字幕一区| 久久香蕉国产线看观看网| 日韩视频免费在线观看| 免费国产自线拍一欧美视频| 欧美成人午夜影院| 国产精品一区二区久久精品| 国产欧美日韩精品专区| 亚洲人成网站在线观看播放| 一区二区三区久久精品| 男人天堂欧美日韩| **欧美日韩vr在线| 欧美日韩在线一区| 亚洲专区国产精品| 亚洲欧洲综合另类| 亚洲一区二区精品视频| 亚洲国产成人精品女人久久久 | 国语对白精品一区二区| 久久永久免费| av成人动漫| 亚洲人在线视频| 欧美成在线视频| 亚洲一区二区视频|