diff --git a/client.go b/client.go index baa925d..d397d1c 100644 --- a/client.go +++ b/client.go @@ -9,13 +9,14 @@ import ( "time" ) -func NewClient(addr string, server string, target string, timeout int, sproto int, rproto int, catch int, key int, tcpmode bool) (*Client, error) { +func NewClient(addr string, server string, target string, timeout int, sproto int, rproto int, catch int, key int, + tcpmode int) (*Client, error) { var ipaddr *net.UDPAddr var tcpaddr *net.TCPAddr var err error - if tcpmode { + if tcpmode > 0 { tcpaddr, err = net.ResolveTCPAddr("tcp", addr) if err != nil { return nil, err @@ -59,7 +60,7 @@ type Client struct { rproto int catch int key int - tcpmode bool + tcpmode int tcpmode_buffersize int tcpmode_maxwin int tcpmode_resend_timems int @@ -129,7 +130,7 @@ func (p *Client) Run() { defer conn.Close() p.conn = conn - if p.tcpmode { + if p.tcpmode > 0 { tcplistenConn, err := net.ListenTCP("tcp", p.tcpaddr) if err != nil { loggo.Error("Error listening for tcp packets: %s", err.Error()) @@ -150,7 +151,7 @@ func (p *Client) Run() { p.localAddrToConnMap = make(map[string]*ClientConn) p.localIdToConnMap = make(map[string]*ClientConn) - if p.tcpmode { + if p.tcpmode > 0 { go p.AcceptTcp() } else { go p.Accept() @@ -269,7 +270,7 @@ func (p *Client) AcceptTcpConn(conn *net.TCPConn) { p.sendPacketSize += (uint64)(f.size) sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, clientConn.id, (uint32)(DATA), mb, - p.sproto, p.rproto, p.catch, p.key) + p.sproto, p.rproto, p.catch, p.key, p.tcpmode) } } @@ -311,7 +312,7 @@ func (p *Client) Accept() error { clientConn.activeTime = now sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, clientConn.id, (uint32)(DATA), bytes[:n], - p.sproto, p.rproto, p.catch, p.key) + p.sproto, p.rproto, p.catch, p.key, p.tcpmode) p.sequence++ @@ -379,7 +380,7 @@ func (p *Client) Close(clientConn *ClientConn) { func (p *Client) checkTimeoutConn() { - if p.tcpmode { + if p.tcpmode > 0 { return } @@ -404,7 +405,7 @@ func (p *Client) ping() { now := time.Now() b, _ := now.MarshalBinary() sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, "", (uint32)(PING), b, - p.sproto, p.rproto, p.catch, p.key) + p.sproto, p.rproto, p.catch, p.key, p.tcpmode) loggo.Info("ping %s %s %d %d %d %d", p.addrServer, now.String(), p.sproto, p.rproto, p.id, p.sequence) p.sequence++ } @@ -425,7 +426,7 @@ func (p *Client) sendCatch() { if p.catch > 0 { for _, conn := range p.localIdToConnMap { sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, conn.id, (uint32)(CATCH), make([]byte, 0), - p.sproto, p.rproto, p.catch, p.key) + p.sproto, p.rproto, p.catch, p.key, p.tcpmode) p.sequence++ p.sendCatchPacket++ } diff --git a/cmd/main.go b/cmd/main.go index e1e78b5..363378e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -58,7 +58,7 @@ func main() { rproto := flag.Int("rproto", 0, "recv ping proto") catch := flag.Int("catch", 0, "catch mode") key := flag.Int("key", 0, "key") - tcpmode := flag.Bool("tcp", false, "tcp mode") + tcpmode := flag.Int("tcp", 0, "tcp mode") flag.Usage = func() { fmt.Printf(usage) } diff --git a/pingtunnel.go b/pingtunnel.go index 8fbae8d..7fac35a 100644 --- a/pingtunnel.go +++ b/pingtunnel.go @@ -6,7 +6,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/hex" - "fmt" + "github.com/esrrhs/go-engine/src/loggo" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "io" @@ -19,6 +19,7 @@ const ( DATA uint32 = 0x01010101 PING uint32 = 0x02020202 CATCH uint32 = 0x03030303 + FRAME uint32 = 0x04040404 END uint32 = 0xAAAABBBB ) @@ -30,6 +31,7 @@ type MyMsg struct { RPROTO uint16 CATCH uint16 KEY uint32 + TCPMODE uint16 ENDTYPE uint32 } @@ -38,7 +40,7 @@ func (p *MyMsg) Len(proto int) int { if p == nil { return 0 } - return 4 + p.LenString(p.ID) + p.LenString(p.TARGET) + p.LenData(p.Data) + 2 + 2 + 4 + 4 + return 4 + p.LenString(p.ID) + p.LenString(p.TARGET) + p.LenData(p.Data) + 2 + 2 + 4 + 2 + 4 } func (p *MyMsg) LenString(s string) int { @@ -71,7 +73,9 @@ func (p *MyMsg) Marshal(proto int) ([]byte, error) { binary.BigEndian.PutUint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+4:], uint32(p.KEY)) - binary.BigEndian.PutUint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+8:], uint32(p.ENDTYPE)) + binary.BigEndian.PutUint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+8:], uint16(p.TCPMODE)) + + binary.BigEndian.PutUint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+10:], uint32(p.ENDTYPE)) return b, nil } @@ -110,7 +114,9 @@ func (p *MyMsg) Unmarshal(b []byte) error { p.KEY = binary.BigEndian.Uint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+4:]) - p.ENDTYPE = binary.BigEndian.Uint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+8:]) + p.TCPMODE = binary.BigEndian.Uint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+8:]) + + p.ENDTYPE = binary.BigEndian.Uint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+10:]) return nil } @@ -136,7 +142,8 @@ func (p *MyMsg) UnmarshalData(b []byte) []byte { } func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, target string, - connId string, msgType uint32, data []byte, sproto int, rproto int, catch int, key int) { + connId string, msgType uint32, data []byte, sproto int, rproto int, catch int, key int, + tcpmode int) { m := &MyMsg{ ID: connId, @@ -146,6 +153,7 @@ func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, ta RPROTO: (uint16)(rproto), CATCH: (uint16)(catch), KEY: (uint32)(key), + TCPMODE: (uint16)(tcpmode), ENDTYPE: END, } @@ -165,7 +173,7 @@ func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, ta bytes, err := msg.Marshal(nil) if err != nil { - fmt.Printf("sendICMP Marshal error %s %s\n", server.String(), err) + loggo.Error("sendICMP Marshal error %s %s", server.String(), err) return } @@ -176,7 +184,7 @@ func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, ta continue } } - fmt.Printf("sendICMP WriteTo error %s %s\n", server.String(), err) + loggo.Error("sendICMP WriteTo error %s %s", server.String(), err) } break } @@ -197,7 +205,7 @@ func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) { // Read timeout continue } else { - fmt.Printf("Error read icmp message %s\n", err) + loggo.Error("Error read icmp message %s", err) continue } } @@ -209,21 +217,21 @@ func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) { my := &MyMsg{} my.Unmarshal(bytes[8:n]) - if (my.TYPE != (uint32)(DATA) && my.TYPE != (uint32)(PING) && my.TYPE != (uint32)(CATCH)) || + if (my.TYPE != (uint32)(DATA) && my.TYPE != (uint32)(PING) && my.TYPE != (uint32)(CATCH) && my.TYPE != (uint32)(FRAME)) || my.ENDTYPE != (uint32)(END) { - //fmt.Printf("processPacket diff type %s %d %d \n", my.ID, my.TYPE, my.ENDTYPE) + loggo.Info("processPacket diff type %s %d %d ", my.ID, my.TYPE, my.ENDTYPE) continue } if my.Data == nil { - fmt.Printf("processPacket data nil %s\n", my.ID) + loggo.Info("processPacket data nil %s", my.ID) return } recv <- &Packet{msgType: my.TYPE, data: my.Data, id: my.ID, target: my.TARGET, src: srcaddr.(*net.IPAddr), rproto: (int)((int16)(my.RPROTO)), echoId: echoId, echoSeq: echoSeq, catch: (int)((int16)(my.CATCH)), - key: (int)(my.KEY)} + key: (int)(my.KEY), tcpmode: (int)((int16)(my.TCPMODE))} } } @@ -238,6 +246,7 @@ type Packet struct { echoSeq int catch int key int + tcpmode int } func UniqueId() string { diff --git a/server.go b/server.go index 45f397b..87e6d21 100644 --- a/server.go +++ b/server.go @@ -1,7 +1,7 @@ package pingtunnel import ( - "fmt" + "github.com/esrrhs/go-engine/src/loggo" "golang.org/x/net/icmp" "net" "time" @@ -35,21 +35,23 @@ type Server struct { } type ServerConn struct { - ipaddrTarget *net.UDPAddr - conn *net.UDPConn - id string - activeTime time.Time - close bool - rproto int - catch int - catchQueue chan *CatchMsg + ipaddrTarget *net.UDPAddr + conn *net.UDPConn + tcpaddrTarget *net.TCPAddr + tcpconn *net.TCPConn + id string + activeTime time.Time + close bool + rproto int + catch int + catchQueue chan *CatchMsg } func (p *Server) Run() { conn, err := icmp.ListenPacket("ip4:icmp", "") if err != nil { - fmt.Printf("Error listening for ICMP packets: %s\n", err.Error()) + loggo.Error("Error listening for ICMP packets: %s", err.Error()) return } p.conn = conn @@ -85,51 +87,78 @@ func (p *Server) processPacket(packet *Packet) { if packet.msgType == PING { t := time.Time{} t.UnmarshalBinary(packet.data) - fmt.Printf("ping from %s %s %d %d %d\n", packet.src.String(), t.String(), packet.rproto, packet.echoId, packet.echoSeq) + loggo.Info("ping from %s %s %d %d %d", packet.src.String(), t.String(), packet.rproto, packet.echoId, packet.echoSeq) sendICMP(packet.echoId, packet.echoSeq, *p.conn, packet.src, "", "", (uint32)(PING), packet.data, - packet.rproto, -1, 0, p.key) + packet.rproto, -1, 0, p.key, packet.tcpmode) return } - //fmt.Printf("processPacket %s %s %d\n", packet.id, packet.src.String(), len(packet.data)) + loggo.Debug("processPacket %s %s %d", packet.id, packet.src.String(), len(packet.data)) now := time.Now() id := packet.id - udpConn := p.localConnMap[id] - if udpConn == nil { + localConn := p.localConnMap[id] + if localConn == nil { - addr := packet.target - ipaddrTarget, err := net.ResolveUDPAddr("udp", addr) - if err != nil { - fmt.Printf("Error ResolveUDPAddr for udp addr: %s %s\n", addr, err.Error()) - return + if packet.tcpmode > 0 { + + addr := packet.target + ipaddrTarget, err := net.ResolveTCPAddr("tcp", addr) + if err != nil { + loggo.Error("Error ResolveUDPAddr for tcp addr: %s %s", addr, err.Error()) + return + } + + targetConn, err := net.DialTCP("tcp", nil, ipaddrTarget) + if err != nil { + loggo.Error("Error listening for tcp packets: %s", err.Error()) + return + } + + catchQueue := make(chan *CatchMsg, packet.catch) + + localConn = &ServerConn{tcpconn: targetConn, tcpaddrTarget: ipaddrTarget, id: id, activeTime: now, close: false, + rproto: packet.rproto, catchQueue: catchQueue} + + p.localConnMap[id] = localConn + + go p.RecvTCP(localConn, id, packet.src) + + } else { + + addr := packet.target + ipaddrTarget, err := net.ResolveUDPAddr("udp", addr) + if err != nil { + loggo.Error("Error ResolveUDPAddr for udp addr: %s %s", addr, err.Error()) + return + } + + targetConn, err := net.DialUDP("udp", nil, ipaddrTarget) + if err != nil { + loggo.Error("Error listening for udp packets: %s", err.Error()) + return + } + + catchQueue := make(chan *CatchMsg, packet.catch) + + localConn = &ServerConn{conn: targetConn, ipaddrTarget: ipaddrTarget, id: id, activeTime: now, close: false, + rproto: packet.rproto, catchQueue: catchQueue} + + p.localConnMap[id] = localConn + + go p.Recv(localConn, id, packet.src) } - - targetConn, err := net.DialUDP("udp", nil, ipaddrTarget) - if err != nil { - fmt.Printf("Error listening for udp packets: %s\n", err.Error()) - return - } - - catchQueue := make(chan *CatchMsg, 1000) - - udpConn = &ServerConn{conn: targetConn, ipaddrTarget: ipaddrTarget, id: id, activeTime: now, close: false, - rproto: packet.rproto, catchQueue: catchQueue} - - p.localConnMap[id] = udpConn - - go p.Recv(udpConn, id, packet.src) } - udpConn.activeTime = now - udpConn.catch = packet.catch + localConn.activeTime = now + localConn.catch = packet.catch if packet.msgType == CATCH { select { - case re := <-udpConn.catchQueue: + case re := <-localConn.catchQueue: sendICMP(packet.echoId, packet.echoSeq, *p.conn, re.src, "", re.id, (uint32)(CATCH), re.data, - re.conn.rproto, -1, 0, p.key) + re.conn.rproto, -1, 0, p.key, packet.tcpmode) p.sendCatchPacket++ case <-time.After(time.Duration(1) * time.Millisecond): } @@ -139,10 +168,10 @@ func (p *Server) processPacket(packet *Packet) { if packet.msgType == DATA { - _, err := udpConn.conn.Write(packet.data) + _, err := localConn.conn.Write(packet.data) if err != nil { - fmt.Printf("WriteToUDP Error %s\n", err) - udpConn.close = true + loggo.Error("WriteToUDP Error %s", err) + localConn.close = true return } @@ -153,7 +182,7 @@ func (p *Server) processPacket(packet *Packet) { func (p *Server) Recv(conn *ServerConn, id string, src *net.IPAddr) { - fmt.Printf("server waiting target response %s -> %s %s\n", conn.ipaddrTarget.String(), conn.id, conn.conn.LocalAddr().String()) + loggo.Info("server waiting target response %s -> %s %s", conn.ipaddrTarget.String(), conn.id, conn.conn.LocalAddr().String()) for { bytes := make([]byte, 2000) @@ -166,7 +195,7 @@ func (p *Server) Recv(conn *ServerConn, id string, src *net.IPAddr) { // Read timeout continue } else { - fmt.Printf("ReadFromUDP Error read udp %s\n", err) + loggo.Error("ReadFromUDP Error read udp %s", err) conn.close = true return } @@ -183,7 +212,7 @@ func (p *Server) Recv(conn *ServerConn, id string, src *net.IPAddr) { } } else { sendICMP(p.echoId, p.echoSeq, *p.conn, src, "", id, (uint32)(DATA), bytes[:n], - conn.rproto, -1, 0, p.key) + conn.rproto, -1, 0, p.key, packet.tcpmode) } p.sendPacket++ @@ -210,14 +239,14 @@ func (p *Server) checkTimeoutConn() { for id, conn := range p.localConnMap { if conn.close { - fmt.Printf("close inactive conn %s %s\n", id, conn.ipaddrTarget.String()) + loggo.Info("close inactive conn %s %s", id, conn.ipaddrTarget.String()) p.Close(conn) } } } func (p *Server) showNet() { - fmt.Printf("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s sendCatch %d/s recvCatch %d/s\n", + loggo.Info("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s sendCatch %d/s recvCatch %d/s", p.sendPacket, p.sendPacketSize/1024, p.recvPacket, p.recvPacketSize/1024, p.sendCatchPacket, p.recvCatchPacket) p.sendPacket = 0 p.recvPacket = 0