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

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

[复制链接]
发表于 2005-2-5 20:02:12 | 显示全部楼层 |阅读模式
  作者: 趙氏軟體(http://chiosoft.51.net)8 v2 v/ z- y# H& J* {+ |2 Q
E-mail: chiosoft@163.net
6 x( \9 B9 |* ^: ~+ }※轉貼請注明出處※
& m& s4 B8 y) K) u/ R
( J- m- w4 u# u& e" ~' }9 x$ D+ o5 o+ h% y* e5 W
本文以QQ為對像,教你如何寫一個SOCK5 PROXY/ h6 ^3 c: L! |. D5 B6 |

+ G8 o* Q- Q1 d: r/ f$ U$ }4 k. m3 J一、準備工作
9 ^0 n0 Y; g" A  V$ F8 O' j, ~8 W===================: ^: Z( J3 |) u3 b" ~
1.編譯器:
; P; y: F0 t3 L; p& j7 {6 V) A! Y為提高程序的可移植性和避免MS秋後算帳,本文將使用GCC作為編譯器,Win32版的GCC可到www.mingw.org下載,或者用Dev-C++自帶的GCC也行.* Z8 @" z6 Y  M2 z+ N
$ x$ F9 E; F2 K/ q
2.程序運行環境:. B6 T+ u, I" t1 w: M: w( {  \
可在Windows 2000/XP和LINUX下運行,Win9x系統沒試過,不知行不行.
% P& o+ u( z4 ^/ ?/ X* P8 V, w" v' C; W
3.如何編譯:
4 Z0 O! u2 N3 o$ W1 e  Q* D. l在LINUX下用 gcc mysock5.c -o mysock5
2 S4 Y. V& b6 O在Win32下用 gcc mysock5.c -o mysock5.exe -lwsock325 \* z  Z* T  z4 q  X5 v* M+ o
其中一定要加參數-lwsock32來指明使用Windows Socket相關的庫,否則連結時會出錯,在Linux下編譯不用.
) G. X0 C) b' z
& u/ m! g$ z! L* a7 z8 u& O9 J! ?/ L! r& H
二、基本思路. R6 m$ R7 c: N
===================
, V9 O$ Z" n& p- {7 a' O0 FProxy是什麼?我想不用我多說吧,還是馬上進入正題吧.SOCK5是一種Proxy協議,支持TCP和UDP協議,也是QQ唯一支持的Proxy類型,詳情可參閱rfc1928.txt.
* x0 ]- l  s2 }; \
( P# z& M  W0 V/ s) A1.握手過程
% r! v/ _3 l+ e/ F6 }' h客戶程序要使用PROXY服務,首先要跟PROXY SERVER進行握手,這個過程是基於TCP/IP協議.* j5 [, M) }- I; k8 H, f
3 j  D1 X! L& P+ k! b7 K0 l( ?9 u
2.資料傳輸
( y( E/ a# _6 e- o/ i! @QQ是使用UDP來傳送資料的,所以當QQ和SOCK5 PROXY握手成功後,就會轉向連接一個UDP SOCKET,也就是說我們這個程序首先要建立一個TCP SOCKET和QQ進行握手,然後再要建立一個UDP SOCKET來進行數據中轉,實現代理服務的功能.: g, G9 _4 k$ v

& w# I$ Q0 R# Z( v% Z這是一個最簡單的PROXY,只支持一個用戶連接一次,連接中止後需退出重新啟動.
2 R2 o* O) p! S: e9 W5 w0 ?2 }4 P4 Q7 a) Y

4 t4 v- s  \8 j4 D三、程序框架" h' G( t+ d4 v8 v
===================* l' o! |+ R4 T: B# d
先看看源代碼mysock5.c! h. D5 W; q* a( o
! _4 X0 _2 c1 ~% t6 z0 v( f

% B/ }! z$ J0 B' W/ Y9 _$ T#include <stdio.h>, L2 T& \6 X+ Z& S7 a2 ^, e+ G
#include <string.h>+ m4 l& }/ a8 u6 I$ W5 I- Q) Z& W
#include <stdlib.h>
/ B4 A* X. r' S+ Q5 u& M& {#include <unistd.h>
- H6 w8 X( h) b5 g: @/ Y+ J8 Q. h( p/ U/ w: w, z
//Windows和LINUX系統所提供的Socket API不一樣,需要分別聲明3 g4 j8 c% L3 p: _
#ifdef _WIN32: Y6 o1 ^: w% }, l7 F
#include <winsock2.h>4 h; ^8 j1 l0 c4 k: m
#include <wininet.h>4 A2 S: m. h7 v* S" Z( P; [, C
#else  _$ B9 W- Z! |2 l0 \- {
#include <sys/socket.h>+ Y$ u$ U, H7 L! Z
#include <arpa/inet.h>$ a1 ]) B: J+ O( k
#include <netdb.h>
  D, {  N7 B, i  p2 Z+ |# w' Y% l  X4 n! N#endif
3 L% y7 `+ I! v( s/ W' y  M+ O" u3 a/ M5 N4 q" r
//定義一段緩衝區! X) q$ u: b0 V7 @7 x/ Q" f6 }( {
#define       BUFSZ       65535
( o/ ]  O. @, [% N% x$ z" hchar buf[ BUFSZ ];6 s3 W' m; V5 d( K" W  W
+ o! I. r) I, s2 X
int main(int argc, char** argv) ) o+ R6 Y. H2 {( m3 T& l" Q5 A
{
3 _: V2 F6 c1 Y6 t0 F       //這是Server的資料,包括IP地址以及用作TCP和UDP連接的端口號
% O0 r" ~+ D3 M       short tcp_proxy_port=8888, udp_proxy_port=8811;
, Z% v  Q# @. V7 I7 q! [4 L       char udp_proxy_ip[]="127.0.0.1";
. E4 A" T( o4 o0 {' w& \+ g& A  E       short clt_udp_port;$ u3 Q/ c! A! f8 M/ I: N) c1 {- E: s
* F! Q0 G) [( [5 f' \
      //在Windows系統下,使用網絡前要先用WSAStartup()來進行初始化,
1 F4 G' ^9 ]7 }       //WSA是Windows Socket API的意思,本文使用WinSock 2.0版本+ w4 X- f# a8 `
      //在VC中可以用WINSOCK_VERSION來指定版本,不過GCC FOR WIN32沒有定義這個宏
8 r$ G6 C& C6 P# Z+ L       //我們需要自己指定* w& v+ o4 V' R
      #ifdef _WIN32+ r7 g5 J: ^, H, t, }
      WSADATA WSAData;" f# `6 w# s. ]; R* b
      if( WSAStartup(0x0110, &WSAData) ) {7 T" U# O1 d' c+ L
      //if( WSAStartup(WINSOCK_VERSION, &WSAData) ) {( e6 n" U% U6 h  o
             p_error("WSA error");
0 k9 U" M3 J0 y- S              exit(-1);0 Q# t& Y4 i6 X" ^- k
      }
6 p9 F0 t% ^; n       #endif
" K' {& `: X& c# O! [
$ o7 z0 y" E6 v+ d% A+ D" ~1 Z; O5 ^. m8 L6 c3 \$ h/ X* s
      //啟動一個TCP SOCKET,用來和QQ進行握手,並記錄QQ用來和我們溝通的UDP端口號(clt_udp_port)
$ N' R+ K/ {: |* V: H) [       Launch_TCP( tcp_proxy_port, udp_proxy_ip, udp_proxy_port, &clt_udp_port );% F' G, G  V/ O. O

7 f1 C& }% d; c1 \       //握手成功後,啟動一個UDP SOCKET,用作數據傳輸,是真正起PROXY作用的部份
9 ~# m) K6 f* M- R  C2 [3 n       Launch_UDP( udp_proxy_port, udp_proxy_ip, clt_udp_port );
1 M* R0 ?& F& U9 Q6 g       " Z$ h; k. O" h8 Z& r) f) A; s
      return 0;; D$ S; w6 [3 A- u: B6 y
}
$ v# l+ {; g$ _8 n* c5 k: `* h0 v+ ?3 t
7 Q' W0 p1 ]! R* ?4 M
% s# a  e5 ~, @, r2 b, T

) r% k  A' B5 Q! V1 q+ J0 `( \6 T$ W9 m9 G, Q5 ^% f# M
四、工具函數  d% N6 V- x% h& K' B$ O1 B# r
===================
2 I5 |' }3 G# U: Q. y- \$ v正所謂工欲善其事,必先利其器,好的程序當然不能缺乏好的工具函數,有了這些函數,進行調試就更加方便了.
0 i! {3 \; }, f% V* H
" _$ W; o! M# k/ e, V3 j1. p_error
( K2 X! x9 n8 E% O* f) e+ ^, F這是一個處理錯誤信息的函數,把所有的錯誤信息集中用一個函數來處理是一個好習慣,目前我們直接用printf()將其輸出,當然也可以輸出到文件或者干脆把它忽略# ~) K6 n0 e$ e. L0 A

3 a# S% B0 v7 f1 y9 ?( l+ i5 y$ E1 k3 {' c
void p_error( const char *err_msg )
" [5 f- z2 C8 k& t! M{
# j8 L. d. E/ |: w+ m. }       printf( "ERR=>%s\n", err_msg );
- }/ t$ c* k& a0 H1 K7 i}
6 R1 H6 q( o# {
  x. u  M( Y4 U" }1 B9 Z7 b
" O# O6 k% @; f3 y6 \, C7 M8 Z; p8 q

! \: G) u: @( b; k* l2. debug_showbin
0 \; r  k# D- z- \9 y! K用來輸出一段數據的內容(16進制)
( y" i; H* x; z- a7 c9 m4 M: n7 D: ?1 {4 G* i

4 Y3 X4 H! Y/ w0 B/ Bvoid debug_showbin( const char *dbuf, int n, const char *name, const char *end )' c; j: y; n4 s- j
{
6 B" z8 F5 N/ L* n' g9 H       int i;
! N5 s1 i* u2 |% i3 \       - @, C+ H5 K5 I
      printf( "%s ==> %d bytes: ", name, n );
* e; K  p' p5 v6 M# Q3 u6 ^( n0 s8 z! d6 z4 w3 i
      for( i=0; i<n; i++ )
- \& D3 Y+ w( S& a. S' C              printf( "(0x%x)", (unsigned char)dbuf );5 ]8 r7 \: J4 P/ {5 y: A; d# v# p3 k

. X8 J! Z, H& p* W5 q       printf( "%s", end );+ i( [8 `( A+ k7 K( j
}4 J/ M2 T$ I5 d, N2 y8 s8 P" @3 u
7 M& h5 T" C  o  d0 G
( r: y# b1 O  D' l: a- R. \$ v  x
3 r7 s, b* I% m2 ^* _
) k# Q( h) b3 @4 Z7 ]5 z( F( O, {
3. debug_showip: X0 ^" e' ]5 y6 `/ X! T1 h+ K
用來顯示sockaddr_in類型數據中的IP和Port
8 c% T) f6 P+ n, J( p; P1 j
. Z$ I  L) `) w0 I7 a, r8 S0 Q1 J0 v
void debug_showip( const struct sockaddr_in *dbuf, const char *name, const char *end )
4 K+ R" V. M" ~7 ]8 W$ @{* n7 e; f1 Y9 q! A% R# S( M
      printf("[ %s ==> %s:%u ]%s", name, inet_ntoa(dbuf->sin_addr), ntohs(dbuf->sin_port), end 6 I& u: A$ a; P! r
& j& Z* @8 q( b# ]: V
);
" ~/ q" J; K- d! L}
9 v  m3 C2 z7 F: @3 }$ P$ ]& Y7 W) B' C

1 |. T$ U" l. R0 z* z9 w  y$ ~6 M9 _& I: L8 L

6 P5 ^6 \- ^' V五、測試! z# z: V% M/ j; j9 R+ N" k
===================
+ Q  v* J+ ~6 P  A& E3 ]8 b下載源代碼後可嘗試編譯,然後執行,看看有沒有錯誤信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-12-29 20:08 , Processed in 0.018331 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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