1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-02 22:21:19 +00:00

shadowsockets fullcone outbound support

This commit is contained in:
Shelikhoo 2021-12-30 22:04:45 +00:00 committed by Xiaokang Wang (Shelikhoo)
parent cdfef7e66b
commit d068b60791
4 changed files with 126 additions and 2 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/buf"
"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
"github.com/v2fly/v2ray-core/v5/common/protocol"
"github.com/v2fly/v2ray-core/v5/common/retry"
"github.com/v2fly/v2ray-core/v5/common/session"
@ -16,9 +17,10 @@ import (
"github.com/v2fly/v2ray-core/v5/features/policy"
"github.com/v2fly/v2ray-core/v5/transport"
"github.com/v2fly/v2ray-core/v5/transport/internet"
"github.com/v2fly/v2ray-core/v5/transport/internet/udp"
)
// Client is an inbound handler for Shadowsocks protocol
// Client is a inbound handler for Shadowsocks protocol
type Client struct {
serverPicker protocol.ServerPicker
policyManager policy.Manager
@ -99,6 +101,28 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
if packetConn, err := packetaddr.ToPacketAddrConn(link, destination); err == nil {
requestDone := func() error {
protocolWriter := &UDPWriter{
Writer: conn,
Request: request,
}
return udp.CopyPacketConn(protocolWriter, packetConn, udp.UpdateActivity(timer))
}
responseDone := func() error {
protocolReader := &UDPReader{
Reader: conn,
User: user,
}
return udp.CopyPacketConn(packetConn, protocolReader, udp.UpdateActivity(timer))
}
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil {
return newError("connection ends").Base(err)
}
return nil
}
if request.Command == protocol.RequestCommandTCP {
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)

View File

@ -6,6 +6,7 @@ import (
"crypto/sha256"
"hash/crc32"
"io"
gonet "net"
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/buf"
@ -253,6 +254,23 @@ func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
return buf.MultiBuffer{payload}, nil
}
func (v *UDPReader) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) {
buffer := buf.New()
_, err = buffer.ReadFrom(v.Reader)
if err != nil {
buffer.Release()
return 0, nil, err
}
vaddr, payload, err := DecodeUDPPacket(v.User, buffer)
if err != nil {
buffer.Release()
return 0, nil, err
}
n = copy(p, payload.Bytes())
payload.Release()
return n, &gonet.UDPAddr{IP: vaddr.Address.IP(), Port: int(vaddr.Port)}, nil
}
type UDPWriter struct {
Writer io.Writer
Request *protocol.RequestHeader
@ -268,3 +286,18 @@ func (w *UDPWriter) Write(payload []byte) (int, error) {
packet.Release()
return len(payload), err
}
func (w *UDPWriter) WriteTo(payload []byte, addr gonet.Addr) (n int, err error) {
request := *w.Request
udpAddr := addr.(*gonet.UDPAddr)
request.Command = protocol.RequestCommandUDP
request.Address = net.IPAddress(udpAddr.IP)
request.Port = net.Port(udpAddr.Port)
packet, err := EncodeUDPPacket(&request, payload)
if err != nil {
return 0, err
}
_, err = w.Writer.Write(packet.Bytes())
packet.Release()
return len(payload), err
}

View File

@ -3,13 +3,33 @@ package internet
import (
"net"
"github.com/v2fly/v2ray-core/v5/features/stats"
"github.com/v2fly/v2ray-core/v4/common"
"github.com/v2fly/v2ray-core/v4/features/stats"
)
type Connection interface {
net.Conn
}
type AbstractPacketConnReader interface {
ReadFrom(p []byte) (n int, addr net.Addr, err error)
}
type AbstractPacketConnWriter interface {
WriteTo(p []byte, addr net.Addr) (n int, err error)
}
type AbstractPacketConn interface {
AbstractPacketConnReader
AbstractPacketConnWriter
common.Closable
}
type PacketConn interface {
AbstractPacketConn
net.PacketConn
}
type StatCouterConnection struct {
Connection
ReadCounter stats.Counter

View File

@ -0,0 +1,47 @@
package udp
import (
gonet "net"
"github.com/v2fly/v2ray-core/v4/common/signal"
"github.com/v2fly/v2ray-core/v4/transport/internet"
)
type dataHandler func(content []byte, address gonet.Addr)
type copyHandler struct {
onData []dataHandler
}
type CopyOption func(*copyHandler)
func CopyPacketConn(dst internet.AbstractPacketConnWriter, src internet.AbstractPacketConnReader, options ...CopyOption) error {
var handler copyHandler
for _, option := range options {
option(&handler)
}
var buffer [2048]byte
for {
n, addr, err := src.ReadFrom(buffer[:])
if err != nil {
return err
}
for _, handler := range handler.onData {
handler(buffer[:n], addr)
}
n, err = dst.WriteTo(buffer[:n], addr)
if err != nil {
return err
}
}
}
func UpdateActivity(timer signal.ActivityUpdater) CopyOption {
return func(handler *copyHandler) {
handler.onData = append(handler.onData, func(content []byte, address gonet.Addr) {
timer.Update()
})
}
}