找回密码
 注册
查看: 6192|回复: 0

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

[复制链接]
发表于 2005-2-5 20:02:12 | 显示全部楼层 |阅读模式
  作者: 趙氏軟體(http://chiosoft.51.net)
5 A+ ]  G2 o# Z" r2 g6 e; i/ cE-mail: chiosoft@163.net) C* @" X, Y- n) C% |2 o
※轉貼請注明出處※' K: Z5 [! y) j( ^2 K

) t- M4 c& r% l9 S+ B5 G0 c! P% |' K
本文以QQ為對像,教你如何寫一個SOCK5 PROXY
1 F' f7 A1 |, S+ }5 Q" m& E8 x3 x* {3 ^% c8 F
一、準備工作
4 q$ [4 n0 X2 M6 Y===================
- a& [" T8 ?( e) J* _. m3 g$ r6 G1.編譯器:8 L* i" {2 k& ?
為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行., R, n# h) y- q6 ?" X- J
) z. k/ A9 j4 g9 W& }
2.程序運行環境:
- T- a1 c0 ?. m1 C$ t, M可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.5 J. s" w# a; q

: {* V3 o0 H6 F. y) m3.如何編譯:
. }  F  w* Y: ~  i0 f; A" F在LINUX下用 gcc mysock5.c -o mysock5
; G% z. V( G# R. M' m- {4 C在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock32! y2 _% k0 V# C: m+ R
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.
: u2 W2 T% g8 U3 {+ P9 E8 I' h  e4 X
7 W3 Y7 ~' u- F/ f) t! U9 @
二、基本思路
: J/ J5 w& h9 p- d4 o===================
' ~" v! a3 S9 o! Q8 VProxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.
7 t2 f& Y/ U8 c" ^# \/ r' s8 L
8 w3 o  A3 W# S+ m1.握手過程
; ]3 d, j6 K' ]8 R: L客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.
. k8 m% [" }  B. F% {: ^& H7 {! F) Y3 T! q8 j8 \  W  d
2.資料傳輸
/ t/ E3 S. i/ p/ D3 wQQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.
5 `! W& `. _, S/ g: Q6 |$ d
6 U8 {5 u+ F& W) K; p! L這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動.
' }+ ^/ E- C3 i6 |- z  w8 i) Y  V/ S' Z
. o# G% `1 Z/ G4 g, L% M" U) q
三、程序框架/ @6 w, M& X) e6 H8 }
===================9 b7 u- n- r* ]7 o3 m9 v6 i' i
先看看源代碼mysock5.c$ }, r2 [9 @! w- Z: S
1 J/ Z/ n7 I/ ?( ~; ~

2 V# \' E2 b6 M" @1 G#include <stdio.h>
# |' ^& U& A- u. X8 s# F/ X5 ^#include <string.h>
$ W& D7 y6 a( m) `# r; Y+ b2 Y. T#include <stdlib.h>
! h( f% s: r1 z; X7 Q- a3 a8 [) k#include <unistd.h>
5 Z4 g7 E2 D* k4 E: i/ p5 _5 w6 w9 @' P0 ^& T6 F. r0 D; b$ L4 r
//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明
  X' V- B3 h3 B0 G#ifdef _WIN32
" N+ x: b  }; U" h#include <winsock2.h>9 C4 n( E" H3 v& P) E! g5 N7 c% {
#include <wininet.h>
9 L. P; `1 {- q2 C$ e' F8 @; p, ?#else: G" l% ?% |: s% X; Z0 I! d7 A$ {
#include <sys/socket.h>
7 R# u$ a/ t9 n1 U#include <arpa/inet.h>$ f! B. C+ P) E( G- H) d: B& r0 x
#include <netdb.h>
, L; q( {, d5 r, d( G* f#endif
4 ^! `7 ^7 Q$ t8 P6 r5 C# U9 x2 {4 M* n" ~
//定義一段緩衝區) w2 j- G. U. L! w3 y9 N
#define       BUFSZ       65535& h' I2 ]8 x) G9 e; K
char buf[ BUFSZ ];
9 Z& r7 N; Y5 E# w9 j- f8 J) I. Q5 j
int main(int argc, char** argv)
* J, X0 b" l8 e% }6 d{* H2 `3 j; u4 c& d
      //這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號8 ^3 {) g+ X' X; V/ a0 d. w
      short tcp_proxy_port=8888, udp_proxy_port=8811;" \$ v3 e  V1 W) w: Z. c/ i8 Q
      char udp_proxy_ip[]="127.0.0.1";+ w: C3 d4 e& W4 U6 a9 L1 ?( |
      short clt_udp_port;% b7 j) q- [/ ^' {4 a' B. J( u+ L3 x* T
. g0 x& Z1 F. b3 a
      //在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,
( F! N- ]7 u' L6 H( M       //WSA是Windows Socket API的意思,本文使用WinSock 2.0版本
  m  ]0 [7 ?( ^4 C       //在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏
1 c% v! s$ g- }* K) }  j       //我們需要自己指定
/ f7 E0 U! m! m- P% `       #ifdef _WIN32
' y; a$ _) C2 F& @8 a1 Q       WSADATA WSAData;
: L0 V4 \$ ]' f# N! V+ K       if( WSAStartup(0x0110, &WSAData) ) {
  }1 F/ S. n3 ]! M( N4 i: c       //if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {
+ Z& K8 t2 H2 r' p: m- O              p_error("WSA error");
! U' V+ |" i! `& O/ Q+ i* x              exit(-1);
$ M. T6 I2 G; L5 T       }/ `3 J) V( Y9 T
      #endif" n5 Q3 @5 b( k( O0 h/ S9 D
% @; i1 b# D  {! x) l0 M
9 s, K; d2 m" Q. P% l  d
      //啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)
: [- B& `! P- c3 I' ~* T9 l, J       Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );
1 {, a( G% I5 [2 d2 }' d
8 T/ ~) W) k2 w/ l% W4 S' l       //握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
. v6 B) g, x& O* T" N" c       Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );
  a# _" [! x: V( I8 M       7 h8 y; v" z1 Y) G
      return 0;
& }7 ]8 }  \7 c# w}- P  B0 |) A' q, w9 g3 ]
; E6 R7 w$ t  B( x

( k$ k4 u, A: c" r  k( n; E) O2 |' H7 w
5 g! D8 J1 @( T5 ~

5 a- {" e1 E' l8 j- q四、工具函數
' Y! I- ]' O# d7 B, v, O8 H) n5 |; K===================
2 W2 [9 K7 j9 W/ D2 M! ^正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.9 O+ f3 f) o+ @; K0 r  w  T2 `- P8 I
1 |! K( g" J0 j6 F. f
1. p_error
. k; }: z: j# e) R% b: }& R這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略8 j1 F/ q' s3 k4 M# U/ \
& W& b4 H9 W$ I. b% g; O

" [5 r+ r% |; C2 ^void p_error( const char *err_msg )3 D4 C, Q% @& [1 ?  v4 N7 q! j8 n# i
{/ q' l4 F/ ^) X1 _- n2 K2 ~! T
      printf( "ERR=>%s\n", err_msg );
7 Z/ t2 q% g7 \+ L}
7 Y7 q+ y9 j" D
& t+ }5 L8 i8 v1 V- C9 x5 q
! Q+ @0 q, W& Z1 W' M3 R5 \* L2 h5 A7 h5 s: U+ H. C& B$ n8 w
0 ]$ t+ ~3 j% B1 k- a' S
2. debug_showbin
% y9 D5 @( X. b( S用來輸出一段數據的內容(16進制)! q# T' n" {" Y( q4 q3 Q+ _

  L6 Q: V8 A- ~2 K; k7 h. H) |: y* G) C
void debug_showbin( const char *dbuf, int n, const char *name, const char *end ); q. p1 S. Z4 h/ P1 z
{
4 Q  }& o: v; Y. x$ _: p       int i;
$ P' P( G/ T4 t* w$ t9 h6 c       
9 S" Z( n& T& b0 }" z  y$ ~8 ~' C       printf( "%s ==> %d bytes: ", name, n );
& K5 l* P3 T: p& @( m1 o3 ^  N' ^
; U3 E6 F& Q' y5 M# s; a       for( i=0; i<n; i++ ) ' q+ K9 S- D# W2 ^
             printf( "(0x%x)", (unsigned char)dbuf );+ K  N2 \- P" |# ~% H

& q& ~7 v2 s- V6 T/ f       printf( "%s", end );; E6 f9 Q& _6 ^+ W; }5 B) J
}
7 p1 Q' g( b1 D. x; a$ Z
* g) }5 E$ f9 l
+ f9 r% C5 n9 A  q: R) g3 _4 g! R" n' N! e: K
( v! V8 `$ o7 _! ^
3. debug_showip
# E7 y. E& c' b! u: }4 ], o0 j用來顯示sockaddr_in類型數據中的IP和Port1 d4 W$ w9 z& m1 p

* V: x7 y8 g0 `* k. D+ D; ?( q2 p/ l$ X' y: I% F: R3 e8 I
void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )* X# |$ F" Q9 `6 l5 U# s5 i
{* J" i& R, K3 ?# c
      printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end 6 L6 q$ D5 h) P# u$ a5 W6 e" v

8 ^3 S3 Y: q3 D) _% k);; P- Y9 E3 `& j
}
; O7 W' b5 V- `  D0 |% x1 i: @1 I; l( P. j3 \8 n6 _. ]* _" a" B3 l
- c- A! [: Z5 C% C+ P( F, w! f
; a2 `) u9 H1 v! m: H

+ S1 q  ?* K9 E+ Z2 F2 Q9 ]五、測試
4 N7 v, J: |$ G% ?+ B===================% O2 w- F; Y0 G
下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 04:39 , Processed in 0.016164 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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