package client import ( "github.com/cnlh/nps/lib/common" "github.com/cnlh/nps/lib/config" "github.com/cnlh/nps/lib/conn" "github.com/cnlh/nps/lib/crypt" "github.com/cnlh/nps/lib/mux" "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs" "github.com/cnlh/nps/vender/github.com/xtaci/kcp" "net" "strings" ) var LocalServer []*net.TCPListener var udpConn net.Conn var muxSession *mux.Mux func CloseLocalServer() { for _, v := range LocalServer { v.Close() } } func StartLocalServer(l *config.LocalServer, config *config.CommonConfig) error { listener, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), l.Port, ""}) if err != nil { logs.Error("Local listener startup failed port %d, error %s", l.Port, err.Error()) return err } LocalServer = append(LocalServer, listener) logs.Info("Successful start-up of local monitoring, port", l.Port) for { c, err := listener.AcceptTCP() if err != nil { if strings.Contains(err.Error(), "use of closed network connection") { break } logs.Info(err) continue } if l.Type == "secret" { go processSecret(c, config, l) } else { go processP2P(c, config, l) } } return nil } func processSecret(localTcpConn net.Conn, config *config.CommonConfig, l *config.LocalServer) { remoteConn, err := NewConn(config.Tp, config.VKey, config.Server, common.WORK_SECRET, config.ProxyUrl) if err != nil { logs.Error("Local connection server failed ", err.Error()) } if _, err := remoteConn.Write([]byte(crypt.Md5(l.Password))); err != nil { logs.Error("Local connection server failed ", err.Error()) } conn.CopyWaitGroup(remoteConn, localTcpConn, false, false, nil, nil) } func processP2P(localTcpConn net.Conn, config *config.CommonConfig, l *config.LocalServer) { if udpConn == nil { newUdpConn(config, l) muxSession = mux.NewMux(udpConn) } nowConn, err := muxSession.NewConn() if err != nil { logs.Error(err) return } link := conn.NewLink(common.CONN_TCP, l.Target, config.Cnf.Crypt, config.Cnf.Compress, localTcpConn.LocalAddr().String()) if _, err := conn.NewConn(nowConn).SendLinkInfo(link); err != nil { logs.Error(err) return } conn.CopyWaitGroup(nowConn, localTcpConn, config.Cnf.Crypt, config.Cnf.Compress, nil, nil) } func newUdpConn(config *config.CommonConfig, l *config.LocalServer) { remoteConn, err := NewConn(config.Tp, config.VKey, config.Server, common.WORK_P2P, config.ProxyUrl) if err != nil { logs.Error("Local connection server failed ", err.Error()) return } if _, err := remoteConn.Write([]byte(crypt.Md5(l.Password))); err != nil { logs.Error("Local connection server failed ", err.Error()) return } var rAddr []byte //读取服务端地址、密钥 继续做处理 if rAddr, err = remoteConn.GetShortLenContent(); err != nil { logs.Error(err) return } //与服务端udp建立连接 tmpConn, err := common.GetLocalUdpAddr() if err != nil { logs.Warn(err) return } //与服务端建立udp连接 localAddr, _ := net.ResolveUDPAddr("udp", tmpConn.LocalAddr().String()) localConn, err := net.ListenUDP("udp", localAddr) if err != nil { logs.Error(err) return } localKcpConn, err := kcp.NewConn(string(rAddr), nil, 150, 3, localConn) conn.SetUdpSession(localKcpConn) if err != nil { logs.Error(err) } //写入密钥、provider身份 if _, err := localKcpConn.Write([]byte(crypt.Md5(l.Password))); err != nil { logs.Error(err) return } if _, err := localKcpConn.Write([]byte(common.WORK_P2P_VISITOR)); err != nil { logs.Error(err) return } //接收服务端传的visitor地址 if b, err := conn.NewConn(localKcpConn).GetShortLenContent(); err != nil { logs.Error(err) return } else { //关闭与服务端连接 localConn.Close() //建立新的连接 localConn, err = net.ListenUDP("udp", localAddr) udpTunnel, err := kcp.NewConn(string(b), nil, 150, 3, localConn) if err != nil || udpTunnel == nil { logs.Warn(err) return } conn.SetUdpSession(udpTunnel) udpConn = udpTunnel } }