From 54655acee926f226340594d7bd90743435135a06 Mon Sep 17 00:00:00 2001 From: esrrhs Date: Sun, 23 Dec 2018 07:02:57 +0800 Subject: [PATCH] add --- client.go | 64 +++++++++++++++++++++++++++++++--------------- cmd/main.go | 5 +++- pingtunnel.go | 34 +++++++++++++++++------- server.go | 71 ++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 126 insertions(+), 48 deletions(-) diff --git a/client.go b/client.go index 21c99eb..e218253 100644 --- a/client.go +++ b/client.go @@ -9,7 +9,7 @@ import ( "time" ) -func NewClient(addr string, server string, target string, timeout int, sproto int, rproto int) (*Client, error) { +func NewClient(addr string, server string, target string, timeout int, sproto int, rproto int, catch int) (*Client, error) { ipaddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { @@ -32,6 +32,7 @@ func NewClient(addr string, server string, target string, timeout int, sproto in timeout: timeout, sproto: sproto, rproto: rproto, + catch: catch, }, nil } @@ -42,6 +43,7 @@ type Client struct { timeout int sproto int rproto int + catch int ipaddr *net.UDPAddr addr string @@ -62,8 +64,8 @@ type Client struct { sendPacketSize uint64 recvPacketSize uint64 - pingPacketSize uint64 - pongPacketSize uint64 + sendCatchPacket uint64 + recvCatchPacket uint64 } type ClientConn struct { @@ -122,16 +124,24 @@ func (p *Client) Run() { interval := time.NewTicker(time.Second) defer interval.Stop() - interval1 := time.NewTicker(time.Millisecond * 1) - defer interval1.Stop() + inter := 1000 + if p.catch > 0 { + inter = 1000 / p.catch + if inter <= 0 { + inter = 1 + } + } + intervalCatch := time.NewTicker(time.Millisecond * time.Duration(inter)) + defer intervalCatch.Stop() for { select { case <-interval.C: p.checkTimeoutConn() - p.showNet() - case <-interval1.C: p.ping() + p.showNet() + case <-intervalCatch.C: + p.sendCatch() case r := <-recv: p.processPacket(r) } @@ -170,7 +180,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) + sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, clientConn.id, (uint32)(DATA), bytes[:n], p.sproto, p.rproto, p.catch) p.sequence++ @@ -188,9 +198,8 @@ func (p *Client) processPacket(packet *Packet) { if packet.msgType == PING { t := time.Time{} t.UnmarshalBinary(packet.data) - //d := time.Now().Sub(t) - //fmt.Printf("pong from %s %s\n", packet.src.String(), d.String()) - p.pongPacketSize++ + d := time.Now().Sub(t) + fmt.Printf("pong from %s %s\n", packet.src.String(), d.String()) return } @@ -207,6 +216,10 @@ func (p *Client) processPacket(packet *Packet) { now := time.Now() clientConn.activeTime = now + if packet.msgType == CATCH { + p.recvCatchPacket++ + } + _, err := p.listenConn.WriteToUDP(packet.data, addr) if err != nil { fmt.Printf("WriteToUDP Error read udp %s\n", err) @@ -214,8 +227,10 @@ func (p *Client) processPacket(packet *Packet) { return } - p.recvPacket++ - p.recvPacketSize += (uint64)(len(packet.data)) + if packet.msgType == DATA { + p.recvPacket++ + p.recvPacketSize += (uint64)(len(packet.data)) + } } func (p *Client) Close(clientConn *ClientConn) { @@ -246,20 +261,29 @@ func (p *Client) ping() { if p.sendPacket == 0 { now := time.Now() b, _ := now.MarshalBinary() - sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, "", (uint32)(PING), b, p.sproto, p.rproto) - //fmt.Printf("ping %s %s %d %d %d %d\n", p.addrServer, now.String(), p.sproto, p.rproto, p.id, p.sequence) + sendICMP(p.id, p.sequence, *p.conn, p.ipaddrServer, p.targetAddr, "", (uint32)(PING), b, p.sproto, p.rproto, p.catch) + fmt.Printf("ping %s %s %d %d %d %d\n", p.addrServer, now.String(), p.sproto, p.rproto, p.id, p.sequence) p.sequence++ - p.pingPacketSize++ } } func (p *Client) showNet() { - fmt.Printf("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s ping %d/s pong %d/s\n", - p.sendPacket, p.sendPacketSize/1024, p.recvPacket, p.recvPacketSize/1024, p.pingPacketSize, p.pongPacketSize) + fmt.Printf("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s sendCatch %d/s recvCatch %d/s\n", + p.sendPacket, p.sendPacketSize/1024, p.recvPacket, p.recvPacketSize/1024, p.sendCatchPacket, p.recvCatchPacket) p.sendPacket = 0 p.recvPacket = 0 p.sendPacketSize = 0 p.recvPacketSize = 0 - p.pingPacketSize = 0 - p.pongPacketSize = 0 + p.sendCatchPacket = 0 + p.recvCatchPacket = 0 +} + +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.sequence++ + p.sendCatchPacket++ + } + } } diff --git a/cmd/main.go b/cmd/main.go index 97ffac0..ea204eb 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -36,6 +36,8 @@ Usage: -rproto 客户端接收ping协议的协议,默认是0 The protocol that the client receives the ping. The default is 0. + + -catch 主动抓模式 ` func main() { @@ -47,6 +49,7 @@ func main() { timeout := flag.Int("timeout", 60, "conn timeout") sproto := flag.Int("sproto", 8, "send ping proto") rproto := flag.Int("rproto", 0, "recv ping proto") + catch := flag.Int("catch", 0, "catch mdoe") flag.Usage = func() { fmt.Printf(usage) } @@ -76,7 +79,7 @@ func main() { fmt.Printf("server %s\n", *server) fmt.Printf("target %s\n", *target) - c, err := pingtunnel.NewClient(*listen, *server, *target, *timeout, *sproto, *rproto) + c, err := pingtunnel.NewClient(*listen, *server, *target, *timeout, *sproto, *rproto, *catch) if err != nil { fmt.Printf("ERROR: %s\n", err.Error()) return diff --git a/pingtunnel.go b/pingtunnel.go index ac61e85..e52c02d 100644 --- a/pingtunnel.go +++ b/pingtunnel.go @@ -16,9 +16,10 @@ import ( ) const ( - DATA uint32 = 0x01010101 - PING uint32 = 0x02020202 - END uint32 = 0xAAAABBBB + DATA uint32 = 0x01010101 + PING uint32 = 0x02020202 + CATCH uint32 = 0x03030303 + END uint32 = 0xAAAABBBB ) type MyMsg struct { @@ -27,6 +28,7 @@ type MyMsg struct { TARGET string Data []byte RPROTO uint16 + CATCH uint16 ENDTYPE uint32 } @@ -35,7 +37,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 + 4 + return 4 + p.LenString(p.ID) + p.LenString(p.TARGET) + p.LenData(p.Data) + 2 + 2 + 4 } func (p *MyMsg) LenString(s string) int { @@ -64,7 +66,9 @@ func (p *MyMsg) Marshal(proto int) ([]byte, error) { binary.BigEndian.PutUint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data):], uint16(p.RPROTO)) - binary.BigEndian.PutUint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+2:], uint32(p.ENDTYPE)) + binary.BigEndian.PutUint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+2:], uint16(p.CATCH)) + + binary.BigEndian.PutUint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+4:], uint32(p.ENDTYPE)) return b, nil } @@ -99,7 +103,9 @@ func (p *MyMsg) Unmarshal(b []byte) error { p.RPROTO = binary.BigEndian.Uint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data):]) - p.ENDTYPE = binary.BigEndian.Uint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+2:]) + p.CATCH = binary.BigEndian.Uint16(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+2:]) + + p.ENDTYPE = binary.BigEndian.Uint32(b[4+p.LenString(p.ID)+p.LenString(p.TARGET)+p.LenData(p.Data)+4:]) return nil } @@ -124,7 +130,8 @@ func (p *MyMsg) UnmarshalData(b []byte) []byte { return data } -func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, target string, connId string, msgType uint32, data []byte, sproto int, rproto int) { +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) { m := &MyMsg{ ID: connId, @@ -132,6 +139,7 @@ func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, ta TARGET: target, Data: data, RPROTO: (uint16)(rproto), + CATCH: (uint16)(catch), ENDTYPE: END, } @@ -196,7 +204,7 @@ func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) { } my.Unmarshal(bytes[8:n]) - if (my.TYPE != (uint32)(DATA) && my.TYPE != (uint32)(PING)) || + if (my.TYPE != (uint32)(DATA) && my.TYPE != (uint32)(PING) && my.TYPE != (uint32)(CATCH)) || my.ENDTYPE != (uint32)(END) { //fmt.Printf("processPacket diff type %s %d %d \n", my.ID, my.TYPE, my.ENDTYPE) continue @@ -209,7 +217,7 @@ func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) { 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} + echoId: echoId, echoSeq: echoSeq, catch: (int)((int16)(my.CATCH))} } } @@ -222,6 +230,7 @@ type Packet struct { rproto int echoId int echoSeq int + catch int } func UniqueId() string { @@ -238,3 +247,10 @@ func GetMd5String(s string) string { h.Write([]byte(s)) return hex.EncodeToString(h.Sum(nil)) } + +type CatchMsg struct { + conn *ServerConn + id string + src *net.IPAddr + data []byte +} diff --git a/server.go b/server.go index f790253..a39890d 100644 --- a/server.go +++ b/server.go @@ -25,8 +25,11 @@ type Server struct { sendPacketSize uint64 recvPacketSize uint64 - echoId int - echoSeq int + sendCatchPacket uint64 + recvCatchPacket uint64 + + echoId int + echoSeq int } type ServerConn struct { @@ -36,6 +39,8 @@ type ServerConn struct { activeTime time.Time close bool rproto int + catch int + catchQueue chan *CatchMsg } func (p *Server) Run() { @@ -72,10 +77,10 @@ func (p *Server) processPacket(packet *Packet) { p.echoSeq = packet.echoSeq 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) - //sendICMP(packet.echoId, packet.echoSeq, *p.conn, packet.src, "", "", (uint32)(PING), packet.data, packet.rproto, -1) + 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) + sendICMP(packet.echoId, packet.echoSeq, *p.conn, packet.src, "", "", (uint32)(PING), packet.data, packet.rproto, -1, 0) return } @@ -99,31 +104,52 @@ func (p *Server) processPacket(packet *Packet) { fmt.Printf("Error listening for udp packets: %s\n", err.Error()) return } - udpConn = &ServerConn{conn: targetConn, ipaddrTarget: ipaddrTarget, id: id, activeTime: now, close: false, rproto: packet.rproto} + + 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 - _, err := udpConn.conn.Write(packet.data) - if err != nil { - fmt.Printf("WriteToUDP Error %s\n", err) - udpConn.close = true + if packet.msgType == CATCH { + select { + case re := <-udpConn.catchQueue: + sendICMP(packet.echoId, packet.echoSeq, *p.conn, re.src, "", re.id, (uint32)(CATCH), re.data, re.conn.rproto, -1, 0) + p.sendCatchPacket++ + case <-time.After(time.Duration(1) * time.Millisecond): + } + p.recvCatchPacket++ return } - p.recvPacket++ - p.recvPacketSize += (uint64)(len(packet.data)) + if packet.msgType == DATA { + + _, err := udpConn.conn.Write(packet.data) + if err != nil { + fmt.Printf("WriteToUDP Error %s\n", err) + udpConn.close = true + return + } + + p.recvPacket++ + p.recvPacketSize += (uint64)(len(packet.data)) + } } 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()) - bytes := make([]byte, 10240) - for { + bytes := make([]byte, 2000) + conn.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) n, _, err := conn.conn.ReadFromUDP(bytes) if err != nil { @@ -142,7 +168,14 @@ func (p *Server) Recv(conn *ServerConn, id string, src *net.IPAddr) { now := time.Now() conn.activeTime = now - sendICMP(p.echoId, p.echoSeq, *p.conn, src, "", id, (uint32)(DATA), bytes[:n], conn.rproto, -1) + if conn.catch > 0 { + select { + case conn.catchQueue <- &CatchMsg{conn: conn, id: id, src: src, data: bytes[:n]}: + case <-time.After(time.Duration(10) * time.Millisecond): + } + } else { + sendICMP(p.echoId, p.echoSeq, *p.conn, src, "", id, (uint32)(DATA), bytes[:n], conn.rproto, -1, 0) + } p.sendPacket++ p.sendPacketSize += (uint64)(n) @@ -175,10 +208,12 @@ func (p *Server) checkTimeoutConn() { } func (p *Server) showNet() { - fmt.Printf("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s\n", - p.sendPacket, p.sendPacketSize/1024, p.recvPacket, p.recvPacketSize/1024) + fmt.Printf("send %dPacket/s %dKB/s recv %dPacket/s %dKB/s sendCatch %d/s recvCatch %d/s\n", + p.sendPacket, p.sendPacketSize/1024, p.recvPacket, p.recvPacketSize/1024, p.sendCatchPacket, p.recvCatchPacket) p.sendPacket = 0 p.recvPacket = 0 p.sendPacketSize = 0 p.recvPacketSize = 0 + p.sendCatchPacket = 0 + p.recvCatchPacket = 0 }