2018-06-28 09:49:23 +08:00
|
|
|
package socks5
|
|
|
|
|
|
|
|
import (
|
2020-04-11 21:08:10 +08:00
|
|
|
"errors"
|
2018-06-28 09:49:23 +08:00
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/nadoo/glider/common/log"
|
2020-04-22 19:37:10 +08:00
|
|
|
"github.com/nadoo/glider/common/pool"
|
2018-06-28 09:49:23 +08:00
|
|
|
"github.com/nadoo/glider/common/socks"
|
|
|
|
)
|
|
|
|
|
|
|
|
// PktConn .
|
|
|
|
type PktConn struct {
|
|
|
|
net.PacketConn
|
|
|
|
|
|
|
|
writeAddr net.Addr // write to and read from addr
|
|
|
|
|
|
|
|
tgtAddr socks.Addr
|
|
|
|
tgtHeader bool
|
|
|
|
|
|
|
|
ctrlConn net.Conn // tcp control conn
|
|
|
|
}
|
|
|
|
|
2020-08-16 12:00:46 +08:00
|
|
|
// NewPktConn returns a PktConn.
|
2018-06-28 09:49:23 +08:00
|
|
|
func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHeader bool, ctrlConn net.Conn) *PktConn {
|
|
|
|
pc := &PktConn{
|
|
|
|
PacketConn: c,
|
|
|
|
writeAddr: writeAddr,
|
|
|
|
tgtAddr: tgtAddr,
|
|
|
|
tgtHeader: tgtHeader,
|
|
|
|
ctrlConn: ctrlConn}
|
|
|
|
|
|
|
|
if ctrlConn != nil {
|
|
|
|
go func() {
|
2020-04-22 19:37:10 +08:00
|
|
|
buf := pool.GetBuffer(1)
|
|
|
|
defer pool.PutBuffer(buf)
|
2018-06-28 09:49:23 +08:00
|
|
|
for {
|
|
|
|
_, err := ctrlConn.Read(buf)
|
|
|
|
if err, ok := err.(net.Error); ok && err.Timeout() {
|
|
|
|
continue
|
|
|
|
}
|
2018-06-28 23:20:04 +08:00
|
|
|
log.F("[socks5] dialudp udp associate end")
|
2018-06-28 09:49:23 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
return pc
|
|
|
|
}
|
|
|
|
|
2020-08-16 12:00:46 +08:00
|
|
|
// ReadFrom overrides the original function from net.PacketConn.
|
2018-06-28 09:49:23 +08:00
|
|
|
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
|
|
|
if !pc.tgtHeader {
|
|
|
|
return pc.PacketConn.ReadFrom(b)
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:37:10 +08:00
|
|
|
buf := pool.GetBuffer(len(b))
|
|
|
|
defer pool.PutBuffer(buf)
|
|
|
|
|
2018-06-28 09:49:23 +08:00
|
|
|
n, raddr, err := pc.PacketConn.ReadFrom(buf)
|
|
|
|
if err != nil {
|
|
|
|
return n, raddr, err
|
|
|
|
}
|
|
|
|
|
2020-04-12 15:27:20 +08:00
|
|
|
if n < 3 {
|
2020-04-11 21:08:10 +08:00
|
|
|
return n, raddr, errors.New("not enough size to get addr")
|
|
|
|
}
|
|
|
|
|
2018-06-28 09:49:23 +08:00
|
|
|
// https://tools.ietf.org/html/rfc1928#section-7
|
|
|
|
// +----+------+------+----------+----------+----------+
|
|
|
|
// |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
|
|
|
// +----+------+------+----------+----------+----------+
|
|
|
|
// | 2 | 1 | 1 | Variable | 2 | Variable |
|
|
|
|
// +----+------+------+----------+----------+----------+
|
|
|
|
tgtAddr := socks.SplitAddr(buf[3:])
|
2020-04-11 21:08:10 +08:00
|
|
|
if tgtAddr == nil {
|
|
|
|
return n, raddr, errors.New("can not get addr")
|
|
|
|
}
|
2018-06-28 09:49:23 +08:00
|
|
|
copy(b, buf[3+len(tgtAddr):])
|
|
|
|
|
|
|
|
//test
|
|
|
|
if pc.writeAddr == nil {
|
|
|
|
pc.writeAddr = raddr
|
|
|
|
}
|
|
|
|
|
|
|
|
if pc.tgtAddr == nil {
|
|
|
|
pc.tgtAddr = tgtAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
return n - len(tgtAddr) - 3, raddr, err
|
|
|
|
}
|
|
|
|
|
2020-08-16 12:00:46 +08:00
|
|
|
// WriteTo overrides the original function from net.PacketConn.
|
2018-06-28 09:49:23 +08:00
|
|
|
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
|
|
|
if !pc.tgtHeader {
|
|
|
|
return pc.PacketConn.WriteTo(b, addr)
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:37:10 +08:00
|
|
|
buf := pool.GetBuffer(3 + len(pc.tgtAddr) + len(b))
|
|
|
|
defer pool.PutBuffer(buf)
|
|
|
|
|
|
|
|
copy(buf, []byte{0, 0, 0})
|
|
|
|
copy(buf[3:], pc.tgtAddr)
|
|
|
|
copy(buf[3+len(pc.tgtAddr):], b)
|
|
|
|
|
2018-06-28 09:49:23 +08:00
|
|
|
return pc.PacketConn.WriteTo(buf, pc.writeAddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close .
|
|
|
|
func (pc *PktConn) Close() error {
|
|
|
|
if pc.ctrlConn != nil {
|
|
|
|
pc.ctrlConn.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
return pc.PacketConn.Close()
|
|
|
|
}
|