0%

100 行代码实现内网穿透

最近需要用到内网穿透,网上有不错的开源解决方案,我也在使用,不过只是这样我是肯定不会满足的所有自己实现了一个最简版。
nat 主要分为两部分一部分部署在带公网 IP 的服务器上,接收用户的请求。另外一部分部署在内网主机接收请求。

外部端

外部端我们需要部署到带公网的服务器上,代码大概类似于这样
package main

import (
    "io"
    "net"
)

func main() {
    publicPort := "30080"  // 公开端口
    privatePort := "30081" // 对端链接端口

    // 外部连接
    publicListen, err := net.Listen("tcp", net.JoinHostPort("", publicPort))
    if err != nil {
        panic(err)
    }

    内部连接
    privateListen, err := net.Listen("tcp", net.JoinHostPort("", privatePort))
    if err != nil {
        panic(err)
    }

    for {
        // 处理内部请求
        privateConn, err := privateListen.Accept()
        if err != nil {
            panic(err)
        }

        go func() {
            // 处理外部请求
            publicConn, err := publicListen.Accept()
            if err != nil {
                panic(err)
            }

            // 拷贝内容
            go func() {
                io.Copy(publicConn, privateConn)
                defer publicConn.Close()
            }()
            go func() {
                io.Copy(privateConn, publicConn)
                defer privateConn.Close()
            }()
        }()
    }
}

内部端

内部端部署在我们的内网服务器上代码类似于这样

package main

import (
    "io"
    "net"
    "os"
)

func main() {
    callPort := "8080"     // 访问端口
    privatePort := "30081" // 从这里获取数据

    serverAddress := os.Getenv("server") // 不存在则默认本地地址(库的行为)

    // 访问需要代理的服务
    callConn, err := net.Dial("tcp", net.JoinHostPort("", callPort))
    if err != nil {
        panic(err)
    }

    // 访问我们部署在公网的服务
    privateConn, err := net.Dial("tcp", net.JoinHostPort(serverAddress, privatePort))
    if err != nil {
        panic(err)
    }

    // 拷贝连接
    go func() {
        go func() {
            io.Copy(callConn, privateConn)
            defer callConn.Close()
        }()
        go func() {
            io.Copy(privateConn, callConn)
            defer privateConn.Close()
        }()
    }()

    // 堵塞住防止退出
    done := make(chan struct{})
    <-done
}

篇外

反向代理所需要的最简代码大概类似于这样,如果你需要更复杂的功能请自行修改