<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] ## socket協議版本 Socket協議分為Socket4和Socket5兩個版本,他們最明顯的區別是Socket5同時支持TCP和UDP兩個協議,而SOcket4只支持TCP。目前大部分使用的是Socket5,我們這里只簡單的介紹Socket5協議。 ## Socket5協議之授權認證 Socket6協議的實現細節和規范 ### 首先客戶端會給服務端發送驗證信息 | VER | NMETHODS |METHODS| | --- | --- |---| | 1 | 1 |1 to 255| 1. 第一個字段VER代表Socket的版本,Soket5默認為0x05,其固定長度為1個字節 2. 第二個字段NMETHODS表示第三個字段METHODS的長度,它的長度也是1個字節 3. 第三個METHODS表示客戶端支持的驗證方式,可以有多種,他的嘗試是1-255個字節。 目前支持的驗證方式一共有: ``` 1. X’00’ NO AUTHENTICATION REQUIRED(不需要驗證) 2. X’01’ GSSAPI 3. X’02’ USERNAME/PASSWORD(用戶名密碼) 4. X’03’ to X’7F’ IANA ASSIGNED 5. X’80’ to X’FE’ RESERVED FOR PRIVATE METHODS 6. X’FF’ NO ACCEPTABLE METHODS(都不支持,沒法連接了) ``` 以上的都是十六進制常量,比如X’00’表示十六進制0x00。 ### 服務器回應客戶端 服務端收到客戶端的驗證信息之后,就要回應客戶端,服務端需要客戶端提供哪種驗證方式的信息。服務端的回應同樣非常簡潔。 | VER | NMETHODS| | --- | --- | | 1 | 1 | 1. 一個字段VER代表Socket的版本,Soket5默認為0x05,其值長度為1個字節 2. 第二個字段METHOD代表需要服務端需要客戶端按照此驗證方式提供驗證信息,其值長度為1個字節,選擇為上面的六種驗證方式。 舉例說明,比如服務端不需要驗證的話,可以這么回應客戶端: | VER | NMETHODS| | --- | --- | | 0x05 | 0x00 | 我們使用Go實現代碼如下: ``` var b [1024]byte n, err := client.Read(b[:]) if err != nil { log.Println(err) return } if b[0] == 0x05 { //只處理Socket5協議 //客戶端回應:Socket服務端不需要驗證方式 client.Write([]byte{0x05, 0x00}) n, err = client.Read(b[:]) } ``` ## Socket5協議之建立連接 Socket5的客戶端和服務端進行雙方授權驗證通過之后,就開始建立連接了。連接由客戶端發起,告訴Sokcet服務端客戶端需要訪問哪個遠程服務器,其中包含,遠程服務器的地址和端口,地址可以是IP4,IP6,也可以是域名。 | VER | CMD | RSV| ATYP | DST.ADDR | DST.PORT| | --- | --- |--- |--- |--- |--- | | 1 | 1 |X’00’|1|Variable |2| 1. VER代表Socket協議的版本,Soket5默認為0x05,其值長度為1個字節 2. CMD代表客戶端請求的類型,值長度也是1個字節,有三種類型 * CONNECT X’01’ * BIND X’02’ * UDP ASSOCIATE X’03’ 3. RSV保留字,值長度為1個字節 4. ATYP代表請求的遠程服務器地址類型,值長度1個字節,有三種類型 * IP V4 address: X’01’ * DOMAINNAME: X’03’ * IP V6 address: X’04’ 5. DST.ADDR代表遠程服務器的地址,根據ATYP進行解析,值長度不定。 6. DST.PORT代表遠程服務器的端口,要訪問哪個端口的意思,值長度2個字節 從協議里解析我們需要的遠程服務器信息,Go代碼實現如下: ``` var host,port string switch b[3] { case 0x01://IP V4 host = net.IPv4(b[4],b[5],b[6],b[7]).String() case 0x03://域名 host = string(b[5:n-2])//b[4]表示域名的長度 case 0x04://IP V6 host = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String() } port = strconv.Itoa(int(b[n-2])<<8|int(b[n-1])) ``` 現在客戶端把要請求的遠程服務器的信息都告訴Socket5代理服務器了,那么Socket5代理服務器就可以和遠程服務器建立連接了,不管連接是否成功等,都要給客戶端回應,其回應格式為: | VER | REP| RSV| ATYP | BND.ADDR | BND.PORT| | --- | --- |--- |--- |--- |--- | | 1 | 1 |X’00’|1|Variable |2| 1. VER代表Socket協議的版本,Soket5默認為0x05,其值長度為1個字節 2. REP代表響應狀態碼,值長度也是1個字節,有以下幾種類型 * X’00’ succeeded * X’01’ general SOCKS server failure * X’02’ connection not allowed by ruleset * X’03’ Network unreachable * X’04’ Host unreachable * X’05’ Connection refused * X’06’ TTL expired * X’07’ Command not supported * X’08’ Address type not supported * X’09’ to X’FF’ unassigned 3. RSV保留字,值長度為1個字節 4. ATYP代表請求的遠程服務器地址類型,值長度1個字節,有三種類型 * IP V4 address: X’01’ * DOMAINNAME: X’03’ * IP V6 address: X’04’ 5. BND.ADDR表示綁定地址,值長度不定。 6. BND.PORT表示綁定端口,值長度2個字節 Go實現的連接和應答如下: ``` server, err := net.Dial("tcp", net.JoinHostPort(host, port)) if err != nil { log.Println(err) return } defer server.Close() client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //響應客戶端連接成功 ``` ## 數據轉發 建立好連接之后,就是數據傳遞轉發,TCP協議可以直接轉發。UDP的話需要特殊處理,具體參考協議定義,其實就是一個特殊格式的回應,和上面的一問一答差不多,更多協議細節 [http://www.ietf.org/rfc/rfc1928.txt](http://www.ietf.org/rfc/rfc1928.txt)。 TCP直接轉發非常簡單: ``` //進行轉發 go io.Copy(server, client) io.Copy(client, server) ``` ## 完整代碼實現 以下是完成的代碼實現: ``` package main import ( "io" "log" "net" "strconv" ) func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) l, err := net.Listen("tcp", ":8081") if err != nil { log.Panic(err) } for { client, err := l.Accept() if err != nil { log.Panic(err) } go handleClientRequest(client) } } func handleClientRequest(client net.Conn) { if client == nil { return } defer client.Close() var b [1024]byte n, err := client.Read(b[:]) if err != nil { log.Println(err) return } if b[0] == 0x05 { //只處理Socket5協議 //客戶端回應:Socket服務端不需要驗證方式 client.Write([]byte{0x05, 0x00}) n, err = client.Read(b[:]) var host, port string switch b[3] { case 0x01: //IP V4 host = net.IPv4(b[4], b[5], b[6], b[7]).String() case 0x03: //域名 host = string(b[5 : n-2]) //b[4]表示域名的長度 case 0x04: //IP V6 host = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String() } port = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1])) server, err := net.Dial("tcp", net.JoinHostPort(host, port)) if err != nil { log.Println(err) return } defer server.Close() client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //響應客戶端連接成功 //進行轉發 go io.Copy(server, client) io.Copy(client, server) } } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看