diff --git a/app/router/script_test.go b/app/router/script_test.go index 599ebbf7d..d85deb145 100644 --- a/app/router/script_test.go +++ b/app/router/script_test.go @@ -24,7 +24,6 @@ import ( "github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/routing" routing_session "github.com/xtls/xray-core/features/routing/session" - "github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/freedom" ) @@ -397,7 +396,7 @@ end`) serial.ToTypedMessage(&proxyman.OutboundConfig{}), }, Outbound: []*core.OutboundHandlerConfig{ - {Tag: "default", ProxySettings: serial.ToTypedMessage(&blackhole.Config{})}, + {Tag: "default", ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}})}, {Tag: "direct", ProxySettings: serial.ToTypedMessage(&freedom.Config{ FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}}, })}, diff --git a/infra/conf/blackhole.go b/infra/conf/blackhole.go index 7046d1efe..3549f63f4 100644 --- a/infra/conf/blackhole.go +++ b/infra/conf/blackhole.go @@ -1,11 +1,10 @@ package conf import ( - "encoding/base64" "strings" "github.com/xtls/xray-core/common/errors" - "github.com/xtls/xray-core/proxy/blackhole" + "github.com/xtls/xray-core/proxy/freedom" "google.golang.org/protobuf/proto" ) @@ -19,24 +18,14 @@ type BlackholeConfig struct { } func (v *BlackholeConfig) Build() (proto.Message, error) { - config := new(blackhole.Config) if v.Response != nil { - responseName := strings.ToLower(v.Response.Type) - switch responseName { + switch strings.ToLower(v.Response.Type) { case "none", "": - config.Response = &blackhole.Response{Type: "none"} - case "http": - config.Response = &blackhole.Response{Type: "http"} - case "custom": - data, err := base64.StdEncoding.DecodeString(v.Response.CustomResponseData) - if err != nil { - return nil, errors.New("failed to decode custom response data: " + err.Error()) - } - config.Response = &blackhole.Response{Type: "custom", CustomResponseData: data} default: - return nil, errors.New("unknown blackhole response: " + responseName) + errors.PrintDeprecatedFeatureWarning(`"blackhole" outbound response`, `the "responder" outbound`) + return (&ResponderConfig{Type: v.Response.Type, Response: v.Response.CustomResponseData}).Build() } } - return config, nil + return &freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}, nil } diff --git a/infra/conf/blackhole_test.go b/infra/conf/blackhole_test.go deleted file mode 100644 index 83e9b1f22..000000000 --- a/infra/conf/blackhole_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package conf_test - -import ( - "testing" - - . "github.com/xtls/xray-core/infra/conf" - "github.com/xtls/xray-core/proxy/blackhole" -) - -func TestHTTPResponseJSON(t *testing.T) { - creator := func() Buildable { - return new(BlackholeConfig) - } - - runMultiTestCase(t, []TestCase{ - { - Input: `{ - "response": { - "type": "http" - } - }`, - Parser: loadJSON(creator), - Output: &blackhole.Config{ - Response: &blackhole.Response{Type: "http"}, - }, - }, - { - Input: `{}`, - Parser: loadJSON(creator), - Output: &blackhole.Config{}, - }, - }) -} - -func TestCustomResponseJSON(t *testing.T) { - creator := func() Buildable { - return new(BlackholeConfig) - } - - runMultiTestCase(t, []TestCase{ - { - Input: `{ - "response": { - "type": "custom", - "customResponseData": "Y3VzdG9tIHJlc3BvbnNl" - } - }`, - Parser: loadJSON(creator), - Output: &blackhole.Config{ - Response: &blackhole.Response{ - Type: "custom", - CustomResponseData: []byte("custom response"), - }, - }, - }, - }) -} diff --git a/main/distro/all/all.go b/main/distro/all/all.go index abe4166b4..8e39e0a59 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -35,7 +35,6 @@ import ( _ "github.com/xtls/xray-core/app/observatory" // Inbound and outbound proxies. - _ "github.com/xtls/xray-core/proxy/blackhole" _ "github.com/xtls/xray-core/proxy/dns" _ "github.com/xtls/xray-core/proxy/dokodemo" _ "github.com/xtls/xray-core/proxy/freedom" diff --git a/proxy/blackhole/blackhole.go b/proxy/blackhole/blackhole.go deleted file mode 100644 index ee0ee7b08..000000000 --- a/proxy/blackhole/blackhole.go +++ /dev/null @@ -1,88 +0,0 @@ -// Package blackhole is an outbound handler that blocks all connections. -package blackhole - -import ( - "bytes" - "context" - "net/http" - "time" - - "github.com/xtls/xray-core/common" - "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/net" - "github.com/xtls/xray-core/common/session" - "github.com/xtls/xray-core/common/signal" - "github.com/xtls/xray-core/transport" - "github.com/xtls/xray-core/transport/internet" -) - -// Handler is an outbound connection that silently swallow the entire payload. -type Handler struct { - response []byte -} - -var http403response = http.Response{ - StatusCode: 403, - ProtoMajor: 1, - ProtoMinor: 1, - Header: http.Header{ - "Connection": {"close"}, - "Cache-Control": {"max-age=3600, public"}, - }, -} - -// New creates a new blackhole handler. -func New(ctx context.Context, config *Config) (*Handler, error) { - response := []byte{} - if config.Response != nil { - switch config.Response.Type { - case "", "none": - case "http": - var data bytes.Buffer - common.Must(http403response.Write(&data)) - response = data.Bytes() - case "custom": - response = config.Response.CustomResponseData - default: - return nil, errors.New("unknown blackhole response: " + config.Response.Type) - } - } - return &Handler{ - response: response, - }, nil -} - -// Process implements OutboundHandler.Dispatch(). -func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error { - outbounds := session.OutboundsFromContext(ctx) - ob := outbounds[len(outbounds)-1] - ob.Name = "blackhole" - - if len(h.response) > 0 { - mbc := buf.MultiBufferContainer{} - common.Must2(mbc.Write(h.response)) - link.Writer.WriteMultiBuffer(mbc.MultiBuffer) - // Sleep a little here to make sure the response is sent to client. - time.Sleep(time.Second) - } - defer common.Interrupt(link.Writer) - defer common.Interrupt(link.Reader) - // wait to drain all the possible incoming UDP data - if ob.Target.Network == net.Network_UDP { - ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, func() { - cancel() - }, time.Duration(30+dice.Roll(61))*time.Second) - go buf.Copy(link.Reader, buf.Discard, buf.UpdateActivity(timer)) - <-ctx.Done() - } - return nil -} - -func init() { - common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { - return New(ctx, config.(*Config)) - })) -} diff --git a/proxy/blackhole/blackhole_test.go b/proxy/blackhole/blackhole_test.go deleted file mode 100644 index ac1822757..000000000 --- a/proxy/blackhole/blackhole_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package blackhole_test - -import ( - "bufio" - "bytes" - "context" - "crypto/rand" - "net/http" - "testing" - - "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/common/buf" - "github.com/xtls/xray-core/common/session" - "github.com/xtls/xray-core/proxy/blackhole" - "github.com/xtls/xray-core/transport" - "github.com/xtls/xray-core/transport/pipe" -) - -func TestBlackholeHTTPResponse(t *testing.T) { - ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{}}) - handler, err := blackhole.New(ctx, &blackhole.Config{ - Response: &blackhole.Response{Type: "http"}, - }) - common.Must(err) - - reader, writer := pipe.New(pipe.WithoutSizeLimit()) - - dataCh := make(chan buf.MultiBuffer, 1) - go func() { - mb := common.Must2(reader.ReadMultiBuffer()) - dataCh <- mb - }() - link := transport.Link{ - Reader: reader, - Writer: writer, - } - common.Must(handler.Process(ctx, &link, nil)) - mb := <-dataCh - data := make([]byte, mb.Len()) - mb.Copy(data) - resp := common.Must2(http.ReadResponse(bufio.NewReader(bytes.NewBuffer(data)), nil)) - if resp.StatusCode != 403 { - t.Errorf("expected 403 response, got %d", resp.StatusCode) - } -} - -func TestBlackholeCustomResponse(t *testing.T) { - ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{}}) - // slightly bigger than a buffer - expected := make([]byte, buf.Size+1000) - if _, err := rand.Read(expected); err != nil { - t.Fatal(err) - } - handler, err := blackhole.New(ctx, &blackhole.Config{ - Response: &blackhole.Response{ - Type: "custom", - CustomResponseData: expected, - }, - }) - common.Must(err) - - reader, writer := pipe.New(pipe.WithoutSizeLimit()) - var actual buf.MultiBuffer - var rerr error - go func() { - actual, rerr = reader.ReadMultiBuffer() - }() - - link := transport.Link{Reader: reader, Writer: writer} - common.Must(handler.Process(ctx, &link, nil)) - common.Must(rerr) - - if actual.String() != string(expected) { - t.Errorf("custom response mismatch") - } -} diff --git a/proxy/blackhole/config.pb.go b/proxy/blackhole/config.pb.go deleted file mode 100644 index ca1f1c923..000000000 --- a/proxy/blackhole/config.pb.go +++ /dev/null @@ -1,180 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc v6.33.5 -// source: proxy/blackhole/config.proto - -package blackhole - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Response struct { - state protoimpl.MessageState `protogen:"open.v1"` - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - CustomResponseData []byte `protobuf:"bytes,2,opt,name=custom_response_data,json=customResponseData,proto3" json:"custom_response_data,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Response) Reset() { - *x = Response{} - mi := &file_proxy_blackhole_config_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Response) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Response) ProtoMessage() {} - -func (x *Response) ProtoReflect() protoreflect.Message { - mi := &file_proxy_blackhole_config_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Response.ProtoReflect.Descriptor instead. -func (*Response) Descriptor() ([]byte, []int) { - return file_proxy_blackhole_config_proto_rawDescGZIP(), []int{0} -} - -func (x *Response) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *Response) GetCustomResponseData() []byte { - if x != nil { - return x.CustomResponseData - } - return nil -} - -type Config struct { - state protoimpl.MessageState `protogen:"open.v1"` - Response *Response `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Config) Reset() { - *x = Config{} - mi := &file_proxy_blackhole_config_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Config) ProtoMessage() {} - -func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_proxy_blackhole_config_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Config.ProtoReflect.Descriptor instead. -func (*Config) Descriptor() ([]byte, []int) { - return file_proxy_blackhole_config_proto_rawDescGZIP(), []int{1} -} - -func (x *Config) GetResponse() *Response { - if x != nil { - return x.Response - } - return nil -} - -var File_proxy_blackhole_config_proto protoreflect.FileDescriptor - -const file_proxy_blackhole_config_proto_rawDesc = "" + - "\n" + - "\x1cproxy/blackhole/config.proto\x12\x14xray.proxy.blackhole\"P\n" + - "\bResponse\x12\x12\n" + - "\x04type\x18\x01 \x01(\tR\x04type\x120\n" + - "\x14custom_response_data\x18\x02 \x01(\fR\x12customResponseData\"D\n" + - "\x06Config\x12:\n" + - "\bresponse\x18\x01 \x01(\v2\x1e.xray.proxy.blackhole.ResponseR\bresponseB^\n" + - "\x18com.xray.proxy.blackholeP\x01Z)github.com/xtls/xray-core/proxy/blackhole\xaa\x02\x14Xray.Proxy.Blackholeb\x06proto3" - -var ( - file_proxy_blackhole_config_proto_rawDescOnce sync.Once - file_proxy_blackhole_config_proto_rawDescData []byte -) - -func file_proxy_blackhole_config_proto_rawDescGZIP() []byte { - file_proxy_blackhole_config_proto_rawDescOnce.Do(func() { - file_proxy_blackhole_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proxy_blackhole_config_proto_rawDesc), len(file_proxy_blackhole_config_proto_rawDesc))) - }) - return file_proxy_blackhole_config_proto_rawDescData -} - -var file_proxy_blackhole_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_proxy_blackhole_config_proto_goTypes = []any{ - (*Response)(nil), // 0: xray.proxy.blackhole.Response - (*Config)(nil), // 1: xray.proxy.blackhole.Config -} -var file_proxy_blackhole_config_proto_depIdxs = []int32{ - 0, // 0: xray.proxy.blackhole.Config.response:type_name -> xray.proxy.blackhole.Response - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_proxy_blackhole_config_proto_init() } -func file_proxy_blackhole_config_proto_init() { - if File_proxy_blackhole_config_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_proxy_blackhole_config_proto_rawDesc), len(file_proxy_blackhole_config_proto_rawDesc)), - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proxy_blackhole_config_proto_goTypes, - DependencyIndexes: file_proxy_blackhole_config_proto_depIdxs, - MessageInfos: file_proxy_blackhole_config_proto_msgTypes, - }.Build() - File_proxy_blackhole_config_proto = out.File - file_proxy_blackhole_config_proto_goTypes = nil - file_proxy_blackhole_config_proto_depIdxs = nil -} diff --git a/proxy/blackhole/config.proto b/proxy/blackhole/config.proto deleted file mode 100644 index 93b4d8e7b..000000000 --- a/proxy/blackhole/config.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; - -package xray.proxy.blackhole; -option csharp_namespace = "Xray.Proxy.Blackhole"; -option go_package = "github.com/xtls/xray-core/proxy/blackhole"; -option java_package = "com.xray.proxy.blackhole"; -option java_multiple_files = true; - -message Response { - string type = 1; - bytes custom_response_data = 2; -} - -message Config { - Response response = 1; -} diff --git a/proxy/blackhole/config_test.go b/proxy/blackhole/config_test.go deleted file mode 100644 index f54cb0154..000000000 --- a/proxy/blackhole/config_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package blackhole_test - -import ( - "context" - "testing" - - "github.com/xtls/xray-core/common" - "github.com/xtls/xray-core/proxy/blackhole" -) - -func TestHTTPResponse(t *testing.T) { - handler, err := blackhole.New(context.Background(), &blackhole.Config{ - Response: &blackhole.Response{Type: "http"}, - }) - common.Must(err) - if handler == nil { - t.Error("expected HTTP response handler") - } -} diff --git a/proxy/tun/tun_linux_dns_route_test.go b/proxy/tun/tun_linux_dns_route_test.go index 120ef7e10..89607b242 100644 --- a/proxy/tun/tun_linux_dns_route_test.go +++ b/proxy/tun/tun_linux_dns_route_test.go @@ -17,7 +17,6 @@ import ( "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy/blackhole" proxydns "github.com/xtls/xray-core/proxy/dns" "github.com/xtls/xray-core/proxy/freedom" ) @@ -73,7 +72,7 @@ func newRouteTestContext(t *testing.T, withDNSApp bool, nameServers []*appdns.Na Outbound: []*core.OutboundHandlerConfig{ {Tag: "direct", ProxySettings: serial.ToTypedMessage(&freedom.Config{})}, {Tag: "dns", ProxySettings: serial.ToTypedMessage(&proxydns.Config{})}, - {Tag: "block", ProxySettings: serial.ToTypedMessage(&blackhole.Config{})}, + {Tag: "block", ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}})}, }, }) if err != nil { diff --git a/testing/scenarios/dns_test.go b/testing/scenarios/dns_test.go index a38f1b200..b65182852 100644 --- a/testing/scenarios/dns_test.go +++ b/testing/scenarios/dns_test.go @@ -13,7 +13,6 @@ import ( "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/socks" "github.com/xtls/xray-core/testing/servers/tcp" @@ -78,7 +77,7 @@ func TestResolveIP(t *testing.T) { }, Outbound: []*core.OutboundHandlerConfig{ { - ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), + ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}), }, { Tag: "direct", diff --git a/testing/scenarios/feature_test.go b/testing/scenarios/feature_test.go index fa1ff3564..f7bc94aef 100644 --- a/testing/scenarios/feature_test.go +++ b/testing/scenarios/feature_test.go @@ -21,7 +21,6 @@ import ( "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/uuid" core "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/dokodemo" "github.com/xtls/xray-core/proxy/freedom" v2http "github.com/xtls/xray-core/proxy/http" @@ -406,7 +405,7 @@ func TestBlackhole(t *testing.T) { }, { Tag: "blocked", - ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), + ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}), }, }, App: []*serial.TypedMessage{ diff --git a/testing/scenarios/reverse_test.go b/testing/scenarios/reverse_test.go index 155386944..dea238b53 100644 --- a/testing/scenarios/reverse_test.go +++ b/testing/scenarios/reverse_test.go @@ -17,7 +17,6 @@ import ( "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/uuid" core "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/dokodemo" "github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/vmess" @@ -100,7 +99,7 @@ func TestReverseProxy(t *testing.T) { }, Outbound: []*core.OutboundHandlerConfig{ { - ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), + ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}), }, }, } @@ -275,7 +274,7 @@ func TestReverseProxyLongRunning(t *testing.T) { }, Outbound: []*core.OutboundHandlerConfig{ { - ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), + ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}), }, }, } diff --git a/testing/scenarios/socks_test.go b/testing/scenarios/socks_test.go index e4682b80e..9245d2a49 100644 --- a/testing/scenarios/socks_test.go +++ b/testing/scenarios/socks_test.go @@ -11,7 +11,6 @@ import ( "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/core" - "github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/dokodemo" "github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/http" @@ -331,7 +330,7 @@ func TestSocksBridageUDPWithRouting(t *testing.T) { }, Outbound: []*core.OutboundHandlerConfig{ { - ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), + ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Block}}}), }, { Tag: "out",