mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-06-30 00:09:57 +00:00
UDP TProxy ACL & Fix SOCKS5 hijack bug
This commit is contained in:
parent
7ba81612f8
commit
b3d149a72f
@ -63,12 +63,12 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
n, rAddr, err := conn.ReadFromUDP(buf)
|
n, rAddr, err := conn.ReadFromUDP(buf)
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
connMapMutex.RLock()
|
connMapMutex.RLock()
|
||||||
cme := connMap[rAddr.String()]
|
entry := connMap[rAddr.String()]
|
||||||
connMapMutex.RUnlock()
|
connMapMutex.RUnlock()
|
||||||
if cme != nil {
|
if entry != nil {
|
||||||
// Existing conn
|
// Existing conn
|
||||||
cme.Deadline.Store(time.Now().Add(r.Timeout))
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
_ = cme.HyConn.WriteTo(buf[:n], r.Remote)
|
_ = entry.HyConn.WriteTo(buf[:n], r.Remote)
|
||||||
} else {
|
} else {
|
||||||
// New
|
// New
|
||||||
r.ConnFunc(rAddr)
|
r.ConnFunc(rAddr)
|
||||||
@ -77,10 +77,10 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
r.ErrorFunc(rAddr, err)
|
r.ErrorFunc(rAddr, err)
|
||||||
} else {
|
} else {
|
||||||
// Add it to the map
|
// Add it to the map
|
||||||
ent := &connEntry{HyConn: hyConn}
|
entry := &connEntry{HyConn: hyConn}
|
||||||
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
connMapMutex.Lock()
|
connMapMutex.Lock()
|
||||||
connMap[rAddr.String()] = ent
|
connMap[rAddr.String()] = entry
|
||||||
connMapMutex.Unlock()
|
connMapMutex.Unlock()
|
||||||
// Start remote to local
|
// Start remote to local
|
||||||
go func() {
|
go func() {
|
||||||
@ -89,14 +89,14 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
_, _ = conn.WriteToUDP(bs, rAddr)
|
_, _ = conn.WriteToUDP(bs, rAddr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Timeout cleanup routine
|
// Timeout cleanup routine
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
ttl := ent.Deadline.Load().(time.Time).Sub(time.Now())
|
ttl := entry.Deadline.Load().(time.Time).Sub(time.Now())
|
||||||
if ttl <= 0 {
|
if ttl <= 0 {
|
||||||
// Time to die
|
// Time to die
|
||||||
connMapMutex.Lock()
|
connMapMutex.Lock()
|
||||||
|
@ -370,7 +370,7 @@ func (s *Server) udpServer(clientConn *net.UDPConn, localRelayConn *net.UDPConn,
|
|||||||
case acl.ActionBlock:
|
case acl.ActionBlock:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
case acl.ActionHijack:
|
case acl.ActionHijack:
|
||||||
hijackAddr := net.JoinHostPort(arg, net.JoinHostPort(arg, strconv.Itoa(int(port))))
|
hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port)))
|
||||||
rAddr, err := net.ResolveUDPAddr("udp", hijackAddr)
|
rAddr, err := net.ResolveUDPAddr("udp", hijackAddr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, _ = localRelayConn.WriteToUDP(d.Data, rAddr)
|
_, _ = localRelayConn.WriteToUDP(d.Data, rAddr)
|
||||||
|
@ -5,7 +5,9 @@ import (
|
|||||||
"github.com/LiamHaworth/go-tproxy"
|
"github.com/LiamHaworth/go-tproxy"
|
||||||
"github.com/tobyxdd/hysteria/pkg/acl"
|
"github.com/tobyxdd/hysteria/pkg/acl"
|
||||||
"github.com/tobyxdd/hysteria/pkg/core"
|
"github.com/tobyxdd/hysteria/pkg/core"
|
||||||
|
"github.com/tobyxdd/hysteria/pkg/utils"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -47,9 +49,53 @@ func NewUDPTProxy(hyClient *core.Client, listen string, timeout time.Duration, a
|
|||||||
|
|
||||||
type connEntry struct {
|
type connEntry struct {
|
||||||
HyConn core.UDPConn
|
HyConn core.UDPConn
|
||||||
|
LocalConn *net.UDPConn
|
||||||
Deadline atomic.Value
|
Deadline atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *UDPTProxy) sendPacket(entry *connEntry, dstAddr *net.UDPAddr, data []byte) error {
|
||||||
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
|
host, port, err := utils.SplitHostPort(dstAddr.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
action, arg := acl.ActionProxy, ""
|
||||||
|
var ipAddr *net.IPAddr
|
||||||
|
var resErr error
|
||||||
|
if r.ACLEngine != nil && entry.LocalConn != nil {
|
||||||
|
action, arg, ipAddr, resErr = r.ACLEngine.ResolveAndMatch(host)
|
||||||
|
// Doesn't always matter if the resolution fails, as we may send it through HyClient
|
||||||
|
}
|
||||||
|
switch action {
|
||||||
|
case acl.ActionDirect:
|
||||||
|
if resErr != nil {
|
||||||
|
return resErr
|
||||||
|
}
|
||||||
|
_, err = entry.LocalConn.WriteToUDP(data, &net.UDPAddr{
|
||||||
|
IP: ipAddr.IP,
|
||||||
|
Port: int(port),
|
||||||
|
Zone: ipAddr.Zone,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
case acl.ActionProxy:
|
||||||
|
return entry.HyConn.WriteTo(data, dstAddr.String())
|
||||||
|
case acl.ActionBlock:
|
||||||
|
// Do nothing
|
||||||
|
return nil
|
||||||
|
case acl.ActionHijack:
|
||||||
|
hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port)))
|
||||||
|
rAddr, err := net.ResolveUDPAddr("udp", hijackAddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = entry.LocalConn.WriteToUDP(data, rAddr)
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
// Do nothing
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *UDPTProxy) ListenAndServe() error {
|
func (r *UDPTProxy) ListenAndServe() error {
|
||||||
conn, err := tproxy.ListenUDP("udp", r.ListenAddr)
|
conn, err := tproxy.ListenUDP("udp", r.ListenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -65,24 +111,33 @@ func (r *UDPTProxy) ListenAndServe() error {
|
|||||||
n, srcAddr, dstAddr, err := tproxy.ReadFromUDP(conn, buf)
|
n, srcAddr, dstAddr, err := tproxy.ReadFromUDP(conn, buf)
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
connMapMutex.RLock()
|
connMapMutex.RLock()
|
||||||
cme := connMap[srcAddr.String()]
|
entry := connMap[srcAddr.String()]
|
||||||
connMapMutex.RUnlock()
|
connMapMutex.RUnlock()
|
||||||
if cme != nil {
|
if entry != nil {
|
||||||
// Existing conn
|
// Existing conn
|
||||||
cme.Deadline.Store(time.Now().Add(r.Timeout))
|
_ = r.sendPacket(entry, dstAddr, buf[:n])
|
||||||
_ = cme.HyConn.WriteTo(buf[:n], dstAddr.String())
|
|
||||||
} else {
|
} else {
|
||||||
// New
|
// New
|
||||||
r.ConnFunc(srcAddr)
|
r.ConnFunc(srcAddr)
|
||||||
hyConn, err := r.HyClient.DialUDP()
|
hyConn, err := r.HyClient.DialUDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.ErrorFunc(srcAddr, err)
|
r.ErrorFunc(srcAddr, err)
|
||||||
} else {
|
continue
|
||||||
|
}
|
||||||
|
var localConn *net.UDPConn
|
||||||
|
if r.ACLEngine != nil {
|
||||||
|
localConn, err = net.ListenUDP("udp", nil)
|
||||||
|
if err != nil {
|
||||||
|
r.ErrorFunc(srcAddr, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Send
|
||||||
|
entry := &connEntry{HyConn: hyConn, LocalConn: localConn}
|
||||||
|
_ = r.sendPacket(entry, dstAddr, buf[:n])
|
||||||
// Add it to the map
|
// Add it to the map
|
||||||
ent := &connEntry{HyConn: hyConn}
|
|
||||||
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
|
||||||
connMapMutex.Lock()
|
connMapMutex.Lock()
|
||||||
connMap[srcAddr.String()] = ent
|
connMap[srcAddr.String()] = entry
|
||||||
connMapMutex.Unlock()
|
connMapMutex.Unlock()
|
||||||
// Start remote to local
|
// Start remote to local
|
||||||
go func() {
|
go func() {
|
||||||
@ -91,18 +146,36 @@ func (r *UDPTProxy) ListenAndServe() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
_, _ = conn.WriteToUDP(bs, srcAddr)
|
_, _ = conn.WriteToUDP(bs, srcAddr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
if localConn != nil {
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, udpBufferSize)
|
||||||
|
for {
|
||||||
|
n, _, err := localConn.ReadFrom(buf)
|
||||||
|
if n > 0 {
|
||||||
|
entry.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
|
_, _ = conn.WriteToUDP(buf[:n], srcAddr)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
// Timeout cleanup routine
|
// Timeout cleanup routine
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
ttl := ent.Deadline.Load().(time.Time).Sub(time.Now())
|
ttl := entry.Deadline.Load().(time.Time).Sub(time.Now())
|
||||||
if ttl <= 0 {
|
if ttl <= 0 {
|
||||||
// Time to die
|
// Time to die
|
||||||
connMapMutex.Lock()
|
connMapMutex.Lock()
|
||||||
_ = hyConn.Close()
|
_ = hyConn.Close()
|
||||||
|
if localConn != nil {
|
||||||
|
_ = localConn.Close()
|
||||||
|
}
|
||||||
delete(connMap, srcAddr.String())
|
delete(connMap, srcAddr.String())
|
||||||
connMapMutex.Unlock()
|
connMapMutex.Unlock()
|
||||||
r.ErrorFunc(srcAddr, ErrTimeout)
|
r.ErrorFunc(srcAddr, ErrTimeout)
|
||||||
@ -112,9 +185,6 @@ func (r *UDPTProxy) ListenAndServe() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Send the packet
|
|
||||||
_ = hyConn.WriteTo(buf[:n], dstAddr.String())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user