是否可以通过WebSocket或其他协议传输TCP连接?

是否可以通过WebSocket或其他协议传输TCP连接?,tcp,go,websocket,socks,Tcp,Go,Websocket,Socks,我想知道,是否可以通过websockets协议传输/隧道TCP连接 有一个io,我似乎可以将TCP连接复制到websockets连接中,但我不知道如何将其重新组装为另一端的TCPConn 例如,我想创建一个socks5 一端是服务器N(NAT后面),另一端是服务器。互联网用户将向服务器发出socks5请求(通过socks5协议),服务器将通过websocket连接向ServerNAT发送socks5请求。然后,ServerNAT将处理socks5请求(即,它是一个socks5服务器) 编辑: 我

我想知道,是否可以通过websockets协议传输/隧道TCP连接

有一个io,我似乎可以将TCP连接复制到websockets连接中,但我不知道如何将其重新组装为另一端的TCPConn

例如,我想创建一个socks5 一端是服务器N(NAT后面),另一端是服务器。互联网用户将向服务器发出socks5请求(通过socks5协议),服务器将通过websocket连接向ServerNAT发送socks5请求。然后,ServerNAT将处理socks5请求(即,它是一个socks5服务器)

编辑: 我已经编写了一些代码,但不幸的是,它在从TCP连接读取WS时被卡住了。要运行它:
go run main.go-logtostderr

package main

import (
    "flag"

    log "github.com/golang/glog"
    "golang.org/x/net/websocket"
    "bufio"
    "net"
    "net/http"
    "time"
//  "io"
)

func main() {
    flag.Parse()
    defer log.Flush()
    log.Infof("wsServer()")
    wsCh := wsServer()
    log.Infof("wsNAT()")
    natWS, err := wsNAT()
    if err != nil {
        log.Error(err)
        return
    }
    done := make(chan struct{}, 1)
        log.Infof("listenTCP()")
        conn := listenTCP()
        buf := bufio.NewReader(conn)
    go func() {
        log.Infof("Write TCP to WS")
        n, err := buf.WriteTo(natWS)
        if err != nil {
            log.Fatal(err)
            return
        }
        log.Infof("newConn.ws.ReadFrom(conn) %v", n)
        close(done)
    }()
    wsToTCP(<- wsCh)
    <-done
}
// wsNAT dials /ws endpoint and returns a websocket connection.
func wsNAT() (*websocket.Conn, error) {
    time.Sleep(1 * time.Second)
    origin := "http://localhost/"
    url := "ws://localhost:12345/ws"
    return websocket.Dial(url, "", origin)
}
 // wsServer returns the websocket
 // connections received on /ws endpoint
func wsServer() chan *websocket.Conn {
    wsCh := make(chan *websocket.Conn, 1)
    http.Handle("/ws", websocket.Handler(func(ws *websocket.Conn) {
        wsCh <- ws
        time.Sleep(1 *time.Hour)
    }))
    go func() {
        err := http.ListenAndServe(":12345", nil)
        if err != nil {
            panic("ListenAndServe: " + err.Error())
        }
    }()
    return wsCh
}
// wsToTCP reads a ws connection and converts its payload
// to a TCP connection.
func wsToTCP(ws *websocket.Conn) {
    conn := &net.TCPConn{}
    var msg []byte
    if _, err := ws.Read(msg); err != nil {
        log.Error(err)
        return
    }
    log.Infof("msg %v", msg)
    n, err := conn.Write(msg)
    if err != nil {
        log.Errorf("conn.Write %v, msg %v", err, msg)
        return
    }
    log.Infof("conn is %v, copied %v", conn, n)
    // END: do something with the connection
    // ..... 
}
//ListenTCP returns the first TCP connection received on port 8080
func listenTCP() *net.TCPConn {
    addr := &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 8080}
    lr, err := net.ListenTCP("tcp", addr)
    if err != nil {
        panic(err)

    }
    defer lr.Close()
    ieConn, err := lr.AcceptTCP()
    if err != nil {
        panic(err)
    }
    log.Infof("connection accepted")
    return ieConn
}
主程序包
进口(
“旗帜”
日志“github.com/golang/glog”
“golang.org/x/net/websocket”
“布菲奥”
“净额”
“net/http”
“时间”
//“io”
)
func main(){
flag.Parse()
延迟log.Flush()
log.Infof(“wsServer()”)
wsCh:=wsServer()
log.Infof(“wsNAT()”)
natWS,err:=wsNAT()
如果错误!=零{
日志错误(err)
返回
}
完成:=make(chan结构{},1)
log.Infof(“listenTCP()”)
conn:=listenTCP()
buf:=bufio.NewReader(康涅狄格州)
go func(){
log.Infof(“将TCP写入WS”)
n、 错误:=buf.WriteTo(natWS)
如果错误!=零{
log.Fatal(错误)
返回
}
log.Infof(“newConn.ws.ReadFrom(conn)%v”,n)
结束(完成)
}()

wsToTCP(这应该不会有任何问题。我已经在许多协议上构建了TCP转发器。从来没有WebSocket,但我看不出有什么不同的原因

你有两个问题:

  • 建立连接的正确方法是使用
    net.Dial
    ,而不仅仅是创建
    net.TCPConn
  • 你只能向一个方向复制。你需要向两个方向复制
这是一个超级简单的代理,我今天早上为一个不同的目的构建了它(我的完整代码每隔一段时间就会破坏一个数据包,所以我可以测试坏的连接)。它应该可以转换为许多其他用途:

func run(inPort int, dest string) {
    l, err := net.Listen("tcp", fmt.Sprintf(":%d", inPort))
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    fmt.Printf("http://%v -> %s\n", l.Addr(), dest)

    for {
        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("Connection from %s\n", conn.RemoteAddr())
        go proxy(conn, dest)
    }
}

func proxy(in net.Conn, dest string) {
    out, err := net.Dial("tcp", dest)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }

    go io.Copy(out, in)
    io.Copy(in, out)
    fmt.Printf("Disconnect from %s\n", in.RemoteAddr())
}
您只需将此处的
net.Dial
替换为对服务器的WS-call,并在服务器端使用
net.Dial
将其转发


但最关键的一点可能是最后几行。你必须向两个方向复制,而人们却忘记了这一点。

你是指类似于或的东西吗?是的,我的意思似乎是wstunnel,尽管javascript不是我的拿手好戏。websockets-proxy似乎也做同样的事情……是否有Go等价物?我不知道有Go等价物。现在我正在考虑使用一个“假”侦听器和拨号来创建TCP连接。我会尝试一下,让你知道它是如何进行的。我尝试过这个,但它似乎是一个死胡同。我已经用我尝试过的代码更新了我的答案。最理想的是有一个“假”仅用于构建TCP连接的侦听器和拨号器似乎是错误的,不起作用。值得注意的是,在您的示例中,您只有两个参与方,但我有3个参与方(NAT、服务器和IE)。我已使用最终解决方案更新了我的答案。事实上,我不得不拨打一个假侦听器,我觉得非常尴尬(即,继续监听本地端口并使用通过WebSocket接收的数据拨号)。我想知道是否可以为网络包创建一个构造函数,以便从WebSocket(io.ReadWriter)读取并返回*net.Conn,而不使用假拨号器/侦听器。