实战:150行Go实现高性能加密隧道

本文介绍了如何使用150行Go代码构建一个高性能的加密TCP隧道,通过Chacha20流加密算法确保通信安全。文章详细阐述了隧道的概念、加密的重要性,以及如何实现不加密的隧道、加密的改进过程,最终实现了一个完整的加密隧道解决方案。同时,文章提醒读者注意合法使用此类技术,避免违反相关法规。
摘要由CSDN通过智能技术生成

2021第一篇,继续写点有意思的小东西。


1. 质疑

上篇《实战:150行Go实现高性能socks5代理》发出来后,有同学提出了一些问题,比如说测试机配置太高,结果“不太具有说服力”、“是在耍赖”,再比如说应该和其他开源 socks 代理对比才比较有说服力。

这些质疑我觉得都非常有道理,经过深刻的反思,我做出一个艰难的决定,那就是不予理会,毕竟有这时间,我还不如另写一篇更有营养的,比如在这篇里,我们将看到,如何使用 150 行 Go 实现一个高性能的加密隧道。

不过有一个质疑值得专门一提:@hjc4869 大佬指出,由于 tcp 是双工通信,而 Socks5Forward 在某个方向结束后就把 src 和 dest 都关闭,不符合 tcp 规范,无法支持 half-closed connection。

这确实是个问题,好在依赖这个特性的场景不多,而且有些网络节点(如部分 NAT 路由器)本身并未完整实现这个特性(遇到fin直接或延迟关闭,可避免一些DoS攻击),因此该特性在实践中并不够可靠;此外,完整实现这个特性,代码会比较啰嗦,所以为了标题的 flag 暂且妥协,感兴趣的同学可以自己试着完善它(提示:可以抄一下 io.Copy 的源码)。


2. 隧道

为了照顾新来的同学,我们可能还应该先介绍一下什么是隧道。

如下图所示,直接访问目标服务时,由于网络上可能存在不安全因素(窃听等),我们会希望采用一个隧道协议,将需要传输的内容封装在协议的负载中,从而保障通信的安全。

一个典型的隧道协议就是 SSL/TLS,通过将 http 封装在 TLS 隧道中,我们就得到了 https,同样我们还可以有 ftps,socks5-over-tls;应用隧道的其他场景还包括需要在不兼容的网络上传输数据等情况。

上图中的“加密设备”并不一定需要是个独立的硬件,在接下来的内容里,我们会看到如何实现一个软件版本。


3. 开挖

饭要一口一口吃,隧道要一点点挖。

所以我们先搞个不加密的、用于传输一个 TCP Stream 的隧道,比如下图所示,将请求先发给中继 A(IP_A:PORT_A),A 转发给 B (IP_B:PORT_B),再由 B 转发到目标节点(IP:PORT)。

对于中继A,实现起来就非常简单了,27行搞定:

func main() {
  listenAddr := "IP_A:PORT_A"
  remoteAddr := "IP_B:PORT_B"
  server, err := net.Listen("tcp", listenAddr)
  if err != nil {
    fmt.Printf("Listen failed: %v\n", err)
    return
  }


  for {
    client, err := server.Accept()
    if err != nil {
      fmt.Printf("Accept failed: %v", err)
      continue
    }
    go Relay(client, remoteAddr)
  }
}


func Relay(client net.Conn, remoteAddr string) {
  remote, err
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值