• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            實現Sock5代理(轉)

            Posted on 2009-01-04 22:47 S.l.e!ep.¢% 閱讀(3983) 評論(0)  編輯 收藏 引用
            有很多公司不能直接和Internet相連,必須通過代理和www連接,瀏覽、下載資料。
            代理服務器支持的協議也有所不同,有支持Sock、HTTP代理的這樣我們做的客戶端軟件就需要支持這些代理,使用戶能夠通過這些代理透過防火墻和外網相連,一般Sock分為Sock4和Sock5,這里我們只實現Sock5協議。
            RFC1928描述了Socks協議的細節,告訴我們客戶程序如何同Socks代理協商,取得透過該協議對外傳輸的途徑。英文的URL為:http://www.ietf.org/rfc/rfc1928.txt,建議先了解以上鏈接內容后在閱讀下文。另外給大家推薦學習協議的好地方:http://www.cnpaf.com中國協議分析網,有很多好東東,可以去看看。
            下面說明一下實現的方法。
            代理的實現方法實際就是Socket編程,只要通訊時遵循它們的協議就可以。首先理解它們的協議是關鍵。
            示意圖:

            1.1??? Sock5協議實現

            1.1.1??????? Sock5協議內容

            1.? 客戶端首先要與代理服務器連接,連接后要向代理發送版本號、認證方法、方法選擇格式如下:
            版本號(1字節) |? 供選擇的認證方法(1字節) ?|? 方法序列(1-255個字節長度)
            如果你支持的版本為SOCK5那么版本號就為0x05;可供選擇的方法是指你的協議支持幾種認證方式,因為我們實現只支持一種所以就填0x01,如果你是兩種就寫0x02;認證方法序列包括(0x00為不需認證、0x02為需要用戶名和密碼認證,通常是這兩種,如果想了解更多請參看Rfc1928)。
            這樣組合你的報文應該為:0x05 0x01 0x00
            如果需要認證那么為:0x05 0x01 0x02
            2.? 代理接收到客戶端的請求,會向客戶端返回信息,格式為:
            版本號 | 服務器選定的方法
            如果服務器支持驗證方式,返回的報文為:
            0x05 0x02
            3.? 接下來根據服務器的驗證方式,發送驗證信息了,報文格式為:
            0x01 | 用戶名長度(1字節)| 用戶名(長度根據用戶名長度域指定) | 口令長度(1字節) | 口令(長度由口令長度域指定)
            4.? 服務器接收信息后進行驗證,返回如下格式:
            0x01 | 驗證結果標志
            驗證結果標志:0x00表示驗證成功,其他值均為錯誤碼

            1.1.2??????? Sock5協議實現

            根據上面所述的步驟和協議內容,就可以實現SOCK5代理了。下面我給出我寫的實現SOCKT5代理的函數代碼和注釋,供參考(delphi6+win2K+sp4調試通過,代理服務器用的是CCProxy6.0)
            function?TBZSock5ProxyApi.SetProxy(ASocket:?Pointer):?Integer;
            var
            ??proxyUser,?proxyPwd:?String;
            ??bIsValid:?Boolean;
            ??sock:?
            ^ TSocket;
            ??sockServer:?TSockAddrIn;
            ??command:?array?[
            0 .. 9 ]?of?Byte;
            ??re,?len,?ulen,?plen:?Integer;
            // ??buffer:?PByte;
            ??buffer:?array?[ 0 .. 1023 ]?of?Byte;
            begin
            ??sock?:
            = ?ASocket;
            ??
            if ?FProxyParam.GetServer? = ? '' ?then
            ??begin
            ????Result?:
            = ? 0 ;
            ????Exit;
            ??end
            ??
            else
            ??begin
            ????Result?:
            = ? 0 ;
            ????sock
            ^ ?: = ?socket(AF_INET,?SOCK_STREAM,? 0 );
            ????
            if ?sock ^ ? = ?INVALID_SOCKET?then
            ????begin
            ??????Result?:
            = ? 1 ;
            ??????Exit;
            ????end;
            ?
            ????sockServer.sin_family?:
            = ?AF_INET;
            ????sockServer.sin_port?:
            = ?htons(FProxyParam.GetPort);???? // 將整形數變為網絡字節流
            ????sockServer.sin_addr.S_addr?: = ?inet_addr(PChar(FProxyParam.GetServer));
            ?
            ????
            // 連接遠程主機
            ???? if ?WinSock.connect(sock ^ ,?sockServer,?SizeOf(sockServer))? <> ? 0 ?then
            ????begin
            ??????Result?:
            = ? 1 ;
            ??????Exit;
            ????end;
            ?
            ????bIsValid?:
            = ?FProxyParam.GetProxyValid;
            ?
            ????
            // 發送SOCK5協議指令
            ????FillChar(command,? 10 ,? 0 );
            ????command[
            0 ]?: = ? 5 ;
            ????
            if ?bIsValid?then
            ??????command[
            1 ]?: = ? 2
            ????
            else
            ??????command[
            1 ]?: = ? 1 ;
            ????
            if ?bIsValid?then
            ??????command[
            2 ]?: = ? 2
            ????
            else
            ??????command[
            2 ]?: = ? 0 ;
            ?
            ????
            // 發送登陸指令
            ???? if ?bIsValid?then
            ??????re?:
            = ?WinSock.send(sock ^ ,?command,? 4 ,? 0 )
            ????
            else
            ??????re?:
            = ?WinSock.send(sock ^ ,?command,? 3 ,? 0 );
            ????
            if ?re? = ?SOCKET_ERROR?then
            ????begin
            ??????Result?:
            = ? 1 ;
            ??????Exit;
            ????end;
            ?
            ????
            // 接收返回的消息
            ????fillchar(command,? 10 ,? 0 );????????????????????????? // 接收前用0再次填充
            ????re?: = ?WinSock.recv(sock ^ ,?command,? 2 ,? 0 );
            ????
            if ?re? <> ? 2 ?then
            ????begin
            ??????Result?:
            = ? 1 ;
            ??????Exit;
            ????end;
            ????
            if ?command[ 1 ] = $FF?then
            ????begin
            ??????Result?:
            = ? 1 ;
            ??????Exit;
            ????end;
            ?
            ????
            if ?(not?bIsValid)?and?(command[ 1 ] = 0 )?then
            ????begin
            ??????Exit;
            ????end;
            ?
            ????proxyUser?:
            = ?FProxyParam.GetUsername;
            ????proxyPwd?:
            = ?FProxyParam.GetPassword;
            ?
            ????
            if ?command[ 1 ]? <> ? 0 ?then
            ????begin
            ??????
            if ?command[ 1 ]? <> ? 2 ?then
            ??????begin
            ????????Result?:
            = ? 1 ;
            ????????Exit;
            ??????end;
            ??????
            if ?bIsValid?then
            ??????begin
            ????????ulen?:
            = ?Length(proxyUser);
            ????????plen?:
            = ?Length(proxyPwd);
            ????????len?:
            = ? 3 ? + ?ulen? + ?plen;
            ????????fillchar(buffer,?
            1024 ,? 0 );
            ?
            ????????buffer[
            0 ]?: = ? 5 ;
            ????????buffer[
            1 ]?: = ?ulen;
            ????????StrPCopy(@buffer[
            2 ],?proxyuser);
            ????????buffer[
            2 ? + ?ulen]?: = ?plen;
            ????????StrPCopy(@buffer[
            2 ? + ?ulen? + ? 1 ],?proxyPwd);
            ?
            ????????
            // 發送驗證信息
            ????????re?: = ?send(sock ^ ,?buffer,?len,? 0 );
            ????????
            if ?re? = ?SOCKET_ERROR?then
            ????????begin
            ??????????Result?:
            = ? 1 ;
            ??????????Exit;
            ????????end;
            ?
            ????????
            // 接收驗證返回信息
            ????????fillchar(command,? 10 ,? 0 );
            ????????re?:
            = ?recv(sock ^ ,?command,? 2 ,? 0 );
            ????????
            if ?((re <> 2 )?or?((command[ 0 ] <> 1 )?and?(command[ 1 ] <> 0 ?)))?then
            ????????begin
            ??????????Result?:
            = ? 1 ;
            ??????????Exit;
            ????????end;
            ??????end???
            // if?bisValid
            ?????? else
            ??????begin
            ????????Result?:
            = ? 1 ;
            ????????Exit;
            ??????end;?????????????????????
            //
            ????end;? // ?if?command[1]<>0
            ??end;?? // end?first?if
            ?
            end;
            上面的函數中有一個FproxyParam變量,它是代理參數的值對象,聲明如下:
            ??TProxyParam?
            = ? class
            ??
            private
            ????FUsername,????????
            // 代理驗證用戶名
            ????FPassword,???????? // 代理驗證密碼
            ????FServer:?String;???? // 代理服務器地址
            ????FPort:?Integer;????? // 代理服務器端口號
            ????FIsValid:?Boolean;?? // 是否驗證?????如果代理服務器是驗證的,那么此值應該為true
            ?
            ????procedure?Clear;
            ??
            public
            ????constructor?Create;
            ????procedure?SetUsername(AUsername:?String);
            ????procedure?SetPassword(APassword:?String);
            ????procedure?SetServer(AServer:?String);
            ????procedure?SetPort(APort:?Integer);
            ????procedure?SetProxyValid(AValid:?Boolean);
            ?
            ????function?GetUsername:?String;
            ????function?GetPassword:?String;
            ????function?GetServer:?String;
            ????function?GetPort:?Integer;
            ????function?GetProxyValid:?Boolean;
            ??end;
            使用此函數:
            假設已經創建了一個ClientSocket1(TclientSocket對象),它的IP和Port設置為代理服務器的IP和Port,那么就有下面的代碼:
            ......
            Var
            Re:Integer;
            Begin
            Re:
            = SetProxy(@(ClientSocket.Socket.SocketHandle))?;?? // 如果驗證成功,那么就可以用返回的//socket進行相應的通訊
            If?Re = 0 ?then?
            Begn
            ??ShowMessage(‘Sock5?is?ok’);?????????
            // 代理服務器就會有連接的數據流顯示
            End
            Else?begin
            ??ShowMessage(‘Sock5?is?error’);
            End;
            End;
            ……
            上面的例子如果設置代理成功,那么代理服務器就會有連接的數據流顯示。表示與代理服務器有數據交換,如果沒有成功則務數據流顯示。
            ?
            ?
            ?????????????????????????????????????????????????????????????? 李孟巖
            ????????????????????????????????????????????????????????????????????? mengyan_yl@sohu.com
            ??????????????????????????????????????????????????????????????????????????????????? 2005-07-05實現Sock5代理
            亚洲精品高清久久| 人妻精品久久无码区| 亚洲国产二区三区久久| 伊人久久大香线蕉AV色婷婷色| 伊人热热久久原色播放www| 91麻精品国产91久久久久| 亚洲国产精品久久66| 亚洲国产精品婷婷久久| 国产成人久久777777| 久久成人18免费网站| 欧美精品丝袜久久久中文字幕 | 免费一级欧美大片久久网 | 日本欧美国产精品第一页久久| 99久久国产亚洲高清观看2024 | 一本一本久久A久久综合精品| 国产69精品久久久久APP下载| 国产欧美久久久精品影院| AV无码久久久久不卡蜜桃| 亚洲AV日韩AV永久无码久久| 久久99精品国产自在现线小黄鸭| 1000部精品久久久久久久久| 国产2021久久精品| 2021最新久久久视精品爱| 亚洲AV乱码久久精品蜜桃| 青青青国产成人久久111网站| 国产成人AV综合久久| 中文字幕无码久久久| 波多野结衣中文字幕久久| 国产精品免费久久久久久久久| 免费精品国产日韩热久久| 久久亚洲精品国产精品| 久久国产免费| 久久精品无码专区免费青青| 国产成人久久777777| 精品伊人久久大线蕉色首页| 国产高潮国产高潮久久久91 | 无码八A片人妻少妇久久| 99久久国语露脸精品国产| 亚洲一级Av无码毛片久久精品| 久久99精品国产麻豆| 最新久久免费视频|