分享

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

 shaobin0604@163.com 2009-04-06
為你的QQ造一個SOCK5 PROXY(Gcc篇)之一

作者: 趙氏軟體(http://chiosoft.)
E-mail: chiosoft@163.net
※轉貼請注明出處※


本文以QQ為對像,教你如何寫一個SOCK5 PROXY

一、準備工作
===================
1.編譯器:
為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行.

2.程序運行環境:
可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.

3.如何編譯:
在LINUX下用 gcc mysock5.c -o mysock5
在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock32
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.


二、基本思路
===================
Proxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.

1.握手過程
客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.

2.資料傳輸
QQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.

這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動.


三、程序框架
===================
先看看源代碼mysock5.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明
#ifdef _WIN32
#include <winsock2.h>
#include <wininet.h>
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

//定義一段緩衝區
#defineBUFSZ65535
char buf[ BUFSZ ];

int main(int argc, char** argv)
{
//這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號
short tcp_proxy_port=8888, udp_proxy_port=8811;
char udp_proxy_ip[]="127.0.0.1";
short clt_udp_port;

//在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,
//WSA是Windows Socket API的意思,本文使用WinSock 2.0版本
//在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏
//我們需要自己指定
#ifdef _WIN32
WSADATA WSAData;
if( WSAStartup(0x0110, &WSAData) ) {
//if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {
p_error("WSA error");
exit(-1);
}
#endif


//啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)
Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );

//握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );

return 0;
}




四、工具函數
===================
正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.

1. p_error
這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略:)

void p_error( const char *err_msg )
{
printf( "ERR=>%s\n", err_msg );
}



2. debug_showbin
用來輸出一段數據的內容(16進制)

void debug_showbin( const char *dbuf, int n, const char *name, const char *end )
{
int i;

printf( "%s ==> %d bytes: ", name, n );

for( i=0; i<n; i++ )
printf( "(0x%x)", (unsigned char)dbuf[i] );

printf( "%s", end );
}



3. debug_showip
用來顯示sockaddr_in類型數據中的IP和Port

void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )
{
printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end

);
}



五、測試
===================
下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息:)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多