mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-11-06 10:12:40 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9638715047 | ||
|
|
f5cc086d6c | ||
|
|
6b45eadf45 | ||
|
|
c684201cd8 | ||
|
|
2218fec173 | ||
|
|
9ffa0f0552 | ||
|
|
2933b0c8d5 | ||
|
|
bb4cd4b6d3 | ||
|
|
468f745fc2 |
@@ -20,7 +20,7 @@ RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
|||||||
{
|
{
|
||||||
"log": {
|
"log": {
|
||||||
"error": "/var/log/xray/error.log",
|
"error": "/var/log/xray/error.log",
|
||||||
"logLevel": "warning",
|
"loglevel": "warning",
|
||||||
"access": "none",
|
"access": "none",
|
||||||
"dnsLog": false
|
"dnsLog": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
|||||||
{
|
{
|
||||||
"log": {
|
"log": {
|
||||||
"error": "/var/log/xray/error.log",
|
"error": "/var/log/xray/error.log",
|
||||||
"logLevel": "warning",
|
"loglevel": "warning",
|
||||||
"access": "none",
|
"access": "none",
|
||||||
"dnsLog": false
|
"dnsLog": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package burst
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
)
|
)
|
||||||
@@ -181,7 +181,7 @@ func (h *HealthPing) doCheck(ctx context.Context, tags []string, duration time.D
|
|||||||
for i := 0; i < rounds; i++ {
|
for i := 0; i < rounds; i++ {
|
||||||
delay := time.Duration(0)
|
delay := time.Duration(0)
|
||||||
if duration > 0 {
|
if duration > 0 {
|
||||||
delay = rand.N(duration)
|
delay = time.Duration(dice.RollInt63n(int64(duration)))
|
||||||
}
|
}
|
||||||
timers = append(timers, time.AfterFunc(delay, func() {
|
timers = append(timers, time.AfterFunc(delay, func() {
|
||||||
errors.LogDebug(h.ctx, "checking ", handler)
|
errors.LogDebug(h.ctx, "checking ", handler)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
mrand "math/rand/v2"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@@ -196,7 +196,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unchangedDomain := ob.Target.Address.Domain()
|
unchangedDomain := ob.Target.Address.Domain()
|
||||||
ob.Target.Address = net.IPAddress(ips[mrand.N(len(ips))])
|
ob.Target.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
errors.LogInfo(ctx, "target: ", unchangedDomain, " resolved to: ", ob.Target.Address.String())
|
errors.LogInfo(ctx, "target: ", unchangedDomain, " resolved to: ", ob.Target.Address.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ package reverse
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"io"
|
"io"
|
||||||
mrand "math/rand/v2"
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Control) FillInRandom() {
|
func (c *Control) FillInRandom() {
|
||||||
randomLength := mrand.N(64)
|
randomLength := dice.Roll(64)
|
||||||
randomLength++
|
randomLength++
|
||||||
c.Random = make([]byte, randomLength)
|
c.Random = make([]byte, randomLength)
|
||||||
io.ReadFull(rand.Reader, c.Random)
|
io.ReadFull(rand.Reader, c.Random)
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package router
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"math/rand/v2"
|
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/observatory"
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/extension"
|
"github.com/xtls/xray-core/features/extension"
|
||||||
@@ -74,7 +74,7 @@ func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {
|
|||||||
// goes to fallbackTag
|
// goes to fallbackTag
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return selects[rand.N(count)].Tag
|
return selects[dice.Roll(count)].Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LeastLoadStrategy) pickOutbounds(candidates []string) []*node {
|
func (s *LeastLoadStrategy) pickOutbounds(candidates []string) []*node {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/rand/v2"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/observatory"
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/extension"
|
"github.com/xtls/xray-core/features/extension"
|
||||||
)
|
)
|
||||||
@@ -63,5 +63,5 @@ func (s *RandomStrategy) PickOutbound(candidates []string) string {
|
|||||||
// goes to fallbackTag
|
// goes to fallbackTag
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return candidates[rand.N(count)]
|
return candidates[dice.Roll(count)]
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@ func (r *TimeoutWrapperReader) ReadMultiBufferTimeout(duration time.Duration) (M
|
|||||||
}
|
}
|
||||||
return r.mb, r.err
|
return r.mb, r.err
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
return nil, ErrReadTimeout
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// Package dice contains common functions to generate random number.
|
||||||
|
// It also initialize math/rand with the time in seconds at launch time.
|
||||||
|
package dice // import "github.com/xtls/xray-core/common/dice"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||||
|
func Roll(n int) int {
|
||||||
|
if n == 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rand.Intn(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RollInt63n returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||||
|
func RollInt63n(n int64) int64 {
|
||||||
|
if n == 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rand.Int63n(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||||
|
func RollDeterministic(n int, seed int64) int {
|
||||||
|
if n == 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rand.New(rand.NewSource(seed)).Intn(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RollUint16 returns a random uint16 value.
|
||||||
|
func RollUint16() uint16 {
|
||||||
|
return uint16(rand.Int63() >> 47)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RollUint64() uint64 {
|
||||||
|
return rand.Uint64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeterministicDice(seed int64) *DeterministicDice {
|
||||||
|
return &DeterministicDice{rand.New(rand.NewSource(seed))}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeterministicDice struct {
|
||||||
|
*rand.Rand
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dd *DeterministicDice) Roll(n int) int {
|
||||||
|
if n == 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return dd.Intn(n)
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package dice_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/xtls/xray-core/common/dice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkRoll1(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Roll(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRoll20(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Roll(20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntn1(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
rand.Intn(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntn20(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
rand.Intn(20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkInt63(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = uint16(rand.Int63() >> 47)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkInt31(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = uint16(rand.Int31() >> 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntn(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = uint16(rand.Intn(65536))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@ package drain
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"math/rand/v2"
|
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,10 +12,10 @@ type BehaviorSeedLimitedDrainer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewBehaviorSeedLimitedDrainer(behaviorSeed int64, drainFoundation, maxBaseDrainSize, maxRandDrain int) (Drainer, error) {
|
func NewBehaviorSeedLimitedDrainer(behaviorSeed int64, drainFoundation, maxBaseDrainSize, maxRandDrain int) (Drainer, error) {
|
||||||
behaviorRand := rand.New(rand.NewPCG(uint64(behaviorSeed), 0))
|
behaviorRand := dice.NewDeterministicDice(behaviorSeed)
|
||||||
BaseDrainSize := behaviorRand.N(maxBaseDrainSize)
|
BaseDrainSize := behaviorRand.Roll(maxBaseDrainSize)
|
||||||
RandDrainMax := behaviorRand.N(maxRandDrain) + 1
|
RandDrainMax := behaviorRand.Roll(maxRandDrain) + 1
|
||||||
RandDrainRolled := rand.N(RandDrainMax)
|
RandDrainRolled := dice.Roll(RandDrainMax)
|
||||||
DrainSize := drainFoundation + BaseDrainSize + RandDrainRolled
|
DrainSize := drainFoundation + BaseDrainSize + RandDrainRolled
|
||||||
return &BehaviorSeedLimitedDrainer{DrainSize: DrainSize}, nil
|
return &BehaviorSeedLimitedDrainer{DrainSize: DrainSize}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand/v2"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Timestamp int64
|
type Timestamp int64
|
||||||
@@ -15,7 +16,7 @@ func NowTime() Timestamp {
|
|||||||
|
|
||||||
func NewTimestampGenerator(base Timestamp, delta int) TimestampGenerator {
|
func NewTimestampGenerator(base Timestamp, delta int) TimestampGenerator {
|
||||||
return func() Timestamp {
|
return func() Timestamp {
|
||||||
rangeInDelta := rand.N(delta*2) - delta
|
rangeInDelta := dice.Roll(delta*2) - delta
|
||||||
return base + Timestamp(rangeInDelta)
|
return base + Timestamp(rangeInDelta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ func TestMarshalConfigJson(t *testing.T) {
|
|||||||
func getConfig() string {
|
func getConfig() string {
|
||||||
return `{
|
return `{
|
||||||
"log": {
|
"log": {
|
||||||
"logLevel": "debug"
|
"loglevel": "debug"
|
||||||
},
|
},
|
||||||
"stats": {},
|
"stats": {},
|
||||||
"policy": {
|
"policy": {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ require (
|
|||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/klauspost/cpuid/v2 v2.4.2
|
github.com/klauspost/cpuid/v2 v2.4.1
|
||||||
github.com/libp2p/go-nat v1.0.1-0.20250821073202-01afc089f138
|
github.com/libp2p/go-nat v1.0.1-0.20250821073202-01afc089f138
|
||||||
github.com/miekg/dns v1.1.73
|
github.com/miekg/dns v1.1.73
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
|
|||||||
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
||||||
github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
|
github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
|
||||||
github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
|
github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
|
||||||
github.com/klauspost/cpuid/v2 v2.4.2 h1:xRw7IZEsAgVCp6trS/DgWbTAqpixhmywgVgBjYGg1bQ=
|
github.com/klauspost/cpuid/v2 v2.4.1 h1:I9KxadAkvo+QjtcEE2f2tyfEvmIla/T0m+14PrZNl0U=
|
||||||
github.com/klauspost/cpuid/v2 v2.4.2/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
|
github.com/klauspost/cpuid/v2 v2.4.1/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
|
||||||
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
|
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
|
||||||
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
|
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
|||||||
+3
-33
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/geodata"
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
xnet "github.com/xtls/xray-core/common/net"
|
xnet "github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
@@ -49,8 +48,6 @@ type FreedomFinalRuleConfig struct {
|
|||||||
Network *NetworkList `json:"network"`
|
Network *NetworkList `json:"network"`
|
||||||
Port *PortList `json:"port"`
|
Port *PortList `json:"port"`
|
||||||
IP *StringList `json:"ip"`
|
IP *StringList `json:"ip"`
|
||||||
Delay *Int32Range `json:"delay"`
|
|
||||||
LogLevel string `json:"logLevel"`
|
|
||||||
BlockDelay *Int32Range `json:"blockDelay"`
|
BlockDelay *Int32Range `json:"blockDelay"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,37 +280,10 @@ func (c *FreedomFinalRuleConfig) Build() (*freedom.FinalRuleConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.BlockDelay != nil {
|
if c.BlockDelay != nil {
|
||||||
errors.PrintDeprecatedFeatureWarning("finalRules.blockDelay", "finalRules.delay")
|
rule.BlockDelay = &freedom.Range{
|
||||||
c.Delay = c.BlockDelay
|
Min: uint64(c.BlockDelay.From),
|
||||||
}
|
Max: uint64(c.BlockDelay.To),
|
||||||
|
|
||||||
if rule.Action != freedom.RuleAction_Block {
|
|
||||||
if c.Delay != nil || c.LogLevel != "" {
|
|
||||||
return nil, errors.New("delay and logLevel are only supported for block finalRules")
|
|
||||||
}
|
}
|
||||||
return rule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Delay != nil {
|
|
||||||
rule.Delay = &freedom.Range{
|
|
||||||
Min: uint64(c.Delay.From),
|
|
||||||
Max: uint64(c.Delay.To),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch strings.ToLower(c.LogLevel) {
|
|
||||||
case "", "info":
|
|
||||||
rule.LogLevel = log.Severity_Info.Enum()
|
|
||||||
case "none":
|
|
||||||
rule.LogLevel = log.Severity_Unknown.Enum()
|
|
||||||
case "debug":
|
|
||||||
rule.LogLevel = log.Severity_Debug.Enum()
|
|
||||||
case "warning":
|
|
||||||
rule.LogLevel = log.Severity_Warning.Enum()
|
|
||||||
case "error":
|
|
||||||
rule.LogLevel = log.Severity_Error.Enum()
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unknown finalRules.logLevel: ", c.LogLevel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rule, nil
|
return rule, nil
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/geodata"
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
. "github.com/xtls/xray-core/infra/conf"
|
. "github.com/xtls/xray-core/infra/conf"
|
||||||
@@ -47,8 +46,7 @@ func TestFreedomConfig(t *testing.T) {
|
|||||||
"network": "tcp,udp",
|
"network": "tcp,udp",
|
||||||
"port": "53,443",
|
"port": "53,443",
|
||||||
"ip": ["10.0.0.0/8", "2001:db8::/32"],
|
"ip": ["10.0.0.0/8", "2001:db8::/32"],
|
||||||
"delay": "30-60",
|
"blockDelay": "30-60"
|
||||||
"logLevel": "debug"
|
|
||||||
}, {
|
}, {
|
||||||
"action": "allow",
|
"action": "allow",
|
||||||
"network": ["udp"]
|
"network": ["udp"]
|
||||||
@@ -88,8 +86,10 @@ func TestFreedomConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Delay: &freedom.Range{Min: 30, Max: 60},
|
BlockDelay: &freedom.Range{
|
||||||
LogLevel: log.Severity_Debug.Enum(),
|
Min: 30,
|
||||||
|
Max: 60,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: freedom.RuleAction_Allow,
|
Action: freedom.RuleAction_Allow,
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ func DefaultLogConfig() *log.Config {
|
|||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
AccessLog string `json:"access"`
|
AccessLog string `json:"access"`
|
||||||
ErrorLog string `json:"error"`
|
ErrorLog string `json:"error"`
|
||||||
LogLevel string `json:"logLevel"`
|
LogLevel string `json:"loglevel"`
|
||||||
DNSLog bool `json:"dnsLog"`
|
DNSLog bool `json:"dnsLog"`
|
||||||
MaskAddress string `json:"maskAddress"`
|
MaskAddress string `json:"maskAddress"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func TestLoaderError(t *testing.T) {
|
|||||||
"log": {
|
"log": {
|
||||||
// abcd
|
// abcd
|
||||||
0,
|
0,
|
||||||
"logLevel": "info"
|
"loglevel": "info"
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
Output: "line 4 char 6",
|
Output: "line 4 char 6",
|
||||||
@@ -27,7 +27,7 @@ func TestLoaderError(t *testing.T) {
|
|||||||
Input: `{
|
Input: `{
|
||||||
"log": {
|
"log": {
|
||||||
// abcd
|
// abcd
|
||||||
"logLevel": "info",
|
"loglevel": "info",
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
Output: "line 5 char 5",
|
Output: "line 5 char 5",
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func TestXrayConfig(t *testing.T) {
|
|||||||
Input: `{
|
Input: `{
|
||||||
"log": {
|
"log": {
|
||||||
"access": "/var/log/xray/access.log",
|
"access": "/var/log/xray/access.log",
|
||||||
"logLevel": "error",
|
"loglevel": "error",
|
||||||
"error": "/var/log/xray/error.log"
|
"error": "/var/log/xray/error.log"
|
||||||
},
|
},
|
||||||
"inbounds": [{
|
"inbounds": [{
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ package blackhole
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"math/rand/v2"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
@@ -74,7 +74,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, func() {
|
timer := signal.CancelAfterInactivity(ctx, func() {
|
||||||
cancel()
|
cancel()
|
||||||
}, time.Duration(30+rand.N(61))*time.Second)
|
}, time.Duration(30+dice.Roll(61))*time.Second)
|
||||||
go buf.Copy(link.Reader, buf.Discard, buf.UpdateActivity(timer))
|
go buf.Copy(link.Reader, buf.Discard, buf.UpdateActivity(timer))
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-34
@@ -8,7 +8,6 @@ package freedom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
geodata "github.com/xtls/xray-core/common/geodata"
|
geodata "github.com/xtls/xray-core/common/geodata"
|
||||||
log "github.com/xtls/xray-core/common/log"
|
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
protocol "github.com/xtls/xray-core/common/protocol"
|
protocol "github.com/xtls/xray-core/common/protocol"
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
internet "github.com/xtls/xray-core/transport/internet"
|
||||||
@@ -358,8 +357,7 @@ type FinalRuleConfig struct {
|
|||||||
Networks []net.Network `protobuf:"varint,2,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
|
Networks []net.Network `protobuf:"varint,2,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
|
||||||
PortList *net.PortList `protobuf:"bytes,3,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
PortList *net.PortList `protobuf:"bytes,3,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||||
Ip []*geodata.IPRule `protobuf:"bytes,4,rep,name=ip,proto3" json:"ip,omitempty"`
|
Ip []*geodata.IPRule `protobuf:"bytes,4,rep,name=ip,proto3" json:"ip,omitempty"`
|
||||||
Delay *Range `protobuf:"bytes,5,opt,name=delay,proto3" json:"delay,omitempty"`
|
BlockDelay *Range `protobuf:"bytes,5,opt,name=block_delay,json=blockDelay,proto3" json:"block_delay,omitempty"`
|
||||||
LogLevel *log.Severity `protobuf:"varint,6,opt,name=log_level,json=logLevel,proto3,enum=xray.common.log.Severity,oneof" json:"log_level,omitempty"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -422,20 +420,13 @@ func (x *FinalRuleConfig) GetIp() []*geodata.IPRule {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FinalRuleConfig) GetDelay() *Range {
|
func (x *FinalRuleConfig) GetBlockDelay() *Range {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Delay
|
return x.BlockDelay
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FinalRuleConfig) GetLogLevel() log.Severity {
|
|
||||||
if x != nil && x.LogLevel != nil {
|
|
||||||
return *x.LogLevel
|
|
||||||
}
|
|
||||||
return log.Severity(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
DomainStrategy internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
DomainStrategy internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
||||||
@@ -532,7 +523,7 @@ var File_proxy_freedom_config_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_proxy_freedom_config_proto_rawDesc = "" +
|
const file_proxy_freedom_config_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x1aproxy/freedom/config.proto\x12\x12xray.proxy.freedom\x1a!common/protocol/server_spec.proto\x1a\x1ftransport/internet/config.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\x1a\x14common/log/log.proto\"S\n" +
|
"\x1aproxy/freedom/config.proto\x12\x12xray.proxy.freedom\x1a!common/protocol/server_spec.proto\x1a\x1ftransport/internet/config.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\"S\n" +
|
||||||
"\x13DestinationOverride\x12<\n" +
|
"\x13DestinationOverride\x12<\n" +
|
||||||
"\x06server\x18\x01 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06server\"\x98\x02\n" +
|
"\x06server\x18\x01 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06server\"\x98\x02\n" +
|
||||||
"\bFragment\x12!\n" +
|
"\bFragment\x12!\n" +
|
||||||
@@ -558,16 +549,14 @@ const file_proxy_freedom_config_proto_rawDesc = "" +
|
|||||||
"\bapply_to\x18\x06 \x01(\tR\aapplyTo\"+\n" +
|
"\bapply_to\x18\x06 \x01(\tR\aapplyTo\"+\n" +
|
||||||
"\x05Range\x12\x10\n" +
|
"\x05Range\x12\x10\n" +
|
||||||
"\x03min\x18\x01 \x01(\x04R\x03min\x12\x10\n" +
|
"\x03min\x18\x01 \x01(\x04R\x03min\x12\x10\n" +
|
||||||
"\x03max\x18\x02 \x01(\x04R\x03max\"\xe0\x02\n" +
|
"\x03max\x18\x02 \x01(\x04R\x03max\"\xa0\x02\n" +
|
||||||
"\x0fFinalRuleConfig\x126\n" +
|
"\x0fFinalRuleConfig\x126\n" +
|
||||||
"\x06action\x18\x01 \x01(\x0e2\x1e.xray.proxy.freedom.RuleActionR\x06action\x124\n" +
|
"\x06action\x18\x01 \x01(\x0e2\x1e.xray.proxy.freedom.RuleActionR\x06action\x124\n" +
|
||||||
"\bnetworks\x18\x02 \x03(\x0e2\x18.xray.common.net.NetworkR\bnetworks\x126\n" +
|
"\bnetworks\x18\x02 \x03(\x0e2\x18.xray.common.net.NetworkR\bnetworks\x126\n" +
|
||||||
"\tport_list\x18\x03 \x01(\v2\x19.xray.common.net.PortListR\bportList\x12+\n" +
|
"\tport_list\x18\x03 \x01(\v2\x19.xray.common.net.PortListR\bportList\x12+\n" +
|
||||||
"\x02ip\x18\x04 \x03(\v2\x1b.xray.common.geodata.IPRuleR\x02ip\x12/\n" +
|
"\x02ip\x18\x04 \x03(\v2\x1b.xray.common.geodata.IPRuleR\x02ip\x12:\n" +
|
||||||
"\x05delay\x18\x05 \x01(\v2\x19.xray.proxy.freedom.RangeR\x05delay\x12;\n" +
|
"\vblock_delay\x18\x05 \x01(\v2\x19.xray.proxy.freedom.RangeR\n" +
|
||||||
"\tlog_level\x18\x06 \x01(\x0e2\x19.xray.common.log.SeverityH\x00R\blogLevel\x88\x01\x01B\f\n" +
|
"blockDelay\"\xaf\x03\n" +
|
||||||
"\n" +
|
|
||||||
"_log_level\"\xaf\x03\n" +
|
|
||||||
"\x06Config\x12P\n" +
|
"\x06Config\x12P\n" +
|
||||||
"\x0fdomain_strategy\x18\x01 \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12Z\n" +
|
"\x0fdomain_strategy\x18\x01 \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12Z\n" +
|
||||||
"\x14destination_override\x18\x03 \x01(\v2'.xray.proxy.freedom.DestinationOverrideR\x13destinationOverride\x12\x1d\n" +
|
"\x14destination_override\x18\x03 \x01(\v2'.xray.proxy.freedom.DestinationOverrideR\x13destinationOverride\x12\x1d\n" +
|
||||||
@@ -610,8 +599,7 @@ var file_proxy_freedom_config_proto_goTypes = []any{
|
|||||||
(net.Network)(0), // 8: xray.common.net.Network
|
(net.Network)(0), // 8: xray.common.net.Network
|
||||||
(*net.PortList)(nil), // 9: xray.common.net.PortList
|
(*net.PortList)(nil), // 9: xray.common.net.PortList
|
||||||
(*geodata.IPRule)(nil), // 10: xray.common.geodata.IPRule
|
(*geodata.IPRule)(nil), // 10: xray.common.geodata.IPRule
|
||||||
(log.Severity)(0), // 11: xray.common.log.Severity
|
(internet.DomainStrategy)(0), // 11: xray.transport.internet.DomainStrategy
|
||||||
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
|
||||||
}
|
}
|
||||||
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
7, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||||
@@ -619,18 +607,17 @@ var file_proxy_freedom_config_proto_depIdxs = []int32{
|
|||||||
8, // 2: xray.proxy.freedom.FinalRuleConfig.networks:type_name -> xray.common.net.Network
|
8, // 2: xray.proxy.freedom.FinalRuleConfig.networks:type_name -> xray.common.net.Network
|
||||||
9, // 3: xray.proxy.freedom.FinalRuleConfig.port_list:type_name -> xray.common.net.PortList
|
9, // 3: xray.proxy.freedom.FinalRuleConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
10, // 4: xray.proxy.freedom.FinalRuleConfig.ip:type_name -> xray.common.geodata.IPRule
|
10, // 4: xray.proxy.freedom.FinalRuleConfig.ip:type_name -> xray.common.geodata.IPRule
|
||||||
4, // 5: xray.proxy.freedom.FinalRuleConfig.delay:type_name -> xray.proxy.freedom.Range
|
4, // 5: xray.proxy.freedom.FinalRuleConfig.block_delay:type_name -> xray.proxy.freedom.Range
|
||||||
11, // 6: xray.proxy.freedom.FinalRuleConfig.log_level:type_name -> xray.common.log.Severity
|
11, // 6: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
12, // 7: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
1, // 7: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||||
1, // 8: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
2, // 8: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||||
2, // 9: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
3, // 9: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||||
3, // 10: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
5, // 10: xray.proxy.freedom.Config.final_rules:type_name -> xray.proxy.freedom.FinalRuleConfig
|
||||||
5, // 11: xray.proxy.freedom.Config.final_rules:type_name -> xray.proxy.freedom.FinalRuleConfig
|
11, // [11:11] is the sub-list for method output_type
|
||||||
12, // [12:12] is the sub-list for method output_type
|
11, // [11:11] is the sub-list for method input_type
|
||||||
12, // [12:12] is the sub-list for method input_type
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
12, // [12:12] is the sub-list for extension type_name
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
12, // [12:12] is the sub-list for extension extendee
|
0, // [0:11] is the sub-list for field type_name
|
||||||
0, // [0:12] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proxy_freedom_config_proto_init() }
|
func init() { file_proxy_freedom_config_proto_init() }
|
||||||
@@ -638,7 +625,6 @@ func file_proxy_freedom_config_proto_init() {
|
|||||||
if File_proxy_freedom_config_proto != nil {
|
if File_proxy_freedom_config_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file_proxy_freedom_config_proto_msgTypes[4].OneofWrappers = []any{}
|
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import "transport/internet/config.proto";
|
|||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "common/net/network.proto";
|
import "common/net/network.proto";
|
||||||
import "common/geodata/geodat.proto";
|
import "common/geodata/geodat.proto";
|
||||||
import "common/log/log.proto";
|
|
||||||
|
|
||||||
message DestinationOverride {
|
message DestinationOverride {
|
||||||
xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
@@ -52,8 +51,7 @@ message FinalRuleConfig {
|
|||||||
repeated xray.common.net.Network networks = 2;
|
repeated xray.common.net.Network networks = 2;
|
||||||
xray.common.net.PortList port_list = 3;
|
xray.common.net.PortList port_list = 3;
|
||||||
repeated xray.common.geodata.IPRule ip = 4;
|
repeated xray.common.geodata.IPRule ip = 4;
|
||||||
Range delay = 5;
|
Range block_delay = 5;
|
||||||
optional xray.common.log.Severity log_level = 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
|||||||
+23
-45
@@ -12,9 +12,9 @@ import (
|
|||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/geodata"
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/common/retry"
|
"github.com/xtls/xray-core/common/retry"
|
||||||
@@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
mrand "math/rand/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -73,26 +72,23 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultBlockPrivateRule = &FinalRule{
|
defaultBlockPrivateRule = &FinalRule{
|
||||||
action: RuleAction_Block,
|
action: RuleAction_Block,
|
||||||
network: allNetworks,
|
network: allNetworks,
|
||||||
ip: geodata.GetPrivateIPMatcher(),
|
ip: geodata.GetPrivateIPMatcher(),
|
||||||
logLevel: log.Severity_Warning.Enum(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultBlockAllRule = &FinalRule{
|
defaultBlockAllRule = &FinalRule{
|
||||||
action: RuleAction_Block,
|
action: RuleAction_Block,
|
||||||
network: allNetworks,
|
network: allNetworks,
|
||||||
logLevel: log.Severity_Warning.Enum(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FinalRule struct {
|
type FinalRule struct {
|
||||||
action RuleAction
|
action RuleAction
|
||||||
network [8]bool
|
network [8]bool
|
||||||
port net.MemoryPortList
|
port net.MemoryPortList
|
||||||
ip geodata.IPMatcher
|
ip geodata.IPMatcher
|
||||||
delay *Range
|
blockDelay *Range
|
||||||
logLevel *log.Severity
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler handles Freedom connections.
|
// Handler handles Freedom connections.
|
||||||
@@ -106,9 +102,8 @@ type Handler struct {
|
|||||||
|
|
||||||
func buildFinalRule(config *FinalRuleConfig) (*FinalRule, error) {
|
func buildFinalRule(config *FinalRuleConfig) (*FinalRule, error) {
|
||||||
rule := &FinalRule{
|
rule := &FinalRule{
|
||||||
action: config.GetAction(),
|
action: config.GetAction(),
|
||||||
delay: config.GetDelay(),
|
blockDelay: config.GetBlockDelay(),
|
||||||
logLevel: config.LogLevel,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(config.Networks) == 0 {
|
if len(config.Networks) == 0 {
|
||||||
@@ -169,7 +164,7 @@ func getDefaultFinalRule(inbound *session.Inbound) *FinalRule {
|
|||||||
switch inbound.Name {
|
switch inbound.Name {
|
||||||
case "vless-reverse":
|
case "vless-reverse":
|
||||||
return defaultBlockAllRule
|
return defaultBlockAllRule
|
||||||
case "vless", "vmess", "trojan", "hysteria", "wireguard", "masque":
|
case "vless", "vmess", "trojan", "hysteria", "wireguard":
|
||||||
return defaultBlockPrivateRule
|
return defaultBlockPrivateRule
|
||||||
default:
|
default:
|
||||||
if strings.HasPrefix(inbound.Name, "shadowsocks") {
|
if strings.HasPrefix(inbound.Name, "shadowsocks") {
|
||||||
@@ -217,40 +212,23 @@ func (h *Handler) policy() policy.Session {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FinalRule) blockDuration() time.Duration {
|
func (h *Handler) blockDelay(rule *FinalRule) time.Duration {
|
||||||
min := uint64(30)
|
min := uint64(30)
|
||||||
max := uint64(90)
|
max := uint64(90)
|
||||||
if r.delay != nil {
|
if rule.blockDelay != nil {
|
||||||
min = r.delay.Min
|
min = rule.blockDelay.Min
|
||||||
max = r.delay.Max
|
max = rule.blockDelay.Max
|
||||||
}
|
}
|
||||||
span := max - min
|
span := max - min
|
||||||
if max < min {
|
if max < min {
|
||||||
span = min - max
|
span = min - max
|
||||||
}
|
}
|
||||||
return time.Duration(min+mrand.N(span+1)) * time.Second
|
return time.Duration(min+uint64(dice.Roll(int(span+1)))) * time.Second
|
||||||
}
|
|
||||||
|
|
||||||
func (r *FinalRule) log(ctx context.Context, msg ...interface{}) {
|
|
||||||
level := log.Severity_Info
|
|
||||||
if r.logLevel != nil {
|
|
||||||
level = *r.logLevel
|
|
||||||
}
|
|
||||||
switch level {
|
|
||||||
case log.Severity_Debug:
|
|
||||||
errors.LogDebug(ctx, msg...)
|
|
||||||
case log.Severity_Info:
|
|
||||||
errors.LogInfo(ctx, msg...)
|
|
||||||
case log.Severity_Warning:
|
|
||||||
errors.LogWarning(ctx, msg...)
|
|
||||||
case log.Severity_Error:
|
|
||||||
errors.LogError(ctx, msg...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Writer, rule *FinalRule, dest *net.Destination) error {
|
func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Writer, rule *FinalRule, dest *net.Destination) error {
|
||||||
delay := rule.blockDuration()
|
delay := h.blockDelay(rule)
|
||||||
rule.log(ctx, "target blocked by a finalrule: ", *dest, ", blackholing connection for ", delay)
|
errors.LogInfo(ctx, "blocked target: ", *dest, ", blackholing connection for ", delay)
|
||||||
defer common.Close(output)
|
defer common.Close(output)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
go func() { // a DispatchLink inbound's reader ignores Interrupt, so don't wait for this copy
|
go func() { // a DispatchLink inbound's reader ignores Interrupt, so don't wait for this copy
|
||||||
@@ -262,7 +240,7 @@ func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Wr
|
|||||||
case <-time.After(delay):
|
case <-time.After(delay):
|
||||||
common.Interrupt(input)
|
common.Interrupt(input)
|
||||||
common.Interrupt(output)
|
common.Interrupt(output)
|
||||||
rule.log(ctx, "closed blackholed connection to blocked target: ", *dest)
|
errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *dest)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -634,7 +612,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ip = net.IPAddress(ips[mrand.N(len(ips))])
|
ip = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
shouldUseSystemResolver = false
|
shouldUseSystemResolver = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"hash/crc64"
|
"hash/crc64"
|
||||||
"math/rand/v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
)
|
)
|
||||||
@@ -158,7 +158,7 @@ func (v *Validator) GetBehaviorSeed() uint64 {
|
|||||||
|
|
||||||
v.behaviorFused = true
|
v.behaviorFused = true
|
||||||
if v.behaviorSeed == 0 {
|
if v.behaviorSeed == 0 {
|
||||||
v.behaviorSeed = rand.Uint64()
|
v.behaviorSeed = dice.RollUint64()
|
||||||
}
|
}
|
||||||
return v.behaviorSeed
|
return v.behaviorSeed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,12 +201,6 @@ startOver:
|
|||||||
}
|
}
|
||||||
err = t.luid.SetDNS(family, dns, nil)
|
err = t.luid.SetDNS(family, dns, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Skip IPv6 the config does not ask for also when setting its DNS
|
|
||||||
// servers fails, as reported on Windows 11 24H2 with IPv6 disabled
|
|
||||||
// (Access is denied).
|
|
||||||
if family == windows.AF_INET6 && !address6 && !route6 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
firstErr = errors.New("unable to set DNS").Base(err)
|
firstErr = errors.New("unable to set DNS").Base(err)
|
||||||
if err == windows.ERROR_NOT_FOUND {
|
if err == windows.ERROR_NOT_FOUND {
|
||||||
goto startOver
|
goto startOver
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/bitmask"
|
"github.com/xtls/xray-core/common/bitmask"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/drain"
|
"github.com/xtls/xray-core/common/drain"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/vmess"
|
"github.com/xtls/xray-core/proxy/vmess"
|
||||||
vmessaead "github.com/xtls/xray-core/proxy/vmess/aead"
|
vmessaead "github.com/xtls/xray-core/proxy/vmess/aead"
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
mrand "math/rand/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClientSession stores connection session info for VMess client.
|
// ClientSession stores connection session info for VMess client.
|
||||||
@@ -72,7 +72,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
|
|||||||
common.Must(buffer.WriteByte(c.responseHeader))
|
common.Must(buffer.WriteByte(c.responseHeader))
|
||||||
common.Must(buffer.WriteByte(byte(header.Option)))
|
common.Must(buffer.WriteByte(byte(header.Option)))
|
||||||
|
|
||||||
paddingLen := mrand.N(16)
|
paddingLen := dice.Roll(16)
|
||||||
security := byte(paddingLen<<4) | byte(header.Security)
|
security := byte(paddingLen<<4) | byte(header.Security)
|
||||||
common.Must2(buffer.Write([]byte{security, byte(0), byte(header.Command)}))
|
common.Must2(buffer.Write([]byte{security, byte(0), byte(header.Command)}))
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"hash/crc64"
|
"hash/crc64"
|
||||||
"math/rand/v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/vmess/aead"
|
"github.com/xtls/xray-core/proxy/vmess/aead"
|
||||||
@@ -117,7 +117,7 @@ func (v *TimedUserValidator) GetBehaviorSeed() uint64 {
|
|||||||
|
|
||||||
v.behaviorFused = true
|
v.behaviorFused = true
|
||||||
if v.behaviorSeed == 0 {
|
if v.behaviorSeed == 0 {
|
||||||
v.behaviorSeed = rand.Uint64()
|
v.behaviorSeed = dice.RollUint64()
|
||||||
}
|
}
|
||||||
return v.behaviorSeed
|
return v.behaviorSeed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
type bind struct {
|
type bind struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
resolveFunc func(ctx context.Context, host string) (net.IP, error)
|
resolveFunc func(host string) (net.IP, error)
|
||||||
listenFunc func(ctx context.Context) (net.PacketConn, error)
|
listenFunc func(ctx context.Context) (net.PacketConn, error)
|
||||||
downFunc func() error
|
downFunc func() error
|
||||||
reserved []byte
|
reserved []byte
|
||||||
@@ -143,11 +143,7 @@ func (b *bind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
|||||||
if port < 0 || port > 65535 {
|
if port < 0 || port > 65535 {
|
||||||
return nil, errors.New("invalid port " + sport)
|
return nil, errors.New("invalid port " + sport)
|
||||||
}
|
}
|
||||||
// up sets the connection's context right before it hands over the endpoint
|
ip, err := b.resolveFunc(host)
|
||||||
b.mu.Lock()
|
|
||||||
ctx := b.ctx
|
|
||||||
b.mu.Unlock()
|
|
||||||
ip, err := b.resolveFunc(ctx, host)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package wireguard
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -15,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -323,12 +323,12 @@ func (h *Handler) up(ctx context.Context) error {
|
|||||||
return h.dev.Up()
|
return h.dev.Up()
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig) func(ctx context.Context, host string) (net.IP, error) {
|
func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig) func(host string) (net.IP, error) {
|
||||||
return func(ctx context.Context, host string) (net.IP, error) {
|
return func(host string) (net.IP, error) {
|
||||||
if ip := net.ParseIP(host); ip != nil {
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
return ip, nil
|
return ip, nil
|
||||||
}
|
}
|
||||||
ips, err := lookupIPContext(ctx, d, host)
|
ips, _, err := d.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -364,28 +364,7 @@ func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig)
|
|||||||
return nil, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return got[rand.N(len(got))], nil
|
return got[dice.Roll(len(got))], nil
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupIPContext(ctx context.Context, d dns.Client, host string) ([]net.IP, error) {
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
type result struct {
|
|
||||||
ips []net.IP
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
done := make(chan result, 1)
|
|
||||||
go func() {
|
|
||||||
ips, _, err := d.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
|
||||||
done <- result{ips, err}
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case r := <-done:
|
|
||||||
return r.ips, r.err
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ func TestVlessRealityFingerprints(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A blocked connection must close after finalRules.delay even while the client keeps it open and sends nothing.
|
// A blocked connection must be closed after blockDelay even while the client keeps it open and sends nothing.
|
||||||
func TestVlessBlockDelay(t *testing.T) {
|
func TestVlessBlockDelay(t *testing.T) {
|
||||||
tcpServer := tcp.Server{
|
tcpServer := tcp.Server{
|
||||||
MsgProcessor: xor,
|
MsgProcessor: xor,
|
||||||
@@ -671,7 +671,7 @@ func TestVlessBlockDelay(t *testing.T) {
|
|||||||
defer tcpServer.Close()
|
defer tcpServer.Close()
|
||||||
|
|
||||||
for _, delay := range []uint64{0, 1} {
|
for _, delay := range []uint64{0, 1} {
|
||||||
t.Run(fmt.Sprint("delay=", delay), func(t *testing.T) {
|
t.Run(fmt.Sprint("blockDelay=", delay), func(t *testing.T) {
|
||||||
userID := protocol.NewID(uuid.New())
|
userID := protocol.NewID(uuid.New())
|
||||||
serverPort := tcp.PickPort()
|
serverPort := tcp.PickPort()
|
||||||
serverConfig := &core.Config{
|
serverConfig := &core.Config{
|
||||||
@@ -697,8 +697,8 @@ func TestVlessBlockDelay(t *testing.T) {
|
|||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
FinalRules: []*freedom.FinalRuleConfig{
|
FinalRules: []*freedom.FinalRuleConfig{
|
||||||
{
|
{
|
||||||
Action: freedom.RuleAction_Block,
|
Action: freedom.RuleAction_Block,
|
||||||
Delay: &freedom.Range{Min: delay, Max: delay},
|
BlockDelay: &freedom.Range{Min: delay, Max: delay},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -726,15 +726,15 @@ func TestVlessBlockDelay(t *testing.T) {
|
|||||||
Port: dest.Port,
|
Port: dest.Port,
|
||||||
}, &encoding.Addons{}))
|
}, &encoding.Addons{}))
|
||||||
|
|
||||||
blockDuration := time.Duration(delay) * time.Second
|
blockDelay := time.Duration(delay) * time.Second
|
||||||
common.Must(conn.SetReadDeadline(time.Now().Add(blockDuration + 5*time.Second)))
|
common.Must(conn.SetReadDeadline(time.Now().Add(blockDelay + 5*time.Second)))
|
||||||
_, err = io.Copy(io.Discard, conn)
|
_, err = io.Copy(io.Discard, conn)
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||||
t.Fatalf("connection is still open after %v", elapsed)
|
t.Fatalf("connection is still open after %v", elapsed)
|
||||||
}
|
}
|
||||||
if elapsed < blockDuration {
|
if elapsed < blockDelay {
|
||||||
t.Fatalf("connection is closed after %v, before finalRules.delay", elapsed)
|
t.Fatalf("connection is closed after %v, before blockDelay", elapsed)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package internet
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
@@ -260,7 +260,7 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else if sockopt.HappyEyeballs == nil || sockopt.HappyEyeballs.TryDelayMs == 0 || sockopt.HappyEyeballs.MaxConcurrentTry == 0 || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
} else if sockopt.HappyEyeballs == nil || sockopt.HappyEyeballs.TryDelayMs == 0 || sockopt.HappyEyeballs.MaxConcurrentTry == 0 || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
||||||
dest.Address = net.IPAddress(ips[rand.N(len(ips))])
|
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
||||||
} else {
|
} else {
|
||||||
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt, dest.Address.String())
|
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt, dest.Address.String())
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package header
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand/v2"
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dns struct {
|
type dns struct {
|
||||||
@@ -16,7 +17,7 @@ func (h *dns) Size() int {
|
|||||||
|
|
||||||
func (h *dns) Serialize(b []byte) {
|
func (h *dns) Serialize(b []byte) {
|
||||||
copy(b, h.header)
|
copy(b, h.header)
|
||||||
binary.BigEndian.PutUint16(b[0:], uint16(rand.Uint32()))
|
binary.BigEndian.PutUint16(b[0:], dice.RollUint16())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHeaderDNS(domain string) (*dns, error) {
|
func NewHeaderDNS(domain string) (*dns, error) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
goerrors "errors"
|
goerrors "errors"
|
||||||
"io"
|
"io"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
stdnet "net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -165,7 +164,7 @@ func (c *udpHopConn) recv(conn net.PacketConn) {
|
|||||||
n, addr, err := conn.ReadFrom(p)
|
n, addr, err := conn.ReadFrom(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pool.Put(p[:cap(p)])
|
pool.Put(p[:cap(p)])
|
||||||
if c.closed() || goerrors.Is(err, stdnet.ErrClosed) {
|
if c.closed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand/v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pickString(arr []string) string {
|
func pickString(arr []string) string {
|
||||||
@@ -13,7 +14,7 @@ func pickString(arr []string) string {
|
|||||||
case 1:
|
case 1:
|
||||||
return arr[0]
|
return arr[0]
|
||||||
default:
|
default:
|
||||||
return arr[rand.N(n)]
|
return arr[dice.Roll(n)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package kcp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"math/rand/v2"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
var globalConv = uint32(uint16(rand.Uint32()))
|
var globalConv = uint32(dice.RollUint16())
|
||||||
|
|
||||||
func fetchInput(_ context.Context, input io.Reader, reader PacketReader, conn *Connection) {
|
func fetchInput(_ context.Context, input io.Reader, reader PacketReader, conn *Connection) {
|
||||||
cache := make(chan *buf.Buffer, 1024)
|
cache := make(chan *buf.Buffer, 1024)
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand/v2"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
)
|
)
|
||||||
@@ -182,7 +182,7 @@ func jitter(backoff time.Duration) time.Duration {
|
|||||||
if half <= 0 {
|
if half <= 0 {
|
||||||
return backoff
|
return backoff
|
||||||
}
|
}
|
||||||
return half + rand.N(half)
|
return half + time.Duration(dice.RollInt63n(int64(half)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func rateLimited(payload []byte) bool {
|
func rateLimited(payload []byte) bool {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (s *localStorage) Get(ctx context.Context, name string) ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := readFile(ctx, full)
|
data, err := os.ReadFile(full)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, errNotFound
|
return nil, errNotFound
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
//go:build !windows
|
|
||||||
|
|
||||||
package xdrive
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func readFile(_ context.Context, name string) ([]byte, error) {
|
|
||||||
return os.ReadFile(name)
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package xdrive
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
// readFile retries os.ReadFile for up to 2 seconds on sharing violations:
|
|
||||||
// os.Rename (MoveFileEx) in Put holds the file with DELETE access, which
|
|
||||||
// os.ReadFile does not share, until a moment after its new name appears in List
|
|
||||||
func readFile(ctx context.Context, name string) ([]byte, error) {
|
|
||||||
deadline := time.Now().Add(2 * time.Second)
|
|
||||||
delay := time.Millisecond
|
|
||||||
for {
|
|
||||||
data, err := os.ReadFile(name)
|
|
||||||
if !errors.Is(err, windows.ERROR_SHARING_VIOLATION) || time.Now().Add(delay).After(deadline) {
|
|
||||||
return data, err
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, err
|
|
||||||
case <-time.After(delay):
|
|
||||||
}
|
|
||||||
delay = min(2*delay, 100*time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package xdrive
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLocalSharingViolation(t *testing.T) {
|
|
||||||
storage, err := newLocalStorage(t.TempDir())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("newLocalStorage: %v", err)
|
|
||||||
}
|
|
||||||
const name = "streams/session/c2s/000000000.seg"
|
|
||||||
if err := storage.Put(context.Background(), name, []byte("segment")); err != nil {
|
|
||||||
t.Fatalf("Put: %v", err)
|
|
||||||
}
|
|
||||||
full, err := storage.resolve(name)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("resolve: %v", err)
|
|
||||||
}
|
|
||||||
path, err := windows.UTF16PtrFromString(full)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("UTF16PtrFromString: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// os.Rename holds the file like this until a moment after its new name
|
|
||||||
// appears
|
|
||||||
handle, err := windows.CreateFile(path, windows.DELETE,
|
|
||||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
|
|
||||||
nil, windows.OPEN_EXISTING, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("CreateFile: %v", err)
|
|
||||||
}
|
|
||||||
var once sync.Once
|
|
||||||
release := func() { once.Do(func() { windows.CloseHandle(handle) }) }
|
|
||||||
defer release()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
|
||||||
defer cancel()
|
|
||||||
if _, err := storage.Get(ctx, name); !errors.Is(err, windows.ERROR_SHARING_VIOLATION) {
|
|
||||||
t.Fatalf("Get returned %v while the file is held, want a sharing violation", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.AfterFunc(100*time.Millisecond, release)
|
|
||||||
data, err := storage.Get(context.Background(), name)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Get: %v", err)
|
|
||||||
}
|
|
||||||
if string(data) != "segment" {
|
|
||||||
t.Fatalf("Get returned %q, want %q", data, "segment")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user