sock代理服務原理(TCP穿透)

來源:互聯網
上載者:User

原文轉自:http://www.cppblog.com/zuhd/archive/2010/06/08/117366.html

sock代理分為sock4代理和 sock5代理。sock4支援TCP(事實僅支援TCP),無需使用者名稱、密碼驗證;sock5支援TCP和UDP,根據Proxy 伺服器設定是否需要使用者名稱、密碼認證。TCP和UDP代理工作原理產不多,UDP代理網上多的是,google一下即可。這裡只講TCP代

理工作原理。
sock代理工作原理大致如下:
1。[需要代理方]向伺服器發出請求資訊;
2。[代理方]應答;
3。[需要代理方]接到應答後發送向[代理方]發送目的ip和連接埠;
4。[代理方]與目的串連;
5。[代理方]將[需要代理方]發出的資訊傳到目的方,將目的方發出的資訊傳到[需要代理方];
6。代理完成。
下面對sock4和sock5的代理工作原理流程分別詳細說明,並給出範例程式碼。
sock4的TCP代理工作流程:
1。我們首先還是串連伺服器,然後發送資料給伺服器。由於是無使用者密碼驗證,我們需要發送9個位元組的資料,展開寫為 04 01 + 目標連接埠(2位元組) + 目標IP(4位元組) + 00,其中目標連接埠和目標IP就是我們真正要已連線的服務器連接埠和伺服器位址;
2。Proxy 伺服器返回8位元組的資料,我們只要判斷第二位元組是否為90即可,若是90串連成功,否則失敗.剩下的操作和不存在Proxy 伺服器一樣,可直接用發送\接受資料。
sock5的TCP代理工作流程:
1。向伺服器的代理連接埠建立tcp串連。一般為1080;
2。向伺服器發送 05 02 00 02(此為16進位碼,以下同),讓Proxy 伺服器選擇認證方式 ;
05
02 這裡確認2種認證方式 無需認證和需要認證,只需要驗證一種方式,可以直接發送05 01 00查詢服務器是否支援無認證代理方式;
00 不需要認證;
02 需要認證;
3。如果接到 05 00 則是可以代理或則05 02需要認證,這裡只需要判斷第二位元組就行;
如果需要認證,需要向伺服器發送01 使用者名稱長度(2位元組)使用者名稱 密碼長度(2位元組)密碼,然後接收伺服器返回資料,如果第二位元組為 00,則認證通過,否則無法認證,則串連失敗;
4。發送 05 01 00 01 + 目的地址(4位元組)+ 目的連接埠(2位元組),目的地址和連接埠都是16進位碼(不是字串)。
例202.103.190.27 - 7201
則發送的資訊為:05 01 00 01 CA 67 BE 1B 1C 21
(CA=202 67=103 BE=190 1B=27 1C21=7201)
5。接收Proxy 伺服器返回的資料,我們只要判斷第二位元組是否為00即表示代理串連完成;
6。以後操作和直接與目的方進行TCP串連相同。

//Proxy 伺服器登入
CString g_proxyserver = “”;
int g_proxyport = 1080;
CString g_proxyuser = “”;
CString g_proxypwd = “”;
int g_proxyid = 3; //2 - sock4代理 3 - sock5代理
char server_name[100]= {0}; //真正的伺服器位址
int server_port=8000; //真正的伺服器連接埠
SOCKET ConnecToProxyServer()
{
SOCKADDR_IN ToAddr;
SOCKET m_hSocketpop = socket(AF_INET, SOCK_STREAM ,0); // SOCK_DGRAM;
memset(&ToAddr, 0, sizeof(ToAddr));
ToAddr.sin_family = AF_INET;
ToAddr.sin_addr.s_addr = inet_addr(g_proxyserver);//這是我的SOCKS伺服器
ToAddr.sin_port = htons(g_proxyport);
int retErr = connect(m_hSocketpop,(SOCKADDR*)&ToAddr,sizeof(ToAddr));
if(retErr == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
char buf[100] = {0};
if(g_proxyid == 3) //sock5 代理方式
{
// 讓PROXY選擇認證方法
buf[0] = 0x05;
buf[1] = 0x02; //確認2種認證方式 無需認證和需要認證
buf[2] = 0x00; // 無需認證
buf[3] = 0x02; // 需要認證
if(send(m_hSocketpop,(const far char*)buf,4,0) == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
Sleep(100);
if(recv(m_hSocketpop,buf,10,0) == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
if(buf[1] == 0x02)
{//需要認證
char userStr[128] = {0};
userStr[0]=0x01;
userStr[1]=g_proxyuser.GetLength();
strcpy(userStr+2,g_proxyuser);
userStr[2+g_proxyuser.GetLength()]=g_proxypwd.GetLength();
strcpy(userStr+3+g_proxyuser.GetLength(),g_proxypwd);
int result=send(m_hSocketpop,userStr,strlen(userStr), 0);
if(result == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
Sleep(100);
char validateChar[2] = {1};
result=recv(m_hSocketpop,validateChar,2, 0);
if(result == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
if(validateChar[1]!=’\x00’)
{//認證失敗
closesocket(m_hSocketpop);
return -1;
}
}
// 向PROXY伺服器發送CONNECT 請求,
memset(buf, 0, 100);
buf[0] = 0x05;
buf[1] = 0x01; // connection request.
buf[2] = 0x00; // reserved!
buf[3] = 0x01; // address type:Ip V4 ;
((ULONG)(buf+4))=inet_addr(server_name);
((USHORT)(buf+8))=htons(server_port);
if(send(m_hSocketpop,(const far char*)buf,10,0) == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
Sleep(100);
// 接收PROXY伺服器返回的REPLY
memset(buf, 1, 100);
if(recv(m_hSocketpop,buf, 20,0) == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
if(buf[1] != 0) // 只有當第二個位元組為0時,才表示成功。
{
// printf(“Cannot connect to the remote server!\n”);
closesocket(m_hSocketpop);
return -1;
}
// theApp.m_ClientSocket.Attach(m_hSocketpop);
}
if(g_proxyid == 2) //sock4 代理方式
{
int result;
memset(buf, 0, 100);
buf[0] = 0x04;
buf[1] = 0x01; // connection request.
((USHORT)(buf+2))=htons(server_port);
((ULONG)(buf+4))=inet_addr(server_name);
buf[8] = 0x00;
result = send(m_hSocketpop, (const far char*)buf, 9, 0);
if(result == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
Sleep(100);
char EchoStr[10];
memset(EchoStr,0,10);
result=recv(m_hSocketpop,EchoStr,8, 0);
if(result == SOCKET_ERROR)
{
closesocket(m_hSocketpop);
return -1;
}
if(EchoStr[1] != 90)
{
closesocket(m_hSocketpop);
return -1;
}
// theApp.m_ClientSocket.Attach(m_hSocketpop);
}
return m_hSocketpop;
}
調用方式:
strcpy(server_name, theApp.m_ServerIP);
server_port = 8080;
SOCKET m_socket = ConnecToProxyServer();
if(m_socket == -1)
{
return 0;
}
int type = 1000;
send(m_socket, (char*)&type, sizeof(int), 0);

SOCK5如何用代理UDP串連

1。向伺服器的1080連接埠建立tcp串連

2。向伺服器發送 05 01 00

3。如果接到 05 00 則是可以代理

4。發送 05 03 00 01 00 00 00 00 + 本地UDP連接埠(2位元組)

5。伺服器返回 05 00 00 01 +伺服器位址+連接埠

7.需要申請方發送
00 00 00 01 +目的地址IP(4位元組)+目的連接埠 +所要發送的資訊

8。當有資料報返回時
向需要代理方發出00 00 00 01 +來源地址IP(4位元組)+來源連接埠 +接受的資訊

使用sock5代理時TCP資料:
用戶端 sock5伺服器
SYN
ACKSYN
ACK
05 01 00 00 00 00
05 00 00 00 00 00
05 01 00 03 0E 31 39 32 2E 31 36 38 2E 37 35 2E 31 31 34 00 6E (…..192.168.75.114.n)
05 00 00 01 C0 A8 4D 56 08 D4
ACK
+OK X1 NT-POP3 Server iflytek.com (IMail 8.15 228888-9)..
USER hjma..
+OK send your password..
PASS xxxxxxx..
+OK maildrop locked and ready..
STAT..
+OK 0 0..
QUIT..
+OK POP3 Server saying Good-Bye..
ACKFIN
ACK
ACKFIN
ACK

出處:http://www.cnblogs.com/zhangdongsheng/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.