這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
用go語言來實現socks5Proxy 伺服器,後面會加入ssh遠程代理,使用者驗證,均衡負載一些吧
首先監聽8080連接埠,迴圈接收tcp串連
server, err := net.Listen("tcp", ":8080")if err != nil {log.Panic(err)}defer server.Close()log.Println("開始接受串連")for {client, err := server.Accept()if err != nil {log.Println(err)return}log.Println("一個新串連")go socks5Proxy(client)}
socks5Proxy函數用來實現sock5代理
先介紹一下sock5代理協議
具體可看 https://www.zybuluo.com/zwh8800/note/347444
client:0x05 0x02 0x00 0x02 或 0x05 0x01 0x00 (主要是使用者驗證方面,咱們忽略,直接返回0x05 0x00)
server:0x05 0x00
client:0x05 0x01 0x00 0x01 ... 或 0x05 0x01 0x00 0x03 ... (0x01後面跟的是ip+port ,0x02是ip6+port, 0x03跟的是domainName+port,因為是二進位,要用到binary包解碼,然後就可以直接用net.Dial進行串連,go會自動轉換到網域名稱到ip,所以可以直接用)
server:0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 (當服務端確定能進行代理返回確定)
然後就是兩個io.Copy來進行代理轉寄就行了,下面是代碼
func socks5Proxy(conn net.Conn) {defer conn.Close()var b [1024]byten, err := conn.Read(b[:])if err != nil {log.Println(err)return}log.Printf("% x", b[:n])conn.Write([]byte{0x05, 0x00})n, err = conn.Read(b[:])if err != nil {log.Println(err)return}log.Printf("% x", b[:n])var addr stringswitch b[3] {case 0x01:sip := sockIP{}if err := binary.Read(bytes.NewReader(b[4:n]), binary.BigEndian, &sip); err != nil {log.Println("請求解析錯誤")return}addr = sip.toAddr()case 0x03:host := string(b[5 : n-2])var port uint16err = binary.Read(bytes.NewReader(b[n-2:n]), binary.BigEndian, &port)if err != nil {log.Println(err)return}addr = fmt.Sprintf("%s:%d", host, port)}server, err := net.Dial("tcp", addr)if err != nil {log.Println(err)return}conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})go io.Copy(server, conn)io.Copy(conn, server)}