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

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

[复制链接]
发表于 2005-2-5 20:02:12 | 显示全部楼层 |阅读模式
  作者: 趙氏軟體(http://chiosoft.51.net)/ e8 K; [8 J. h" i' M
E-mail: chiosoft@163.net" m- y) ^; l3 V0 K- p) ^
※轉貼請注明出處※* t, I, x/ a: w# d( J" C

; X  q7 a& K5 P
  C) Q  q0 c! T3 V本文以QQ為對像,教你如何寫一個SOCK5 PROXY0 s% k/ }+ Y+ Z' `3 J0 x; {$ e

8 t$ e3 T- e6 O9 i! u一、準備工作8 V: G% w# @) v* [
===================
/ G# v; n  Y6 Z1.編譯器:, G: \4 w+ ]: u% K2 ^3 \7 [
為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行.
3 F. K! j( W% J, `4 I# z% S& c! O8 m* a1 [3 e2 S) _+ }
2.程序運行環境:* _' s5 o  K7 S
可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.
; y- [; [' h( a5 e' i; L
/ d6 e  `) [7 v% j1 h& d3.如何編譯:7 u% H  ]$ ]8 B% v- P
在LINUX下用 gcc mysock5.c -o mysock5
- H) Y1 e! |+ q8 ?, W* q% r* a在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock326 S. u7 F8 b6 H; W
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.  Q# V! B. C3 f
" Y. p. x7 r& B$ Z- A; J

; X/ ?1 w9 e+ x, e' P' y二、基本思路% D- s& M% p7 k# ?) r: e
===================
) L# I* _# Y" h; I2 u8 G8 W$ RProxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.! T9 p) B* A4 H& c$ e$ ]. O& s
, O% }& T5 o& e* j* U5 r# T* c2 ]
1.握手過程
# O8 `/ f( ^$ B客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.
, p2 M! {8 Y0 j8 O' a8 p- {. n: l! D9 c6 n1 P3 {# f+ ?1 J& |
2.資料傳輸
( z- A. B3 L3 w7 @QQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.) r8 s  c. m" M: M( k2 B/ U

, r4 r# U2 ?" O這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動." I. G; W) U# s, o5 t! z
3 d1 A3 q7 X: ?% w4 L

5 O5 U( i. ~! {8 M: d! ^三、程序框架
0 q6 \: _7 |6 L' z* i  M===================
4 P! c, ?( t, D1 t2 |- B! v先看看源代碼mysock5.c' z8 T( ~7 f5 u' i

# |& {# L" y1 R% L$ F  K# m5 `# u1 b
#include <stdio.h>
- \; u/ }$ ~$ C' |9 c+ Q3 z#include <string.h>
& o# n( w: r. b; A2 j' }0 I#include <stdlib.h>
7 N2 {( [: E% `, o#include <unistd.h>
/ u5 s+ n$ w! v3 n- L3 {9 e8 W! L' t- \2 Z) ^5 H& X# ?/ w# w  p
//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明* n' U9 X3 O% Z. E$ z/ P4 p2 m
#ifdef _WIN32
% ]5 N9 [# F6 t* F1 B#include <winsock2.h>
) s* l5 i: T  B/ s( X$ f3 b9 m#include <wininet.h>
' u  S& e8 g9 V' Z6 y9 R  i) N4 U#else
( ^+ x. X  N% m7 ]#include <sys/socket.h>
4 D7 I( \+ b3 l; u3 @! m#include <arpa/inet.h>
5 r$ E1 }0 X6 d#include <netdb.h>
+ G7 M3 g' Y& x; ~#endif
$ M, c5 w  J& ~+ Q
3 j6 a$ F: n& P" w& r0 P2 ]' |//定義一段緩衝區
4 q* ?) j' d. M#define       BUFSZ       655357 ^( @* d! S$ H- Z' Z# J7 \, C) [
char buf[ BUFSZ ];( k& H! q3 p. }4 C3 d- ~2 M  b: I
/ {2 A* p6 M" m
int main(int argc, char** argv) 7 A* ]# u" M$ L* i- u% x
{( d1 X2 K5 p6 O- D2 h  u
      //這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號( G2 ~( j7 B2 _$ D& P2 |' R7 A! Y0 w
      short tcp_proxy_port=8888, udp_proxy_port=8811;9 |7 [  O5 X  g2 u
      char udp_proxy_ip[]="127.0.0.1";
2 q/ ]: u& h; L* \7 L       short clt_udp_port;
" h+ S4 R9 S" i( G& q: ]  N- a3 g3 H$ o  T! i0 g. K$ v8 @. s
      //在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,
& j7 G4 j$ M) R5 P( K* Y4 F- p. y& w( ^       //WSA是Windows Socket API的意思,本文使用WinSock 2.0版本
  |1 \2 U& j& g9 h       //在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏
* _8 w9 Q+ r+ e' V2 a       //我們需要自己指定
4 ~& |+ Z% U) r* C% E$ ~       #ifdef _WIN325 B. }) J+ L' P4 D$ ]
      WSADATA WSAData;6 }- b3 f/ T0 o3 w7 J' }. a
      if( WSAStartup(0x0110, &WSAData) ) {4 W  n$ ?% K3 H1 s
      //if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {, L1 Q* g$ _6 p. r' \" m
             p_error("WSA error");
0 Q' P; _5 C* ?+ Q4 `* D              exit(-1);! ]# f" ?; m7 o
      }* G6 S, S8 o2 {& X& P2 n3 G% G$ p
      #endif0 C5 i5 }3 A- \$ T5 F0 X
4 _/ U* Q, f' a  Y! {3 A( Y1 R

; i, n, P3 C: S+ H3 O       //啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)
% f7 ^0 S+ j* J, ?       Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );
+ D/ r9 w$ F5 U) B' d) Z" t# ?
0 t$ G3 B; c! @1 `       //握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
9 R6 ]3 J1 [2 Z7 j3 g       Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );3 n( D$ o2 ^# v* T- u
      7 F: Z3 A( Q( }6 E" m, k
      return 0;2 h* R/ Q. {2 c
}
7 \' |% e* E5 u" K6 F7 Y, ]2 P  |* b$ {

: a& A' Q; l& p2 @2 y
% x9 s; C- j% S
" l" v: z# ^( l7 c: {* w; T
9 J- J! p9 {$ |# M- d四、工具函數/ A' o" p0 l+ q. Q8 v7 H# q
===================. ^2 q7 @% I  Q, \# E+ E" m9 k4 M
正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.
, j" ]  u* E' E" z( z
; f5 t5 N. |* X7 E5 i( I8 ^1. p_error% o; z( h; F! y& Q
這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略/ M$ I+ K  e  a" p7 f' M6 k
3 g; l) l9 ]. _3 ~$ O/ X6 A  J) |

. i5 c! h3 _' [; h3 Gvoid p_error( const char *err_msg ); m# `5 ~& i9 a/ F$ b* C* r
{) M6 d4 H, R9 s
      printf( "ERR=>%s\n", err_msg );
8 P5 V3 S+ C( Q* P}
& y0 ]: C9 P* u+ b3 K3 ]2 Z/ k! T( a4 @% a0 A, d

& ], V- ?1 f/ [' C; b+ r0 `$ @% f3 F9 }3 j/ n  m# i
) t6 O% z2 H& g& n- B) V8 P
2. debug_showbin
; S3 l  }  W# T0 E8 ?用來輸出一段數據的內容(16進制)
/ Q  W! ^+ U# Z0 y+ Q, T- Z$ J1 J/ Q& z2 o2 ~3 ~
! b( ~6 b2 G, X6 A
void debug_showbin( const char *dbuf, int n, const char *name, const char *end )
- w4 g1 l2 l3 C! C7 T2 B) i: r{( P1 `$ E' C/ |# {) u+ C' y4 G
      int i;6 d  Z6 x, d; ]+ J, w; Q5 @
      
) @, q- _; [2 A: l       printf( "%s ==> %d bytes: ", name, n );
, I5 \) ~) j+ x( n: E5 _2 P4 y3 Q7 U, q3 d6 S$ {
      for( i=0; i<n; i++ )
9 k) {# k; q! W6 q1 {0 [& [7 h              printf( "(0x%x)", (unsigned char)dbuf );
' B+ O$ a# G+ R3 X- A" r' c# K
      printf( "%s", end );
2 k0 o* h/ v) a4 ]/ H1 d}
! i! V- `! {! K: C
& Z9 U! M' D; h7 |$ G& K9 R
$ k- ]' x- `' L! w
. ~9 y! N' S* P1 h& M$ B: P, e
: _- f0 R8 L7 G* Q; A3. debug_showip8 v$ i1 N) _& E9 F' T
用來顯示sockaddr_in類型數據中的IP和Port3 i) I6 k7 `, M- [1 I
5 k5 J% H. ?# q% r
. x+ ?- E. S( [! C& @) l$ o# p% B
void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )* b/ K& s% l6 C" w) ^
{
8 f( P% L* z: q. i1 ^       printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end " M. ~" p: M9 O1 p) x

" _; O9 j: t; v);
3 s" x$ Y: C0 ]}# a% }# {, S6 Q) }" y

0 L: B  B. m: S7 m+ y  U) R
, X8 q# P" h7 v6 r, ]
- L/ W# {9 n8 v0 y7 n  }4 ~5 B! A; m' B0 I9 N$ m
五、測試6 b6 ]6 \& ]: H
===================
7 S* w- L- `  ]. a  I6 X/ J5 U: b下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 13:32 , Processed in 0.015408 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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