mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			WIP tunnel states, re-dial when not required needs debugging.
This commit is contained in:
		
							parent
							
								
									dd37922fb2
								
							
						
					
					
						commit
						3b35751e2e
					
				| 
						 | 
				
			
			@ -56,7 +56,6 @@ const (
 | 
			
		|||
 | 
			
		||||
	// Tunnel setup/control/status
 | 
			
		||||
	CSOTunSetup    // client -> server tunnel setup request (dstport)
 | 
			
		||||
	CSOTunInUse    // server -> client: tunnel rport is in use
 | 
			
		||||
	CSOTunSetupAck // server -> client tunnel setup ack
 | 
			
		||||
	CSOTunAccept   // client -> server: tunnel client got an Accept()
 | 
			
		||||
	// (Do we need a CSOTunAcceptAck server->client?)
 | 
			
		||||
| 
						 | 
				
			
			@ -66,23 +65,26 @@ const (
 | 
			
		|||
	CSOTunHangup  // client -> server: tunnel lport hung up
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TunEndpoint.tunCtl control values
 | 
			
		||||
// TunEndpoint.tunCtl control values - used to control workers for client or server tunnels
 | 
			
		||||
// depending on the code
 | 
			
		||||
const (
 | 
			
		||||
	TunCtl_AcceptedClient = 'a' // client side has accept()ed a conn
 | 
			
		||||
	TunCtl_Client_Listen = 'a'
 | 
			
		||||
	
 | 
			
		||||
	TunCtl_Server_Dial = 'd' // server has dialled OK, client side can accept() conns
 | 
			
		||||
	// [CSOTunAccept]
 | 
			
		||||
	// status: client listen() worker accepted conn on lport
 | 
			
		||||
	// action:server side should dial() rport on client's behalf
 | 
			
		||||
 | 
			
		||||
	TunCtl_LostClient = 'h' // client side has hung up
 | 
			
		||||
	TunCtl_Info_Hangup = 'h' // client side has hung up
 | 
			
		||||
	// [CSOTunHangup]
 | 
			
		||||
	// status: client side conn hung up from lport
 | 
			
		||||
	// action:server side should hang up on rport, on client's behalf
 | 
			
		||||
 | 
			
		||||
	TunCtl_ConnRefused = 'r' // server side couldn't complete tunnel
 | 
			
		||||
	TunCtl_Info_ConnRefused = 'r' // server side couldn't complete tunnel
 | 
			
		||||
	// [CSOTunRefused]
 | 
			
		||||
	// status:server side could not dial() remote side
 | 
			
		||||
 | 
			
		||||
	TunCtl_LostConn = 'l' // server side disconnected
 | 
			
		||||
	
 | 
			
		||||
	TunCtl_Info_LostConn = 'x' // server side disconnected
 | 
			
		||||
	// [CSOTunDisconn]
 | 
			
		||||
	// status:server side lost connection to rport
 | 
			
		||||
	// action:client should disconnect accepted lport connection
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ type (
 | 
			
		|||
		Cols       uint16
 | 
			
		||||
 | 
			
		||||
		chaff ChaffConfig
 | 
			
		||||
		tuns  map[uint16]*TunEndpoint
 | 
			
		||||
		tuns  *map[uint16](*TunEndpoint)
 | 
			
		||||
 | 
			
		||||
		closeStat *CSOType      // close status (CSOExitStatus)
 | 
			
		||||
		r         cipher.Stream //read cipherStream
 | 
			
		||||
| 
						 | 
				
			
			@ -208,6 +208,8 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) {
 | 
			
		|||
		closeStat: new(CSOType),
 | 
			
		||||
		WinCh:     make(chan WinSize, 1),
 | 
			
		||||
		dBuf:      new(bytes.Buffer)}
 | 
			
		||||
	tempMap := make(map[uint16]*TunEndpoint)
 | 
			
		||||
	hc.tuns = &tempMap
 | 
			
		||||
 | 
			
		||||
	*hc.closeStat = CSEStillOpen // open or prematurely-closed status
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -814,39 +816,58 @@ func (hc Conn) Read(b []byte) (n int, err error) {
 | 
			
		|||
				// server side tunnel setup in response to client
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("Read(): Tunnel setup [%d:%d]", lport, rport))
 | 
			
		||||
				hc.StartServerTunnel(lport, rport)
 | 
			
		||||
				hc.tuns[rport].Ctl <- 'a' // Dial() rport
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d", rport))
 | 
			
		||||
				if _, ok := (*hc.tuns)[rport]; !ok {
 | 
			
		||||
					// tunnel first-time open
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Server] Got Initial CSOTunSetup [%d:%d]", lport, rport))
 | 
			
		||||
					hc.StartServerTunnel(lport, rport)
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Server] Got CSOTunSetup [%d:%d]", lport, rport))
 | 
			
		||||
				}
 | 
			
		||||
				(*hc.tuns)[rport].Ctl <- 'd' // Dial() rport
 | 
			
		||||
			} else if ctrlStatOp == CSOTunSetupAck {
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("Read(): Tunnel setup ack [%d:%d]", lport, rport))
 | 
			
		||||
				hc.dBuf.Write(payloadBytes)
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d\n", rport))
 | 
			
		||||
				if _, ok := (*hc.tuns)[rport]; !ok {
 | 
			
		||||
					// tunnel first-time open
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Client] Got Initial CSOTunSetupAck [%d:%d]", lport, rport))
 | 
			
		||||
					hc.StartClientTunnel(lport, rport)
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Client] Got CSOTunSetupAck [%d:%d]", lport, rport))
 | 
			
		||||
				}
 | 
			
		||||
				(*hc.tuns)[rport].Ctl <- 'a' // Listen() for lport connection
 | 
			
		||||
			} else if ctrlStatOp == CSOTunRefused {
 | 
			
		||||
				// client side has been told nothing is listening on rport
 | 
			
		||||
				// client side receiving CSOTunRefused means the remote side
 | 
			
		||||
				// could not dial() rport. So we cannot yet listen()
 | 
			
		||||
				// for client-side on lport.
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("Read(): Tunnel refused [%d:%d]", lport, rport))
 | 
			
		||||
				hc.dBuf.Write(payloadBytes)
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d\n", rport))
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[Client] Got CSOTunRefused [%d:%d]", lport, rport))
 | 
			
		||||
				(*hc.tuns)[rport].Ctl <- 'r' // client should NOT Listen()
 | 
			
		||||
			} else if ctrlStatOp == CSOTunDisconn {
 | 
			
		||||
				// server side's rport has disconnected (server lost)
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("Read(): Tunnel server disconnected [%d:%d]", lport, rport))
 | 
			
		||||
				hc.dBuf.Write(payloadBytes)
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d\n", rport))
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[Client] Got CSOTunDisconn [%d:%d]", lport, rport))
 | 
			
		||||
				(*hc.tuns)[rport].Ctl <- 'x' // client should hangup on current lport conn
 | 
			
		||||
			} else if ctrlStatOp == CSOTunHangup {
 | 
			
		||||
				// client side's lport has hung up
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("Read(): Tunnel client hung up [%d:%d]", lport, rport))
 | 
			
		||||
				hc.dBuf.Write(payloadBytes)
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d\n", rport))
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[Server] Got CSOTunHangup [%d:%d]", lport, rport))
 | 
			
		||||
				(*hc.tuns)[rport].Ctl <- 'h' // server should hang up on currently-dialled rport
 | 
			
		||||
			} else if ctrlStatOp == CSOTunData {
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes[0:2])
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("mapkey is %d\n", rport))
 | 
			
		||||
				//fmt.Printf("[Got CSOTunData: [lport %d:rport %d] data:%v\n", lport, rport, payloadBytes[4:])
 | 
			
		||||
				if hc.tuns[rport] != nil {
 | 
			
		||||
				if _, ok := (*hc.tuns)[rport]; ok {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Writing data to rport [%d:%d]", lport, rport))
 | 
			
		||||
					hc.tuns[rport].Data <- payloadBytes[4:]
 | 
			
		||||
					(*hc.tuns)[rport].Data <- payloadBytes[4:]
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Attempt to write data to closed tun [%d:%d]", lport, rport))
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,118 +48,147 @@ type (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func (hc *Conn) InitTunEndpoint(lp uint16, p string /* net.Addr */, rp uint16) {
 | 
			
		||||
	if hc.tuns == nil {
 | 
			
		||||
		hc.tuns = make(map[uint16]*TunEndpoint)
 | 
			
		||||
	if (*hc.tuns) == nil {
 | 
			
		||||
		(*hc.tuns) = make(map[uint16]*TunEndpoint)
 | 
			
		||||
	}
 | 
			
		||||
	if hc.tuns[rp] == nil {
 | 
			
		||||
	if (*hc.tuns)[rp] == nil {
 | 
			
		||||
		var addrs []net.Addr
 | 
			
		||||
		if p == "" {
 | 
			
		||||
			addrs, _ = net.InterfaceAddrs()
 | 
			
		||||
			p = addrs[0].String()
 | 
			
		||||
		}
 | 
			
		||||
		hc.tuns[rp] = &TunEndpoint{ /*Status: CSOTunSetup,*/ Peer: p,
 | 
			
		||||
		(*hc.tuns)[rp] = &TunEndpoint{ /*Status: CSOTunSetup,*/ Peer: p,
 | 
			
		||||
			Lport: lp, Rport: rp, Data: make(chan []byte, 1),
 | 
			
		||||
			Ctl: make(chan rune, 1)}
 | 
			
		||||
		logger.LogDebug(fmt.Sprintf("InitTunEndpoint [%d:%s:%d]\n", lp, p, rp))
 | 
			
		||||
		logger.LogDebug(fmt.Sprintf("InitTunEndpoint [%d:%s:%d]", lp, p, rp))
 | 
			
		||||
	} else {
 | 
			
		||||
		logger.LogDebug(fmt.Sprintf("InitTunEndpoint [reusing] [%d:%s:%d]", (*hc.tuns)[rp].Lport, (*hc.tuns)[rp].Peer, (*hc.tuns)[rp].Rport))
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hc *Conn) StartClientTunnel(lport, rport uint16) {
 | 
			
		||||
	hc.InitTunEndpoint(lport, "", rport)
 | 
			
		||||
	t := hc.tuns[rport] // for convenience
 | 
			
		||||
 | 
			
		||||
	t := (*hc.tuns)[rport] // for convenience
 | 
			
		||||
	var l HKExListener
 | 
			
		||||
	go func() {
 | 
			
		||||
		logger.LogDebug(fmt.Sprintf("Listening for client tunnel port %d", lport))
 | 
			
		||||
		l, e := net.Listen("tcp", fmt.Sprintf(":%d", lport))
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			logger.LogDebug(fmt.Sprintf("[Could not get lport %d! (%s)", lport, e))
 | 
			
		||||
		} else {
 | 
			
		||||
			defer l.Close()
 | 
			
		||||
			for {
 | 
			
		||||
				c, e := l.Accept()
 | 
			
		||||
 | 
			
		||||
				defer func() {
 | 
			
		||||
					c.Close()
 | 
			
		||||
				}()
 | 
			
		||||
		weAreListening := false
 | 
			
		||||
		for cmd := range t.Ctl {
 | 
			
		||||
			logger.LogDebug(fmt.Sprintf("[ClientTun] Listening for client tunnel port %d", lport))
 | 
			
		||||
 | 
			
		||||
			if cmd == 'a' && !weAreListening {
 | 
			
		||||
				l, e := net.Listen("tcp", fmt.Sprintf(":%d", lport))
 | 
			
		||||
				if e != nil {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("Accept() got error(%v), hanging up.", e))
 | 
			
		||||
					break
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[ClientTun] Could not get lport %d! (%s)", lport, e))
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintln("Accepted tunnel client"))
 | 
			
		||||
 | 
			
		||||
					// outside client -> tunnel lport
 | 
			
		||||
					go func() {
 | 
			
		||||
					weAreListening = true
 | 
			
		||||
					for {
 | 
			
		||||
						c, e := l.Accept()
 | 
			
		||||
						var tunDst bytes.Buffer
 | 
			
		||||
						// ask server to dial() its side, rport
 | 
			
		||||
						binary.Write(&tunDst, binary.BigEndian, lport)
 | 
			
		||||
						binary.Write(&tunDst, binary.BigEndian, rport)
 | 
			
		||||
						for {
 | 
			
		||||
							rBuf := make([]byte, 1024)
 | 
			
		||||
							//Read data from c, encrypt/write via hc to client(lport)
 | 
			
		||||
							n, e := c.Read(rBuf)
 | 
			
		||||
							if e != nil {
 | 
			
		||||
								if e == io.EOF {
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("lport Disconnected: shutting down tunnel [%d:%d]", lport, rport))
 | 
			
		||||
								} else {
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("Read error from lport of tun [%d:%d]\n%s", lport, rport, e))
 | 
			
		||||
						hc.WritePacket(tunDst.Bytes(), CSOTunSetup)
 | 
			
		||||
 | 
			
		||||
						if e != nil {
 | 
			
		||||
							logger.LogDebug(fmt.Sprintf("[ClientTun] Accept() got error(%v), hanging up.", e))
 | 
			
		||||
							break
 | 
			
		||||
						} else {
 | 
			
		||||
							logger.LogDebug(fmt.Sprintf("[ClientTun] Accepted tunnel client %v", t))
 | 
			
		||||
 | 
			
		||||
							// outside client -> tunnel lport
 | 
			
		||||
							go func() {
 | 
			
		||||
								defer func() {
 | 
			
		||||
									c.Close()
 | 
			
		||||
								}()
 | 
			
		||||
 | 
			
		||||
								var tunDst bytes.Buffer
 | 
			
		||||
								binary.Write(&tunDst, binary.BigEndian, lport)
 | 
			
		||||
								binary.Write(&tunDst, binary.BigEndian, rport)
 | 
			
		||||
								for {
 | 
			
		||||
									rBuf := make([]byte, 1024)
 | 
			
		||||
									//Read data from c, encrypt/write via hc to client(lport)
 | 
			
		||||
									n, e := c.Read(rBuf)
 | 
			
		||||
									if e != nil {
 | 
			
		||||
										if e == io.EOF {
 | 
			
		||||
											logger.LogDebug(fmt.Sprintf("[ClientTun] lport Disconnected: shutting down tunnel %v", t))
 | 
			
		||||
										} else {
 | 
			
		||||
											logger.LogDebug(fmt.Sprintf("[ClientTun] Read error from lport of tun %v\n%s", t, e))
 | 
			
		||||
										}
 | 
			
		||||
										hc.WritePacket(tunDst.Bytes(), CSOTunHangup)
 | 
			
		||||
										break
 | 
			
		||||
									}
 | 
			
		||||
									if n > 0 {
 | 
			
		||||
										rBuf = append(tunDst.Bytes(), rBuf[:n]...)
 | 
			
		||||
										_, de := hc.WritePacket(rBuf[:n+4], CSOTunData)
 | 
			
		||||
										if de != nil {
 | 
			
		||||
											logger.LogDebug(fmt.Sprintf("[ClientTun] Error writing to tunnel %v, %s]\n", t, de))
 | 
			
		||||
											break
 | 
			
		||||
										}
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
								hc.WritePacket(tunDst.Bytes(), CSOTunHangup)
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
							if n > 0 {
 | 
			
		||||
								rBuf = append(tunDst.Bytes(), rBuf[:n]...)
 | 
			
		||||
								hc.WritePacket(rBuf[:n+4], CSOTunData)
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}()
 | 
			
		||||
							}()
 | 
			
		||||
 | 
			
		||||
					// tunnel lport -> outside client (c)
 | 
			
		||||
					go func() {
 | 
			
		||||
						defer func() {
 | 
			
		||||
							c.Close()
 | 
			
		||||
						}()
 | 
			
		||||
							// tunnel lport -> outside client (c)
 | 
			
		||||
							go func() {
 | 
			
		||||
								defer func() {
 | 
			
		||||
									c.Close()
 | 
			
		||||
								}()
 | 
			
		||||
 | 
			
		||||
						for {
 | 
			
		||||
							bytes, ok := <-t.Data
 | 
			
		||||
							if ok {
 | 
			
		||||
								c.Write(bytes)
 | 
			
		||||
							} else {
 | 
			
		||||
								logger.LogDebug(fmt.Sprintf("[Channel closed?]\n"))
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}()
 | 
			
		||||
								for {
 | 
			
		||||
									bytes, ok := <-t.Data
 | 
			
		||||
									if ok {
 | 
			
		||||
										_, e := c.Write(bytes)
 | 
			
		||||
										if e != nil {
 | 
			
		||||
											logger.LogDebug(fmt.Sprintf("[ClientTun] lport conn closed"))
 | 
			
		||||
											break
 | 
			
		||||
										}
 | 
			
		||||
									} else {
 | 
			
		||||
										logger.LogDebug(fmt.Sprintf("[ClientTun] Channel closed?"))
 | 
			
		||||
										break
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
							}()
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
						} // end Accept() worker block
 | 
			
		||||
					} // end for-accept
 | 
			
		||||
				} // end Listen() block
 | 
			
		||||
			} else if cmd == 'r' {
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[ClientTun] Server replied TunRefused %v\n", t))
 | 
			
		||||
			} else if cmd == 'x' {
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[ClientTun] Server replied TunDisconn, closing lport %v\n", t))
 | 
			
		||||
				l.Close()
 | 
			
		||||
				weAreListening = false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		} // end t.Ctl for
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hc *Conn) StartServerTunnel(lport, rport uint16) {
 | 
			
		||||
	hc.InitTunEndpoint(lport, "", rport)
 | 
			
		||||
	t := hc.tuns[rport] // for convenience
 | 
			
		||||
	t := (*hc.tuns)[rport] // for convenience
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		weAreDialled := false
 | 
			
		||||
		for cmd := range t.Ctl {
 | 
			
		||||
			var c net.Conn
 | 
			
		||||
			if cmd == 'a' {
 | 
			
		||||
				logger.LogDebug("Server dialling...")
 | 
			
		||||
			if cmd == 'd' && !weAreDialled {
 | 
			
		||||
				logger.LogDebug("[ServerTun] dialling...")
 | 
			
		||||
				c, err = net.Dial("tcp", fmt.Sprintf(":%d", rport))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("Nothing is serving at rport :%d!", rport))
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[ServerTun] Dial() error for tun %v: %s", t, err))
 | 
			
		||||
					var resp bytes.Buffer
 | 
			
		||||
					binary.Write(&resp, binary.BigEndian /*lport*/, uint16(0))
 | 
			
		||||
					binary.Write(&resp, binary.BigEndian, rport)
 | 
			
		||||
					hc.WritePacket(resp.Bytes(), CSOTunRefused)
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Tunnel Opened - %d:%s:%d]", lport, t.Peer, rport))
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[ServerTun] Tunnel Opened - %v", t))
 | 
			
		||||
					weAreDialled = true
 | 
			
		||||
					var resp bytes.Buffer
 | 
			
		||||
					binary.Write(&resp, binary.BigEndian, lport)
 | 
			
		||||
					binary.Write(&resp, binary.BigEndian, rport)
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[Writing CSOTunSetupAck[%d:%d]", lport, rport))
 | 
			
		||||
					logger.LogDebug(fmt.Sprintf("[ServerTun] Writing CSOTunSetupAck %v", t))
 | 
			
		||||
					hc.WritePacket(resp.Bytes(), CSOTunSetupAck)
 | 
			
		||||
 | 
			
		||||
					//
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +196,9 @@ func (hc *Conn) StartServerTunnel(lport, rport uint16) {
 | 
			
		|||
					//
 | 
			
		||||
					go func() {
 | 
			
		||||
						defer func() {
 | 
			
		||||
							logger.LogDebug("[ServerTun] (deferred hangup workerA)")
 | 
			
		||||
							c.Close()
 | 
			
		||||
							weAreDialled = false
 | 
			
		||||
						}()
 | 
			
		||||
 | 
			
		||||
						var tunDst bytes.Buffer
 | 
			
		||||
| 
						 | 
				
			
			@ -179,15 +210,15 @@ func (hc *Conn) StartServerTunnel(lport, rport uint16) {
 | 
			
		|||
							n, e := c.Read(rBuf)
 | 
			
		||||
							if e != nil {
 | 
			
		||||
								if e == io.EOF {
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("rport Disconnected: shutting down tunnel %v\n", t))
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("[ServerTun] rport Disconnected: shutting down tunnel %v", t))
 | 
			
		||||
								} else {
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("Read error from rport of tun %v\n%s", t, e))
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("[ServerTun] Read error from rport of tun %v: %s", t, e))
 | 
			
		||||
								}
 | 
			
		||||
								var resp bytes.Buffer
 | 
			
		||||
								binary.Write(&resp, binary.BigEndian, lport)
 | 
			
		||||
								binary.Write(&resp, binary.BigEndian, rport)
 | 
			
		||||
								hc.WritePacket(resp.Bytes(), CSOTunDisconn)
 | 
			
		||||
								logger.LogDebug(fmt.Sprintf("Closing server rport %d net.Dial()", t.Rport))
 | 
			
		||||
								logger.LogDebug(fmt.Sprintf("[ServerTun] Closing server rport %d net.Dial()", t.Rport))
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
							if n > 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,22 +231,32 @@ func (hc *Conn) StartServerTunnel(lport, rport uint16) {
 | 
			
		|||
					// worker to read data from client (already decrypted) & fwd to rport
 | 
			
		||||
					go func() {
 | 
			
		||||
						defer func() {
 | 
			
		||||
							logger.LogDebug("[ServerTun] (deferred hangup workerB)")
 | 
			
		||||
							c.Close()
 | 
			
		||||
							weAreDialled = false
 | 
			
		||||
						}()
 | 
			
		||||
 | 
			
		||||
						for {
 | 
			
		||||
							rData, ok := <-t.Data
 | 
			
		||||
							if ok {
 | 
			
		||||
								c.Write(rData)
 | 
			
		||||
								_, e := c.Write(rData)
 | 
			
		||||
								if e != nil {
 | 
			
		||||
									logger.LogDebug(fmt.Sprintf("[ServerTun] ERROR writing to rport conn"))
 | 
			
		||||
									break
 | 
			
		||||
								}
 | 
			
		||||
							} else {
 | 
			
		||||
								logger.LogDebug("[ERROR reading from hc.tuns[] channel - closed?]")
 | 
			
		||||
								logger.LogDebug("[ServerTun] ERROR reading from hc.tuns[] channel - closed?")
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}()
 | 
			
		||||
				}
 | 
			
		||||
			} // TODO: elseifs for other state transtions driven by client
 | 
			
		||||
		}
 | 
			
		||||
	}() // t.Ctl read loop
 | 
			
		||||
	logger.LogDebug("[ServerTunnel() exiting t.Ctl read loop - channel closed??]")
 | 
			
		||||
			} else if cmd == 'h' {
 | 
			
		||||
				// client side has hung up
 | 
			
		||||
				logger.LogDebug(fmt.Sprintf("[ServerTun] Client hung up: hanging up on rport %v", t))
 | 
			
		||||
				weAreDialled = false
 | 
			
		||||
			}
 | 
			
		||||
		} // t.Ctl read loop
 | 
			
		||||
		logger.LogDebug("[ServerTun] Tunnel exiting t.Ctl read loop - channel closed??")
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -349,26 +349,7 @@ func reqTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) {
 | 
			
		|||
	fmt.Printf("bTmp:%x\n", bTmp.Bytes())
 | 
			
		||||
	logger.LogDebug(fmt.Sprintln("[Client sending CSOTunSetup]"))
 | 
			
		||||
	hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunSetup)
 | 
			
		||||
	
 | 
			
		||||
	// Server should reply immediately with CSOTunSetupAck[lport:rport]
 | 
			
		||||
	// hkexnet.Read() on server side handles server side tun setup.
 | 
			
		||||
	resp := make([]byte, 4)
 | 
			
		||||
	var lpResp, rpResp uint16
 | 
			
		||||
	n, e := io.ReadFull(hc, resp)
 | 
			
		||||
	if n < 4 || e != nil {
 | 
			
		||||
		logger.LogErr(fmt.Sprintf("[Client tun response len %d, %s\n", n, e))
 | 
			
		||||
	} else {
 | 
			
		||||
		lpResp = binary.BigEndian.Uint16(resp[0:2])
 | 
			
		||||
		rpResp = binary.BigEndian.Uint16(resp[2:4])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if lpResp == lp && rpResp == rp {
 | 
			
		||||
		logger.LogDebug("[Client got tun setup ack OK]")
 | 
			
		||||
		hc.StartClientTunnel(lp, rp)
 | 
			
		||||
	} else {
 | 
			
		||||
		logger.LogDebug(fmt.Sprintf("[Client tun response ports [%d:%d]\n", lpResp, rpResp))
 | 
			
		||||
		logger.LogDebug(fmt.Sprintln("[Client tun setup FAILED]"))
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue