mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-29 06:31:56 +00:00
Direct/Freedom outbound: Fix blockDelay for DispatchLink() inbounds such as VLESS, Hysteria, etc. (#7238)
https://github.com/XTLS/Xray-core/pull/7238#pullrequestreview-5627787937 https://github.com/XTLS/Xray-core/pull/7238#issuecomment-6467092152 https://github.com/XTLS/Xray-core/pull/6060#issuecomment-4384511163
This commit is contained in:
1 parent
3071fbfa25
commit
229799a7a3
2 files changed
+92
-5
No files matched your search
@@ -229,14 +229,19 @@ func (h *Handler) blockDelay(rule *FinalRule) time.Duration {
|
|||||||
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 := h.blockDelay(rule)
|
delay := h.blockDelay(rule)
|
||||||
errors.LogInfo(ctx, "blocked target: ", *dest, ", blackholing connection for ", delay)
|
errors.LogInfo(ctx, "blocked target: ", *dest, ", blackholing connection for ", delay)
|
||||||
timer := time.AfterFunc(delay, func() {
|
defer common.Close(output)
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() { // a DispatchLink inbound's reader ignores Interrupt, so don't wait for this copy
|
||||||
|
_ = buf.Copy(input, buf.Discard)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(delay):
|
||||||
common.Interrupt(input)
|
common.Interrupt(input)
|
||||||
common.Interrupt(output)
|
common.Interrupt(output)
|
||||||
errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *dest)
|
errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *dest)
|
||||||
})
|
}
|
||||||
defer timer.Stop()
|
|
||||||
defer common.Close(output)
|
|
||||||
_ = buf.Copy(input, buf.Discard)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package scenarios
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -20,6 +22,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy/dokodemo"
|
"github.com/xtls/xray-core/proxy/dokodemo"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"github.com/xtls/xray-core/proxy/vless"
|
"github.com/xtls/xray-core/proxy/vless"
|
||||||
|
"github.com/xtls/xray-core/proxy/vless/encoding"
|
||||||
"github.com/xtls/xray-core/proxy/vless/inbound"
|
"github.com/xtls/xray-core/proxy/vless/inbound"
|
||||||
"github.com/xtls/xray-core/proxy/vless/outbound"
|
"github.com/xtls/xray-core/proxy/vless/outbound"
|
||||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
@@ -657,3 +660,82 @@ func TestVlessRealityFingerprints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A blocked connection must be closed after blockDelay even while the client keeps it open and sends nothing.
|
||||||
|
func TestVlessBlockDelay(t *testing.T) {
|
||||||
|
tcpServer := tcp.Server{
|
||||||
|
MsgProcessor: xor,
|
||||||
|
}
|
||||||
|
dest, err := tcpServer.Start()
|
||||||
|
common.Must(err)
|
||||||
|
defer tcpServer.Close()
|
||||||
|
|
||||||
|
for _, delay := range []uint64{0, 1} {
|
||||||
|
t.Run(fmt.Sprint("blockDelay=", delay), func(t *testing.T) {
|
||||||
|
userID := protocol.NewID(uuid.New())
|
||||||
|
serverPort := tcp.PickPort()
|
||||||
|
serverConfig := &core.Config{
|
||||||
|
Inbound: []*core.InboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||||
|
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
||||||
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
}),
|
||||||
|
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
||||||
|
Users: []*protocol.User{
|
||||||
|
{
|
||||||
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
|
Id: userID.String(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{
|
||||||
|
{
|
||||||
|
Action: freedom.RuleAction_Block,
|
||||||
|
BlockDelay: &freedom.Range{Min: delay, Max: delay},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
servers, err := InitializeServerConfigs(serverConfig)
|
||||||
|
common.Must(err)
|
||||||
|
defer CloseAllServers(servers)
|
||||||
|
|
||||||
|
conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
|
||||||
|
IP: []byte{127, 0, 0, 1},
|
||||||
|
Port: int(serverPort),
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
common.Must(encoding.EncodeRequestHeader(conn, &protocol.RequestHeader{
|
||||||
|
Version: encoding.Version,
|
||||||
|
User: &protocol.MemoryUser{Account: &vless.MemoryAccount{ID: userID}},
|
||||||
|
Command: protocol.RequestCommandTCP,
|
||||||
|
Address: dest.Address,
|
||||||
|
Port: dest.Port,
|
||||||
|
}, &encoding.Addons{}))
|
||||||
|
|
||||||
|
blockDelay := time.Duration(delay) * time.Second
|
||||||
|
common.Must(conn.SetReadDeadline(time.Now().Add(blockDelay + 5*time.Second)))
|
||||||
|
_, err = io.Copy(io.Discard, conn)
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||||
|
t.Fatalf("connection is still open after %v", elapsed)
|
||||||
|
}
|
||||||
|
if elapsed < blockDelay {
|
||||||
|
t.Fatalf("connection is closed after %v, before blockDelay", elapsed)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user