pingtunnel/pingtunnel.go

226 lines
4.8 KiB
Go
Raw Permalink Normal View History

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"
2018-12-17 14:06:46 +03:00
"fmt"
"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-17 10:21:15 +03:00
const (
2018-12-18 14:07:35 +03:00
DATA uint32 = 0x01010101
2018-12-19 10:00:30 +03:00
PING uint32 = 0x02020202
END uint32 = 0xAAAABBBB
2018-12-17 10:21:15 +03:00
)
2018-12-16 08:56:40 +03:00
2018-12-17 14:06:46 +03:00
// An Echo represents an ICMP echo request or reply message body.
type MyMsg struct {
2018-12-19 09:38:44 +03:00
TYPE uint32
ID string
TARGET string
Data []byte
RPROTO uint16
ENDTYPE uint32
2018-12-16 08:56:40 +03:00
}
2018-12-17 14:06:46 +03:00
// Len implements the Len method of MessageBody interface.
func (p *MyMsg) Len(proto int) int {
2018-12-16 08:56:40 +03:00
if p == nil {
return 0
}
2018-12-19 09:38:44 +03:00
return 4 + p.LenString(p.ID) + p.LenString(p.TARGET) + p.LenData(p.Data) + 2 + 4
2018-12-18 10:36:59 +03:00
}
func (p *MyMsg) LenString(s string) int {
return 2 + len(s)
2018-12-16 08:56:40 +03:00
}
2018-12-19 09:38:44 +03:00
func (p *MyMsg) LenData(data []byte) int {
return 2 + len(data)
}
2018-12-17 14:06:46 +03:00
// Marshal implements the Marshal method of MessageBody interface.
func (p *MyMsg) Marshal(proto int) ([]byte, error) {
2018-12-18 10:36:59 +03:00
2018-12-17 10:21:15 +03:00
b := make([]byte, p.Len(proto))
2018-12-18 10:36:59 +03:00
binary.BigEndian.PutUint32(b[:4], uint32(p.TYPE))
id := p.MarshalString(p.ID)
copy(b[4:], id)
target := p.MarshalString(p.TARGET)
copy(b[4+p.LenString(p.ID):], target)
2018-12-19 09:38:44 +03:00
data := p.MarshalData(p.Data)
copy(b[4+p.LenString(p.ID)+p.LenString(p.TARGET):], data)
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))
2018-12-18 10:36:59 +03:00
2018-12-16 08:56:40 +03:00
return b, nil
}
2018-12-18 10:36:59 +03:00
func (p *MyMsg) MarshalString(s string) []byte {
b := make([]byte, p.LenString(s))
binary.BigEndian.PutUint16(b[:2], uint16(len(s)))
copy(b[2:], []byte(s))
return b
}
2018-12-19 09:38:44 +03:00
func (p *MyMsg) MarshalData(data []byte) []byte {
b := make([]byte, p.LenData(data))
binary.BigEndian.PutUint16(b[:2], uint16(len(data)))
copy(b[2:], []byte(data))
return b
}
2018-12-17 14:06:46 +03:00
// Marshal implements the Marshal method of MessageBody interface.
func (p *MyMsg) Unmarshal(b []byte) error {
2018-12-18 11:08:28 +03:00
defer func() {
2018-12-18 11:17:57 +03:00
recover()
2018-12-18 11:08:28 +03:00
}()
2018-12-18 10:36:59 +03:00
p.TYPE = binary.BigEndian.Uint32(b[:4])
p.ID = p.UnmarshalString(b[4:])
p.TARGET = p.UnmarshalString(b[4+p.LenString(p.ID):])
2018-12-19 09:38:44 +03:00
p.Data = p.UnmarshalData(b[4+p.LenString(p.ID)+p.LenString(p.TARGET):])
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:])
2018-12-18 10:36:59 +03:00
2018-12-17 14:06:46 +03:00
return nil
}
2018-12-18 10:36:59 +03:00
func (p *MyMsg) UnmarshalString(b []byte) string {
len := binary.BigEndian.Uint16(b[:2])
2018-12-19 09:38:44 +03:00
if len > 32 || len < 0 {
panic(nil)
}
2018-12-18 10:36:59 +03:00
data := make([]byte, len)
copy(data, b[2:])
return string(data)
2018-12-17 14:06:46 +03:00
}
2018-12-19 09:38:44 +03:00
func (p *MyMsg) UnmarshalData(b []byte) []byte {
len := binary.BigEndian.Uint16(b[:2])
if len > 2048 || len < 0 {
panic(nil)
}
data := make([]byte, len)
copy(data, b[2:])
return data
}
func sendICMP(conn icmp.PacketConn, server *net.IPAddr, target string, connId string, msgType uint32, data []byte, sproto int, rproto int) {
2018-12-17 14:06:46 +03:00
m := &MyMsg{
2018-12-19 09:38:44 +03:00
ID: connId,
TYPE: msgType,
TARGET: target,
Data: data,
RPROTO: (uint16)(rproto),
2018-12-19 10:00:30 +03:00
ENDTYPE: END,
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,
Body: m,
}
2018-12-16 08:56:40 +03:00
2018-12-17 14:06:46 +03:00
bytes, err := msg.Marshal(nil)
if err != nil {
2018-12-18 06:39:16 +03:00
fmt.Printf("sendICMP Marshal error %s %s\n", 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
}
}
2018-12-18 06:39:16 +03:00
fmt.Printf("sendICMP WriteTo error %s %s\n", 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 {
if neterr, ok := err.(*net.OpError); ok {
if neterr.Timeout() {
// Read timeout
continue
} else {
fmt.Printf("Error read icmp message %s\n", err)
continue
}
}
}
my := &MyMsg{
}
my.Unmarshal(bytes[4:n])
2018-12-19 10:00:30 +03:00
if (my.TYPE != (uint32)(DATA) && my.TYPE != (uint32)(PING)) || my.ENDTYPE != (uint32)(END) {
2018-12-19 09:42:53 +03:00
//fmt.Printf("processPacket diff type %s %d %d \n", my.ID, my.TYPE, my.ENDTYPE)
2018-12-17 14:06:46 +03:00
continue
}
2018-12-19 09:38:44 +03:00
if my.Data == nil {
2018-12-19 10:00:30 +03:00
fmt.Printf("processPacket data nil %s\n", my.ID)
2018-12-19 09:38:44 +03:00
return
}
2018-12-20 09:31:01 +03:00
recv <- &Packet{msgType: my.TYPE, data: my.Data, id: my.ID, target: my.TARGET, src: srcaddr.(*net.IPAddr), rproto: (int)((int16)(my.RPROTO))}
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 {
2018-12-19 10:00:30 +03:00
msgType uint32
data []byte
id string
target string
src *net.IPAddr
rproto 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))
}