0c97db3c05
1. Modify ss/ssu handler and connector 2. Add users to metadata of ss and ssu handler
122 lines
2.5 KiB
Go
122 lines
2.5 KiB
Go
package ss
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"net/netip"
|
|
"sync"
|
|
|
|
"github.com/go-gost/core/common/bufpool"
|
|
"github.com/go-gost/go-shadowsocks2/core"
|
|
"github.com/go-gost/go-shadowsocks2/socks"
|
|
)
|
|
|
|
const (
|
|
defaultBufferSize = 4096
|
|
)
|
|
|
|
var (
|
|
_ net.PacketConn = (*UDPConn)(nil)
|
|
_ net.Conn = (*UDPConn)(nil)
|
|
)
|
|
|
|
// This wrapped connection has different behavior than ordinary connection:
|
|
// 1. ReadFrom will return target addr of shadowsocks instead of remote addr
|
|
type UDPConn struct {
|
|
client *core.UDPClient
|
|
server *core.UDPServer
|
|
sessionMap *sync.Map
|
|
net.PacketConn
|
|
raddr net.Addr
|
|
taddr net.Addr
|
|
bufferSize int
|
|
}
|
|
|
|
func UDPClientConn(c net.PacketConn, remoteAddr, targetAddr net.Addr, bufferSize int, client *core.UDPClient, sessionMap *sync.Map) *UDPConn {
|
|
if bufferSize <= 0 {
|
|
bufferSize = defaultBufferSize
|
|
}
|
|
|
|
return &UDPConn{
|
|
PacketConn: c,
|
|
raddr: remoteAddr,
|
|
taddr: targetAddr,
|
|
bufferSize: bufferSize,
|
|
client: client,
|
|
sessionMap: sessionMap,
|
|
}
|
|
}
|
|
|
|
func (c *UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
buf := bufpool.Get(c.bufferSize)
|
|
defer bufpool.Put(buf)
|
|
|
|
clientAddr, err := netip.ParseAddrPort(c.LocalAddr().String())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
n, _, err = c.PacketConn.ReadFrom(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var payload []byte
|
|
var session core.UDPSession
|
|
if c.client != nil {
|
|
s, ok := c.sessionMap.Load(core.SessionHashFromAddrPort(clientAddr))
|
|
if !ok {
|
|
return 0, nil, errors.New("udp session cannot find")
|
|
}
|
|
session = s.(core.UDPSession)
|
|
payload, err = c.client.Outbound(buf[:n], session)
|
|
if err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
return 0, nil, errors.New("UDPConn must be client ")
|
|
}
|
|
|
|
n = copy(b, payload)
|
|
addr, err = net.ResolveUDPAddr("udp", session.Target().String())
|
|
|
|
return
|
|
}
|
|
|
|
func (c *UDPConn) Read(b []byte) (n int, err error) {
|
|
n, _, err = c.ReadFrom(b)
|
|
return
|
|
}
|
|
|
|
func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
target := socks.ParseAddr(c.taddr.String())
|
|
clientAddr, err := netip.ParseAddrPort(c.LocalAddr().String())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var session core.UDPSession
|
|
var encrypted []byte
|
|
if c.client != nil {
|
|
session, encrypted, err = c.client.Inbound(b, clientAddr, target)
|
|
if err != nil {
|
|
return
|
|
}
|
|
c.sessionMap.Store(session.Hash(), session)
|
|
} else {
|
|
return 0, errors.New("UDPConn must be client")
|
|
}
|
|
|
|
_, err = c.PacketConn.WriteTo(encrypted, c.raddr)
|
|
n = len(b)
|
|
return
|
|
}
|
|
|
|
func (c *UDPConn) Write(b []byte) (n int, err error) {
|
|
return c.WriteTo(b, c.taddr)
|
|
}
|
|
|
|
func (c *UDPConn) RemoteAddr() net.Addr {
|
|
return c.raddr
|
|
}
|