Go 实践项目03——Socks5代理 | 青训营笔记

79 阅读3分钟

3 Socks5代理

SOCKS(SOCKetSecure)是一种互联网协议,通过代理服务器转发用户的互联网流量。任何第三方观察者都只能看到SOCKS代理服务器的IP地址,而不是您的真实IP地址。

​ Socks5代理IP是一种协议,它允许用户通过代理服务器连接到网络服务。这种代理协议能够提供更高的安全性和更好的性能,因为它支持UDP和TCP连接,可以在不影响数据传输速度的情况下隐藏用户的IP地址。 在使用Socks5代理IP时,用户需要将其IP地址和端口号配置为代理服务器的IP地址和端口号。当用户请求网络服务时,代理服务器将代表用户发起请求,并将响应数据返回给用户。这种代理技术适用于需要保护用户隐私和安全的场景,如在公共Wi-Fi网络上浏览网站或访问敏感信息。

3.1 Socks5交互原理图

1684139547722.png

图片摘自:blog.csdn.net/CZD__CZD/ar…

3.2 TCP echo server

  1. 创建一个TCP server
  2. 等待客户端的连接
  3. 如果连接成功,启动一个线程去处理这个连接
    1. 扫描来自客户端的输入
    2. 向客户端输出同样的内容
    3. 循环扫描客户端的输入
  4. 循环,处理下一个客户端的连接
  1. 创建一个TCP server

    通过标准库 net 的Listen函数来创建一个server,协议类型是tcp,IP及端口是一个字符串"127.0.0.1:1080”

    如果成功,函数返回一个接口。该接口有一个方法可以返回侦听的地址,同时该接口具有Accept()的方法能够接受来自客户端的连接

      
      server, err := net.Listen("tcp", "127.0.0.1:1080")  // 创建一个server
      if err != nil{
          panic(err)
      }
      fmt.Printf("Listing on %v",server.Addr()) // 返回侦听的地址
    
  2. 等待客户端的连接

    Accept()方法可以接受客户端的连接,如果成功,返回一个接口,该接口具有读写方法,也具有获取本地及远端连接地址的方法

      
      client, err := server.Accept() // 接受客户端连接
      if err != nil{
          log.Printf("Accept failed %v", err)
          continue
      }
      fmt.Printf("Accepted connection to %v from %v", client.LocalAddr(), client.RemoteAddr()) // 打印本地及远端连接地址
    
  3. 如果连接成功,启动一个线程去处理这个连接

    启用线程的目的是为了性能,每个连接都运行在各自的线程里。

    允许并发。

    线程里需要传入创建的client 这个接口作为参数

      
      go process(client) // 启用线程
    

    使用bufio.NewReader来创建一个带缓冲区的只读流(可以减少底层系统的调用次数,这里为了方便一个字节一个字节的读取,但底层可能合并成几次大的读取操作)

    使用readbyte读取单个字节,再将这一个字节写进去连接

      
      func process(conn net.Conn){
          defer conn.Close() // 在这个函数退出时将这个连接关掉,否则会有资源的泄露
          reader := bufio.NewReader(conn) // 创建只读流
          for{
              b, err := reader.ReadByte() //  读取字节
              if err != nil{
                  break
              }
              _, err = conn.Write([]byte{b})
              if err != nil{
                  break
              }
          }
      }
    
  4. 循环,处理下一个客户端的连接

    使用for {}循环,循环读取IO及接受新的客户端连接

      
      for{
          client, err := server.Accept() // 接受客户端连接
          if err != nil{
              log.Printf("Accept failed %v", err)
              continue
          }
          fmt.Printf("Accepted connection to %v from %v", client.LocalAddr(), client.RemoteAddr()) // 打印本地及远端连接地址
          go process(client) // 启用线程
      }