2018-12-17 15:21:15 +08:00
|
|
|
package pingtunnel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"golang.org/x/net/icmp"
|
|
|
|
"net"
|
2018-12-18 11:39:16 +08:00
|
|
|
"strconv"
|
2018-12-17 15:21:15 +08:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
func NewServer() (*Server, error) {
|
2018-12-17 15:21:15 +08:00
|
|
|
return &Server{
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type Server struct {
|
2018-12-17 19:06:46 +08:00
|
|
|
conn *icmp.PacketConn
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
localConnMap map[uint32]*Conn
|
2018-12-17 15:21:15 +08:00
|
|
|
}
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
type Conn struct {
|
|
|
|
ipaddrTarget *net.UDPAddr
|
|
|
|
conn *net.UDPConn
|
|
|
|
id uint32
|
2018-12-17 15:21:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Server) Run() {
|
|
|
|
|
|
|
|
conn, err := icmp.ListenPacket("ip4:icmp", "")
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error listening for ICMP packets: %s\n", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.conn = conn
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
p.localConnMap = make(map[uint32]*Conn)
|
2018-12-17 19:06:46 +08:00
|
|
|
|
|
|
|
recv := make(chan *Packet, 1000)
|
|
|
|
go recvICMP(*p.conn, recv)
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case r := <-recv:
|
|
|
|
p.processPacket(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Server) processPacket(packet *Packet) {
|
|
|
|
|
|
|
|
fmt.Printf("processPacket %d %s %d\n", packet.id, packet.src.String(), len(packet.data))
|
|
|
|
|
|
|
|
id := packet.id
|
|
|
|
udpConn := p.localConnMap[id]
|
|
|
|
if udpConn == nil {
|
2018-12-18 11:39:16 +08:00
|
|
|
|
|
|
|
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)
|
2018-12-17 19:06:46 +08:00
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error listening for udp packets: %s\n", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2018-12-18 11:39:16 +08:00
|
|
|
udpConn = &Conn{conn: targetConn, ipaddrTarget: ipaddrTarget, id: id}
|
2018-12-17 19:06:46 +08:00
|
|
|
p.localConnMap[id] = udpConn
|
|
|
|
go p.Recv(udpConn, id, packet.src)
|
|
|
|
}
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
_, err := udpConn.conn.Write(packet.data)
|
2018-12-17 19:06:46 +08:00
|
|
|
if err != nil {
|
2018-12-18 11:39:16 +08:00
|
|
|
fmt.Printf("WriteToUDP Error %s\n", err)
|
|
|
|
p.Close(udpConn)
|
2018-12-17 19:06:46 +08:00
|
|
|
return
|
|
|
|
}
|
2018-12-17 15:21:15 +08:00
|
|
|
}
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
func (p *Server) Recv(conn *Conn, id uint32, src *net.IPAddr) {
|
2018-12-17 19:06:46 +08:00
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
fmt.Printf("server waiting target response %s\n", conn.ipaddrTarget.String())
|
2018-12-17 19:06:46 +08:00
|
|
|
|
|
|
|
bytes := make([]byte, 10240)
|
2018-12-17 15:21:15 +08:00
|
|
|
|
|
|
|
for {
|
2018-12-18 11:39:16 +08:00
|
|
|
conn.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100))
|
|
|
|
n, _, err := conn.conn.ReadFromUDP(bytes)
|
2018-12-17 15:21:15 +08:00
|
|
|
if err != nil {
|
|
|
|
if neterr, ok := err.(*net.OpError); ok {
|
|
|
|
if neterr.Timeout() {
|
|
|
|
// Read timeout
|
|
|
|
continue
|
|
|
|
} else {
|
2018-12-17 19:06:46 +08:00
|
|
|
fmt.Printf("ReadFromUDP Error read udp %s\n", err)
|
2018-12-18 11:39:16 +08:00
|
|
|
p.Close(conn)
|
2018-12-17 19:06:46 +08:00
|
|
|
return
|
2018-12-17 15:21:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-18 11:39:16 +08:00
|
|
|
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
|
2018-12-17 15:21:15 +08:00
|
|
|
}
|
|
|
|
}
|