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

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

[复制链接]
发表于 2005-2-5 20:02:12 | 显示全部楼层 |阅读模式
  作者: 趙氏軟體(http://chiosoft.51.net)
) M$ b% Q/ L% J8 L7 _E-mail: chiosoft@163.net
' O2 m* {9 w7 B; ?8 j※轉貼請注明出處※* H& i* ^( P, `0 N+ J# M

; l, P! i6 S+ V, u! v2 S9 H- z
" A( K7 [1 ^2 ~本文以QQ為對像,教你如何寫一個SOCK5 PROXY' k' K% ^: E# v' r6 d
' Z& O2 `! w3 `  ]4 l" C
一、準備工作" q6 b4 i4 ~# z* T' d6 ~" Q1 G
===================
% k; p2 t, t0 e' ]0 L1.編譯器:
  C. M. E7 N+ @為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行.
2 r8 Y, _7 f8 F0 ~7 Y
8 b- x1 V8 t* {2.程序運行環境:$ F' u. W" ?$ j
可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.  [/ q( d2 K6 G8 M) a

8 f7 {/ x0 V( v% i, i3 r3.如何編譯:
# N  H2 H: p2 B4 {在LINUX下用 gcc mysock5.c -o mysock57 z: {/ u* {) m" M4 T0 m. U
在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock320 a) ~4 V: @9 i2 i8 o& Z# S
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.0 p7 ^, ]' h) F) X& _4 L* i% z

( z( e2 A( o* ~; x" R- D+ r8 z' v$ E5 c0 R- B6 L2 z+ h0 ~+ ^
二、基本思路
3 }9 c4 d6 p. d# h7 j& u===================
( j' R! U1 T" [* K0 k$ mProxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.
" b  r3 e% w9 y  K
+ W! M& S  [2 d  y/ q1.握手過程" X! b2 a) h, p: ]* E
客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.5 s3 p5 o5 ^/ ?+ \8 ^* Y
! j+ {: t& d% a# E* n! _
2.資料傳輸
9 ?' ?' T% N4 Z9 _- UQQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.
( m& \  M- w2 \% ?2 l2 W- w* o
+ q$ f. l# O: O- K. J這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動.( `- e6 K& f, b& ?
& V) b4 @" I( V+ _

# i0 j; t+ j& D# H  B+ `三、程序框架- B( A( r. v5 x$ q+ W2 O- p
===================8 Y. }7 n8 e5 ?9 V+ t: ~! L2 a" I) T/ O
先看看源代碼mysock5.c+ c* I5 l1 z% T* Q' f! a

0 x+ N& B- I7 |; U2 t8 g: T2 r2 i/ L) h
#include <stdio.h>, [3 w; @# M) U1 O, x( J/ y
#include <string.h>; a2 @0 O( Y6 a7 d3 |/ d$ @5 y
#include <stdlib.h>5 H1 J. W5 s; `7 y; W0 S* L. W& }
#include <unistd.h>, Z$ x5 F6 K6 N+ e" I5 L
6 x. K; t" M0 s! V- m) r
//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明
! e2 @) P  i7 O) T8 b" S#ifdef _WIN32
' e5 k- X: m7 d8 W#include <winsock2.h>
/ a, a( b. [4 Q; f. ~# h#include <wininet.h>7 X9 [- p! z( D/ |- s) r. g
#else
: u6 O" l6 w5 y" I" V6 D#include <sys/socket.h>
- Q$ X: L; {  f" f/ A#include <arpa/inet.h>* @  m+ f6 `6 v3 i5 X
#include <netdb.h>
" v. A( t' e( ]6 j1 P2 w& T% Q#endif: {, G8 _' R* T+ w

9 q0 x# c$ [6 i//定義一段緩衝區
$ b4 C& m4 f5 h, v#define       BUFSZ       65535
* y. ^8 N) m; Q( @char buf[ BUFSZ ];
" @8 P! k7 Z' K$ r
' j" s+ z- s& D! \) ]' nint main(int argc, char** argv) 4 i$ V3 W+ G9 f* B
{5 m0 N. Z0 R6 X
      //這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號
3 g4 Q' I; c0 i) \$ h; c5 k( x9 Q       short tcp_proxy_port=8888, udp_proxy_port=8811;
+ O* R9 C" C( e& j& }5 P5 b6 b- B+ X       char udp_proxy_ip[]="127.0.0.1";# U0 v0 H. L) h( D) t5 T9 V2 q6 f6 D
      short clt_udp_port;
) w. \5 |- Y+ w" \1 ?7 M. c+ _3 u2 Z% u
      //在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,3 p* p" L# r, `5 P
      //WSA是Windows Socket API的意思,本文使用WinSock 2.0版本
4 `# ]6 E- E8 W; P/ F& ?       //在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏
  f4 b" T8 F# e       //我們需要自己指定
$ }) j+ @+ y0 P' W       #ifdef _WIN322 r2 ~! X9 |) k6 |: c
      WSADATA WSAData;$ u0 W! x4 w' j+ E6 l' ]
      if( WSAStartup(0x0110, &WSAData) ) {( d" I& E- d" O" I6 ]
      //if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {
' h# n4 _1 D3 K9 b8 G+ G5 l( M& N  m              p_error("WSA error");8 x% C! ]$ ?( x0 g# W
             exit(-1);! U/ |4 G5 J9 ?; B2 M
      }. t& x; m" x7 K- B. `6 n
      #endif
, S- L( ~7 x' m& z- A* [4 N& ?# }3 @- z9 J' T- Y$ |

$ O* {( k5 H( {       //啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)$ K1 S1 d7 d2 T9 a  D" b! T
      Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );
+ l8 s6 `. W" x; R- b- \, |( M7 `  |7 u/ g+ J9 N- z+ s9 ~- p7 F
      //握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
) P7 C8 i4 j9 ?; k* q       Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );7 Z: t. Y  R; X! w
      
8 i9 ?* m3 V& `* e4 v       return 0;
2 f5 T' e; j6 z}
) S. C& U8 d+ J" s. [/ s! Y5 ]* S- p4 t& v. Q/ e
5 q! b" p! O  e* N: F5 E

1 }6 F0 q6 |% J! T0 b9 J8 {2 n& |2 K9 `& L! h7 O6 O$ k
8 x" k/ M/ Y' Q: ?! _/ a
四、工具函數
0 G! |4 P5 E. u$ R: r===================
/ d" [8 Q# p, K4 L1 i" q正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.: k8 d6 R( |. ]* g# F

, J# p% ^1 j0 g2 h& ^$ r1. p_error- g* B4 E% o5 i/ `6 a/ Z6 d
這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略2 |4 x. N" G9 O% @7 [, [8 P
& |  _2 U) E4 a9 G7 Y" b" o9 A# v1 l

( w5 Y- p. o% I& Pvoid p_error( const char *err_msg )+ _3 W$ ^7 p) W1 G5 S( L
{3 [! P2 K, t, J6 `2 c; f
      printf( "ERR=>%s\n", err_msg );/ P  u; j) ^6 w4 }
}
) m1 G+ E4 o7 C4 Q6 U8 C$ l
0 }# _* L# n* w/ }1 q7 [% u
9 b' c# ?/ v/ U7 l) g
4 S; ^! J' \0 ~, g$ d" d3 d9 W+ G. q$ b/ {# B. e1 u6 Z6 I# Y$ J2 E  m
2. debug_showbin/ D  _1 g0 U( U6 ?( ~/ A
用來輸出一段數據的內容(16進制)
5 u1 I/ H* z  `( `6 d6 Q
; g- q; t. X- c3 ]) H3 T+ b8 O" f7 ?4 i2 ~; S9 z2 Y2 p/ f
void debug_showbin( const char *dbuf, int n, const char *name, const char *end )
% M" E! K5 B7 v( h9 N{
: G9 n) i! m9 b% H% |1 u- A! m( }       int i;2 W9 f7 \1 `4 U# B  s
      # g5 I: y$ L. j1 Q9 j. b$ ]) C
      printf( "%s ==> %d bytes: ", name, n );8 I5 B5 j0 [; k6 L  r6 G, R
. W% K7 i+ s: y
      for( i=0; i<n; i++ )
+ K) s0 C( I' t5 A              printf( "(0x%x)", (unsigned char)dbuf );
% v2 O# b2 P+ C- x4 J
5 d: F; b' o3 k+ W% u! {       printf( "%s", end );
( @0 x# }$ d, N}* {+ V% ~/ ^: M! A/ V
% S. s( N* V, p; q
) m8 B9 ?# k+ q3 Z1 `4 E

) k9 V; u  s) ^. T" @! A+ D
+ ~, o4 F' B1 g4 f3. debug_showip
/ ~( s& R6 S# |  Z4 ~5 [$ F  n5 ?. t用來顯示sockaddr_in類型數據中的IP和Port2 y% z) {& \) o8 l

9 F; o$ i. M9 z7 I* g/ v: V, |8 f" K2 K& G* l  f( l
void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )  H. k' R$ X1 L( n+ d4 p5 v
{4 D' G/ N- p' d2 b) B
      printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end
& w% V: g" ?$ f3 a1 {  \; h, e+ c0 e9 N
);
& J2 c( A; W( s. u3 W) B9 v}
! T. F3 r4 F3 R. m$ _# v, j( j2 U) }* F- U6 \: I
7 q! h' a! n4 p, J
: P" `/ \0 f  N% V$ o
4 ^. H% C. E  t: O
五、測試( W* @5 J5 |; W1 x
===================
, N0 x8 f, D+ I下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 10:27 , Processed in 0.019379 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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