GOLANG实现Socks5代理(2)|青训营笔记

46 阅读2分钟

(续接上文)
在了解了defer之后,我们再来看process函数。在main函数中,我们已经获取了一个server,并通过server.Accept得到client,也就是Conn链接。在process函数中,先将关闭Conn链接的操作放入defer中,用于释放资源。也就是在这个函数结束的时候,这个链接的生命周期也就随之结束。

接下来使用bufio.NewReader(conn)创建一个只读的缓冲流,此时,我们可以使用eader.ReadByte()对缓冲流中的数据进行读取,并通过conn.Write([]byte{b})将读取的信息输出至控制台,以便校验。

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
      }
   }
}

注: 这里测试时我们不仅要使用go run XX.go启动程序(XX.go为你对该程序的命名),也要用nc命令创建一个tcp连接,比如现在我们使用的ip和端口号是127.0.0.1:1080,则创建命令为nc 127.0.0.1 1080,此时你就可以在控制台输入一些字符以验证该程序的正确性了,比如输入hello world,那么服务器就会同时返回一个hello world。(不一样的语言,一样的hello world!)

2. 认证阶段
在验证完上述实验,是不是一个大大的amazing,给自己点个赞之后,我们继续下一步。刚刚我们已经做了一个可以返回你输入信息的TCP Server。但代理服务器肯定不可能这么简单,我们要一步一步为它添加功能,我们来看一下鉴权。我们先对process函数的程序稍稍做一下改动。

func process(conn net.Conn) {
   defer conn.Close()
   reader := bufio.NewReader(conn)
   err := auth(reader, conn)
   if err != nil {
      log.Printf("client %v auth failed:%v", conn.RemoteAddr(), err)
      return
   }
   err = connect(reader, conn)
   if err != nil {
      log.Printf("client %v auth failed:%v", conn.RemoteAddr(), err)
      return
   }
}

与之前process函数相比,我们通过使用auth(reader, conn)函数,对链接信息进行鉴权,如果失败,那自然不可能进行下一步操作,直接输出err,退出程序即可。若验证成功,则进行链接,同样,若失败,则打印err信息,退出程序;若成功,则Socks5代理服务器功能已经实现。