diff --git a/cmd/main.go b/cmd/main.go index fdaca9d..9c1b72e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,9 +9,9 @@ import ( var usage = ` Usage: - pingtunnel -type server -t TARGET_IP:4455 + pingtunnel -type server - pingtunnel -type client -l LOCAL_IP:4455 -t SERVER_IP + pingtunnel -type client -l LOCAL_IP:4455 -s SERVER_IP -t 4455 ` @@ -20,7 +20,8 @@ func main() { t := flag.String("type", "client", "client or server") listen := flag.String("l", ":4455", "listen addr") - target := flag.String("t", ":443", "target addr") + target := flag.Int("t", 4455, "target port") + server := flag.String("s", "127.0.0.1", "server addr") flag.Usage = func() { fmt.Printf(usage) } @@ -34,24 +35,26 @@ func main() { fmt.Printf("type %s\n", *t) fmt.Printf("listen %s\n", *listen) - fmt.Printf("target %s\n", *target) + fmt.Printf("server %s\n", *server) + fmt.Printf("target port %d\n", *target) if *t == "server" { - s, err := pingtunnel.NewServer(*target) + s, err := pingtunnel.NewServer() if err != nil { fmt.Printf("ERROR: %s\n", err.Error()) return } - fmt.Printf("Server Target %s (%s):\n", s.TargetAddr(), s.TargetIPAddr()) + fmt.Printf("Server start\n") s.Run() } if *t == "client" { - c, err := pingtunnel.NewClient(*listen, *target) + c, err := pingtunnel.NewClient(*listen, *server, *target) if err != nil { fmt.Printf("ERROR: %s\n", err.Error()) return } - fmt.Printf("Client Listen %s (%s) Target %s (%s):\n", c.Addr(), c.IPAddr(), c.TargetAddr(), c.TargetIPAddr()) + fmt.Printf("Client Listen %s (%s) Server %s (%s) TargetPort %d:\n", c.Addr(), c.IPAddr(), + c.ServerAddr(), c.ServerIPAddr(), c.TargetPort()) c.Run() } } diff --git a/src/pingtunnel/client.go b/src/pingtunnel/client.go index 1c2db53..3be3f5d 100644 --- a/src/pingtunnel/client.go +++ b/src/pingtunnel/client.go @@ -7,14 +7,14 @@ import ( "time" ) -func NewClient(addr string, target string) (*Client, error) { +func NewClient(addr string, server string, target int) (*Client, error) { ipaddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return nil, err } - ipaddrTarget, err := net.ResolveIPAddr("ip", target) + ipaddrServer, err := net.ResolveIPAddr("ip", server) if err != nil { return nil, err } @@ -22,8 +22,9 @@ func NewClient(addr string, target string) (*Client, error) { return &Client{ ipaddr: ipaddr, addr: addr, - ipaddrTarget: ipaddrTarget, - addrTarget: target, + ipaddrServer: ipaddrServer, + addrServer: server, + targetPort: (uint16)(target), }, nil } @@ -31,8 +32,10 @@ type Client struct { ipaddr *net.UDPAddr addr string - ipaddrTarget *net.IPAddr - addrTarget string + ipaddrServer *net.IPAddr + addrServer string + + targetPort uint16 conn *icmp.PacketConn listenConn *net.UDPConn @@ -49,12 +52,16 @@ func (p *Client) IPAddr() *net.UDPAddr { return p.ipaddr } -func (p *Client) TargetAddr() string { - return p.addrTarget +func (p *Client) TargetPort() uint16 { + return p.targetPort } -func (p *Client) TargetIPAddr() *net.IPAddr { - return p.ipaddrTarget +func (p *Client) ServerIPAddr() *net.IPAddr { + return p.ipaddrServer +} + +func (p *Client) ServerAddr() string { + return p.addrServer } func (p *Client) Run() { @@ -98,7 +105,7 @@ func (p *Client) Accept() error { bytes := make([]byte, 10240) for { - p.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) + p.listenConn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) n, srcaddr, err := p.listenConn.ReadFromUDP(bytes) if err != nil { if neterr, ok := err.(*net.OpError); ok { @@ -120,7 +127,7 @@ func (p *Client) Accept() error { fmt.Printf("client accept new local %d %s\n", uuid, srcaddr.String()) } - sendICMP(*p.conn, p.ipaddrTarget, uuid, (uint32)(DATA), bytes[:n]) + sendICMP(*p.conn, p.ipaddrServer, p.targetPort, uuid, (uint32)(DATA), bytes[:n]) } } diff --git a/src/pingtunnel/pingtunnel.go b/src/pingtunnel/pingtunnel.go index 56d5a94..ac9f8b0 100644 --- a/src/pingtunnel/pingtunnel.go +++ b/src/pingtunnel/pingtunnel.go @@ -17,15 +17,12 @@ const ( DATA MSGID = 0xDEADBEEF ) -const ( - protocolICMP = 1 -) - // An Echo represents an ICMP echo request or reply message body. type MyMsg struct { - ID uint32 - TYPE uint32 - Data []byte + ID uint32 + TYPE uint32 + TARGET uint16 + Data []byte } // Len implements the Len method of MessageBody interface. @@ -33,7 +30,7 @@ func (p *MyMsg) Len(proto int) int { if p == nil { return 0 } - return 8 + len(p.Data) + return 10 + len(p.Data) } // Marshal implements the Marshal method of MessageBody interface. @@ -41,7 +38,8 @@ func (p *MyMsg) Marshal(proto int) ([]byte, error) { b := make([]byte, p.Len(proto)) binary.BigEndian.PutUint32(b[:4], uint32(p.ID)) binary.BigEndian.PutUint32(b[4:8], uint32(p.TYPE)) - copy(b[8:], p.Data) + binary.BigEndian.PutUint16(b[8:10], uint16(p.TARGET)) + copy(b[10:], p.Data) return b, nil } @@ -49,8 +47,9 @@ func (p *MyMsg) Marshal(proto int) ([]byte, error) { func (p *MyMsg) Unmarshal(b []byte) error { p.ID = binary.BigEndian.Uint32(b[:4]) p.TYPE = binary.BigEndian.Uint32(b[4:8]) - p.Data = make([]byte, len(b[8:])) - copy(p.Data, b[8:]) + p.TARGET = binary.BigEndian.Uint16(b[8:10]) + p.Data = make([]byte, len(b[10:])) + copy(p.Data, b[10:]) return nil } @@ -61,12 +60,13 @@ func UniqueId() uint32 { return (uint32)(newValue) } -func sendICMP(conn icmp.PacketConn, target *net.IPAddr, connId uint32, msgType uint32, data []byte) { +func sendICMP(conn icmp.PacketConn, server *net.IPAddr, target uint16, connId uint32, msgType uint32, data []byte) { m := &MyMsg{ - ID: connId, - TYPE: msgType, - Data: data, + ID: connId, + TYPE: msgType, + TARGET: target, + Data: data, } msg := &icmp.Message{ @@ -77,18 +77,18 @@ func sendICMP(conn icmp.PacketConn, target *net.IPAddr, connId uint32, msgType u bytes, err := msg.Marshal(nil) if err != nil { - fmt.Printf("sendICMP Marshal error %s %s\n", target.String(), err) + fmt.Printf("sendICMP Marshal error %s %s\n", server.String(), err) return } for { - if _, err := conn.WriteTo(bytes, target); err != nil { + if _, err := conn.WriteTo(bytes, server); err != nil { if neterr, ok := err.(*net.OpError); ok { if neterr.Err == syscall.ENOBUFS { continue } } - fmt.Printf("sendICMP WriteTo error %s %s\n", target.String(), err) + fmt.Printf("sendICMP WriteTo error %s %s\n", server.String(), err) } break } @@ -124,12 +124,13 @@ func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) { continue } - recv <- &Packet{data: my.Data, id: my.ID, src: srcaddr.(*net.IPAddr)} + recv <- &Packet{data: my.Data, id: my.ID, target: my.TARGET, src: srcaddr.(*net.IPAddr)} } } type Packet struct { - data []byte - id uint32 - src *net.IPAddr + data []byte + id uint32 + target uint16 + src *net.IPAddr } diff --git a/src/pingtunnel/server.go b/src/pingtunnel/server.go index 7afc986..3052ef9 100644 --- a/src/pingtunnel/server.go +++ b/src/pingtunnel/server.go @@ -4,37 +4,25 @@ import ( "fmt" "golang.org/x/net/icmp" "net" + "strconv" "time" ) -func NewServer(target string) (*Server, error) { - - ipaddrTarget, err := net.ResolveUDPAddr("udp", target) - if err != nil { - return nil, err - } - +func NewServer() (*Server, error) { return &Server{ - ipaddrTarget: ipaddrTarget, - addrTarget: target, }, nil } type Server struct { - ipaddrTarget *net.UDPAddr - addrTarget string - conn *icmp.PacketConn - localConnMap map[uint32]*net.UDPConn + localConnMap map[uint32]*Conn } -func (p *Server) TargetAddr() string { - return p.addrTarget -} - -func (p *Server) TargetIPAddr() *net.UDPAddr { - return p.ipaddrTarget +type Conn struct { + ipaddrTarget *net.UDPAddr + conn *net.UDPConn + id uint32 } func (p *Server) Run() { @@ -46,7 +34,7 @@ func (p *Server) Run() { } p.conn = conn - p.localConnMap = make(map[uint32]*net.UDPConn) + p.localConnMap = make(map[uint32]*Conn) recv := make(chan *Packet, 1000) go recvICMP(*p.conn, recv) @@ -66,33 +54,41 @@ func (p *Server) processPacket(packet *Packet) { id := packet.id udpConn := p.localConnMap[id] if udpConn == nil { - targetConn, err := net.ListenUDP("udp", p.ipaddrTarget) + + addr := ":" + strconv.Itoa((int)(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 + } + + targetConn, err := net.DialUDP("udp", nil, ipaddrTarget) if err != nil { fmt.Printf("Error listening for udp packets: %s\n", err.Error()) return } - udpConn = targetConn + udpConn = &Conn{conn: targetConn, ipaddrTarget: ipaddrTarget, id: id} p.localConnMap[id] = udpConn go p.Recv(udpConn, id, packet.src) } - _, err := udpConn.WriteToUDP(packet.data, p.ipaddrTarget) + _, err := udpConn.conn.Write(packet.data) if err != nil { - fmt.Printf("WriteToUDP Error read udp %s\n", err) - p.localConnMap[id] = nil + fmt.Printf("WriteToUDP Error %s\n", err) + p.Close(udpConn) return } } -func (p *Server) Recv(conn *net.UDPConn, id uint32, src *net.IPAddr) { +func (p *Server) Recv(conn *Conn, id uint32, src *net.IPAddr) { - fmt.Println("server waiting target response") + fmt.Printf("server waiting target response %s\n", conn.ipaddrTarget.String()) bytes := make([]byte, 10240) for { - p.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) - n, _, err := conn.ReadFromUDP(bytes) + conn.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) + n, _, err := conn.conn.ReadFromUDP(bytes) if err != nil { if neterr, ok := err.(*net.OpError); ok { if neterr.Timeout() { @@ -100,12 +96,19 @@ func (p *Server) Recv(conn *net.UDPConn, id uint32, src *net.IPAddr) { continue } else { fmt.Printf("ReadFromUDP Error read udp %s\n", err) - p.localConnMap[id] = nil + p.Close(conn) return } } } - sendICMP(*p.conn, src, id, (uint32)(DATA), bytes[:n]) + sendICMP(*p.conn, src, 0, id, (uint32)(DATA), bytes[:n]) + } +} + +func (p *Server) Close(conn *Conn) { + if p.localConnMap[conn.id] != nil { + conn.conn.Close() + p.localConnMap[conn.id] = nil } }