mirror of
https://github.com/apernet/hysteria.git
synced 2025-04-02 03:57:38 +03:00
wip: obfs rework, needs further testing & profiling, wechat & faketcp not available yet
This commit is contained in:
parent
a5647379b1
commit
dc78d4b528
12 changed files with 113 additions and 158 deletions
|
@ -31,11 +31,11 @@ import (
|
|||
)
|
||||
|
||||
var clientPacketConnFuncFactoryMap = map[string]pktconns.ClientPacketConnFuncFactory{
|
||||
"": pktconns.NewClientUDPConnFunc,
|
||||
"udp": pktconns.NewClientUDPConnFunc,
|
||||
"wechat": pktconns.NewClientWeChatConnFunc,
|
||||
"wechat-video": pktconns.NewClientWeChatConnFunc,
|
||||
"faketcp": pktconns.NewClientFakeTCPConnFunc,
|
||||
"": pktconns.NewClientUDPConnFunc,
|
||||
"udp": pktconns.NewClientUDPConnFunc,
|
||||
// "wechat": pktconns.NewClientWeChatConnFunc,
|
||||
// "wechat-video": pktconns.NewClientWeChatConnFunc,
|
||||
// "faketcp": pktconns.NewClientFakeTCPConnFunc,
|
||||
}
|
||||
|
||||
func client(config *clientConfig) {
|
||||
|
|
|
@ -25,11 +25,11 @@ import (
|
|||
)
|
||||
|
||||
var serverPacketConnFuncFactoryMap = map[string]pktconns.ServerPacketConnFuncFactory{
|
||||
"": pktconns.NewServerUDPConnFunc,
|
||||
"udp": pktconns.NewServerUDPConnFunc,
|
||||
"wechat": pktconns.NewServerWeChatConnFunc,
|
||||
"wechat-video": pktconns.NewServerWeChatConnFunc,
|
||||
"faketcp": pktconns.NewServerFakeTCPConnFunc,
|
||||
"": pktconns.NewServerUDPConnFunc,
|
||||
"udp": pktconns.NewServerUDPConnFunc,
|
||||
// "wechat": pktconns.NewServerWeChatConnFunc,
|
||||
// "wechat-video": pktconns.NewServerWeChatConnFunc,
|
||||
// "faketcp": pktconns.NewServerFakeTCPConnFunc,
|
||||
}
|
||||
|
||||
func server(config *serverConfig) {
|
||||
|
|
|
@ -29,12 +29,10 @@ require (
|
|||
github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/coreos/go-iptables v0.6.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
|
@ -92,7 +90,7 @@ require (
|
|||
|
||||
replace github.com/apernet/hysteria/core => ../core/
|
||||
|
||||
replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c
|
||||
replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b
|
||||
|
||||
replace github.com/LiamHaworth/go-tproxy => github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88
|
||||
|
||||
|
|
|
@ -51,8 +51,8 @@ github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88 h1:YNsl7PMiU9x/0
|
|||
github.com/apernet/go-tproxy v0.0.0-20221025153553-ed04a2935f88/go.mod h1:uxH+nFzlJug5OHjPYmzKwvVVb9wOToeGuLNVeerwWtc=
|
||||
github.com/apernet/goproxy v0.0.0-20221124043924-155acfaf278f h1:v3Bn97M5KWzdVajNphf3PxoHdsRF/RzBVovIsH/DEvY=
|
||||
github.com/apernet/goproxy v0.0.0-20221124043924-155acfaf278f/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c h1:YoKqNVd+1knWdkYD/VjDNgEV+5FDAXTylFWAZV9PAa0=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
|
@ -72,8 +72,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
||||
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -155,8 +153,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
|
|
@ -43,4 +43,4 @@ require (
|
|||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c
|
||||
replace github.com/lucas-clemente/quic-go => github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b
|
||||
|
|
|
@ -38,8 +38,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c h1:YoKqNVd+1knWdkYD/VjDNgEV+5FDAXTylFWAZV9PAa0=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
|
|
@ -5,10 +5,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/apernet/hysteria/core/pktconns/faketcp"
|
||||
"github.com/apernet/hysteria/core/pktconns/obfs"
|
||||
"github.com/apernet/hysteria/core/pktconns/udp"
|
||||
"github.com/apernet/hysteria/core/pktconns/wechat"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -54,6 +52,7 @@ func NewClientUDPConnFunc(obfsPassword string, hopInterval time.Duration) Client
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func NewClientWeChatConnFunc(obfsPassword string, hopInterval time.Duration) ClientPacketConnFunc {
|
||||
if obfsPassword == "" {
|
||||
return func(server string) (net.PacketConn, net.Addr, error) {
|
||||
|
@ -108,6 +107,7 @@ func NewClientFakeTCPConnFunc(obfsPassword string, hopInterval time.Duration) Cl
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func NewServerUDPConnFunc(obfsPassword string) ServerPacketConnFunc {
|
||||
if obfsPassword == "" {
|
||||
|
@ -134,6 +134,7 @@ func NewServerUDPConnFunc(obfsPassword string) ServerPacketConnFunc {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func NewServerWeChatConnFunc(obfsPassword string) ServerPacketConnFunc {
|
||||
if obfsPassword == "" {
|
||||
return func(listen string) (net.PacketConn, error) {
|
||||
|
@ -179,6 +180,7 @@ func NewServerFakeTCPConnFunc(obfsPassword string) ServerPacketConnFunc {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func isMultiPortAddr(addr string) bool {
|
||||
_, portStr, err := net.SplitHostPort(addr)
|
||||
|
|
|
@ -5,54 +5,73 @@ import (
|
|||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
)
|
||||
|
||||
type Obfuscator interface {
|
||||
Deobfuscate(in []byte, out []byte) int
|
||||
Obfuscate(in []byte, out []byte) int
|
||||
}
|
||||
|
||||
const xpSaltLen = 16
|
||||
const (
|
||||
xpSaltLen = 16
|
||||
udpBufferSize = 4096
|
||||
)
|
||||
|
||||
// XPlusObfuscator obfuscates payload using one-time keys generated from hashing a pre-shared key and random salt.
|
||||
// Packet format: [salt][obfuscated payload]
|
||||
type XPlusObfuscator struct {
|
||||
Key []byte
|
||||
RandSrc *rand.Rand
|
||||
|
||||
lk sync.Mutex
|
||||
key []byte
|
||||
randSrc *rand.Rand
|
||||
randLk sync.Mutex
|
||||
bufPool sync.Pool
|
||||
saltPool sync.Pool
|
||||
}
|
||||
|
||||
func NewXPlusObfuscator(key []byte) *XPlusObfuscator {
|
||||
func NewXPlusObfuscator(key []byte) quic.Obfuscator {
|
||||
return &XPlusObfuscator{
|
||||
Key: key,
|
||||
RandSrc: rand.New(rand.NewSource(time.Now().UnixNano())),
|
||||
key: key,
|
||||
randSrc: rand.New(rand.NewSource(time.Now().UnixNano())),
|
||||
bufPool: sync.Pool{New: func() interface{} { return make([]byte, udpBufferSize) }},
|
||||
saltPool: sync.Pool{New: func() interface{} { return make([]byte, xpSaltLen) }},
|
||||
}
|
||||
}
|
||||
|
||||
func (x *XPlusObfuscator) Deobfuscate(in []byte, out []byte) int {
|
||||
outLen := len(in) - xpSaltLen
|
||||
if outLen <= 0 || len(out) < outLen {
|
||||
return 0
|
||||
func (x *XPlusObfuscator) Obfuscate(data []byte, scat bool) ([][]byte, func()) {
|
||||
if scat {
|
||||
salt := x.saltPool.Get().([]byte)
|
||||
x.randLk.Lock()
|
||||
_, _ = x.randSrc.Read(salt)
|
||||
x.randLk.Unlock()
|
||||
key := sha256.Sum256(append(x.key, salt...))
|
||||
buf := x.bufPool.Get().([]byte)
|
||||
for i, c := range data {
|
||||
buf[i] = c ^ key[i%sha256.Size]
|
||||
}
|
||||
payload := buf[:len(data)]
|
||||
return [][]byte{salt, payload}, func() {
|
||||
x.saltPool.Put(salt)
|
||||
x.bufPool.Put(buf)
|
||||
}
|
||||
} else {
|
||||
buf := x.bufPool.Get().([]byte)
|
||||
x.randLk.Lock()
|
||||
_, _ = x.randSrc.Read(buf[:xpSaltLen])
|
||||
x.randLk.Unlock()
|
||||
key := sha256.Sum256(append(x.key, buf[:xpSaltLen]...))
|
||||
for i, c := range data {
|
||||
buf[i+xpSaltLen] = c ^ key[i%sha256.Size]
|
||||
}
|
||||
payload := buf[:xpSaltLen+len(data)]
|
||||
return [][]byte{payload}, func() {
|
||||
x.bufPool.Put(buf)
|
||||
}
|
||||
}
|
||||
key := sha256.Sum256(append(x.Key, in[:xpSaltLen]...))
|
||||
for i, c := range in[xpSaltLen:] {
|
||||
out[i] = c ^ key[i%sha256.Size]
|
||||
}
|
||||
return outLen
|
||||
}
|
||||
|
||||
func (x *XPlusObfuscator) Obfuscate(in []byte, out []byte) int {
|
||||
outLen := len(in) + xpSaltLen
|
||||
if len(out) < outLen {
|
||||
func (x *XPlusObfuscator) Deobfuscate(data []byte) int {
|
||||
if len(data) <= xpSaltLen {
|
||||
return 0
|
||||
}
|
||||
x.lk.Lock()
|
||||
_, _ = x.RandSrc.Read(out[:xpSaltLen])
|
||||
x.lk.Unlock()
|
||||
key := sha256.Sum256(append(x.Key, out[:xpSaltLen]...))
|
||||
for i, c := range in {
|
||||
out[i+xpSaltLen] = c ^ key[i%sha256.Size]
|
||||
key := sha256.Sum256(append(x.key, data[:xpSaltLen]...))
|
||||
for i, c := range data[xpSaltLen:] {
|
||||
data[i] = c ^ key[i%sha256.Size]
|
||||
}
|
||||
return outLen
|
||||
return len(data) - xpSaltLen
|
||||
}
|
||||
|
|
|
@ -18,13 +18,35 @@ func TestXPlusObfuscator(t *testing.T) {
|
|||
"And by opposing end them. To die—to sleep,\nNo more; and by a sleep to say we end")},
|
||||
{name: "empty", p: []byte("")},
|
||||
}
|
||||
// Non-scat
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
buf := make([]byte, 10240)
|
||||
n := x.Obfuscate(tt.p, buf)
|
||||
n2 := x.Deobfuscate(buf[:n], buf[n:])
|
||||
if !bytes.Equal(tt.p, buf[n:n+n2]) {
|
||||
t.Errorf("Inconsistent deobfuscate result: got %v, want %v", buf[n:n+n2], tt.p)
|
||||
bb, _ := x.Obfuscate(tt.p, false)
|
||||
if len(bb) != 1 {
|
||||
t.Errorf("Incorrect number of buffers returned: %d", len(bb))
|
||||
}
|
||||
n := x.Deobfuscate(bb[0])
|
||||
if !bytes.Equal(tt.p, bb[0][:n]) {
|
||||
t.Errorf("Inconsistent deobfuscation: %s", string(bb[0][:n]))
|
||||
}
|
||||
})
|
||||
}
|
||||
// Scat
|
||||
for _, tt := range tests {
|
||||
t.Run("scat-"+tt.name, func(t *testing.T) {
|
||||
bb, _ := x.Obfuscate(tt.p, true)
|
||||
if len(bb) != 2 {
|
||||
t.Errorf("Incorrect number of buffers returned: %d", len(bb))
|
||||
}
|
||||
if len(bb[0]) != xpSaltLen || len(bb[1]) != len(tt.p) {
|
||||
t.Errorf("Incorrect buffer length: %d, %d", len(bb[0]), len(bb[1]))
|
||||
}
|
||||
var data []byte
|
||||
data = append(data, bb[0]...)
|
||||
data = append(data, bb[1]...)
|
||||
n := x.Deobfuscate(data)
|
||||
if !bytes.Equal(tt.p, data[:n]) {
|
||||
t.Errorf("Inconsistent deobfuscation: %s", string(bb[0][:n]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/apernet/hysteria/core/pktconns/obfs"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -24,7 +24,7 @@ type ObfsUDPHopClientPacketConn struct {
|
|||
serverAddrs []net.Addr
|
||||
hopInterval time.Duration
|
||||
|
||||
obfs obfs.Obfuscator
|
||||
quic.Obfuscator
|
||||
|
||||
connMutex sync.RWMutex
|
||||
prevConn net.PacketConn
|
||||
|
@ -57,7 +57,7 @@ type udpPacket struct {
|
|||
addr net.Addr
|
||||
}
|
||||
|
||||
func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obfs obfs.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) {
|
||||
func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obfs quic.Obfuscator) (*ObfsUDPHopClientPacketConn, net.Addr, error) {
|
||||
host, ports, err := parseAddr(server)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -79,7 +79,7 @@ func NewObfsUDPHopClientPacketConn(server string, hopInterval time.Duration, obf
|
|||
serverAddr: &hopAddr,
|
||||
serverAddrs: serverAddrs,
|
||||
hopInterval: hopInterval,
|
||||
obfs: obfs,
|
||||
Obfuscator: obfs,
|
||||
addrIndex: rand.Intn(len(serverAddrs)),
|
||||
recvQueue: make(chan *udpPacket, packetQueueSize),
|
||||
closeChan: make(chan struct{}),
|
||||
|
@ -155,11 +155,7 @@ func (c *ObfsUDPHopClientPacketConn) hop() {
|
|||
_ = c.prevConn.Close() // recvRoutine will exit on error
|
||||
}
|
||||
c.prevConn = c.currentConn
|
||||
if c.obfs != nil {
|
||||
c.currentConn = NewObfsUDPConn(newConn, c.obfs)
|
||||
} else {
|
||||
c.currentConn = newConn
|
||||
}
|
||||
c.currentConn = newConn
|
||||
// Set buffer sizes if previously set
|
||||
if c.readBufferSize > 0 {
|
||||
_ = trySetPacketConnReadBuffer(c.currentConn, c.readBufferSize)
|
||||
|
|
|
@ -2,99 +2,20 @@ package udp
|
|||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/apernet/hysteria/core/pktconns/obfs"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
)
|
||||
|
||||
const udpBufferSize = 4096
|
||||
|
||||
type ObfsUDPPacketConn struct {
|
||||
orig *net.UDPConn
|
||||
obfs obfs.Obfuscator
|
||||
|
||||
readBuf []byte
|
||||
readMutex sync.Mutex
|
||||
writeBuf []byte
|
||||
writeMutex sync.Mutex
|
||||
type ObfsUDPConn struct {
|
||||
net.UDPConn
|
||||
quic.Obfuscator
|
||||
}
|
||||
|
||||
func NewObfsUDPConn(orig *net.UDPConn, obfs obfs.Obfuscator) *ObfsUDPPacketConn {
|
||||
return &ObfsUDPPacketConn{
|
||||
orig: orig,
|
||||
obfs: obfs,
|
||||
readBuf: make([]byte, udpBufferSize),
|
||||
writeBuf: make([]byte, udpBufferSize),
|
||||
func NewObfsUDPConn(udpConn *net.UDPConn, obfs quic.Obfuscator) *ObfsUDPConn {
|
||||
return &ObfsUDPConn{
|
||||
UDPConn: *udpConn,
|
||||
Obfuscator: obfs,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) ReadFrom(p []byte) (int, net.Addr, error) {
|
||||
for {
|
||||
c.readMutex.Lock()
|
||||
n, addr, err := c.orig.ReadFrom(c.readBuf)
|
||||
if n <= 0 {
|
||||
c.readMutex.Unlock()
|
||||
return 0, addr, err
|
||||
}
|
||||
newN := c.obfs.Deobfuscate(c.readBuf[:n], p)
|
||||
c.readMutex.Unlock()
|
||||
if newN > 0 {
|
||||
// Valid packet
|
||||
return newN, addr, err
|
||||
} else if err != nil {
|
||||
// Not valid and orig.ReadFrom had some error
|
||||
return 0, addr, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
c.writeMutex.Lock()
|
||||
bn := c.obfs.Obfuscate(p, c.writeBuf)
|
||||
_, err = c.orig.WriteTo(c.writeBuf[:bn], addr)
|
||||
c.writeMutex.Unlock()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return len(p), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) Close() error {
|
||||
return c.orig.Close()
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) LocalAddr() net.Addr {
|
||||
return c.orig.LocalAddr()
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SetDeadline(t time.Time) error {
|
||||
return c.orig.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SetReadDeadline(t time.Time) error {
|
||||
return c.orig.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SetWriteDeadline(t time.Time) error {
|
||||
return c.orig.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SetReadBuffer(bytes int) error {
|
||||
return c.orig.SetReadBuffer(bytes)
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SetWriteBuffer(bytes int) error {
|
||||
return c.orig.SetWriteBuffer(bytes)
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) SyscallConn() (syscall.RawConn, error) {
|
||||
return c.orig.SyscallConn()
|
||||
}
|
||||
|
||||
func (c *ObfsUDPPacketConn) File() (f *os.File, err error) {
|
||||
return c.orig.File()
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
|
|||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221208013043-a01b50646f2c/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b h1:Z49X7P2v8otyir1SAcAbbEzVZNn+AiYwInpf0dbhBJI=
|
||||
github.com/apernet/quic-go v0.31.1-0.20221217071728-fd43ba23387b/go.mod h1:NVsR0x0u2DwoSL69OKbkbiF2vljWREImECy9jD04+R0=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue