最近需要用到内网穿透,网上有不错的开源解决方案,我也在使用,不过只是这样我是肯定不会满足的所有自己实现了一个最简版。
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
}
篇外
反向代理所需要的最简代码大概类似于这样,如果你需要更复杂的功能请自行修改