找回密码
 注册
搜索
查看: 5737|回复: 0

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

[复制链接]
发表于 2005-2-5 20:02:12 | 显示全部楼层 |阅读模式
  作者: 趙氏軟體(http://chiosoft.51.net)# c! X9 h0 s2 \+ n
E-mail: chiosoft@163.net
. k" t; x, _1 F. j( \& ~※轉貼請注明出處※9 {; h( U% A% q" R

6 b* z  ]( c9 i1 e7 Z; w. y& w) P9 s+ ]! D: w' n
本文以QQ為對像,教你如何寫一個SOCK5 PROXY
7 M6 m2 Z. I% Z. _  M6 T0 P9 O( s) M9 [( O2 H+ u8 `4 w( c4 {
一、準備工作
* S! P: u0 E$ ~: h& B; S===================
: Z. y# n, l9 w1.編譯器:4 p! ]) U/ a7 I) f1 X
為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行.2 X5 D+ G- u8 E2 v( Y" J5 x0 D
4 N& c) ?0 ^* E2 Q' e- a
2.程序運行環境:. R) k* \6 A8 m+ r
可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.
4 J0 b! ^! C; e- p# a1 b( w3 @. I
3.如何編譯:
/ b) k" R3 t4 [* ~; h在LINUX下用 gcc mysock5.c -o mysock5
1 R: q: I: J; g6 Z在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock32$ @1 n& @1 @' J: L
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.
3 ]7 ?; i; x: i5 }" X1 o) j% j, x3 V8 _9 _7 o. A
& M& y' a: B8 K
二、基本思路
" Z$ ~' a' s% I+ U$ X===================
6 t. ]2 d5 C6 Z9 L8 I: q5 s0 H, rProxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.+ G9 k" h  \% O/ ^. I
8 n# I5 x: O  Z( }9 l
1.握手過程
- [! r9 t; f/ P6 k3 k客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.& H; G. r5 H: P3 i, ~+ q$ G$ h/ p/ a
6 v( O+ b- |, U! |
2.資料傳輸! `0 E6 n* z* n0 b! g+ i% w
QQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.6 d, `/ p6 H; A' h( j5 ?

5 t# j) {; k+ [6 F6 E2 U這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動.6 x7 A4 Q+ y. j
8 G: P( `  l2 p8 ?

5 v$ C9 p* x- k" W5 @三、程序框架0 b6 K# ~  A# Q! K, b
===================
8 _8 u3 _& }1 X先看看源代碼mysock5.c! T9 {; u( @) A! w* l

9 u; w- t, t, |% a. v# P! W
; q: d/ C4 T: M: ?1 R1 [/ v#include <stdio.h>/ U1 ^1 I) e3 \# l& E
#include <string.h>; b4 o) H% P& c) ]5 W. ^
#include <stdlib.h>
* ~9 y9 G# Y. C% X- n0 H7 T#include <unistd.h>
4 z' `- S& y% N& m( m1 G  L
/ G% w# d- }; o) [+ \3 C, s//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明; N1 c, m9 N, x) f2 u
#ifdef _WIN32/ D$ R5 ^1 D) p) ?1 n' |
#include <winsock2.h>. [, q( X+ ?0 {. C( j
#include <wininet.h>+ F3 O9 L4 r9 e( Z# c  C; n
#else7 K. Q* W1 a. D; u
#include <sys/socket.h>3 X  P7 R9 ?: R" f6 W
#include <arpa/inet.h>
" e2 N- j+ i. b4 F& @#include <netdb.h>% A$ l- r5 J1 T" D* L- R, U. e9 A
#endif
6 E* C9 }+ H0 m& v$ f) T# E) K9 n7 u" G- t8 s2 z: O
//定義一段緩衝區
" U+ ~: d# I( K9 n#define       BUFSZ       65535
0 }3 E, G) l& a3 O+ V' O# nchar buf[ BUFSZ ];- {& o. Y3 S- D7 I+ {8 f7 s7 e9 ^
! j/ V% I' z- U3 f* a
int main(int argc, char** argv) ) m& _0 H* w9 L# o. H3 }$ J, t
{( W9 G5 U- P6 N% B, `" F2 m
      //這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號' J) \$ D" G7 Q' u1 G
      short tcp_proxy_port=8888, udp_proxy_port=8811;
9 n; {  r% `! _( n       char udp_proxy_ip[]="127.0.0.1";9 a( q& ?! m/ ?0 {- q2 |
      short clt_udp_port;+ Z6 F& J" ?7 `4 r" ^! S

) F1 g6 z/ Y# m" b2 j( a       //在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,2 T8 J( h2 Z8 S+ }8 e7 B; D
      //WSA是Windows Socket API的意思,本文使用WinSock 2.0版本& C/ t& R$ u2 L6 v: C; e% l' ?
      //在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏) d! L) @0 k9 b, s( m
      //我們需要自己指定; q2 v2 S5 w$ z2 S
      #ifdef _WIN32
% b) c+ j/ m$ m" [2 K+ B; N6 W/ j' n       WSADATA WSAData;5 a6 d- K  i" a5 l8 A
      if( WSAStartup(0x0110, &WSAData) ) {: q* P. ^6 d) M: k0 L
      //if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {: T+ I  k& |0 Q9 m! V& K
             p_error("WSA error");
# X) E* r3 o8 u6 m  U% R& _              exit(-1);; {. Y$ l5 y9 C# n
      }
7 p% T9 |' \" H# ]4 N' Z  R# p       #endif0 G9 I& i* T5 t
! H6 f* h6 d; K/ F/ B

. C( |2 F# F- e  X+ ~# P8 }/ c       //啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)) n6 p9 J$ i- q
      Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );. \- [8 A0 y/ D; M- R' o$ s
" ]) E! a3 s+ M; o
      //握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
6 L9 G; v: i2 \, d, |" z: Z0 p! L: B% D       Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );
* c$ C' U3 m+ c* l3 x: t" h8 o% z       
6 ~- k: @7 E/ P! J       return 0;! L7 O5 M4 J8 M% t2 v5 n( W
}
: z$ K+ ^$ d1 W0 A5 R' \; k7 Z9 }2 j0 e

! {% C/ t5 H  i# U. ~1 s" ^. i: d7 K) \

* g3 L5 B0 Z' ]7 V% a% J7 f
) c: j) n- L( H# R0 [; }四、工具函數- |# O8 f( K" o- h$ q/ G: N
===================  l6 g# g+ f$ V
正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.
- b' v# F4 z4 {' V' q% C( Q/ {$ q. b% a# w
1. p_error& D9 S! K8 Q! z2 z! J$ a. `5 P
這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略
! w8 z9 ^# j( ]7 Z. x1 b
" i( l# @- j+ r' D0 h  J! N
0 n+ O: B! ]5 W& w& d! \void p_error( const char *err_msg )
( X& c# i! y0 h1 _{2 ?; O4 K3 i) E) E% _
      printf( "ERR=>%s\n", err_msg );$ k0 o$ F5 P7 y: v6 V/ b3 E
}4 q1 B9 t) r1 i2 C

6 }  m5 E& X& X( {" t( \( R8 o8 ], n- n- g. m
  A" n5 N9 g5 e) k+ X* p2 c$ p% S9 D

+ F" r% I3 D) b/ _9 Q3 m$ \+ w1 \2 {0 g2. debug_showbin* W! ]* k: |+ ]) o
用來輸出一段數據的內容(16進制)" j9 ]; a. f9 T6 |% `: ?5 L
. f/ R( Z" v+ s7 P! B
3 Z: O  |& M  i0 @# [$ @, \  M5 `/ i
void debug_showbin( const char *dbuf, int n, const char *name, const char *end )  F; Y# z" y& G5 x% _
{' o6 E& a) @+ Q2 g+ H* o& B
      int i;' Y, u) G3 V8 L2 M+ f9 }2 i# e4 ^4 O
      ; j) i& D) R: u/ K! A0 x
      printf( "%s ==> %d bytes: ", name, n );* _0 W4 ^  Q& l3 N) i/ L
, o& Y' O6 r6 p9 ~" |& N% W( z
      for( i=0; i<n; i++ ) 2 ~( Q+ F( L' X2 `
             printf( "(0x%x)", (unsigned char)dbuf );
7 B+ s0 X( j5 g: n+ o& r' C
3 x2 a8 P' r% I8 ]% g8 w       printf( "%s", end );  y+ s! e' `1 [- D( X4 a( }; w
}" x, Z0 [" m  x6 r

1 I8 R$ G1 b: f. P* \; Z: S* r2 ?* I0 C  m3 a) O6 s4 N% C

  `, S6 v$ ?( i
2 @* ^/ l) H0 K$ z3. debug_showip* \2 `1 {3 T1 W; r2 G9 p+ F8 \& e7 B
用來顯示sockaddr_in類型數據中的IP和Port
+ G# i- c3 \/ n2 A9 P' h
' E! X+ t# @/ J1 H9 U7 w8 _& G% w# r; ]+ x  y# d
void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )
8 h: a' s) y  M  Q6 h3 {/ J5 R; [{
; W, j( r: v, F       printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end
# F! w" ^8 u/ u% h! n8 h5 ?$ |% J
);
. L. ?, D* A& o1 n0 h}8 i/ J  R* E! L2 Y3 }
4 |) p  M& h7 x4 u

8 Q) Z  U& u( m. J, i3 t3 O- {: m' g
( T1 m! ?+ s3 ^; \* w
五、測試- Z% I6 Q! |0 O3 o7 d3 M# }
===================
: U4 w/ T9 O# E下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-8-9 06:23 , Processed in 0.034617 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表