glider/proxy/trojan/packet.go

93 lines
1.8 KiB
Go
Raw Normal View History

2020-04-12 15:27:20 +08:00
package trojan
import (
"encoding/binary"
"errors"
"io"
"net"
"github.com/nadoo/glider/pkg/pool"
"github.com/nadoo/glider/pkg/socks"
2020-04-12 15:27:20 +08:00
)
2020-10-03 20:51:27 +08:00
// PktConn is a udp Packet.Conn.
2020-04-12 15:27:20 +08:00
type PktConn struct {
net.Conn
target socks.Addr
2020-04-12 15:27:20 +08:00
}
2020-04-13 00:55:11 +08:00
// NewPktConn returns a PktConn.
func NewPktConn(c net.Conn, target socks.Addr) *PktConn {
return &PktConn{Conn: c, target: target}
2020-04-12 15:27:20 +08:00
}
2020-04-13 00:55:11 +08:00
// ReadFrom implements the necessary function of net.PacketConn.
2020-04-12 15:27:20 +08:00
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
// ATYP, DST.ADDR, DST.PORT
tgtAddr, err := socks.ReadAddr(pc.Conn)
if err != nil {
return 0, nil, err
}
target, err := net.ResolveUDPAddr("udp", tgtAddr.String())
2020-04-12 15:27:20 +08:00
if err != nil {
return 0, nil, err
}
// TODO: we know that we use it in proxy.CopyUDP and the length of b is enough, check it later.
if len(b) < 2 {
return 0, nil, errors.New("buf size is not enough")
}
2020-04-12 15:27:20 +08:00
// Length
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
return 0, nil, err
}
length := int(binary.BigEndian.Uint16(b[:2]))
if len(b) < length {
return 0, nil, errors.New("buf size is not enough")
2020-04-12 15:27:20 +08:00
}
// CRLF
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
return 0, nil, err
}
// Payload
n, err := io.ReadFull(pc.Conn, b[:length])
if err != nil {
2020-10-03 20:51:27 +08:00
return n, nil, err
2020-04-12 15:27:20 +08:00
}
return n, target, err
2020-04-12 15:27:20 +08:00
}
2020-04-13 12:26:21 +08:00
// WriteTo implements the necessary function of net.PacketConn.
2020-04-12 15:27:20 +08:00
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
target := pc.target
if addr != nil {
target = socks.ParseAddr(addr.String())
}
if target == nil {
return 0, errors.New("invalid addr")
}
2020-11-03 22:52:50 +08:00
buf := pool.GetBytesBuffer()
defer pool.PutBytesBuffer(buf)
2020-04-19 23:20:15 +08:00
tgtLen, _ := buf.Write(target)
2020-04-19 23:20:15 +08:00
binary.Write(buf, binary.BigEndian, uint16(len(b)))
2020-04-12 15:27:20 +08:00
buf.WriteString("\r\n")
buf.Write(b)
2020-10-02 19:09:12 +08:00
n, err := pc.Write(buf.Bytes())
if n > tgtLen+4 {
return n - tgtLen - 4, nil
}
return 0, err
2020-04-12 15:27:20 +08:00
}