github.com/metacubex/mihomo@v1.18.5/transport/hysteria/conns/wechat/obfs.go (about)

     1  package wechat
     2  
     3  import (
     4  	"encoding/binary"
     5  	"net"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/metacubex/mihomo/log"
    10  	"github.com/metacubex/mihomo/transport/hysteria/obfs"
    11  
    12  	"github.com/zhangyunhao116/fastrand"
    13  )
    14  
    15  const udpBufferSize = 65535
    16  
    17  type ObfsWeChatUDPConn struct {
    18  	orig       net.PacketConn
    19  	obfs       obfs.Obfuscator
    20  	readBuf    []byte
    21  	readMutex  sync.Mutex
    22  	writeBuf   []byte
    23  	writeMutex sync.Mutex
    24  	sn         uint32
    25  }
    26  
    27  func NewObfsWeChatUDPConn(orig net.PacketConn, obfs obfs.Obfuscator) *ObfsWeChatUDPConn {
    28  	log.Infoln("new wechat")
    29  	return &ObfsWeChatUDPConn{
    30  		orig:     orig,
    31  		obfs:     obfs,
    32  		readBuf:  make([]byte, udpBufferSize),
    33  		writeBuf: make([]byte, udpBufferSize),
    34  		sn:       fastrand.Uint32() & 0xFFFF,
    35  	}
    36  }
    37  
    38  func (c *ObfsWeChatUDPConn) ReadFrom(p []byte) (int, net.Addr, error) {
    39  	for {
    40  		c.readMutex.Lock()
    41  		n, addr, err := c.orig.ReadFrom(c.readBuf)
    42  		if n <= 13 {
    43  			c.readMutex.Unlock()
    44  			return 0, addr, err
    45  		}
    46  		newN := c.obfs.Deobfuscate(c.readBuf[13:n], p)
    47  		c.readMutex.Unlock()
    48  		if newN > 0 {
    49  			// Valid packet
    50  			return newN, addr, err
    51  		} else if err != nil {
    52  			// Not valid and orig.ReadFrom had some error
    53  			return 0, addr, err
    54  		}
    55  	}
    56  }
    57  
    58  func (c *ObfsWeChatUDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
    59  	c.writeMutex.Lock()
    60  	c.writeBuf[0] = 0xa1
    61  	c.writeBuf[1] = 0x08
    62  	binary.BigEndian.PutUint32(c.writeBuf[2:], c.sn)
    63  	c.sn++
    64  	c.writeBuf[6] = 0x00
    65  	c.writeBuf[7] = 0x10
    66  	c.writeBuf[8] = 0x11
    67  	c.writeBuf[9] = 0x18
    68  	c.writeBuf[10] = 0x30
    69  	c.writeBuf[11] = 0x22
    70  	c.writeBuf[12] = 0x30
    71  	bn := c.obfs.Obfuscate(p, c.writeBuf[13:])
    72  	_, err = c.orig.WriteTo(c.writeBuf[:13+bn], addr)
    73  	c.writeMutex.Unlock()
    74  	if err != nil {
    75  		return 0, err
    76  	} else {
    77  		return len(p), nil
    78  	}
    79  }
    80  
    81  func (c *ObfsWeChatUDPConn) Close() error {
    82  	return c.orig.Close()
    83  }
    84  
    85  func (c *ObfsWeChatUDPConn) LocalAddr() net.Addr {
    86  	return c.orig.LocalAddr()
    87  }
    88  
    89  func (c *ObfsWeChatUDPConn) SetDeadline(t time.Time) error {
    90  	return c.orig.SetDeadline(t)
    91  }
    92  
    93  func (c *ObfsWeChatUDPConn) SetReadDeadline(t time.Time) error {
    94  	return c.orig.SetReadDeadline(t)
    95  }
    96  
    97  func (c *ObfsWeChatUDPConn) SetWriteDeadline(t time.Time) error {
    98  	return c.orig.SetWriteDeadline(t)
    99  }