Compare commits

..

5 Commits

21 changed files with 188 additions and 393 deletions
-2
View File
@@ -73,7 +73,6 @@
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless) - [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU) - [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
- Magisk - Magisk
- [NetProxy-Magisk](https://github.com/Fanju6/NetProxy-Magisk)
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk) - [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
- [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk) - [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk)
- Homebrew - Homebrew
@@ -120,7 +119,6 @@
- [SimpleXray](https://github.com/lhear/SimpleXray) - [SimpleXray](https://github.com/lhear/SimpleXray)
- [XrayFA](https://github.com/Q7DF1/XrayFA) - [XrayFA](https://github.com/Q7DF1/XrayFA)
- [AnyPortal](https://github.com/AnyPortal/AnyPortal) - [AnyPortal](https://github.com/AnyPortal/AnyPortal)
- [NetProxy-Magisk](https://github.com/Fanju6/NetProxy-Magisk)
- [OneXray](https://github.com/OneXray/OneXray) - [OneXray](https://github.com/OneXray/OneXray)
- iOS & macOS arm64 & tvOS - iOS & macOS arm64 & tvOS
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274) - [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274)
-14
View File
@@ -267,20 +267,6 @@ func (h *Handler) DestIpAddress() net.IP {
return internet.DestIpAddress() return internet.DestIpAddress()
} }
func (h *Handler) SocketSettings() *internet.SocketConfig {
if h.streamSettings == nil {
return nil
}
return h.streamSettings.SocketSettings
}
func (h *Handler) UsesProxySettings() bool {
if h.senderSettings != nil && h.senderSettings.ProxySettings.HasTag() {
return true
}
return h.streamSettings != nil && h.streamSettings.SocketSettings != nil && len(h.streamSettings.SocketSettings.DialerProxy) > 0
}
// Dial implements internet.Dialer. // Dial implements internet.Dialer.
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) { func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if h.senderSettings != nil { if h.senderSettings != nil {
+2 -2
View File
@@ -19,8 +19,8 @@ import (
var ( var (
Version_x byte = 26 Version_x byte = 26
Version_y byte = 4 Version_y byte = 5
Version_z byte = 25 Version_z byte = 3
) )
var ( var (
+6 -17
View File
@@ -497,8 +497,8 @@ func (b Bandwidth) Bps() (uint64, error) {
} }
type UdpHop struct { type UdpHop struct {
PortList json.RawMessage `json:"ports"` PortList PortList `json:"ports"`
Interval *Int32Range `json:"interval"` Interval Int32Range `json:"interval"`
} }
type Masquerade struct { type Masquerade struct {
@@ -2142,18 +2142,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal") return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal")
} }
var hop *PortList if (c.FinalMask.QuicParams.UdpHop.Interval.From != 0 && c.FinalMask.QuicParams.UdpHop.Interval.From < 5) || (c.FinalMask.QuicParams.UdpHop.Interval.To != 0 && c.FinalMask.QuicParams.UdpHop.Interval.To < 5) {
if err := json.Unmarshal(c.FinalMask.QuicParams.UdpHop.PortList, &hop); err != nil {
hop = &PortList{}
}
var inertvalMin, inertvalMax int64
if c.FinalMask.QuicParams.UdpHop.Interval != nil {
inertvalMin = int64(c.FinalMask.QuicParams.UdpHop.Interval.From)
inertvalMax = int64(c.FinalMask.QuicParams.UdpHop.Interval.To)
}
if (inertvalMin != 0 && inertvalMin < 5) || (inertvalMax != 0 && inertvalMax < 5) {
return nil, errors.New("Interval must be at least 5") return nil, errors.New("Interval must be at least 5")
} }
@@ -2190,9 +2179,9 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
BrutalUp: up, BrutalUp: up,
BrutalDown: down, BrutalDown: down,
UdpHop: &internet.UdpHop{ UdpHop: &internet.UdpHop{
Ports: hop.Build().Ports(), Ports: c.FinalMask.QuicParams.UdpHop.PortList.Build().Ports(),
IntervalMin: inertvalMin, IntervalMin: int64(c.FinalMask.QuicParams.UdpHop.Interval.From),
IntervalMax: inertvalMax, IntervalMax: int64(c.FinalMask.QuicParams.UdpHop.Interval.To),
}, },
InitStreamReceiveWindow: c.FinalMask.QuicParams.InitStreamReceiveWindow, InitStreamReceiveWindow: c.FinalMask.QuicParams.InitStreamReceiveWindow,
MaxStreamReceiveWindow: c.FinalMask.QuicParams.MaxStreamReceiveWindow, MaxStreamReceiveWindow: c.FinalMask.QuicParams.MaxStreamReceiveWindow,
+88 -133
View File
@@ -38,14 +38,6 @@ var defaultBlockAllRule *FinalRule
func init() { func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
h := new(Handler) h := new(Handler)
if handler, ok := session.FullHandlerFromContext(ctx).(handlerWithSocketSettings); ok {
if sockopt := handler.SocketSettings(); sockopt != nil {
h.socketStrategy = sockopt.DomainStrategy
}
}
if handler, ok := session.FullHandlerFromContext(ctx).(handlerWithProxySettings); ok {
h.usesProxySettings = handler.UsesProxySettings()
}
if err := core.RequireFeatures(ctx, func(pm policy.Manager) error { if err := core.RequireFeatures(ctx, func(pm policy.Manager) error {
return h.Init(config.(*Config), pm) return h.Init(config.(*Config), pm)
}); err != nil { }); err != nil {
@@ -96,14 +88,6 @@ func init() {
} }
} }
type handlerWithSocketSettings interface {
SocketSettings() *internet.SocketConfig
}
type handlerWithProxySettings interface {
UsesProxySettings() bool
}
type FinalRule struct { type FinalRule struct {
action RuleAction action RuleAction
network [8]bool network [8]bool
@@ -114,11 +98,9 @@ type FinalRule struct {
// Handler handles Freedom connections. // Handler handles Freedom connections.
type Handler struct { type Handler struct {
policyManager policy.Manager policyManager policy.Manager
config *Config config *Config
finalRules []*FinalRule finalRules []*FinalRule
socketStrategy internet.DomainStrategy
usesProxySettings bool
} }
func buildFinalRule(config *FinalRuleConfig) (*FinalRule, error) { func buildFinalRule(config *FinalRuleConfig) (*FinalRule, error) {
@@ -195,6 +177,22 @@ func getDefaultFinalRule(inbound *session.Inbound) *FinalRule {
return nil return nil
} }
func (h *Handler) shouldResolveDomainBeforeFinalRules(dialDest net.Destination, defaultRule *FinalRule) bool {
if !dialDest.Address.Family().IsDomain() {
return false
}
if len(h.finalRules) > 0 {
rule := h.finalRules[0]
if rule.action == RuleAction_Allow && rule.network[dialDest.Network] && len(rule.port) == 0 && rule.ip == nil {
return false
}
}
if defaultRule != nil || len(h.finalRules) > 0 {
return true
}
return false
}
func (h *Handler) matchFinalRule(network net.Network, address net.Address, port net.Port, defaultRule *FinalRule) *FinalRule { func (h *Handler) matchFinalRule(network net.Network, address net.Address, port net.Port, defaultRule *FinalRule) *FinalRule {
for _, rule := range h.finalRules { for _, rule := range h.finalRules {
if rule.Apply(network, address, port) { if rule.Apply(network, address, port) {
@@ -207,6 +205,13 @@ func (h *Handler) matchFinalRule(network net.Network, address net.Address, port
return nil return nil
} }
func (h *Handler) applyFinalRules(network net.Network, address net.Address, port net.Port, defaultRule *FinalRule) RuleAction {
if rule := h.matchFinalRule(network, address, port, defaultRule); rule != nil {
return rule.action
}
return RuleAction_Allow
}
// Init initializes the Handler with necessary parameters. // Init initializes the Handler with necessary parameters.
func (h *Handler) Init(config *Config, pm policy.Manager) error { func (h *Handler) Init(config *Config, pm policy.Manager) error {
h.config = config h.config = config
@@ -234,32 +239,11 @@ func (h *Handler) blockDelay(rule *FinalRule) time.Duration {
min = rule.blockDelay.Min min = rule.blockDelay.Min
max = rule.blockDelay.Max max = rule.blockDelay.Max
} }
span := max - min abs := max - min
if max < min { if max < min {
span = min - max abs = min - max
} }
return time.Duration(min+uint64(dice.Roll(int(span+1)))) * time.Second return time.Duration(min+uint64(dice.Roll(int(abs+1)))) * time.Second
}
func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Writer, rule *FinalRule, dest *net.Destination) error {
delay := h.blockDelay(rule)
errors.LogInfo(ctx, "blocked target: ", *dest, ", blackholing connection for ", delay)
timer := time.AfterFunc(delay, func() {
common.Interrupt(input)
common.Interrupt(output)
errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *dest)
})
defer timer.Stop()
defer common.Close(output)
_ = buf.Copy(input, buf.Discard)
return nil
}
func (h *Handler) udpDomainStrategy() internet.DomainStrategy {
if h.config.DomainStrategy.HasStrategy() {
return h.config.DomainStrategy
}
return h.socketStrategy
} }
func isValidAddress(addr *net.IPOrDomain) bool { func isValidAddress(addr *net.IPOrDomain) bool {
@@ -311,73 +295,40 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
var blockedRule *FinalRule var blockedRule *FinalRule
err := retry.ExponentialBackoff(5, 100).On(func() error { err := retry.ExponentialBackoff(5, 100).On(func() error {
dialDest := destination dialDest := destination
if h.config.DomainStrategy.HasStrategy() && dialDest.Address.Family().IsDomain() {
if dialDest.Address.Family().IsDomain() { strategy := h.config.DomainStrategy
if strategy := h.config.DomainStrategy; strategy.HasStrategy() { if destination.Network == net.Network_UDP && origTargetAddr != nil && outGateway == nil {
if destination.Network == net.Network_UDP && origTargetAddr != nil && outGateway == nil { strategy = strategy.GetDynamicStrategy(origTargetAddr.Family())
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
} }
ips, err := internet.LookupForIP(dialDest.Address.Domain(), strategy, outGateway) } else {
if err != nil { // SRV/TXT dialDest = net.Destination{
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain()) Network: dialDest.Network,
if h.config.DomainStrategy.ForceIP() || defaultRule != nil || len(h.finalRules) > 0 { Address: net.IPAddress(ips[dice.Roll(len(ips))]),
return err // retry Port: dialDest.Port,
} }
} else { // to ip errors.LogInfo(ctx, "dialing to ", dialDest)
dialDest = net.Destination{ }
Network: dialDest.Network, } else if h.shouldResolveDomainBeforeFinalRules(dialDest, defaultRule) { // asis + domain + hasrules
Address: net.IPAddress(ips[dice.Roll(len(ips))]), addrs, err := net.DefaultResolver.LookupIPAddr(ctx, dialDest.Address.Domain())
Port: dialDest.Port, if err != nil {
} errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
} else if len(addrs) > 0 {
if addr := net.IPAddress(addrs[dice.Roll(len(addrs))].IP); addr != nil {
dialDest.Address = addr
errors.LogInfo(ctx, "dialing to ", dialDest) errors.LogInfo(ctx, "dialing to ", dialDest)
if rule := h.matchFinalRule(dialDest.Network, dialDest.Address, dialDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
blockedDest = &dialDest
blockedRule = rule
return nil
}
}
} else if defaultRule != nil || len(h.finalRules) > 0 { // freedom asis + hasrules
if strategy := h.socketStrategy; strategy.HasStrategy() {
ips, err := internet.LookupForIP(dialDest.Address.Domain(), strategy, outGateway)
if err != nil { // SRV/TXT
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
if strategy.ForceIP() {
return err // retry
}
}
for _, ip := range ips {
if addr := net.IPAddress(ip); addr != nil {
if rule := h.matchFinalRule(dialDest.Network, addr, dialDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
blockedDest = &dialDest
blockedDest.Address = addr
blockedRule = rule
return nil
}
}
}
} else { // sockopt asis
addrs, err := net.DefaultResolver.LookupIPAddr(ctx, dialDest.Address.Domain())
if err != nil { // SRV/TXT
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
}
for _, addr := range addrs {
if ipAddr := net.IPAddress(addr.IP); ipAddr != nil {
if rule := h.matchFinalRule(dialDest.Network, ipAddr, dialDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
blockedDest = &dialDest
blockedDest.Address = ipAddr
blockedRule = rule
return nil
}
}
}
} }
} }
} else { }
if rule := h.matchFinalRule(dialDest.Network, dialDest.Address, dialDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block { if rule := h.matchFinalRule(dialDest.Network, dialDest.Address, dialDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
blockedDest = &dialDest blockedDest = &dialDest
blockedRule = rule blockedRule = rule
return nil return nil
}
} }
rawConn, err := dialer.Dial(ctx, dialDest) rawConn, err := dialer.Dial(ctx, dialDest)
@@ -392,21 +343,25 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return errors.New("failed to open connection to ", destination).Base(err) return errors.New("failed to open connection to ", destination).Base(err)
} }
if blockedDest != nil { if blockedDest != nil {
return h.blackhole(ctx, input, output, blockedRule, blockedDest) delay := h.blockDelay(blockedRule)
} errors.LogInfo(ctx, "blocked target: ", *blockedDest, ", blackholing connection for ", delay)
if defaultRule != nil || len(h.finalRules) > 0 { timer := time.AfterFunc(delay, func() {
if h.usesProxySettings { common.Interrupt(input)
errors.LogInfo(ctx, "skipping final rule check for proxied remote endpoint, original target: ", destination) common.Interrupt(output)
} else { errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *blockedDest)
// SRV/TXT, lookup failed })
remoteDest := net.DestinationFromAddr(conn.RemoteAddr()) defer timer.Stop()
if rule := h.matchFinalRule(remoteDest.Network, remoteDest.Address, remoteDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block { defer common.Close(output)
conn.Close() if err := buf.Copy(input, buf.Discard); err != nil {
return h.blackhole(ctx, input, output, rule, &remoteDest) return nil
}
} }
return nil
} }
// TODO: SRV/TXT
// if remoteDest := net.DestinationFromAddr(conn.RemoteAddr()); h.applyFinalRules(remoteDest.Network, remoteDest.Address, remoteDest.Port, defaultRule) == RuleAction_Block {
// conn.Close()
// return blackhole(remoteDest)
// }
if h.config.ProxyProtocol > 0 && h.config.ProxyProtocol <= 2 { if h.config.ProxyProtocol > 0 && h.config.ProxyProtocol <= 2 {
version := byte(h.config.ProxyProtocol) version := byte(h.config.ProxyProtocol)
srcAddr := inbound.Source.RawNetAddr() srcAddr := inbound.Source.RawNetAddr()
@@ -451,7 +406,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
writer = buf.NewWriter(conn) writer = buf.NewWriter(conn)
} }
} else { } else {
writer = NewPacketWriter(conn, h, defaultRule, UDPOverride, destination, outGateway) writer = NewPacketWriter(conn, h, defaultRule, UDPOverride, destination)
if h.config.Noises != nil { if h.config.Noises != nil {
errors.LogDebug(ctx, "NOISE", h.config.Noises) errors.LogDebug(ctx, "NOISE", h.config.Noises)
writer = &NoisePacketWriter{ writer = &NoisePacketWriter{
@@ -555,7 +510,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
} }
udpAddr := d.(*net.UDPAddr) udpAddr := d.(*net.UDPAddr)
sourceAddr := net.IPAddress(udpAddr.IP) sourceAddr := net.IPAddress(udpAddr.IP)
if rule := r.Handler.matchFinalRule(net.Network_UDP, sourceAddr, net.Port(udpAddr.Port), r.DefaultRule); rule != nil && rule.action == RuleAction_Block { if r.Handler.applyFinalRules(net.Network_UDP, sourceAddr, net.Port(udpAddr.Port), r.DefaultRule) == RuleAction_Block {
continue continue
} }
b.Resize(0, int32(n)) b.Resize(0, int32(n))
@@ -580,7 +535,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
} }
// DialDest means the dial target used in the dialer when creating conn // DialDest means the dial target used in the dialer when creating conn
func NewPacketWriter(conn net.Conn, h *Handler, defaultRule *FinalRule, UDPOverride net.Destination, DialDest net.Destination, outGateway net.Address) buf.Writer { func NewPacketWriter(conn net.Conn, h *Handler, defaultRule *FinalRule, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
iConn := conn iConn := conn
statConn, ok := iConn.(*stat.CounterConnection) statConn, ok := iConn.(*stat.CounterConnection)
if ok { if ok {
@@ -604,7 +559,7 @@ func NewPacketWriter(conn net.Conn, h *Handler, defaultRule *FinalRule, UDPOverr
DefaultRule: defaultRule, DefaultRule: defaultRule,
UDPOverride: UDPOverride, UDPOverride: UDPOverride,
ResolvedUDPAddr: resolvedUDPAddr, ResolvedUDPAddr: resolvedUDPAddr,
OutGateway: outGateway, LocalAddr: net.DestinationFromAddr(conn.LocalAddr()).Address,
} }
} }
@@ -623,7 +578,7 @@ type PacketWriter struct {
// Resulting in these packets being sent to many different IPs randomly // Resulting in these packets being sent to many different IPs randomly
// So, cache and keep the resolve result // So, cache and keep the resolve result
ResolvedUDPAddr *utils.TypedSyncMap[string, net.Address] ResolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
OutGateway net.Address LocalAddr net.Address
} }
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
@@ -646,21 +601,21 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
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 b.UDP.Address = ip
} else { } else {
shouldUseSystemResolver := true ShouldUseSystemResolver := true
if resolveStrategy := w.Handler.udpDomainStrategy(); resolveStrategy.HasStrategy() { if w.Handler.config.DomainStrategy.HasStrategy() {
ips, err := internet.LookupForIP(b.UDP.Address.Domain(), resolveStrategy, w.OutGateway) ips, err := internet.LookupForIP(b.UDP.Address.Domain(), w.Handler.config.DomainStrategy, w.LocalAddr)
if err != nil { if err != nil {
// drop packet if resolve failed when forceIP // drop packet if resolve failed when forceIP
if resolveStrategy.ForceIP() { if w.Handler.config.DomainStrategy.ForceIP() {
b.Release() b.Release()
continue continue
} }
} else { } else {
ip = net.IPAddress(ips[dice.Roll(len(ips))]) ip = net.IPAddress(ips[dice.Roll(len(ips))])
shouldUseSystemResolver = false ShouldUseSystemResolver = false
} }
} }
if shouldUseSystemResolver { if ShouldUseSystemResolver {
udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr()) udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
if err != nil { if err != nil {
b.Release() b.Release()
@@ -674,7 +629,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
} }
} }
} }
if rule := w.matchFinalRule(net.Network_UDP, b.UDP.Address, b.UDP.Port, w.DefaultRule); rule != nil && rule.action == RuleAction_Block { if w.applyFinalRules(net.Network_UDP, b.UDP.Address, b.UDP.Port, w.DefaultRule) == RuleAction_Block {
b.Release() b.Release()
continue continue
} }
+3 -1
View File
@@ -12,7 +12,7 @@ var (
globalTransportConfigCreatorCache = make(map[string]ConfigCreator) globalTransportConfigCreatorCache = make(map[string]ConfigCreator)
) )
var strategy = [11][3]byte{ var strategy = [][]byte{
// name strategy, prefer, fallback // name strategy, prefer, fallback
{0, 0, 0}, // AsIs none, /, / {0, 0, 0}, // AsIs none, /, /
{1, 0, 0}, // UseIP use, both, none {1, 0, 0}, // UseIP use, both, none
@@ -27,6 +27,8 @@ var strategy = [11][3]byte{
{2, 6, 4}, // ForceIPv6v4 force, 6, 4 {2, 6, 4}, // ForceIPv6v4 force, 6, 4
} }
const unknownProtocol = "unknown"
func RegisterProtocolConfigCreator(name string, creator ConfigCreator) error { func RegisterProtocolConfigCreator(name string, creator ConfigCreator) error {
if _, found := globalTransportConfigCreatorCache[name]; found { if _, found := globalTransportConfigCreatorCache[name]; found {
return errors.New("protocol ", name, " is already registered").AtError() return errors.New("protocol ", name, " is already registered").AtError()
+2 -20
View File
@@ -730,8 +730,6 @@ type SocketConfig struct {
// ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket // ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket
// option. This option is for UDP only. // option. This option is for UDP only.
ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"`
BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"`
BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"`
AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"`
DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"` DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"` DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"`
@@ -811,20 +809,6 @@ func (x *SocketConfig) GetReceiveOriginalDestAddress() bool {
return false return false
} }
func (x *SocketConfig) GetBindAddress() []byte {
if x != nil {
return x.BindAddress
}
return nil
}
func (x *SocketConfig) GetBindPort() uint32 {
if x != nil {
return x.BindPort
}
return 0
}
func (x *SocketConfig) GetAcceptProxyProtocol() bool { func (x *SocketConfig) GetAcceptProxyProtocol() bool {
if x != nil { if x != nil {
return x.AcceptProxyProtocol return x.AcceptProxyProtocol
@@ -1066,14 +1050,12 @@ const file_transport_internet_config_proto_rawDesc = "" +
"\x05level\x18\x03 \x01(\tR\x05level\x12\x10\n" + "\x05level\x18\x03 \x01(\tR\x05level\x12\x10\n" +
"\x03opt\x18\x04 \x01(\tR\x03opt\x12\x14\n" + "\x03opt\x18\x04 \x01(\tR\x03opt\x12\x14\n" +
"\x05value\x18\x05 \x01(\tR\x05value\x12\x12\n" + "\x05value\x18\x05 \x01(\tR\x05value\x12\x12\n" +
"\x04type\x18\x06 \x01(\tR\x04type\"\x89\t\n" + "\x04type\x18\x06 \x01(\tR\x04type\"\xc9\b\n" +
"\fSocketConfig\x12\x12\n" + "\fSocketConfig\x12\x12\n" +
"\x04mark\x18\x01 \x01(\x05R\x04mark\x12\x10\n" + "\x04mark\x18\x01 \x01(\x05R\x04mark\x12\x10\n" +
"\x03tfo\x18\x02 \x01(\x05R\x03tfo\x12H\n" + "\x03tfo\x18\x02 \x01(\x05R\x03tfo\x12H\n" +
"\x06tproxy\x18\x03 \x01(\x0e20.xray.transport.internet.SocketConfig.TProxyModeR\x06tproxy\x12A\n" + "\x06tproxy\x18\x03 \x01(\x0e20.xray.transport.internet.SocketConfig.TProxyModeR\x06tproxy\x12A\n" +
"\x1dreceive_original_dest_address\x18\x04 \x01(\bR\x1areceiveOriginalDestAddress\x12!\n" + "\x1dreceive_original_dest_address\x18\x04 \x01(\bR\x1areceiveOriginalDestAddress\x122\n" +
"\fbind_address\x18\x05 \x01(\fR\vbindAddress\x12\x1b\n" +
"\tbind_port\x18\x06 \x01(\rR\bbindPort\x122\n" +
"\x15accept_proxy_protocol\x18\a \x01(\bR\x13acceptProxyProtocol\x12P\n" + "\x15accept_proxy_protocol\x18\a \x01(\bR\x13acceptProxyProtocol\x12P\n" +
"\x0fdomain_strategy\x18\b \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12!\n" + "\x0fdomain_strategy\x18\b \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12!\n" +
"\fdialer_proxy\x18\t \x01(\tR\vdialerProxy\x125\n" + "\fdialer_proxy\x18\t \x01(\tR\vdialerProxy\x125\n" +
-4
View File
@@ -124,10 +124,6 @@ message SocketConfig {
// option. This option is for UDP only. // option. This option is for UDP only.
bool receive_original_dest_address = 4; bool receive_original_dest_address = 4;
bytes bind_address = 5;
uint32 bind_port = 6;
bool accept_proxy_protocol = 7; bool accept_proxy_protocol = 7;
DomainStrategy domain_strategy = 8; DomainStrategy domain_strategy = 8;
+46 -44
View File
@@ -3,6 +3,7 @@ package hysteria
import ( import (
"context" "context"
go_tls "crypto/tls" go_tls "crypto/tls"
"math/rand"
"net/http" "net/http"
"net/url" "net/url"
"reflect" "reflect"
@@ -64,7 +65,7 @@ func (c *client) close() {
c.udpSM = nil c.udpSM = nil
} }
func (c *client) dial() error { func (c *client) dial(ctx context.Context) error {
status := c.status() status := c.status()
if status == StatusActive { if status == StatusActive {
return nil return nil
@@ -113,30 +114,54 @@ func (c *client) dial() error {
// quicConfig.KeepAlivePeriod = 10 * time.Second // quicConfig.KeepAlivePeriod = 10 * time.Second
// } // }
udpHopDialer := func(addr *net.UDPAddr) (net.PacketConn, error) {
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig)
if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("")
}
var pktConn net.PacketConn
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
default:
panic(reflect.TypeOf(c))
}
return pktConn, nil
}
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr *net.UDPAddr var udpAddr *net.UDPAddr
var err error
udpAddr, err = net.ResolveUDPAddr("udp", c.dest.NetAddr())
if err != nil {
return err
}
if len(quicParams.UdpHop.Ports) > 0 { if len(quicParams.UdpHop.Ports) > 0 {
pktConn, err = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, c.udpHopDialer) index := rand.Intn(len(quicParams.UdpHop.Ports))
c.dest.Port = net.Port(quicParams.UdpHop.Ports[index])
conn, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil { if err != nil {
return err return errors.New("failed to dial to dest").Base(err)
}
} else {
conn, err := internet.DialSystem(context.Background(), c.dest, c.socketConfig)
if err != nil {
return err
} }
switch c := conn.(type) { switch c := conn.(type) {
case *internet.PacketConnWrapper: case *internet.PacketConnWrapper:
pktConn = c.PacketConn pktConn = c.PacketConn
case *net.UDPConn: udpAddr = conn.RemoteAddr().(*net.UDPAddr)
pktConn = c default:
panic(reflect.TypeOf(c))
}
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
} else {
conn, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil {
return errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = c.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection: case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c} pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default: default:
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }
@@ -228,11 +253,11 @@ func (c *client) dial() error {
return nil return nil
} }
func (c *client) tcp() (stat.Connection, error) { func (c *client) tcp(ctx context.Context) (stat.Connection, error) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
err := c.dial() err := c.dial(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -251,11 +276,11 @@ func (c *client) tcp() (stat.Connection, error) {
}, nil }, nil
} }
func (c *client) udp() (stat.Connection, error) { func (c *client) udp(ctx context.Context) (stat.Connection, error) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
err := c.dial() err := c.dial(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -271,29 +296,6 @@ func (c *client) clean() {
c.Unlock() c.Unlock()
} }
func (c *client) udpHopDialer(addr *net.UDPAddr) (net.PacketConn, error) {
conn, err := internet.DialSystem(context.Background(), net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig)
if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("failed to dial to dest").Base(err)
}
var pktConn net.PacketConn
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *net.UDPConn:
pktConn = c
default:
errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c))
conn.Close()
return nil, errors.New("invalid conn ", reflect.TypeOf(c))
}
return pktConn, nil
}
type dialerConf struct { type dialerConf struct {
net.Destination net.Destination
*internet.MemoryStreamConfig *internet.MemoryStreamConfig
@@ -356,9 +358,9 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
} }
if datagram { if datagram {
return c.udp() return c.udp(ctx)
} }
return c.tcp() return c.tcp(ctx)
} }
func init() { func init() {
+4 -9
View File
@@ -47,7 +47,7 @@ type udpPacket struct {
Err error Err error
} }
func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopIntervalMax time.Duration, listenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error)) (net.PacketConn, error) { func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopIntervalMax time.Duration, listenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error), currentConn net.PacketConn, addrIndex int) net.PacketConn {
if len(addrs) == 0 { if len(addrs) == 0 {
panic("len(addrs) == 0") panic("len(addrs) == 0")
} }
@@ -75,8 +75,8 @@ func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopInte
HopIntervalMax: hopIntervalMax, HopIntervalMax: hopIntervalMax,
ListenUDPFunc: listenUDPFunc, ListenUDPFunc: listenUDPFunc,
prevConn: nil, prevConn: nil,
currentConn: nil, currentConn: currentConn,
addrIndex: rand.Intn(len(addrs)), addrIndex: addrIndex,
recvQueue: make(chan *udpPacket, packetQueueSize), recvQueue: make(chan *udpPacket, packetQueueSize),
closeChan: make(chan struct{}), closeChan: make(chan struct{}),
bufPool: sync.Pool{ bufPool: sync.Pool{
@@ -85,14 +85,9 @@ func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopInte
}, },
}, },
} }
var err error
hConn.currentConn, err = listenUDPFunc(hConn.Addrs[hConn.addrIndex].(*net.UDPAddr))
if err != nil {
return nil, err
}
go hConn.recvLoop(hConn.currentConn) go hConn.recvLoop(hConn.currentConn)
go hConn.hopLoop() go hConn.hopLoop()
return hConn, nil return hConn
} }
func (u *UdpHopPacketConn) recvLoop(conn net.PacketConn) { func (u *UdpHopPacketConn) recvLoop(conn net.PacketConn) {
+3 -3
View File
@@ -58,14 +58,14 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
if streamSettings.UdpmaskManager != nil { if streamSettings.UdpmaskManager != nil {
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr = conn.RemoteAddr().(*net.UDPAddr) var udpAddr *net.UDPAddr
switch c := conn.(type) { switch c := conn.(type) {
case *internet.PacketConnWrapper: case *internet.PacketConnWrapper:
pktConn = c.PacketConn pktConn = c.PacketConn
case *net.UDPConn: udpAddr = c.RemoteAddr().(*net.UDPAddr)
pktConn = c
case *cnc.Connection: case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c} pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default: default:
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }
-26
View File
@@ -288,32 +288,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
return nil return nil
} }
func bindAddr(fd uintptr, address []byte, port uint32) error {
setReuseAddr(fd)
setReusePort(fd)
var sockaddr unix.Sockaddr
switch len(address) {
case net.IPv4len:
a4 := &unix.SockaddrInet4{
Port: int(port),
}
copy(a4.Addr[:], address)
sockaddr = a4
case net.IPv6len:
a6 := &unix.SockaddrInet6{
Port: int(port),
}
copy(a6.Addr[:], address)
sockaddr = a6
default:
return errors.New("unexpected length of ip")
}
return unix.Bind(int(fd), sockaddr)
}
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
-26
View File
@@ -222,32 +222,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
return nil return nil
} }
func bindAddr(fd uintptr, ip []byte, port uint32) error {
setReuseAddr(fd)
setReusePort(fd)
var sockaddr syscall.Sockaddr
switch len(ip) {
case net.IPv4len:
a4 := &syscall.SockaddrInet4{
Port: int(port),
}
copy(a4.Addr[:], ip)
sockaddr = a4
case net.IPv6len:
a6 := &syscall.SockaddrInet6{
Port: int(port),
}
copy(a6.Addr[:], ip)
sockaddr = a6
default:
return errors.New("unexpected length of ip")
}
return syscall.Bind(int(fd), sockaddr)
}
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
-27
View File
@@ -2,7 +2,6 @@ package internet
import ( import (
"context" "context"
"net"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@@ -12,32 +11,6 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
func bindAddr(fd uintptr, ip []byte, port uint32) error {
setReuseAddr(fd)
setReusePort(fd)
var sockaddr syscall.Sockaddr
switch len(ip) {
case net.IPv4len:
a4 := &syscall.SockaddrInet4{
Port: int(port),
}
copy(a4.Addr[:], ip)
sockaddr = a4
case net.IPv6len:
a6 := &syscall.SockaddrInet6{
Port: int(port),
}
copy(a6.Addr[:], ip)
sockaddr = a6
default:
return errors.New("unexpected length of ip")
}
return syscall.Bind(int(fd), sockaddr)
}
// applyOutboundSocketOptions applies socket options for outbound connection. // applyOutboundSocketOptions applies socket options for outbound connection.
// note that unlike other part of Xray, this function needs network with speified network stack(tcp4/tcp6/udp4/udp6) // note that unlike other part of Xray, this function needs network with speified network stack(tcp4/tcp6/udp4/udp6)
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
-4
View File
@@ -11,10 +11,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
return nil return nil
} }
func bindAddr(fd uintptr, ip []byte, port uint32) error {
return nil
}
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
return nil return nil
} }
-4
View File
@@ -181,10 +181,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
return nil return nil
} }
func bindAddr(fd uintptr, ip []byte, port uint32) error {
return nil
}
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
return nil return nil
} }
+2
View File
@@ -71,6 +71,7 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
errors.LogInfoInner(ctx, err, "failed to "+method+" "+url) errors.LogInfoInner(ctx, err, "failed to "+method+" "+url)
} }
gotConn.Close() gotConn.Close()
common.Close(body)
wrc.Close() wrc.Close()
return return
} }
@@ -80,6 +81,7 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
if resp.StatusCode != 200 || uploadOnly { // stream-up if resp.StatusCode != 200 || uploadOnly { // stream-up
io.Copy(io.Discard, resp.Body) io.Copy(io.Discard, resp.Body)
resp.Body.Close() // if it is called immediately, the upload will be interrupted also resp.Body.Close() // if it is called immediately, the upload will be interrupted also
common.Close(body)
wrc.Close() wrc.Close()
return return
} }
+21 -19
View File
@@ -5,6 +5,7 @@ import (
gotls "crypto/tls" gotls "crypto/tls"
"fmt" "fmt"
"io" "io"
"math/rand"
"net/http" "net/http"
"net/http/httptrace" "net/http/httptrace"
"net/url" "net/url"
@@ -199,7 +200,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings) conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings)
if err != nil { if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest") errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("failed to dial to dest").Base(err) return nil, errors.New("")
} }
var pktConn net.PacketConn var pktConn net.PacketConn
@@ -207,12 +208,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
switch c := conn.(type) { switch c := conn.(type) {
case *internet.PacketConnWrapper: case *internet.PacketConnWrapper:
pktConn = c.PacketConn pktConn = c.PacketConn
case *net.UDPConn:
pktConn = c
default: default:
errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c)) panic(reflect.TypeOf(c))
conn.Close()
return nil, errors.New("invalid conn ", reflect.TypeOf(c))
} }
return pktConn, nil return pktConn, nil
@@ -220,28 +217,33 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr *net.UDPAddr var udpAddr *net.UDPAddr
var err error
udpAddr, err = net.ResolveUDPAddr("udp", dest.NetAddr())
if err != nil {
return nil, err
}
if len(quicParams.UdpHop.Ports) > 0 { if len(quicParams.UdpHop.Ports) > 0 {
pktConn, err = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer) index := rand.Intn(len(quicParams.UdpHop.Ports))
if err != nil { dest.Port = net.Port(quicParams.UdpHop.Ports[index])
return nil, err
}
} else {
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil { if err != nil {
return nil, err return nil, errors.New("failed to dial to dest").Base(err)
} }
switch c := conn.(type) { switch c := conn.(type) {
case *internet.PacketConnWrapper: case *internet.PacketConnWrapper:
pktConn = c.PacketConn pktConn = c.PacketConn
case *net.UDPConn: udpAddr = conn.RemoteAddr().(*net.UDPAddr)
pktConn = c default:
panic(reflect.TypeOf(c))
}
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
} else {
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = c.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection: case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c} pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default: default:
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }
+5 -13
View File
@@ -441,7 +441,7 @@ type Listener struct {
server http.Server server http.Server
h3server *http3.Server h3server *http3.Server
listener net.Listener listener net.Listener
h3listener Qface h3listener http3.QUICListener
config *Config config *Config
addConn internet.ConnHandler addConn internet.ConnHandler
isH3 bool isH3 bool
@@ -519,8 +519,8 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err) return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err)
} }
l.h3listener = &QListener{ l.h3listener = &QListener{
Qface: l.h3listener, QUICListener: l.h3listener,
quicParams: quicParams, quicParams: quicParams,
} }
errors.LogInfo(ctx, "listening QUIC for XHTTP/3 on ", address, ":", port) errors.LogInfo(ctx, "listening QUIC for XHTTP/3 on ", address, ":", port)
@@ -615,21 +615,13 @@ func init() {
common.Must(internet.RegisterTransportListener(protocolName, ListenXH)) common.Must(internet.RegisterTransportListener(protocolName, ListenXH))
} }
type Qface interface {
Accept(ctx context.Context) (*quic.Conn, error)
Addr() net.Addr
Close() error
}
var _ Qface = (*quic.EarlyListener)(nil)
type QListener struct { type QListener struct {
Qface http3.QUICListener
quicParams *internet.QuicParams quicParams *internet.QuicParams
} }
func (l *QListener) Accept(ctx context.Context) (*quic.Conn, error) { func (l *QListener) Accept(ctx context.Context) (*quic.Conn, error) {
conn, err := l.Qface.Accept(ctx) conn, err := l.QUICListener.Accept(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+3 -22
View File
@@ -44,14 +44,10 @@ func resolveSrcAddr(network net.Network, src net.Address) net.Addr {
} }
} }
func hasBindAddr(sockopt *SocketConfig) bool {
return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0
}
func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
errors.LogDebug(ctx, "dialing to "+dest.String()) errors.LogDebug(ctx, "dialing to "+dest.String())
if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { if dest.Network == net.Network_UDP {
srcAddr := resolveSrcAddr(net.Network_UDP, src) srcAddr := resolveSrcAddr(net.Network_UDP, src)
if srcAddr == nil { if srcAddr == nil {
srcAddr = &net.UDPAddr{ srcAddr = &net.UDPAddr{
@@ -132,11 +128,6 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
errors.LogInfoInner(ctx, err, "failed to apply socket options") errors.LogInfoInner(ctx, err, "failed to apply socket options")
} }
if dest.Network == net.Network_UDP && hasBindAddr(sockopt) {
if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil {
errors.LogInfoInner(ctx, err, "failed to bind source address to ", sockopt.BindAddress)
}
}
} }
}) })
} }
@@ -228,7 +219,7 @@ type FakePacketConn struct {
func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
n, err = c.Read(p) n, err = c.Read(p)
return n, c.RemoteAddr(), err return n, &net.UDPAddr{IP: c.Conn.RemoteAddr().(*net.TCPAddr).IP, Port: c.Conn.RemoteAddr().(*net.TCPAddr).Port}, err
} }
func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) {
@@ -236,15 +227,5 @@ func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) {
} }
func (c *FakePacketConn) LocalAddr() net.Addr { func (c *FakePacketConn) LocalAddr() net.Addr {
return &net.UDPAddr{ return &net.UDPAddr{IP: c.Conn.LocalAddr().(*net.TCPAddr).IP, Port: c.Conn.LocalAddr().(*net.TCPAddr).Port}
IP: []byte{0, 0, 0, 0},
Port: 0,
}
}
func (c *FakePacketConn) RemoteAddr() net.Addr {
return &net.UDPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
}
} }
+3 -3
View File
@@ -26,14 +26,14 @@ func init() {
if streamSettings != nil && streamSettings.UdpmaskManager != nil { if streamSettings != nil && streamSettings.UdpmaskManager != nil {
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr = conn.RemoteAddr().(*net.UDPAddr) var udpAddr *net.UDPAddr
switch c := conn.(type) { switch c := conn.(type) {
case *internet.PacketConnWrapper: case *internet.PacketConnWrapper:
pktConn = c.PacketConn pktConn = c.PacketConn
case *net.UDPConn: udpAddr = c.RemoteAddr().(*net.UDPAddr)
pktConn = c
case *cnc.Connection: case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c} pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default: default:
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }