mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-21 09:36:34 -05:00
shadowsockets fullcone outbound support
This commit is contained in:
parent
cdfef7e66b
commit
d068b60791
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/v2fly/v2ray-core/v5/common"
|
"github.com/v2fly/v2ray-core/v5/common"
|
||||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
"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/protocol"
|
||||||
"github.com/v2fly/v2ray-core/v5/common/retry"
|
"github.com/v2fly/v2ray-core/v5/common/retry"
|
||||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
"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/features/policy"
|
||||||
"github.com/v2fly/v2ray-core/v5/transport"
|
"github.com/v2fly/v2ray-core/v5/transport"
|
||||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
"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 {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
@ -99,6 +101,28 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
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 {
|
if request.Command == protocol.RequestCommandTCP {
|
||||||
requestDone := func() error {
|
requestDone := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
|
gonet "net"
|
||||||
|
|
||||||
"github.com/v2fly/v2ray-core/v5/common"
|
"github.com/v2fly/v2ray-core/v5/common"
|
||||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||||
@ -253,6 +254,23 @@ func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||||||
return buf.MultiBuffer{payload}, nil
|
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 {
|
type UDPWriter struct {
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
Request *protocol.RequestHeader
|
Request *protocol.RequestHeader
|
||||||
@ -268,3 +286,18 @@ func (w *UDPWriter) Write(payload []byte) (int, error) {
|
|||||||
packet.Release()
|
packet.Release()
|
||||||
return len(payload), err
|
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
|
||||||
|
}
|
||||||
|
@ -3,13 +3,33 @@ package internet
|
|||||||
import (
|
import (
|
||||||
"net"
|
"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 {
|
type Connection interface {
|
||||||
net.Conn
|
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 {
|
type StatCouterConnection struct {
|
||||||
Connection
|
Connection
|
||||||
ReadCounter stats.Counter
|
ReadCounter stats.Counter
|
||||||
|
47
transport/internet/udp/copy.go
Normal file
47
transport/internet/udp/copy.go
Normal 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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user