Freedom: Fast-path unconditional first block rule

This commit is contained in:
Codex
2026-11-12 13:13:01 +08:00
parent 646e2aff94
commit b608614611
2 changed files with 39 additions and 0 deletions
+6
View File
@@ -318,6 +318,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
ob.Name = "freedom"
ob.CanSpliceCopy = 1
if !h.usesDialerProxy && len(h.firewall) > 0 {
rule := h.firewall[0]
if rule.action == RuleAction_Block && rule.network == allNetworks && len(rule.port) == 0 && rule.ip == nil {
return h.blackhole(ctx, link.Reader, link.Writer, rule, &ob.Target)
}
}
inbound := session.InboundFromContext(ctx)
var defaultRule *Firewall
if !h.usesDialerProxy { // freedom is not the final outbound, firewall does not apply (and the domain is not resolved)
+33
View File
@@ -9,8 +9,41 @@ import (
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/transport"
)
func TestUnconditionalBlockFastPath(t *testing.T) {
for _, network := range []net.Network{net.Network_TCP, net.Network_UDP} {
t.Run(network.String(), func(t *testing.T) {
const reply = "blocked"
h := new(Handler)
if err := h.Init(&Config{Firewall: []*FirewallConfig{{
Action: RuleAction_Block,
Delay: &Range{},
Reply: &Reply{Type: "custom", CustomResponseData: []byte(reply)},
}}}, nil); err != nil {
t.Fatal(err)
}
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
Target: net.Destination{Network: network, Address: net.DomainAddress("blocked.invalid"), Port: 443},
}})
var output bytes.Buffer
link := &transport.Link{
Reader: buf.NewReader(bytes.NewReader(nil)),
Writer: &buf.BufferToBytesWriter{Writer: &output},
}
// An unconditional block must finish without touching the dialer or resolving the domain.
if err := h.Process(ctx, link, nil); err != nil {
t.Fatal(err)
}
if output.String() != reply {
t.Fatalf("reply = %q, want %q", output.String(), reply)
}
})
}
}
func TestFirewallReply(t *testing.T) {
custom := bytes.Repeat([]byte("custom response"), buf.Size)
for _, test := range []struct {