コード例 #1
0
ファイル: admin.go プロジェクト: vzex/dog-tunnel
func _adminKickSession(w http.ResponseWriter, r *http.Request) (result string, bSuccess bool) {
	server := r.FormValue("server")
	session := r.FormValue("session")
	if server == "" || session == "" {
		result = "please spec server and session"
		bSuccess = false
		return
	}
	conn, bHave := common.ServerName2Conn[server]
	if bHave {
		server, bHave2 := common.Conn2ClientInfo[conn]
		if bHave2 {
			session, bHave := server.Id2Session[session]
			if bHave {
				if session.ClientA != conn {
					common.Write(session.ClientA, "0", "showandquit", "admin kick you out")
				} else if session.ClientB != conn {
					common.Write(session.ClientB, "0", "showandquit", "admin kick you out")
				}
				result = "kick session ok"
			} else {
				result = "no need kick"
			}
		} else {
			bSuccess = false
			result = "donnot have this conn"
		}
	} else {
		bSuccess = false
		result = "donnot have this serverName"
		return
	}
	bSuccess = true
	return
}
コード例 #2
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func handleLocalPortResponse(client *Client, id string) {
	sessionId := id
	if !client.bUdp {
		arr := strings.Split(id, "-")
		sessionId = arr[1]
	}
	session := client.getSession(sessionId)
	if session == nil {
		return
	}
	conn := session.localConn
	if conn == nil {
		return
	}
	arr := make([]byte, nat.SendBuffSize)
	reader := bufio.NewReader(conn)
	for {
		size, err := reader.Read(arr)
		if err != nil {
			break
		}
		if common.Write(session.pipe, id, "tunnel_msg_s", string(arr[0:size])) != nil {
			break
		}
	}
	// log.Println("handlerlocal down")
	if client.removeSession(sessionId) {
		common.Write(session.pipe, id, "tunnel_close_s", "")
	}
}
コード例 #3
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func handleLocalServerResponse(client *Client, sessionId string) {
	session := client.getSession(sessionId)
	if session == nil {
		return
	}
	pipe := session.pipe
	if pipe == nil {
		return
	}
	conn := session.localConn
	common.Write(pipe, sessionId, "tunnel_open", "")
	arr := make([]byte, nat.SendBuffSize)
	reader := bufio.NewReader(conn)
	for {
		size, err := reader.Read(arr)
		if err != nil {
			break
		}
		if common.Write(pipe, sessionId, "tunnel_msg_c", string(arr[0:size])) != nil {
			break
		}
	}
	common.Write(pipe, sessionId, "tunnel_close", "")
	client.removeSession(sessionId)
}
コード例 #4
0
ファイル: admin.go プロジェクト: vzex/dog-tunnel
func _adminBroadcast(w http.ResponseWriter, r *http.Request) (result string, bSuccess bool) {
	msgtype := r.FormValue("type")
	if msgtype == "" {
		result = "please spec type"
		bSuccess = false
		return
	}
	msg := r.FormValue("msg")
	quit := r.FormValue("quit")
	cmd := "show"
	if quit != "" {
		cmd = "showandquit"
	}
	n := 0
	for conn, info := range common.Conn2ClientInfo {
		hit := false
		if msgtype == "s" && info.IsServer {
			hit = true
		} else if msgtype == "c" && !info.IsServer {
			hit = true
		} else if msgtype == "a" {
			hit = true
		}
		if hit {
			common.Write(conn, "0", cmd, msg)
			n++
		}
	}
	result = fmt.Sprintf("%d", n)
	bSuccess = true
	return
}
コード例 #5
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func (session *UDPMakeSession) reportAddrList(buster bool, outip string) {
	id := session.id
	var otherAddrList string
	if !buster {
		arr := strings.SplitN(outip, ":", 2)
		outip, otherAddrList = arr[0], arr[1]
	} else {
		arr := strings.SplitN(outip, ":", 2)
		var delayTime string
		outip, delayTime = arr[0], arr[1]
		session.delay, _ = strconv.Atoi(delayTime)
		if session.delay < 0 {
			session.delay = 0
		}
	}
	outip += ";" + *addInitAddr
	_id, _ := strconv.Atoi(id)
	engine, err := nat.Init(outip, buster, _id, *serverBustAddr)
	engine.Kcp = getKcpSetting()
	engine.D = *dataShards
	engine.P = *parityShards
	if err != nil {
		println("init error", err.Error())
		disconnect()
		return
	}
	session.engine = engine
	session.buster = buster
	if !buster {
		engine.SetOtherAddrList(otherAddrList)
	}
	addrList := engine.GetAddrList()
	println("addrList", addrList)
	common.Write(remoteConn, id, "report_addrlist", addrList)
}
コード例 #6
0
ファイル: server.go プロジェクト: vzex/dog-tunnel
func handleClient(conn net.Conn) {
	common.Conn2ClientInfo[conn] = &common.ClientInfo{Conn: conn, ClientMap: make(map[net.Conn]*common.Session), Id2Session: make(map[string]*common.Session), IsServer: false, Quit: make(chan bool), ResponseTime: time.Now().Unix()}
	log.Println("client linked success", conn.RemoteAddr().String())
	common.Conn2ClientInfo[conn].Loop()
	common.Read(conn, handleResponse)
	client, bHave := common.Conn2ClientInfo[conn]
	if bHave {
		close(client.Quit)
		if client.IsServer {
			for conn, session := range client.ClientMap {
				conn.Close()
				common.RmId(client.ServerName, session.Id)
			}
			delete(common.ServerName2Conn, client.ServerName)
			log.Println("unregister service Name", client.ServerName)
			if bUseDB {
				user, _ := auth.GetUser(client.UserName)
				if user != nil {
					user.OnLogout()
				}
			}
		} else {
			common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
				id := server.DelClient(conn)
				log.Println("send quit")
				common.Write(server.Conn, id, "clientquit", "")
			}, func() {})
		}
		delete(common.Conn2ClientInfo, conn)
	}
	conn.Close()
	log.Println("client disconnected", conn.RemoteAddr().String())
}
コード例 #7
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func (sc *Client) MultiListen() bool {
	if g_LocalConn == nil {
		g_LocalConn, err := net.Listen("tcp", *localAddr)
		if err != nil {
			log.Println("cannot listen addr:" + err.Error())
			if remoteConn != nil {
				remoteConn.Close()
			}
			return false
		}
		go func() {
			quit := false
			ping := time.NewTicker(time.Second * 5)
			go func() {
			out:
				for {
					select {
					case <-ping.C:
						if quit {
							break out
						}
						for _, pipe := range sc.pipes {
							common.Write(pipe, "-1", "ping", "")
						}
					}
				}
			}()
			ping.Stop()
			for {
				conn, err := g_LocalConn.Accept()
				if err != nil {
					continue
				}
				sessionId := common.GetId("udp")
				pipe := sc.getOnePipe()
				if pipe == nil {
					log.Println("cannot get pipe for client")
					if remoteConn != nil {
						remoteConn.Close()
					}
					return
				}
				sc.sessionLock.Lock()
				sc.sessions[sessionId] = &clientSession{pipe: pipe, localConn: conn}
				sc.sessionLock.Unlock()
				log.Println("client", sc.id, "create session", sessionId)
				go handleLocalServerResponse(sc, sessionId)
			}
			quit = true
		}()
		mode := "p2p mode"
		if !sc.bUdp {
			mode = "c/s mode"
			delete(g_ClientMapKey, sc.id)
		}
		println("service start success,please connect", *localAddr, mode)
	}
	return true
}
コード例 #8
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func connect() {
	if *pipeNum <= 0 {
		*pipeNum = 1
	}
	clientInfo := common.ClientSetting{Version: common.Version, Delay: *delayTime, Mode: *clientMode, PipeNum: *pipeNum, AccessKey: *accessKey, ClientKey: *clientKey, AesKey: ""}
	if *bEncrypt {
		clientInfo.AesKey = string([]byte(fmt.Sprintf("asd4%d%d", int32(time.Now().Unix()), (rand.Intn(100000) + 100)))[:16])
		log.Println("debug aeskey", clientInfo.AesKey)
		key, _ := aes.NewCipher([]byte(clientInfo.AesKey))
		aesKey = &key
	}
	if *bLoadSettingFromFile {
		var setting fileSetting
		err := loadSettings(&setting)
		if err == nil {
			clientInfo.AccessKey = setting.Key
		} else {
			log.Println("load setting fail", err.Error())
		}
	} else {
		if clientInfo.AccessKey != "" {
			var setting = fileSetting{Key: clientInfo.AccessKey}
			err := saveSettings(setting)
			if err != nil {
				log.Println("save setting error", err.Error())
			} else {
				println("save setting ok, nexttime please use -f to replace -key")
			}
		}
	}
	if clientType == 0 {
		markName = *serveName
		clientInfo.ClientType = "reg"
	} else if clientType == 1 {
		markName = *linkName
		clientInfo.ClientType = "link"
	} else {
		println("no clienttype!")
	}
	clientInfo.Name = markName
	clientInfoStr, err := json.Marshal(clientInfo)
	if err != nil {
		println("encode args error")
	}
	log.Println("init client", string(clientInfoStr))
	common.Write(remoteConn, "0", "init", string(clientInfoStr))
}
コード例 #9
0
ファイル: server.go プロジェクト: vzex/dog-tunnel
func shutdown() {
	for conn, client := range common.Conn2ClientInfo {
		if !client.IsServer {
			log.Println("shutdown client", client.ServerName)
			common.Write(conn, "0", "showandquit", "server shutdown")
		} else {
			log.Println("unregister service Name", client.ServerName)
			if bUseDB {
				user, _ := auth.GetUser(client.UserName)
				if user != nil {
					user.OnLogout()
				}
			}
			//donnot showandquit,because client_server need to reconnect
		}
	}
}
コード例 #10
0
ファイル: admin.go プロジェクト: vzex/dog-tunnel
func _adminKickServer(w http.ResponseWriter, r *http.Request) (result string, bSuccess bool) {
	server := r.FormValue("server")
	if server == "" {
		result = "please spec server"
		bSuccess = false
		return
	}
	conn, bHave := common.ServerName2Conn[server]
	if bHave {
		common.Write(conn, "0", "showandquit", "admin kick you out")
		result = "kick server ok"
	} else {
		bSuccess = false
		result = "donnot have this serverName"
		return
	}
	bSuccess = true
	return
}
コード例 #11
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func handleResponse(conn net.Conn, clientId string, action string, content string) {
	//log.Println("got", clientId, action)
	switch action {
	case "aeskey":
		fmt.Println("init aeskey for client", clientId, content)
		block, _ := aes.NewCipher([]byte(content))
		g_ClientMapKey[clientId] = &block
	case "show":
		fmt.Println(time.Now().Format("2006-01-02 15:04:05"), content)
	case "showandretry":
		fmt.Println(time.Now().Format("2006-01-02 15:04:05"), content)
		remoteConn.Close()
	case "showandquit":
		fmt.Println(time.Now().Format("2006-01-02 15:04:05"), content)
		remoteConn.Close()
		bForceQuit = true
	case "clientquit":
		client := g_ClientMap[clientId]
		log.Println("clientquit!!!", clientId, client)
		if client != nil {
			client.Quit()
		}
	case "remove_udpsession":
		log.Println("server force remove udpsession", clientId)
		delete(g_Id2UDPSession, clientId)
	case "query_addrlist_a":
		outip := content
		arr := strings.Split(clientId, "-")
		id := arr[0]
		sessionId := arr[1]
		pipeType := arr[2]
		g_Id2UDPSession[id] = &UDPMakeSession{id: id, sessionId: sessionId, pipeType: pipeType}
		go g_Id2UDPSession[id].reportAddrList(true, outip)
	case "query_addrlist_b":
		arr := strings.Split(clientId, "-")
		id := arr[0]
		sessionId := arr[1]
		pipeType := arr[2]
		g_Id2UDPSession[id] = &UDPMakeSession{id: id, sessionId: sessionId, pipeType: pipeType}
		go g_Id2UDPSession[id].reportAddrList(false, content)
	case "tell_bust_a":
		session, bHave := g_Id2UDPSession[clientId]
		if bHave {
			go session.beginMakeHole(content)
		}
	case "tell_bust_b":
		session, bHave := g_Id2UDPSession[clientId]
		if bHave {
			go session.beginMakeHole("")
		}
	case "csmode_c_tunnel_close":
		log.Println("receive close msg from server")
		arr := strings.Split(clientId, "-")
		clientId = arr[0]
		sessionId := arr[1]
		client, bHave := g_ClientMap[clientId]
		if bHave {
			client.removeSession(sessionId)
		}
	case "csmode_s_tunnel_close":
		arr := strings.Split(clientId, "-")
		clientId = arr[0]
		sessionId := arr[1]
		client, bHave := g_ClientMap[clientId]
		if bHave {
			client.removeSession(sessionId)
		}
	case "csmode_s_tunnel_open":
		oriId := clientId
		arr := strings.Split(oriId, "-")
		clientId = arr[0]
		sessionId := arr[1]
		client, bHave := g_ClientMap[clientId]
		if !bHave {
			client = &Client{id: clientId, pipes: make(map[int]net.Conn), engine: nil, buster: true, sessions: make(map[string]*clientSession), ready: true, bUdp: false}
			client.pipes[0] = remoteConn
			g_ClientMap[clientId] = client
		} else {
			client.pipes[0] = remoteConn
			client.ready = true
			client.bUdp = false
		}
		//log.Println("client init csmode", clientId, sessionId)
		if *localAddr != "socks5" {
			s_conn, err := net.DialTimeout("tcp", *localAddr, 10*time.Second)
			if err != nil {
				log.Println("connect to local server fail:", err.Error())
				msg := "cannot connect to bind addr" + *localAddr
				common.Write(remoteConn, clientId, "tunnel_error", msg)
				//remoteConn.Close()
				return
			} else {
				client.sessionLock.Lock()
				client.sessions[sessionId] = &clientSession{pipe: remoteConn, localConn: s_conn}
				client.sessionLock.Unlock()
				go handleLocalPortResponse(client, oriId)
			}
		} else {
			client.sessionLock.Lock()
			client.sessions[sessionId] = &clientSession{pipe: remoteConn, localConn: nil, status: "init", recvMsg: ""}
			client.sessionLock.Unlock()
		}
	case "csmode_c_begin":
		client, bHave := g_ClientMap[clientId]
		if !bHave {
			client = &Client{id: clientId, pipes: make(map[int]net.Conn), engine: nil, buster: false, sessions: make(map[string]*clientSession), ready: true, bUdp: false}
			client.pipes[0] = remoteConn
			g_ClientMap[clientId] = client
		} else {
			client.pipes[0] = remoteConn
			client.ready = true
			client.bUdp = false
		}
		if client.MultiListen() {
			common.Write(remoteConn, clientId, "makeholeok", "csmode")
		}
	case "csmode_msg_c":
		oriId := clientId
		arr := strings.Split(clientId, "-")
		clientId = arr[0]
		sessionId := arr[1]
		client, bHave := g_ClientMap[clientId]
		if bHave {
			session := client.getSession(sessionId)
			if session != nil && session.localConn != nil {
				session.localConn.Write([]byte(content))
			} else if session != nil && *localAddr == "socks5" {
				session.processSockProxy(client, oriId, content, func() {
					if len(session.recvMsg) > 0 && session.localConn != nil {
						session.localConn.Write([]byte(session.recvMsg))
					}
				})
			}
		}
	case "csmode_msg_s":
		arr := strings.Split(clientId, "-")
		clientId = arr[0]
		sessionId := arr[1]
		client, bHave := g_ClientMap[clientId]
		if bHave {
			session := client.getSession(sessionId)
			if session != nil && session.localConn != nil {
				session.localConn.Write([]byte(content))
			} else {
				//log.Println("cs:cannot tunnel msg", sessionId)
			}
		}
	}
}
コード例 #12
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func (session *clientSession) processSockProxy(sc *Client, sessionId, content string, callback func()) {
	pipe := session.pipe
	session.recvMsg += content
	bytes := []byte(session.recvMsg)
	size := len(bytes)
	//log.Println("recv msg-====", len(session.recvMsg),  session.recvMsg, session.status, sessionId)
	switch session.status {
	case "init":
		if session.localConn != nil {
			session.localConn.Close()
			session.localConn = nil
		}
		if size < 2 {
			//println("wait init")
			return
		}
		var _, nmethod uint8 = bytes[0], bytes[1]
		//println("version", version, nmethod)
		session.status = "version"
		session.recvMsg = string(bytes[2:])
		session.extra = nmethod
	case "version":
		if uint8(size) < session.extra {
			//println("wait version")
			return
		}
		var send = []uint8{5, 0}
		go common.Write(pipe, sessionId, "tunnel_msg_s", string(send))
		session.status = "hello"
		session.recvMsg = string(bytes[session.extra:])
		session.extra = 0
		//log.Println("now", len(session.recvMsg))
	case "hello":
		var hello reqMsg
		bOk, tail := hello.read(bytes)
		if bOk {
			go func() {
				var ansmsg ansMsg
				url := hello.url
				var s_conn net.Conn
				var err error
				if *dnsCacheNum > 0 && hello.atyp == 3 {
					host := string(hello.dst_addr[1 : 1+hello.dst_addr[0]])
					resChan := make(chan *dnsQueryRes)
					checkDns <- &dnsQueryReq{c: resChan, host: host, port: int(hello.dst_port2), reqtype: hello.reqtype, url: url}
					res := <-resChan
					s_conn = res.conn
					err = res.err
					if res.ip != "" {
						url = net.JoinHostPort(res.ip, fmt.Sprintf("%d", hello.dst_port2))
					}
				}
				if s_conn == nil && err == nil {
					s_conn, err = net.DialTimeout(hello.reqtype, url, 30*time.Second)
				}
				if err != nil {
					log.Println("connect to local server fail:", err.Error())
					ansmsg.gen(&hello, 4)
					go common.Write(pipe, sessionId, "tunnel_msg_s", string(ansmsg.buf[:ansmsg.mlen]))
					return
				} else {
					session.localConn = s_conn
					go handleLocalPortResponse(sc, sessionId)
					ansmsg.gen(&hello, 0)
					go common.Write(pipe, sessionId, "tunnel_msg_s", string(ansmsg.buf[:ansmsg.mlen]))
					session.status = "ok"
					session.recvMsg = string(tail)
					callback()
					return
				}
			}()
		} else {
			//log.Println("wait hello")
		}
		return
	case "ok":
		return
	}
	session.processSockProxy(sc, sessionId, "", callback)
}
コード例 #13
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func main() {
	flag.Parse()
	checkDns = make(chan *dnsQueryReq)
	checkDnsRes = make(chan *dnsQueryBack)
	go dnsLoop()
	if *bShowVersion {
		fmt.Printf("%.2f\n", common.Version)
		return
	}
	if !*bVerbose {
		log.SetOutput(ioutil.Discard)
	}
	if *dataShards < 0 || *dataShards >= 128 {
		println("-ds should in [0-127]")
		return
	}
	if *parityShards < 0 || *parityShards >= 128 {
		println("-ds should in [0-127]")
		return
	}
	if *serveName == "" && *linkName == "" {
		println("you must assign reg or link")
		return
	}
	if *serveName != "" && *linkName != "" {
		println("you must assign reg or link, not both of them")
		return
	}
	if *localAddr == "" {
		println("you must assign the local addr")
		return
	}
	if *serveName != "" {
		clientType = 0
	} else {
		clientType = 1
	}
	if *bEncrypt {
		if clientType != 1 {
			println("only link size need encrypt")
			return
		}
	}
	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt, syscall.SIGTERM)
		n := 0
		for {
			<-c
			log.Println("received signal,shutdown")
			bForceQuit = true
			if remoteConn != nil {
				remoteConn.Close()
			}
			n++
			if n > 5 {
				log.Println("force shutdown")
				os.Exit(-1)
			}
		}
	}()

	loop := func() bool {
		if bForceQuit {
			return true
		}
		g_ClientMap = make(map[string]*Client)
		g_ClientMapKey = make(map[string]*cipher.Block)
		g_Id2UDPSession = make(map[string]*UDPMakeSession)
		//var err error
		if *bUseSSL {
			_remoteConn, err := tls.Dial("tcp", *serverAddr, &tls.Config{InsecureSkipVerify: true})
			if err != nil {
				println("connect remote err:" + err.Error())
				return false
			}
			remoteConn = net.Conn(_remoteConn)
		} else {
			_remoteConn, err := net.DialTimeout("tcp", *serverAddr, 10*time.Second)
			if err != nil {
				println("connect remote err:" + err.Error())
				return false
			}
			remoteConn = _remoteConn
		}
		println("connect to server succeed")
		go connect()
		q := make(chan bool)
		go func() {
			c := time.NewTicker(time.Second * 10)
		out:
			for {
				select {
				case <-c.C:
					if remoteConn != nil {
						common.Write(remoteConn, "-1", "ping", "")
					}
				case <-q:
					break out
				}
			}
			c.Stop()
		}()

		common.Read(remoteConn, handleResponse)
		q <- true
		for clientId, client := range g_ClientMap {
			log.Println("client shutdown", clientId)
			client.Quit()
		}

		for _, session := range g_Id2UDPSession {
			if session.engine != nil {
				session.engine.Fail()
			}
		}
		if remoteConn != nil {
			remoteConn.Close()
		}
		if bForceQuit {
			return true
		}
		return false
	}
	if clientType == 0 {
		for {
			if loop() {
				break
			}
			time.Sleep(10 * time.Second)
		}
	} else {
		loop()
	}
	log.Println("service shutdown")
}
コード例 #14
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func (session *UDPMakeSession) beginMakeHole(content string) {
	engine := session.engine
	if engine == nil {
		return
	}
	addrList := content
	if session.buster {
		engine.SetOtherAddrList(addrList)
	}
	log.Println("begin bust", session.id, session.sessionId, session.buster)
	if clientType == 1 && !session.buster {
		log.Println("retry bust!")
	}
	report := func() {
		if session.buster {
			if session.delay > 0 {
				log.Println("try to delay", session.delay, "seconds")
				time.Sleep(time.Duration(session.delay) * time.Second)
			}
			go common.Write(remoteConn, session.id, "success_bust_a", "")
		}
	}
	oldSession := session
	var aesBlock *cipher.Block
	if clientType == 1 {
		aesBlock = aesKey
	} else {
		aesBlock, _ = g_ClientMapKey[session.sessionId]
	}
	var conn net.Conn
	var err error
	if aesBlock == nil {
		conn, err = engine.GetConn(report, nil, nil)
	} else {
		conn, err = engine.GetConn(report, func(s []byte) []byte {
			if aesBlock == nil {
				return s
			} else {
				padLen := aes.BlockSize - (len(s) % aes.BlockSize)
				for i := 0; i < padLen; i++ {
					s = append(s, byte(padLen))
				}
				srcLen := len(s)
				encryptText := make([]byte, srcLen+aes.BlockSize)
				iv := encryptText[srcLen:]
				for i := 0; i < len(iv); i++ {
					iv[i] = byte(i)
				}
				mode := cipher.NewCBCEncrypter(*aesBlock, iv)
				mode.CryptBlocks(encryptText[:srcLen], s)
				return encryptText
			}
		}, func(s []byte) []byte {
			if aesBlock == nil {
				return s
			} else {
				if len(s) < aes.BlockSize*2 || len(s)%aes.BlockSize != 0 {
					return []byte{}
				}
				srcLen := len(s) - aes.BlockSize
				decryptText := make([]byte, srcLen)
				iv := s[srcLen:]
				mode := cipher.NewCBCDecrypter(*aesBlock, iv)
				mode.CryptBlocks(decryptText, s[:srcLen])
				paddingLen := int(decryptText[srcLen-1])
				if paddingLen > 16 {
					return []byte{}
				}
				return decryptText[:srcLen-paddingLen]
			}
		})
	}
	session, _bHave := g_Id2UDPSession[session.id]
	if session != oldSession {
		return
	}
	if !_bHave {
		return
	}
	delete(g_Id2UDPSession, session.id)
	if err == nil {
		if !session.buster {
			common.Write(remoteConn, session.id, "makeholeok", "")
		}
		client, bHave := g_ClientMap[session.sessionId]
		if !bHave {
			client = &Client{id: session.sessionId, engine: session.engine, buster: session.buster, ready: true, bUdp: true, sessions: make(map[string]*clientSession), specPipes: make(map[string]net.Conn), pipes: make(map[int]net.Conn)}
			g_ClientMap[session.sessionId] = client
		}
		if isCommonSessionId(session.pipeType) {
			size := len(client.pipes)
			client.pipes[size] = conn
			go client.Run(size, "")
			log.Println("add common session", session.buster, session.sessionId, session.id)
			if clientType == 1 {
				if len(client.pipes) == *pipeNum {
					client.MultiListen()
				}
			}
		} else {
			client.specPipes[session.pipeType] = conn
			go client.Run(-1, session.pipeType)
			log.Println("add session for", session.pipeType)
		}
	} else {
		delete(g_ClientMap, session.sessionId)
		delete(g_ClientMapKey, session.sessionId)
		log.Println("cannot connect", err.Error())
		if !session.buster && err.Error() != "quit" {
			common.Write(remoteConn, session.id, "makeholefail", "")
		}
	}
}
コード例 #15
0
ファイル: client.go プロジェクト: vzex/dog-tunnel
func (sc *Client) OnTunnelRecv(pipe net.Conn, sessionId string, action string, content string) {
	//println("recv p2p tunnel", sessionId, action, content)
	session := sc.getSession(sessionId)
	var conn net.Conn
	if session != nil {
		conn = session.localConn
	}
	switch action {
	case "tunnel_error":
		if conn != nil {
			conn.Write([]byte(content))
			log.Println("tunnel error", content, sessionId)
		}
		sc.removeSession(sessionId)
		//case "serve_begin":
	case "tunnel_msg_s":
		if conn != nil {
			//println("tunnel msg", sessionId, len(content))
			conn.Write([]byte(content))
		} else {
			//log.Println("cannot tunnel msg", sessionId)
		}
	case "tunnel_close_s":
		sc.removeSession(sessionId)
	case "ping", "pingback":
		//log.Println("recv", action)
		if action == "ping" {
			common.Write(pipe, sessionId, "pingback", "")
		}
	case "tunnel_msg_c":
		if conn != nil {
			//log.Println("tunnel", len(content), sessionId)
			conn.Write([]byte(content))
		} else if *localAddr == "socks5" {
			if session == nil {
				return
			}
			session.processSockProxy(sc, sessionId, content, func() {
				sc.OnTunnelRecv(pipe, sessionId, action, session.recvMsg)
			})
		}
	case "tunnel_close":
		sc.removeSession(sessionId)
	case "tunnel_open":
		if clientType == 0 {
			if *localAddr != "socks5" {
				s_conn, err := net.DialTimeout("tcp", *localAddr, 10*time.Second)
				if err != nil {
					log.Println("connect to local server fail:", err.Error())
					msg := "cannot connect to bind addr" + *localAddr
					common.Write(pipe, sessionId, "tunnel_error", msg)
					//remoteConn.Close()
					return
				} else {
					sc.sessionLock.Lock()
					sc.sessions[sessionId] = &clientSession{pipe: pipe, localConn: s_conn}
					sc.sessionLock.Unlock()
					go handleLocalPortResponse(sc, sessionId)
				}
			} else {
				sc.sessionLock.Lock()
				sc.sessions[sessionId] = &clientSession{pipe: pipe, localConn: nil, status: "init", recvMsg: ""}
				sc.sessionLock.Unlock()
			}
		}
	}
}
コード例 #16
0
ファイル: server.go プロジェクト: vzex/dog-tunnel
func handleResponse(conn net.Conn, id string, action string, content string) {
	//log.Println("got", id, action, content)
	common.GetClientInfoByConn(conn, func(client *common.ClientInfo) {
		client.ResponseTime = time.Now().Unix()
	}, func() {
	})
	switch action {
	case "init":
		clientInfoStr := content
		var clientInfo common.ClientSetting
		err := json.Unmarshal([]byte(clientInfoStr), &clientInfo)
		if err != nil {
			log.Println("error decode clientinfo, kick out", conn.RemoteAddr().String())
			common.Write(conn, "0", "showandquit", "server decode clientInfo error")
			return
		}
		if common.Version != clientInfo.Version {
			s_version := fmt.Sprintf("%.2f", common.Version)
			c_version := fmt.Sprintf("%.2f", clientInfo.Version)
			log.Println("version not eq", conn.RemoteAddr().String(), s_version, c_version)
			common.Write(conn, "0", "showandquit", "client version:"+c_version+" not eq with server:"+s_version)
			return
		}
		ServerName := clientInfo.Name
		if clientInfo.ClientType == "reg" {
			var user *auth.User
			if bUseDB {
				if clientInfo.AccessKey == "" {
					user, _ = auth.GetUser("test")
				} else {
					user, _ = auth.GetUserByKey(clientInfo.AccessKey)
				}
			} else {
				user = &auth.User{UserType: auth.UserType_Admin}
			}
			//fmt.Printf("%+v\n", user)
			if user == nil {
				common.Write(conn, "0", "showandquit", "invalid user accessKey:"+clientInfo.AccessKey+"!!!")
				return
			}
			if !user.CheckOnlineServiceNum() {
				common.Write(conn, "0", "showandquit", "online service num cannot overstep "+strconv.Itoa(user.MaxOnlineServerNum))
				return
			}
			if !user.CheckIpLimit(conn.RemoteAddr().(*net.TCPAddr).IP.String()) {
				common.Write(conn, "0", "showandquit", "ip limit service num cannot overstep "+strconv.Itoa(user.MaxSameIPServers))
				return
			}
			f := func() {
				common.ServerName2Conn[ServerName] = conn
				common.GetClientInfoByConn(conn, func(info *common.ClientInfo) {
					info.ServerName = ServerName
					info.IsServer = true
					info.Id2MakeSession = make(map[string]*common.UDPMakeSession)
					info.UserName = user.UserName
					info.ClientKey = clientInfo.ClientKey
				}, func() {})
				log.Println("client reg service success", conn.RemoteAddr().String(), user.UserName, ServerName)
				common.Write(conn, "0", "show", "register service ok, user:"******"force unregister service Name", server.ServerName)
					if bUseDB {
						user, _ := auth.GetUser(server.UserName)
						if user != nil {
							user.OnLogout()
						}
					}
					delete(common.Conn2ClientInfo, _conn)
					common.Write(_conn, "0", "showandquit", "some one kick you out")
					_conn.Close()
					f()
				} else {
					common.Write(conn, "0", "showandretry", "already have the ServerName!")
				}
			}, f)
		} else if clientInfo.ClientType == "link" {
			if clientInfo.Mode < 0 || clientInfo.Mode > 2 {
				clientInfo.Mode = 0
			}
			ServerName := clientInfo.Name
			bAuth := true
			common.GetClientInfoByName(ServerName, func(info *common.ClientInfo) {
				var user *auth.User
				if bUseDB {
					user, _ = auth.GetUser(info.UserName)
				} else {
					user = &auth.User{UserType: auth.UserType_Admin}
				}
				//fmt.Printf("%+v\n", user)
				if user == nil {
					common.Write(conn, "0", "showandquit", "invalid user:"******"!!!")
					bAuth = false
					return
				}
				if info.ClientKey != clientInfo.ClientKey {
					common.Write(conn, "0", "showandquit", "clientkey invalid!!!")
					bAuth = false
					return
				}
				if !user.CheckSessionNum(len(info.ClientMap)) {
					common.Write(conn, "0", "showandquit", "session numcannot overstep "+strconv.Itoa(len(info.ClientMap)))
					bAuth = false
					return
				}
				if !user.CheckPipeNum(clientInfo.PipeNum) {
					common.Write(conn, "0", "showandquit", "pipenum cannot overstep "+strconv.Itoa(user.MaxPipeNum))
					bAuth = false
					return
				}
			}, func() {
				common.Write(conn, "0", "showandquit", "serverName invalid!!!")
				bAuth = false
			})
			if !bAuth {
				return
			}
			common.GetClientInfoByConn(conn, func(client *common.ClientInfo) {
				client.ServerName = ServerName
			}, func() {
			})
			common.GetClientInfoByName(ServerName, func(server *common.ClientInfo) {
				log.Println("client link service success", conn.RemoteAddr().String(), ServerName)
				server.AddClient(conn, clientInfo)
			}, func() {
				common.Write(conn, "0", "showandquit", "donnt have this service name")
			})
		}
	case "tunnel_error":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			log.Println("<<=====tunnel_error", server.ServerName, conn.RemoteAddr().String())
			session, bHave := server.Id2Session[id]
			if bHave {
				session.Status = "fail"
				common.Write(session.ClientA, "0", "showandquit", content)
				server.DelClient(session.ClientA)
			}
		}, func() {
		})
	case "makeholefail":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			udpsession, bHave := server.Id2MakeSession[id]
			if bHave {
				log.Println("<<=====make hole fail", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id)
				sessionId := udpsession.SessionId
				session, _bHave := server.Id2Session[sessionId]
				if _bHave {
					session.Status = "fail"
					session.MakeHoleResponseN++
					session.MakeHoleHasFail = true
					if session.MakeHoleResponseN == session.Setting.PipeNum {
						if session.Method == "udp" {
							session.RestartSession(server.ServerName)
						} else if session.Method == "restart" {
							if session.Setting.Mode == 0 {
								tmp := session.ClientA
								session.ClientA = session.ClientB
								session.ClientB = tmp
								session.StartCSMode()
							} else {
								server.DelClient(session.ClientB)
							}
						} else {
							server.DelClient(session.ClientA)
						}
					}
				}
				udpsession.Remove(false)
			}
		}, func() {
		})
	case "makeholeok":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			if content == "csmode" {
				session, _bHave := server.Id2Session[id]
				if _bHave {
					log.Println("<<=====make hole ok", conn.RemoteAddr().String(), server.ServerName, session.Id)
					session.Status = "ok"
					session.MakeHoleResponseN++
				}
			}
			udpsession, bHave := server.Id2MakeSession[id]
			if bHave {
				log.Println("<<=====make hole ok", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id)
				sessionId := udpsession.SessionId
				session, _bHave := server.Id2Session[sessionId]
				if _bHave {
					session.MakeHoleResponseN++
					if session.MakeHoleResponseN == session.Setting.PipeNum {
						if !session.MakeHoleHasFail {
							session.Status = "ok"
						}
					}
				}
				udpsession.Remove(false)
			}
		}, func() {
		})
	case "report_addrlist":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			udpsession, bHave := server.Id2MakeSession[id]
			//log.Println("test", udpsession, id, server.ServerName)
			if bHave {
				log.Println("<<===report addr list ok", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.Id)
				udpsession.BeginMakeHole(1, content)
			}
		}, func() {
		})
	case "success_bust_a":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			udpsession, bHave := server.Id2MakeSession[id]
			if bHave {
				log.Println("<<=====success_bust_a", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id)
				udpsession.BeginMakeHole(2, content)
			}
		}, func() {
		})
	// for c/s mode
	case "tunnel_close":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			session := server.GetSession(conn)
			if session != nil {
				common.Write(session.ClientB, session.Id+"-"+id, "csmode_s_tunnel_close", content)
			} else {
				println("no session")
			}
		}, func() {
		})
	case "tunnel_open":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			session := server.GetSession(conn)
			if session != nil {
				common.Write(session.ClientB, session.Id+"-"+id, "csmode_s_tunnel_open", content)
			} else {
				println("no session")
			}
		}, func() {
		})
	case "tunnel_msg_c":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			var user *auth.User
			if bUseDB {
				user, _ = auth.GetUser(server.UserName)
			} else {
				user = &auth.User{UserType: auth.UserType_Admin}
			}
			if user == nil {
				common.Write(conn, "0", "showandquit", "cannot get userinfo of this service "+server.UserName)
				return
			}
			if !user.UpdateCSMode(len(content)) {
				common.Write(conn, "0", "showandquit", "reach today's csmode data limit")
				return
			}
			session := server.GetSession(conn)
			if session != nil {
				common.Write(session.ClientB, session.Id+"-"+id, "csmode_msg_c", content)
			} else {
				println("no session")
			}
		}, func() {
		})
	case "tunnel_msg_s":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			var user *auth.User
			if bUseDB {
				user, _ = auth.GetUser(server.UserName)
			} else {
				user = &auth.User{UserType: auth.UserType_Admin}
			}
			if user == nil {
				common.Write(conn, "0", "showandquit", "cannot get userinfo of this service"+server.UserName)
				return
			}
			if !user.UpdateCSMode(len(content)) {
				common.Write(conn, "0", "show", "reach today's csmode data limit")
				return
			}
			arr := strings.Split(id, "-")
			clientId := arr[0]
			session, bHave := server.Id2Session[clientId]
			if bHave {
				common.Write(session.ClientA, id, "csmode_msg_s", content)
			} else {
				println("no session")
			}
		}, func() {
		})
	case "tunnel_close_s":
		common.GetServerInfoByConn(conn, func(server *common.ClientInfo) {
			arr := strings.Split(id, "-")
			clientId := arr[0]
			session, bHave := server.Id2Session[clientId]
			if bHave {
				common.Write(session.ClientA, id, "csmode_c_tunnel_close", content)
			} else {
				println("no session")
			}
		}, func() {
		})
	}
}