mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 06:28:35 +00:00
Compare commits
13 Commits
4217cccdc3
...
887da9e8e9
Author | SHA1 | Date | |
---|---|---|---|
|
887da9e8e9 | ||
|
6d1695a686 | ||
|
3a54924045 | ||
|
d218a5e8c5 | ||
|
3d7ed5450b | ||
|
c29af68a2f | ||
|
e4a5344189 | ||
|
33acf3c2b6 | ||
|
7c78408df9 | ||
|
129b2be9c1 | ||
|
358bdc258e | ||
|
c660bf7e37 | ||
|
414379ca96 |
40
.gitignore
vendored
40
.gitignore
vendored
@ -11,21 +11,23 @@
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# macOS specific files
|
||||
*.DS_Store
|
||||
.DS_Store
|
||||
|
||||
# IDE specific files
|
||||
# IDE/editor specific files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Archive files
|
||||
# Archives and compressed files
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.tar
|
||||
*.gz
|
||||
*.bz2
|
||||
|
||||
# Binaries
|
||||
# Go build binaries
|
||||
xray
|
||||
xray_softfloat
|
||||
mockgen
|
||||
@ -36,11 +38,31 @@ errorgen
|
||||
*.dat
|
||||
|
||||
# Build assets
|
||||
/build_assets
|
||||
/build_assets/
|
||||
|
||||
# Output from dlv test
|
||||
**/debug.*
|
||||
|
||||
# Certificates
|
||||
# Certificates and keys
|
||||
*.crt
|
||||
*.key
|
||||
|
||||
# Dependency directories (uncomment if needed)
|
||||
# vendor/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Coverage reports
|
||||
coverage.*
|
||||
|
||||
# Node modules (in case of frontend assets)
|
||||
node_modules/
|
||||
|
||||
# System files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Other common ignores
|
||||
*.bak
|
||||
*.tmp
|
||||
|
@ -322,10 +322,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
outbounds[0].Target = originalDest
|
||||
}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
local := net.DestinationFromAddr(w.hub.Addr())
|
||||
if local.Address == net.AnyIP || local.Address == net.AnyIPv6 {
|
||||
if source.Address.Family().IsIPv4() {
|
||||
local.Address = net.AnyIP
|
||||
} else if source.Address.Family().IsIPv6() {
|
||||
local.Address = net.AnyIPv6
|
||||
}
|
||||
}
|
||||
|
||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Source: source,
|
||||
Local: net.DestinationFromAddr(w.hub.Addr()), // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
|
||||
Local: local, // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
|
||||
Gateway: net.UDPDestination(w.address, w.port),
|
||||
Tag: w.tag,
|
||||
})
|
||||
|
@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
goerrors "errors"
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
"io"
|
||||
"math/big"
|
||||
gonet "net"
|
||||
"os"
|
||||
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@ -180,7 +181,11 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
content := session.ContentFromContext(ctx)
|
||||
if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
|
||||
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), h.senderSettings.TargetStrategy, nil)
|
||||
strategy := h.senderSettings.TargetStrategy
|
||||
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
|
||||
strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
|
||||
}
|
||||
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
|
||||
if h.senderSettings.TargetStrategy.ForceIP() {
|
||||
@ -251,14 +256,6 @@ out:
|
||||
common.Interrupt(link.Reader)
|
||||
}
|
||||
|
||||
// Address implements internet.Dialer.
|
||||
func (h *Handler) Address() net.Address {
|
||||
if h.senderSettings == nil || h.senderSettings.Via == nil {
|
||||
return nil
|
||||
}
|
||||
return h.senderSettings.Via.AsAddress()
|
||||
}
|
||||
|
||||
func (h *Handler) DestIpAddress() net.IP {
|
||||
return internet.DestIpAddress()
|
||||
}
|
||||
@ -293,41 +290,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
return h.getStatCouterConnection(conn), nil
|
||||
}
|
||||
|
||||
errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
|
||||
errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
|
||||
return nil, errors.New("failed to get outbound handler with tag: " + tag)
|
||||
}
|
||||
|
||||
if h.senderSettings.Via != nil {
|
||||
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
var domain string
|
||||
addr := h.senderSettings.Via.AsAddress()
|
||||
domain = h.senderSettings.Via.GetDomain()
|
||||
switch {
|
||||
case h.senderSettings.ViaCidr != "":
|
||||
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
|
||||
|
||||
case domain == "origin":
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
|
||||
ob.Gateway = inbound.Local.Address
|
||||
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
|
||||
}
|
||||
}
|
||||
case domain == "srcip":
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
|
||||
ob.Gateway = inbound.Source.Address
|
||||
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
|
||||
}
|
||||
}
|
||||
//case addr.Family().IsDomain():
|
||||
default:
|
||||
ob.Gateway = addr
|
||||
|
||||
}
|
||||
|
||||
h.SetOutboundGateway(ctx, ob)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||
@ -342,6 +314,38 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session.Outbound) {
|
||||
if ob.Gateway == nil && h.senderSettings != nil && h.senderSettings.Via != nil && !h.senderSettings.ProxySettings.HasTag() && (h.streamSettings.SocketSettings == nil || len(h.streamSettings.SocketSettings.DialerProxy) == 0) {
|
||||
var domain string
|
||||
addr := h.senderSettings.Via.AsAddress()
|
||||
domain = h.senderSettings.Via.GetDomain()
|
||||
switch {
|
||||
case h.senderSettings.ViaCidr != "":
|
||||
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
|
||||
|
||||
case domain == "origin":
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
|
||||
ob.Gateway = inbound.Local.Address
|
||||
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
|
||||
}
|
||||
}
|
||||
case domain == "srcip":
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
|
||||
ob.Gateway = inbound.Source.Address
|
||||
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
|
||||
}
|
||||
}
|
||||
//case addr.Family().IsDomain():
|
||||
default:
|
||||
ob.Gateway = addr
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
|
||||
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
||||
return &stat.CounterConnection{
|
||||
|
@ -1,11 +1,13 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
)
|
||||
|
||||
// ChunkSizeDecoder is a utility class to decode size value from bytes.
|
||||
@ -117,6 +119,7 @@ func (r *ChunkStreamReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
}
|
||||
r.leftOverSize = size
|
||||
|
||||
errors.LogInfo(context.Background(), "StreamReader read ", size)
|
||||
mb, err := r.reader.ReadAtMost(size)
|
||||
if !mb.IsEmpty() {
|
||||
r.leftOverSize -= mb.Len()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@ -33,6 +34,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
}
|
||||
|
||||
size, err := serial.ReadUint16(r.reader)
|
||||
errors.LogInfo(context.Background(), "PacketReader read ", size, r.dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -90,7 +90,8 @@ func TestRegressionOutboundLeak(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
b := buf.FromBytes([]byte("hello"))
|
||||
b := buf.New()
|
||||
b.Write([]byte("hello"))
|
||||
common.Must(muxClientDownlink.Writer.WriteMultiBuffer(buf.MultiBuffer{b}))
|
||||
}
|
||||
|
||||
@ -102,7 +103,8 @@ func TestRegressionOutboundLeak(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
b := buf.FromBytes([]byte("world"))
|
||||
b := buf.New()
|
||||
b.Write([]byte("world"))
|
||||
common.Must(websiteUplink.Writer.WriteMultiBuffer(buf.MultiBuffer{b}))
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
@ -75,10 +78,10 @@ func writeMetaWithFrame(writer buf.Writer, meta FrameMetadata, data buf.MultiBuf
|
||||
if _, err := serial.WriteUint16(frame, uint16(data.Len())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mb2 := make(buf.MultiBuffer, 0, len(data)+1)
|
||||
mb2 = append(mb2, frame)
|
||||
mb2 = append(mb2, data...)
|
||||
mb2 = buf.Compact(mb2)
|
||||
return writer.WriteMultiBuffer(mb2)
|
||||
}
|
||||
|
||||
@ -106,6 +109,7 @@ func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
mb = mb2
|
||||
chunk = buf.MultiBuffer{b}
|
||||
}
|
||||
errors.LogInfo(context.Background(), "MuxWriter write ", chunk.Len(), w.dest)
|
||||
if err := w.writeData(chunk); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
type FreedomConfig struct {
|
||||
@ -47,27 +48,27 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
switch strings.ToLower(targetStrategy) {
|
||||
case "asis", "":
|
||||
config.DomainStrategy = freedom.Config_AS_IS
|
||||
config.DomainStrategy = internet.DomainStrategy_AS_IS
|
||||
case "useip":
|
||||
config.DomainStrategy = freedom.Config_USE_IP
|
||||
config.DomainStrategy = internet.DomainStrategy_USE_IP
|
||||
case "useipv4":
|
||||
config.DomainStrategy = freedom.Config_USE_IP4
|
||||
config.DomainStrategy = internet.DomainStrategy_USE_IP4
|
||||
case "useipv6":
|
||||
config.DomainStrategy = freedom.Config_USE_IP6
|
||||
config.DomainStrategy = internet.DomainStrategy_USE_IP6
|
||||
case "useipv4v6":
|
||||
config.DomainStrategy = freedom.Config_USE_IP46
|
||||
config.DomainStrategy = internet.DomainStrategy_USE_IP46
|
||||
case "useipv6v4":
|
||||
config.DomainStrategy = freedom.Config_USE_IP64
|
||||
config.DomainStrategy = internet.DomainStrategy_USE_IP64
|
||||
case "forceip":
|
||||
config.DomainStrategy = freedom.Config_FORCE_IP
|
||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP
|
||||
case "forceipv4":
|
||||
config.DomainStrategy = freedom.Config_FORCE_IP4
|
||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP4
|
||||
case "forceipv6":
|
||||
config.DomainStrategy = freedom.Config_FORCE_IP6
|
||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP6
|
||||
case "forceipv4v6":
|
||||
config.DomainStrategy = freedom.Config_FORCE_IP46
|
||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP46
|
||||
case "forceipv6v4":
|
||||
config.DomainStrategy = freedom.Config_FORCE_IP64
|
||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP64
|
||||
default:
|
||||
return nil, errors.New("unsupported domain strategy: ", targetStrategy)
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
. "github.com/xtls/xray-core/infra/conf"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
func TestFreedomConfig(t *testing.T) {
|
||||
@ -23,7 +24,7 @@ func TestFreedomConfig(t *testing.T) {
|
||||
}`,
|
||||
Parser: loadJSON(creator),
|
||||
Output: &freedom.Config{
|
||||
DomainStrategy: freedom.Config_AS_IS,
|
||||
DomainStrategy: internet.DomainStrategy_AS_IS,
|
||||
DestinationOverride: &freedom.DestinationOverride{
|
||||
Server: &protocol.ServerEndpoint{
|
||||
Address: &net.IPOrDomain{
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/splithttp"
|
||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||
@ -332,6 +333,22 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type QUICConfig struct {
|
||||
// Header json.RawMessage `json:"header"`
|
||||
// Security string `json:"security"`
|
||||
// Key string `json:"key"`
|
||||
|
||||
Fec bool `json:"fec"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
func (c *QUICConfig) Build() (proto.Message, error) {
|
||||
config := &quic.Config{
|
||||
Fec: c.Fec,
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func readFileOrString(f string, s []string) ([]byte, error) {
|
||||
if len(f) > 0 {
|
||||
return filesystem.ReadCert(f)
|
||||
@ -744,8 +761,8 @@ func (p TransportProtocol) Build() (string, error) {
|
||||
return "httpupgrade", nil
|
||||
case "h2", "h3", "http":
|
||||
return "", errors.PrintRemovedFeatureError("HTTP transport (without header padding, etc.)", "XHTTP stream-one H2 & H3")
|
||||
case "quic":
|
||||
return "", errors.PrintRemovedFeatureError("QUIC transport (without web service, etc.)", "XHTTP stream-one H3")
|
||||
case "quic", "datagram":
|
||||
return "quic", nil
|
||||
default:
|
||||
return "", errors.New("Config: unknown transport protocol: ", p)
|
||||
}
|
||||
@ -938,6 +955,7 @@ type StreamConfig struct {
|
||||
XHTTPSettings *SplitHTTPConfig `json:"xhttpSettings"`
|
||||
SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
GRPCSettings *GRPCConfig `json:"grpcSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||
@ -1029,6 +1047,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
Settings: serial.ToTypedMessage(ts),
|
||||
})
|
||||
}
|
||||
if c.QUICSettings != nil {
|
||||
qs, err := c.QUICSettings.Build()
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to build QUIC config").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "quic",
|
||||
Settings: serial.ToTypedMessage(qs),
|
||||
})
|
||||
}
|
||||
if c.GRPCSettings != nil {
|
||||
gs, err := c.GRPCSettings.Build()
|
||||
if err != nil {
|
||||
|
@ -53,6 +53,7 @@ import (
|
||||
_ "github.com/xtls/xray-core/transport/internet/grpc"
|
||||
_ "github.com/xtls/xray-core/transport/internet/httpupgrade"
|
||||
_ "github.com/xtls/xray-core/transport/internet/kcp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/quic"
|
||||
_ "github.com/xtls/xray-core/transport/internet/reality"
|
||||
_ "github.com/xtls/xray-core/transport/internet/splithttp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/tcp"
|
||||
|
@ -1,44 +1 @@
|
||||
package freedom
|
||||
|
||||
var strategy = [][]byte{
|
||||
// name strategy, prefer, fallback
|
||||
{0, 0, 0}, // AsIs none, /, /
|
||||
{1, 0, 0}, // UseIP use, both, none
|
||||
{1, 4, 0}, // UseIPv4 use, 4, none
|
||||
{1, 6, 0}, // UseIPv6 use, 6, none
|
||||
{1, 4, 6}, // UseIPv4v6 use, 4, 6
|
||||
{1, 6, 4}, // UseIPv6v4 use, 6, 4
|
||||
{2, 0, 0}, // ForceIP force, both, none
|
||||
{2, 4, 0}, // ForceIPv4 force, 4, none
|
||||
{2, 6, 0}, // ForceIPv6 force, 6, none
|
||||
{2, 4, 6}, // ForceIPv4v6 force, 4, 6
|
||||
{2, 6, 4}, // ForceIPv6v4 force, 6, 4
|
||||
}
|
||||
|
||||
func (c *Config) hasStrategy() bool {
|
||||
return strategy[c.DomainStrategy][0] != 0
|
||||
}
|
||||
|
||||
func (c *Config) forceIP() bool {
|
||||
return strategy[c.DomainStrategy][0] == 2
|
||||
}
|
||||
|
||||
func (c *Config) preferIP4() bool {
|
||||
return strategy[c.DomainStrategy][1] == 4 || strategy[c.DomainStrategy][1] == 0
|
||||
}
|
||||
|
||||
func (c *Config) preferIP6() bool {
|
||||
return strategy[c.DomainStrategy][1] == 6 || strategy[c.DomainStrategy][1] == 0
|
||||
}
|
||||
|
||||
func (c *Config) hasFallback() bool {
|
||||
return strategy[c.DomainStrategy][2] != 0
|
||||
}
|
||||
|
||||
func (c *Config) fallbackIP4() bool {
|
||||
return strategy[c.DomainStrategy][2] == 4
|
||||
}
|
||||
|
||||
func (c *Config) fallbackIP6() bool {
|
||||
return strategy[c.DomainStrategy][2] == 6
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package freedom
|
||||
|
||||
import (
|
||||
protocol "github.com/xtls/xray-core/common/protocol"
|
||||
internet "github.com/xtls/xray-core/transport/internet"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@ -21,79 +22,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Config_DomainStrategy int32
|
||||
|
||||
const (
|
||||
Config_AS_IS Config_DomainStrategy = 0
|
||||
Config_USE_IP Config_DomainStrategy = 1
|
||||
Config_USE_IP4 Config_DomainStrategy = 2
|
||||
Config_USE_IP6 Config_DomainStrategy = 3
|
||||
Config_USE_IP46 Config_DomainStrategy = 4
|
||||
Config_USE_IP64 Config_DomainStrategy = 5
|
||||
Config_FORCE_IP Config_DomainStrategy = 6
|
||||
Config_FORCE_IP4 Config_DomainStrategy = 7
|
||||
Config_FORCE_IP6 Config_DomainStrategy = 8
|
||||
Config_FORCE_IP46 Config_DomainStrategy = 9
|
||||
Config_FORCE_IP64 Config_DomainStrategy = 10
|
||||
)
|
||||
|
||||
// Enum value maps for Config_DomainStrategy.
|
||||
var (
|
||||
Config_DomainStrategy_name = map[int32]string{
|
||||
0: "AS_IS",
|
||||
1: "USE_IP",
|
||||
2: "USE_IP4",
|
||||
3: "USE_IP6",
|
||||
4: "USE_IP46",
|
||||
5: "USE_IP64",
|
||||
6: "FORCE_IP",
|
||||
7: "FORCE_IP4",
|
||||
8: "FORCE_IP6",
|
||||
9: "FORCE_IP46",
|
||||
10: "FORCE_IP64",
|
||||
}
|
||||
Config_DomainStrategy_value = map[string]int32{
|
||||
"AS_IS": 0,
|
||||
"USE_IP": 1,
|
||||
"USE_IP4": 2,
|
||||
"USE_IP6": 3,
|
||||
"USE_IP46": 4,
|
||||
"USE_IP64": 5,
|
||||
"FORCE_IP": 6,
|
||||
"FORCE_IP4": 7,
|
||||
"FORCE_IP6": 8,
|
||||
"FORCE_IP46": 9,
|
||||
"FORCE_IP64": 10,
|
||||
}
|
||||
)
|
||||
|
||||
func (x Config_DomainStrategy) Enum() *Config_DomainStrategy {
|
||||
p := new(Config_DomainStrategy)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x Config_DomainStrategy) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (Config_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_proxy_freedom_config_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (Config_DomainStrategy) Type() protoreflect.EnumType {
|
||||
return &file_proxy_freedom_config_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Config_DomainStrategy.Descriptor instead.
|
||||
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
|
||||
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3, 0}
|
||||
}
|
||||
|
||||
type DestinationOverride struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -330,12 +258,12 @@ type Config struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.proxy.freedom.Config_DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
||||
UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
||||
Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
|
||||
ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
|
||||
Noises []*Noise `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
|
||||
DomainStrategy internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
||||
UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
||||
Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
|
||||
ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
|
||||
Noises []*Noise `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@ -368,11 +296,11 @@ func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Config) GetDomainStrategy() Config_DomainStrategy {
|
||||
func (x *Config) GetDomainStrategy() internet.DomainStrategy {
|
||||
if x != nil {
|
||||
return x.DomainStrategy
|
||||
}
|
||||
return Config_AS_IS
|
||||
return internet.DomainStrategy(0)
|
||||
}
|
||||
|
||||
func (x *Config) GetDestinationOverride() *DestinationOverride {
|
||||
@ -418,81 +346,72 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
||||
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d,
|
||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||
0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72, 0x61,
|
||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
|
||||
0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
|
||||
0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
|
||||
0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61,
|
||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
|
||||
0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
|
||||
0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
|
||||
0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67,
|
||||
0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
|
||||
0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d, 0x6d,
|
||||
0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e, 0x12,
|
||||
0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61, 0x78,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74,
|
||||
0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64,
|
||||
0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
|
||||
0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61,
|
||||
0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c,
|
||||
0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a,
|
||||
0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f,
|
||||
0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69,
|
||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13,
|
||||
0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||
0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
|
||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06,
|
||||
0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
|
||||
0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
|
||||
0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||
0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36,
|
||||
0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34,
|
||||
0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||
0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72,
|
||||
0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
||||
0x73, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61,
|
||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63,
|
||||
0x6b, 0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70,
|
||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67,
|
||||
0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65,
|
||||
0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
|
||||
0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
|
||||
0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
||||
0x61, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d,
|
||||
0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e,
|
||||
0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61,
|
||||
0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69,
|
||||
0x74, 0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c,
|
||||
0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65,
|
||||
0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19,
|
||||
0x0a, 0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0xe9, 0x02, 0x0a, 0x06, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64,
|
||||
0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
||||
0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||
0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e,
|
||||
0x6f, 0x69, 0x73, 0x65, 0x73, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50,
|
||||
0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -507,22 +426,21 @@ func file_proxy_freedom_config_proto_rawDescGZIP() []byte {
|
||||
return file_proxy_freedom_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proxy_freedom_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_proxy_freedom_config_proto_goTypes = []any{
|
||||
(Config_DomainStrategy)(0), // 0: xray.proxy.freedom.Config.DomainStrategy
|
||||
(*DestinationOverride)(nil), // 1: xray.proxy.freedom.DestinationOverride
|
||||
(*Fragment)(nil), // 2: xray.proxy.freedom.Fragment
|
||||
(*Noise)(nil), // 3: xray.proxy.freedom.Noise
|
||||
(*Config)(nil), // 4: xray.proxy.freedom.Config
|
||||
(*protocol.ServerEndpoint)(nil), // 5: xray.common.protocol.ServerEndpoint
|
||||
(*DestinationOverride)(nil), // 0: xray.proxy.freedom.DestinationOverride
|
||||
(*Fragment)(nil), // 1: xray.proxy.freedom.Fragment
|
||||
(*Noise)(nil), // 2: xray.proxy.freedom.Noise
|
||||
(*Config)(nil), // 3: xray.proxy.freedom.Config
|
||||
(*protocol.ServerEndpoint)(nil), // 4: xray.common.protocol.ServerEndpoint
|
||||
(internet.DomainStrategy)(0), // 5: xray.transport.internet.DomainStrategy
|
||||
}
|
||||
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||
5, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||
0, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.proxy.freedom.Config.DomainStrategy
|
||||
1, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||
2, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||
3, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||
4, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||
5, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
0, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||
1, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||
2, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
@ -540,14 +458,13 @@ func file_proxy_freedom_config_proto_init() {
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proxy_freedom_config_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_proxy_freedom_config_proto_goTypes,
|
||||
DependencyIndexes: file_proxy_freedom_config_proto_depIdxs,
|
||||
EnumInfos: file_proxy_freedom_config_proto_enumTypes,
|
||||
MessageInfos: file_proxy_freedom_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proxy_freedom_config_proto = out.File
|
||||
|
@ -7,6 +7,7 @@ option java_package = "com.xray.proxy.freedom";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/protocol/server_spec.proto";
|
||||
import "transport/internet/config.proto";
|
||||
|
||||
message DestinationOverride {
|
||||
xray.common.protocol.ServerEndpoint server = 1;
|
||||
@ -32,20 +33,7 @@ message Noise {
|
||||
}
|
||||
|
||||
message Config {
|
||||
enum DomainStrategy {
|
||||
AS_IS = 0;
|
||||
USE_IP = 1;
|
||||
USE_IP4 = 2;
|
||||
USE_IP6 = 3;
|
||||
USE_IP46 = 4;
|
||||
USE_IP64 = 5;
|
||||
FORCE_IP = 6;
|
||||
FORCE_IP4 = 7;
|
||||
FORCE_IP6 = 8;
|
||||
FORCE_IP46 = 9;
|
||||
FORCE_IP64 = 10;
|
||||
}
|
||||
DomainStrategy domain_strategy = 1;
|
||||
xray.transport.internet.DomainStrategy domain_strategy = 1;
|
||||
DestinationOverride destination_override = 3;
|
||||
uint32 user_level = 4;
|
||||
Fragment fragment = 5;
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/features/stats"
|
||||
"github.com/xtls/xray-core/proxy"
|
||||
@ -35,8 +34,8 @@ var useSplice bool
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
h := new(Handler)
|
||||
if err := core.RequireFeatures(ctx, func(pm policy.Manager, d dns.Client) error {
|
||||
return h.Init(config.(*Config), pm, d)
|
||||
if err := core.RequireFeatures(ctx, func(pm policy.Manager) error {
|
||||
return h.Init(config.(*Config), pm)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -53,16 +52,13 @@ func init() {
|
||||
// Handler handles Freedom connections.
|
||||
type Handler struct {
|
||||
policyManager policy.Manager
|
||||
dns dns.Client
|
||||
config *Config
|
||||
}
|
||||
|
||||
// Init initializes the Handler with necessary parameters.
|
||||
func (h *Handler) Init(config *Config, pm policy.Manager, d dns.Client) error {
|
||||
func (h *Handler) Init(config *Config, pm policy.Manager) error {
|
||||
h.config = config
|
||||
h.policyManager = pm
|
||||
h.dns = d
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -71,28 +67,6 @@ func (h *Handler) policy() policy.Session {
|
||||
return p
|
||||
}
|
||||
|
||||
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
|
||||
ips, _, err := h.dns.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && h.config.preferIP4(),
|
||||
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && h.config.preferIP6(),
|
||||
})
|
||||
{ // Resolve fallback
|
||||
if (len(ips) == 0 || err != nil) && h.config.hasFallback() && localAddr == nil {
|
||||
ips, _, err = h.dns.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: h.config.fallbackIP4(),
|
||||
IPv6Enable: h.config.fallbackIP6(),
|
||||
})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", domain)
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return nil
|
||||
}
|
||||
return net.IPAddress(ips[dice.Roll(len(ips))])
|
||||
}
|
||||
|
||||
func isValidAddress(addr *net.IPOrDomain) bool {
|
||||
if addr == nil {
|
||||
return false
|
||||
@ -114,6 +88,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
|
||||
destination := ob.Target
|
||||
origTargetAddr := ob.OriginalTarget.Address
|
||||
if origTargetAddr == nil {
|
||||
origTargetAddr = ob.Target.Address
|
||||
}
|
||||
dialer.SetOutboundGateway(ctx, ob)
|
||||
outGateway := ob.Gateway
|
||||
UDPOverride := net.UDPDestination(nil, 0)
|
||||
if h.config.DestinationOverride != nil {
|
||||
server := h.config.DestinationOverride.Server
|
||||
@ -133,17 +113,24 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
var conn stat.Connection
|
||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||
dialDest := destination
|
||||
if h.config.hasStrategy() && dialDest.Address.Family().IsDomain() {
|
||||
ip := h.resolveIP(ctx, dialDest.Address.Domain(), dialer.Address())
|
||||
if ip != nil {
|
||||
if h.config.DomainStrategy.HasStrategy() && dialDest.Address.Family().IsDomain() {
|
||||
strategy := h.config.DomainStrategy
|
||||
if destination.Network == net.Network_UDP && origTargetAddr != nil && outGateway == nil {
|
||||
strategy = strategy.GetDynamicStrategy(origTargetAddr.Family())
|
||||
}
|
||||
ips, err := internet.LookupForIP(dialDest.Address.Domain(), strategy, outGateway)
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
|
||||
if h.config.DomainStrategy.ForceIP() {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
dialDest = net.Destination{
|
||||
Network: dialDest.Network,
|
||||
Address: ip,
|
||||
Address: net.IPAddress(ips[dice.Roll(len(ips))]),
|
||||
Port: dialDest.Port,
|
||||
}
|
||||
errors.LogInfo(ctx, "dialing to ", dialDest)
|
||||
} else if h.config.forceIP() {
|
||||
return dns.ErrEmptyResponse
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +190,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
writer = buf.NewWriter(conn)
|
||||
}
|
||||
} else {
|
||||
writer = NewPacketWriter(conn, h, ctx, UDPOverride, destination)
|
||||
writer = NewPacketWriter(conn, h, UDPOverride, destination)
|
||||
if h.config.Noises != nil {
|
||||
errors.LogDebug(ctx, "NOISE", h.config.Noises)
|
||||
writer = &NoisePacketWriter{
|
||||
@ -339,7 +326,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
}
|
||||
|
||||
// DialDest means the dial target used in the dialer when creating conn
|
||||
func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
|
||||
func NewPacketWriter(conn net.Conn, h *Handler, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
|
||||
iConn := conn
|
||||
statConn, ok := iConn.(*stat.CounterConnection)
|
||||
if ok {
|
||||
@ -360,9 +347,9 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride
|
||||
PacketConnWrapper: c,
|
||||
Counter: counter,
|
||||
Handler: h,
|
||||
Context: ctx,
|
||||
UDPOverride: UDPOverride,
|
||||
resolvedUDPAddr: resolvedUDPAddr,
|
||||
ResolvedUDPAddr: resolvedUDPAddr,
|
||||
LocalAddr: net.DestinationFromAddr(conn.LocalAddr()).Address,
|
||||
}
|
||||
|
||||
}
|
||||
@ -373,14 +360,14 @@ type PacketWriter struct {
|
||||
*internet.PacketConnWrapper
|
||||
stats.Counter
|
||||
*Handler
|
||||
context.Context
|
||||
UDPOverride net.Destination
|
||||
|
||||
// Dest of udp packets might be a domain, we will resolve them to IP
|
||||
// But resolver will return a random one if the domain has many IPs
|
||||
// Resulting in these packets being sent to many different IPs randomly
|
||||
// So, cache and keep the resolve result
|
||||
resolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
|
||||
ResolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
|
||||
LocalAddr net.Address
|
||||
}
|
||||
|
||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
@ -400,20 +387,22 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
b.UDP.Port = w.UDPOverride.Port
|
||||
}
|
||||
if b.UDP.Address.Family().IsDomain() {
|
||||
if ip, ok := w.resolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
|
||||
if ip, ok := w.ResolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
|
||||
b.UDP.Address = ip
|
||||
} else {
|
||||
ShouldUseSystemResolver := true
|
||||
if w.Handler.config.hasStrategy() {
|
||||
ip = w.Handler.resolveIP(w.Context, b.UDP.Address.Domain(), nil)
|
||||
if ip != nil {
|
||||
if w.Handler.config.DomainStrategy.HasStrategy() {
|
||||
ips, err := internet.LookupForIP(b.UDP.Address.Domain(), w.Handler.config.DomainStrategy, w.LocalAddr)
|
||||
if err != nil {
|
||||
// drop packet if resolve failed when forceIP
|
||||
if w.Handler.config.DomainStrategy.ForceIP() {
|
||||
b.Release()
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
ip = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||
ShouldUseSystemResolver = false
|
||||
}
|
||||
// drop packet if resolve failed when forceIP
|
||||
if ip == nil && w.Handler.config.forceIP() {
|
||||
b.Release()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ShouldUseSystemResolver {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
|
||||
@ -425,7 +414,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
}
|
||||
}
|
||||
if ip != nil {
|
||||
b.UDP.Address, _ = w.resolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
|
||||
b.UDP.Address, _ = w.ResolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,7 +485,10 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||
err = w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n.DelayMin != 0 || n.DelayMax != 0 {
|
||||
time.Sleep(time.Duration(crypto.RandBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
"github.com/xtls/xray-core/proxy/socks"
|
||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
xproxy "golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
@ -83,7 +84,7 @@ func TestResolveIP(t *testing.T) {
|
||||
{
|
||||
Tag: "direct",
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||
DomainStrategy: freedom.Config_USE_IP,
|
||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -2,6 +2,7 @@ package internet
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
)
|
||||
|
||||
@ -127,3 +128,25 @@ func (s DomainStrategy) FallbackIP4() bool {
|
||||
func (s DomainStrategy) FallbackIP6() bool {
|
||||
return strategy[s][2] == 6
|
||||
}
|
||||
|
||||
func (s DomainStrategy) GetDynamicStrategy(addrFamily net.AddressFamily) DomainStrategy {
|
||||
if addrFamily.IsDomain(){
|
||||
return s
|
||||
}
|
||||
switch s {
|
||||
case DomainStrategy_USE_IP:
|
||||
if addrFamily.IsIPv4() {
|
||||
return DomainStrategy_USE_IP46
|
||||
} else if addrFamily.IsIPv6() {
|
||||
return DomainStrategy_USE_IP64
|
||||
}
|
||||
case DomainStrategy_FORCE_IP:
|
||||
if addrFamily.IsIPv4() {
|
||||
return DomainStrategy_FORCE_IP46
|
||||
} else if addrFamily.IsIPv6() {
|
||||
return DomainStrategy_FORCE_IP64
|
||||
}
|
||||
default:
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -24,11 +24,11 @@ type Dialer interface {
|
||||
// Dial dials a system connection to the given destination.
|
||||
Dial(ctx context.Context, destination net.Destination) (stat.Connection, error)
|
||||
|
||||
// Address returns the address used by this Dialer. Maybe nil if not known.
|
||||
Address() net.Address
|
||||
|
||||
// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
|
||||
DestIpAddress() net.IP
|
||||
|
||||
// SetOutboundGateway set outbound gateway
|
||||
SetOutboundGateway(ctx context.Context, ob *session.Outbound)
|
||||
}
|
||||
|
||||
// dialFunc is an interface to dial network connection to a specific destination.
|
||||
@ -91,8 +91,8 @@ func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address)
|
||||
}
|
||||
|
||||
ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && strategy.PreferIP4(),
|
||||
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && strategy.PreferIP6(),
|
||||
IPv4Enable: (localAddr == nil && strategy.PreferIP4()) || (localAddr != nil && localAddr.Family().IsIPv4() && (strategy.PreferIP4() || strategy.FallbackIP4())),
|
||||
IPv6Enable: (localAddr == nil && strategy.PreferIP6()) || (localAddr != nil && localAddr.Family().IsIPv6() && (strategy.PreferIP6() || strategy.FallbackIP6())),
|
||||
})
|
||||
{ // Resolve fallback
|
||||
if (len(ips) == 0 || err != nil) && strategy.HasFallback() && localAddr == nil {
|
||||
@ -109,13 +109,6 @@ func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address)
|
||||
return ips, err
|
||||
}
|
||||
|
||||
func canLookupIP(dst net.Destination, sockopt *SocketConfig) bool {
|
||||
if dst.Address.Family().IsIP() {
|
||||
return false
|
||||
}
|
||||
return sockopt.DomainStrategy.HasStrategy()
|
||||
}
|
||||
|
||||
func redirect(ctx context.Context, dst net.Destination, obt string, h outbound.Handler) net.Conn {
|
||||
errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
@ -235,9 +228,18 @@ func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt
|
||||
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
|
||||
var src net.Address
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
var outboundName string
|
||||
var origTargetAddr net.Address
|
||||
if len(outbounds) > 0 {
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
src = ob.Gateway
|
||||
if sockopt == nil || len(sockopt.DialerProxy) == 0 {
|
||||
src = ob.Gateway
|
||||
}
|
||||
outboundName = ob.Name
|
||||
origTargetAddr = ob.OriginalTarget.Address
|
||||
if origTargetAddr == nil {
|
||||
origTargetAddr = ob.Target.Address
|
||||
}
|
||||
}
|
||||
if sockopt == nil {
|
||||
return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
|
||||
@ -248,8 +250,12 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
||||
dest = *newDest
|
||||
}
|
||||
|
||||
if canLookupIP(dest, sockopt) {
|
||||
ips, err := LookupForIP(dest.Address.String(), sockopt.DomainStrategy, src)
|
||||
if sockopt.DomainStrategy.HasStrategy() && dest.Address.Family().IsDomain() {
|
||||
finalStrategy := sockopt.DomainStrategy
|
||||
if outboundName == "freedom" && dest.Network == net.Network_UDP && origTargetAddr != nil && src == nil {
|
||||
finalStrategy = finalStrategy.GetDynamicStrategy(origTargetAddr.Family())
|
||||
}
|
||||
ips, err := LookupForIP(dest.Address.Domain(), finalStrategy, src)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to resolve ip")
|
||||
if sockopt.DomainStrategy.ForceIP() {
|
||||
|
137
transport/internet/quic/config.pb.go
Normal file
137
transport/internet/quic/config.pb.go
Normal file
@ -0,0 +1,137 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.35.1
|
||||
// protoc v5.28.2
|
||||
// source: transport/internet/quic/config.proto
|
||||
|
||||
package quic
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// string key = 1;
|
||||
// xray.common.protocol.SecurityConfig security = 2;
|
||||
// xray.common.serial.TypedMessage header = 3;
|
||||
Fec bool `protobuf:"varint,4,opt,name=fec,proto3" json:"fec,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
mi := &file_transport_internet_quic_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Config) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_quic_config_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_quic_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Config) GetFec() bool {
|
||||
if x != nil {
|
||||
return x.Fec
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_transport_internet_quic_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_quic_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x24, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x71, 0x75, 0x69, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||
0x71, 0x75, 0x69, 0x63, 0x22, 0x1a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x66, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x66, 0x65, 0x63,
|
||||
0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||
0x71, 0x75, 0x69, 0x63, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72,
|
||||
0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x71, 0x75, 0x69, 0x63, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x65, 0x74, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_transport_internet_quic_config_proto_rawDescOnce sync.Once
|
||||
file_transport_internet_quic_config_proto_rawDescData = file_transport_internet_quic_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_transport_internet_quic_config_proto_rawDescGZIP() []byte {
|
||||
file_transport_internet_quic_config_proto_rawDescOnce.Do(func() {
|
||||
file_transport_internet_quic_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_quic_config_proto_rawDescData)
|
||||
})
|
||||
return file_transport_internet_quic_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_quic_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_transport_internet_quic_config_proto_goTypes = []any{
|
||||
(*Config)(nil), // 0: xray.transport.internet.quic.Config
|
||||
}
|
||||
var file_transport_internet_quic_config_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_quic_config_proto_init() }
|
||||
func file_transport_internet_quic_config_proto_init() {
|
||||
if File_transport_internet_quic_config_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_quic_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_transport_internet_quic_config_proto_goTypes,
|
||||
DependencyIndexes: file_transport_internet_quic_config_proto_depIdxs,
|
||||
MessageInfos: file_transport_internet_quic_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_transport_internet_quic_config_proto = out.File
|
||||
file_transport_internet_quic_config_proto_rawDesc = nil
|
||||
file_transport_internet_quic_config_proto_goTypes = nil
|
||||
file_transport_internet_quic_config_proto_depIdxs = nil
|
||||
}
|
14
transport/internet/quic/config.proto
Normal file
14
transport/internet/quic/config.proto
Normal file
@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package xray.transport.internet.quic;
|
||||
option csharp_namespace = "Xray.Transport.Internet.Quic";
|
||||
option go_package = "github.com/xtls/xray-core/transport/internet/quic";
|
||||
option java_package = "com.xray.transport.internet.quic";
|
||||
option java_multiple_files = true;
|
||||
|
||||
message Config {
|
||||
// string key = 1;
|
||||
// xray.common.protocol.SecurityConfig security = 2;
|
||||
// xray.common.serial.TypedMessage header = 3;
|
||||
bool fec = 4;
|
||||
}
|
247
transport/internet/quic/conn.go
Normal file
247
transport/internet/quic/conn.go
Normal file
@ -0,0 +1,247 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/mux"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
)
|
||||
|
||||
var MaxIncomingStreams = 16
|
||||
var currentStream = 0
|
||||
|
||||
type interConn struct {
|
||||
ctx context.Context
|
||||
quicConn quic.Connection // small udp packet can be sent with Datagram directly
|
||||
streams []quic.Stream // other packets can be sent via steam, it offer mux, reliability, fragmentation and ordering
|
||||
readChannel chan readResult
|
||||
reader buf.MultiBufferContainer
|
||||
done *done.Instance
|
||||
local net.Addr
|
||||
remote net.Addr
|
||||
}
|
||||
|
||||
type readResult struct {
|
||||
buffer []byte
|
||||
err error
|
||||
}
|
||||
|
||||
func NewConnInitReader(ctx context.Context, quicConn quic.Connection, done *done.Instance, remote net.Addr) *interConn {
|
||||
c := &interConn{
|
||||
ctx: ctx,
|
||||
quicConn: quicConn,
|
||||
readChannel: make(chan readResult),
|
||||
reader: buf.MultiBufferContainer{},
|
||||
done: done,
|
||||
local: quicConn.LocalAddr(),
|
||||
remote: remote,
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
received, e := c.quicConn.ReceiveDatagram(c.ctx)
|
||||
errors.LogInfo(c.ctx, "Read ReceiveDatagram ", len(received))
|
||||
c.readChannel <- readResult{buffer: received, err: e}
|
||||
}
|
||||
}()
|
||||
go c.acceptStreams()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *interConn) acceptStreams() {
|
||||
for {
|
||||
stream, err := c.quicConn.AcceptStream(context.Background())
|
||||
errors.LogInfo(c.ctx, "Read AcceptStream ", err)
|
||||
if err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "failed to accept stream")
|
||||
select {
|
||||
case <-c.quicConn.Context().Done():
|
||||
return
|
||||
case <-c.done.Wait():
|
||||
if err := c.quicConn.CloseWithError(0, ""); err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "failed to close connection")
|
||||
}
|
||||
return
|
||||
default:
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
}
|
||||
go c.readMuxCoolPacket(stream)
|
||||
c.streams = append(c.streams, stream)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *interConn) readMuxCoolPacket(stream quic.Stream) {
|
||||
for {
|
||||
received := make([]byte, buf.Size)
|
||||
i, e := stream.Read(received)
|
||||
if e != nil {
|
||||
errors.LogErrorInner(c.ctx, e, "Error read stream, drop this buffer ", i)
|
||||
c.readChannel <- readResult{buffer: nil, err: e}
|
||||
continue;
|
||||
}
|
||||
errors.LogInfo(c.ctx, "Read stream ", i)
|
||||
|
||||
buffer := buf.New()
|
||||
buffer.Write(received[:i])
|
||||
muxCoolReader := &buf.MultiBufferContainer{}
|
||||
muxCoolReader.MultiBuffer = append(muxCoolReader.MultiBuffer, buffer)
|
||||
var meta mux.FrameMetadata
|
||||
err := meta.Unmarshal(muxCoolReader)
|
||||
if err != nil {
|
||||
errors.LogInfo(c.ctx, "Not a Mux Cool packet beginning, copy directly ", i)
|
||||
buf.ReleaseMulti(muxCoolReader.MultiBuffer)
|
||||
c.readChannel <- readResult{buffer: received[:i], err: e}
|
||||
continue;
|
||||
}
|
||||
if !meta.Option.Has(mux.OptionData) {
|
||||
errors.LogInfo(c.ctx, "No option data, copy directly ", i)
|
||||
buf.ReleaseMulti(muxCoolReader.MultiBuffer)
|
||||
c.readChannel <- readResult{buffer: received[:i], err: e}
|
||||
continue;
|
||||
}
|
||||
size, err := serial.ReadUint16(muxCoolReader)
|
||||
remaining := uint16(muxCoolReader.MultiBuffer.Len())
|
||||
errors.LogInfo(c.ctx, "Read stream ", i, " option size ", size, " remaining size ", remaining)
|
||||
if err != nil || size <= remaining || size > remaining + 1500 {
|
||||
errors.LogInfo(c.ctx, "do not wait for second part of UDP packet ", i)
|
||||
buf.ReleaseMulti(muxCoolReader.MultiBuffer)
|
||||
c.readChannel <- readResult{buffer: received[:i], err: e}
|
||||
continue;
|
||||
}
|
||||
|
||||
i2, e := stream.Read(received[i:])
|
||||
if e != nil {
|
||||
errors.LogErrorInner(c.ctx, e, "Error read stream, drop this buffer ", i2)
|
||||
buf.ReleaseMulti(muxCoolReader.MultiBuffer)
|
||||
c.readChannel <- readResult{buffer: nil, err: e}
|
||||
continue;
|
||||
}
|
||||
errors.LogInfo(c.ctx, "Read stream i2 size ", i2)
|
||||
buf.ReleaseMulti(muxCoolReader.MultiBuffer)
|
||||
c.readChannel <- readResult{buffer: received[:(i + i2)], err: e}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *interConn) Read(b []byte) (int, error) {
|
||||
if c.reader.MultiBuffer.Len() > 0 {
|
||||
return c.reader.Read(b)
|
||||
}
|
||||
received := <- c.readChannel
|
||||
if received.err != nil {
|
||||
return 0, received.err
|
||||
}
|
||||
buffer := buf.New()
|
||||
buffer.Write(received.buffer)
|
||||
c.reader.MultiBuffer = append(c.reader.MultiBuffer, buffer)
|
||||
errors.LogInfo(c.ctx, "Read copy ", len(received.buffer))
|
||||
return c.reader.Read(b)
|
||||
}
|
||||
|
||||
func (c *interConn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
mb = buf.Compact(mb)
|
||||
mb, err := buf.WriteMultiBuffer(c, mb)
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *interConn) Write(b []byte) (int, error) {
|
||||
if len(b) > 1240 { // TODO: why quic-go increase internal MTU causing packet loss?
|
||||
if len(c.streams) < MaxIncomingStreams {
|
||||
stream, err := c.quicConn.OpenStream()
|
||||
errors.LogInfo(c.ctx, "Write OpenStream ", err)
|
||||
if err == nil {
|
||||
c.streams = append(c.streams, stream)
|
||||
} else {
|
||||
errors.LogInfoInner(c.ctx, err, "failed to openStream: ")
|
||||
}
|
||||
}
|
||||
currentStream++;
|
||||
if currentStream > len(c.streams) - 1 {
|
||||
currentStream = 0;
|
||||
}
|
||||
errors.LogInfo(c.ctx, "Write stream ", len(b), currentStream, len(c.streams))
|
||||
return c.streams[currentStream].Write(b)
|
||||
}
|
||||
var err = c.quicConn.SendDatagram(b)
|
||||
errors.LogInfo(c.ctx, "Write SendDatagram ", len(b), err)
|
||||
if _, ok := err.(*quic.DatagramTooLargeError); ok {
|
||||
if len(c.streams) < MaxIncomingStreams {
|
||||
stream, err := c.quicConn.OpenStream()
|
||||
errors.LogInfo(c.ctx, "Write OpenStream ", err)
|
||||
if err == nil {
|
||||
c.streams = append(c.streams, stream)
|
||||
} else {
|
||||
errors.LogInfoInner(c.ctx, err, "failed to openStream: ")
|
||||
}
|
||||
}
|
||||
currentStream++;
|
||||
if currentStream > len(c.streams) - 1 {
|
||||
currentStream = 0;
|
||||
}
|
||||
errors.LogInfo(c.ctx, "Write stream ", len(b), currentStream, len(c.streams))
|
||||
return c.streams[currentStream].Write(b)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (c *interConn) Close() error {
|
||||
var err error
|
||||
for _, s := range c.streams {
|
||||
e := s.Close()
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *interConn) LocalAddr() net.Addr {
|
||||
return c.local
|
||||
}
|
||||
|
||||
func (c *interConn) RemoteAddr() net.Addr {
|
||||
return c.remote
|
||||
}
|
||||
|
||||
func (c *interConn) SetDeadline(t time.Time) error {
|
||||
var err error
|
||||
for _, s := range c.streams {
|
||||
e := s.SetDeadline(t)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *interConn) SetReadDeadline(t time.Time) error {
|
||||
var err error
|
||||
for _, s := range c.streams {
|
||||
e := s.SetReadDeadline(t)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *interConn) SetWriteDeadline(t time.Time) error {
|
||||
var err error
|
||||
for _, s := range c.streams {
|
||||
e := s.SetWriteDeadline(t)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
95
transport/internet/quic/dialer.go
Normal file
95
transport/internet/quic/dialer.go
Normal file
@ -0,0 +1,95 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{
|
||||
ServerName: internalDomain,
|
||||
AllowInsecure: true,
|
||||
}
|
||||
}
|
||||
|
||||
var destAddr *net.UDPAddr
|
||||
if dest.Address.Family().IsIP() {
|
||||
destAddr = &net.UDPAddr{
|
||||
IP: dest.Address.IP(),
|
||||
Port: int(dest.Port),
|
||||
}
|
||||
} else {
|
||||
dialerIp := internet.DestIpAddress()
|
||||
if dialerIp != nil {
|
||||
destAddr = &net.UDPAddr{
|
||||
IP: dialerIp,
|
||||
Port: int(dest.Port),
|
||||
}
|
||||
errors.LogInfo(ctx, "quic Dial use dialer dest addr: ", destAddr)
|
||||
} else {
|
||||
addr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
destAddr = addr
|
||||
}
|
||||
}
|
||||
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
return openConnection(ctx, destAddr, config, tlsConfig, streamSettings.SocketSettings)
|
||||
}
|
||||
|
||||
func openConnection(ctx context.Context, destAddr net.Addr, config *Config, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (stat.Connection, error) {
|
||||
dest := net.DestinationFromAddr(destAddr)
|
||||
errors.LogInfo(ctx, "dialing quic to ", dest)
|
||||
rawConn, err := internet.DialSystem(ctx, dest, sockopt)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err)
|
||||
}
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
KeepAlivePeriod: 0,
|
||||
HandshakeIdleTimeout: time.Second * 8,
|
||||
MaxIdleTimeout: time.Second * 300,
|
||||
EnableDatagrams: true,
|
||||
}
|
||||
|
||||
var udpConn *net.UDPConn
|
||||
switch conn := rawConn.(type) {
|
||||
case *net.UDPConn:
|
||||
udpConn = conn
|
||||
case *internet.PacketConnWrapper:
|
||||
udpConn = conn.Conn.(*net.UDPConn)
|
||||
default:
|
||||
rawConn.Close()
|
||||
return nil, errors.New("QUIC with sockopt is unsupported").AtWarning()
|
||||
}
|
||||
|
||||
tr := quic.Transport{
|
||||
ConnectionIDLength: 12,
|
||||
Conn: udpConn,
|
||||
}
|
||||
conn, err := tr.Dial(context.Background(), destAddr, tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig)
|
||||
if err != nil {
|
||||
udpConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewConnInitReader(ctx, conn, done.New(), destAddr), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
||||
}
|
108
transport/internet/quic/hub.go
Normal file
108
transport/internet/quic/hub.go
Normal file
@ -0,0 +1,108 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
// Listener is an internet.Listener that listens for TCP connections.
|
||||
type Listener struct {
|
||||
rawConn *net.UDPConn
|
||||
listener *quic.Listener
|
||||
done *done.Instance
|
||||
addConn internet.ConnHandler
|
||||
}
|
||||
|
||||
func (l *Listener) keepAccepting(ctx context.Context) {
|
||||
for {
|
||||
conn, err := l.listener.Accept(context.Background())
|
||||
if err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "failed to accept QUIC connection")
|
||||
if l.done.Done() {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
l.addConn(NewConnInitReader(ctx, conn, l.done, conn.RemoteAddr()))
|
||||
}
|
||||
}
|
||||
|
||||
// Addr implements internet.Listener.Addr.
|
||||
func (l *Listener) Addr() net.Addr {
|
||||
return l.listener.Addr()
|
||||
}
|
||||
|
||||
// Close implements internet.Listener.Close.
|
||||
func (l *Listener) Close() error {
|
||||
l.done.Close()
|
||||
l.listener.Close()
|
||||
l.rawConn.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Listen creates a new Listener based on configurations.
|
||||
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
||||
if address.Family().IsDomain() {
|
||||
return nil, errors.New("domain address is not allows for listening quic")
|
||||
}
|
||||
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.DNSNames(internalDomain), cert.CommonName(internalDomain)))},
|
||||
}
|
||||
}
|
||||
|
||||
//config := streamSettings.ProtocolSettings.(*Config)
|
||||
rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
|
||||
IP: address.IP(),
|
||||
Port: int(port),
|
||||
}, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
KeepAlivePeriod: 0,
|
||||
HandshakeIdleTimeout: time.Second * 8,
|
||||
MaxIdleTimeout: time.Second * 300,
|
||||
MaxIncomingStreams: 16,
|
||||
MaxIncomingUniStreams: -1,
|
||||
EnableDatagrams: true,
|
||||
}
|
||||
|
||||
tr := quic.Transport{
|
||||
ConnectionIDLength: 12,
|
||||
Conn: rawConn.(*net.UDPConn),
|
||||
}
|
||||
qListener, err := tr.Listen(tlsConfig.GetTLSConfig(), quicConfig)
|
||||
if err != nil {
|
||||
rawConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := &Listener{
|
||||
done: done.New(),
|
||||
rawConn: rawConn.(*net.UDPConn),
|
||||
listener: qListener,
|
||||
addConn: handler,
|
||||
}
|
||||
|
||||
go listener.keepAccepting(ctx)
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportListener(protocolName, Listen))
|
||||
}
|
17
transport/internet/quic/quic.go
Normal file
17
transport/internet/quic/quic.go
Normal file
@ -0,0 +1,17 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
const (
|
||||
protocolName = "quic"
|
||||
internalDomain = "quic.internal.example.com"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
}))
|
||||
}
|
105
transport/internet/quic/quic_test.go
Normal file
105
transport/internet/quic/quic_test.go
Normal file
@ -0,0 +1,105 @@
|
||||
package quic_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||
"github.com/xtls/xray-core/testing/servers/udp"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
func TestShortQuicConnection(t *testing.T) {
|
||||
testQuicConnection(t, 1024)
|
||||
}
|
||||
|
||||
func TestAroundMTUQuicConnection(t *testing.T) {
|
||||
testQuicConnection(t, 1247)
|
||||
}
|
||||
|
||||
func TestLongQuicConnection(t *testing.T) {
|
||||
testQuicConnection(t, 1500)
|
||||
}
|
||||
|
||||
func testQuicConnection(t *testing.T, dataLen int32) {
|
||||
port := udp.PickPort()
|
||||
|
||||
listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
||||
ProtocolName: "quic",
|
||||
ProtocolSettings: &quic.Config{},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
Certificate: []*tls.Certificate{
|
||||
tls.ParseCertificate(
|
||||
cert.MustGenerate(nil,
|
||||
cert.DNSNames("www.example.com"),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}, func(conn stat.Connection) {
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
b := buf.New()
|
||||
defer b.Release()
|
||||
|
||||
for {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFrom(conn); err != nil {
|
||||
return
|
||||
}
|
||||
common.Must2(conn.Write(b.Bytes()))
|
||||
}
|
||||
}()
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
dctx := context.Background()
|
||||
conn, err := quic.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "quic",
|
||||
ProtocolSettings: &quic.Config{},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
ServerName: "www.example.com",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
defer conn.Close()
|
||||
|
||||
b1 := make([]byte, dataLen)
|
||||
common.Must2(rand.Read(b1))
|
||||
b2 := buf.New()
|
||||
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, dataLen))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, dataLen))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user