2018-12-16 08:56:40 +03:00
|
|
|
package pingtunnel
|
|
|
|
|
|
|
|
import (
|
2018-12-18 10:36:59 +03:00
|
|
|
"crypto/md5"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/base64"
|
2018-12-16 08:56:40 +03:00
|
|
|
"encoding/binary"
|
2018-12-18 10:36:59 +03:00
|
|
|
"encoding/hex"
|
2019-10-20 11:27:03 +03:00
|
|
|
"github.com/esrrhs/go-engine/src/loggo"
|
2019-10-22 16:04:25 +03:00
|
|
|
"github.com/golang/protobuf/proto"
|
2018-12-17 14:06:46 +03:00
|
|
|
"golang.org/x/net/icmp"
|
|
|
|
"golang.org/x/net/ipv4"
|
2018-12-18 10:36:59 +03:00
|
|
|
"io"
|
2018-12-17 14:06:46 +03:00
|
|
|
"net"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
2018-12-16 08:56:40 +03:00
|
|
|
)
|
|
|
|
|
2018-12-23 02:02:57 +03:00
|
|
|
func sendICMP(id int, sequence int, conn icmp.PacketConn, server *net.IPAddr, target string,
|
2019-10-22 16:27:21 +03:00
|
|
|
connId string, msgType uint32, data []byte, sproto int, rproto int, key int,
|
2019-10-27 14:06:55 +03:00
|
|
|
tcpmode int, tcpmode_buffer_size int, tcpmode_maxwin int, tcpmode_resend_time int, tcpmode_compress int,
|
2019-10-26 07:07:20 +03:00
|
|
|
timeout int) {
|
2018-12-17 14:06:46 +03:00
|
|
|
|
|
|
|
m := &MyMsg{
|
2019-10-22 16:04:25 +03:00
|
|
|
Id: connId,
|
|
|
|
Type: (int32)(msgType),
|
|
|
|
Target: target,
|
|
|
|
Data: data,
|
|
|
|
Rproto: (int32)(rproto),
|
|
|
|
Key: (int32)(key),
|
|
|
|
Tcpmode: (int32)(tcpmode),
|
|
|
|
TcpmodeBuffersize: (int32)(tcpmode_buffer_size),
|
|
|
|
TcpmodeMaxwin: (int32)(tcpmode_maxwin),
|
|
|
|
TcpmodeResendTimems: (int32)(tcpmode_resend_time),
|
2019-10-27 14:06:55 +03:00
|
|
|
TcpmodeCompress: (int32)(tcpmode_compress),
|
2019-10-26 07:07:20 +03:00
|
|
|
Timeout: (int32)(timeout),
|
2019-10-25 16:28:30 +03:00
|
|
|
Magic: (int32)(MyMsg_MAGIC),
|
2018-12-17 14:06:46 +03:00
|
|
|
}
|
|
|
|
|
2019-10-22 16:04:25 +03:00
|
|
|
mb, err := proto.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
loggo.Error("sendICMP Marshal MyMsg error %s %s", server.String(), err)
|
|
|
|
return
|
|
|
|
}
|
2018-12-21 10:52:34 +03:00
|
|
|
|
|
|
|
body := &icmp.Echo{
|
|
|
|
ID: id,
|
|
|
|
Seq: sequence,
|
|
|
|
Data: mb,
|
|
|
|
}
|
|
|
|
|
2018-12-17 14:06:46 +03:00
|
|
|
msg := &icmp.Message{
|
2018-12-19 09:38:44 +03:00
|
|
|
Type: (ipv4.ICMPType)(sproto),
|
2018-12-17 14:06:46 +03:00
|
|
|
Code: 0,
|
2018-12-21 10:52:34 +03:00
|
|
|
Body: body,
|
2018-12-17 14:06:46 +03:00
|
|
|
}
|
2018-12-16 08:56:40 +03:00
|
|
|
|
2018-12-17 14:06:46 +03:00
|
|
|
bytes, err := msg.Marshal(nil)
|
|
|
|
if err != nil {
|
2019-10-20 11:27:03 +03:00
|
|
|
loggo.Error("sendICMP Marshal error %s %s", server.String(), err)
|
2018-12-17 14:06:46 +03:00
|
|
|
return
|
2018-12-16 08:56:40 +03:00
|
|
|
}
|
2018-12-17 14:06:46 +03:00
|
|
|
|
|
|
|
for {
|
2018-12-18 06:39:16 +03:00
|
|
|
if _, err := conn.WriteTo(bytes, server); err != nil {
|
2018-12-17 14:06:46 +03:00
|
|
|
if neterr, ok := err.(*net.OpError); ok {
|
|
|
|
if neterr.Err == syscall.ENOBUFS {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
2019-10-26 07:01:30 +03:00
|
|
|
loggo.Info("sendICMP WriteTo error %s %s", server.String(), err)
|
2018-12-17 14:06:46 +03:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2018-12-17 10:21:15 +03:00
|
|
|
}
|
|
|
|
|
2018-12-17 14:06:46 +03:00
|
|
|
func recvICMP(conn icmp.PacketConn, recv chan<- *Packet) {
|
|
|
|
|
|
|
|
bytes := make([]byte, 10240)
|
|
|
|
for {
|
|
|
|
conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100))
|
|
|
|
n, srcaddr, err := conn.ReadFrom(bytes)
|
|
|
|
|
|
|
|
if err != nil {
|
2019-10-25 16:17:47 +03:00
|
|
|
nerr, ok := err.(net.Error)
|
|
|
|
if !ok || !nerr.Timeout() {
|
2019-10-26 07:01:30 +03:00
|
|
|
loggo.Info("Error read icmp message %s", err)
|
2019-10-25 16:17:47 +03:00
|
|
|
continue
|
2018-12-17 14:06:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-25 16:19:00 +03:00
|
|
|
if n <= 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2018-12-21 11:09:54 +03:00
|
|
|
echoId := int(binary.BigEndian.Uint16(bytes[4:6]))
|
|
|
|
echoSeq := int(binary.BigEndian.Uint16(bytes[6:8]))
|
|
|
|
|
2019-10-18 16:30:54 +03:00
|
|
|
my := &MyMsg{}
|
2019-10-22 16:04:25 +03:00
|
|
|
err = proto.Unmarshal(bytes[8:n], my)
|
|
|
|
if err != nil {
|
|
|
|
loggo.Debug("Unmarshal MyMsg error: %s", err)
|
2018-12-17 14:06:46 +03:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-10-25 16:31:04 +03:00
|
|
|
if my.Magic != (int32)(MyMsg_MAGIC) {
|
2019-10-25 16:28:30 +03:00
|
|
|
loggo.Debug("processPacket data invalid %s", my.Id)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-10-22 16:04:25 +03:00
|
|
|
recv <- &Packet{my: my,
|
|
|
|
src: srcaddr.(*net.IPAddr),
|
|
|
|
echoId: echoId, echoSeq: echoSeq}
|
2018-12-17 14:06:46 +03:00
|
|
|
}
|
2018-12-17 10:21:15 +03:00
|
|
|
}
|
|
|
|
|
2018-12-17 14:06:46 +03:00
|
|
|
type Packet struct {
|
2019-10-22 16:04:25 +03:00
|
|
|
my *MyMsg
|
2018-12-19 10:00:30 +03:00
|
|
|
src *net.IPAddr
|
2018-12-21 11:09:54 +03:00
|
|
|
echoId int
|
|
|
|
echoSeq int
|
2018-12-16 08:56:40 +03:00
|
|
|
}
|
2018-12-18 10:36:59 +03:00
|
|
|
|
|
|
|
func UniqueId() string {
|
|
|
|
b := make([]byte, 48)
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return GetMd5String(base64.URLEncoding.EncodeToString(b))
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMd5String(s string) string {
|
|
|
|
h := md5.New()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
|
|
}
|
2018-12-23 02:02:57 +03:00
|
|
|
|
2019-10-18 16:30:54 +03:00
|
|
|
const (
|
|
|
|
FRAME_MAX_SIZE int = 888
|
2019-10-26 15:45:58 +03:00
|
|
|
FRAME_MAX_ID int = 100000
|
2019-10-19 17:36:17 +03:00
|
|
|
)
|