mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-29 14:37:05 +00:00
add responder
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/proxy/responder"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type ResponderConfig struct {
|
||||
Type string `json:"type"`
|
||||
Response string `json:"response"`
|
||||
}
|
||||
|
||||
func (c *ResponderConfig) Build() (proto.Message, error) {
|
||||
config := new(responder.Config)
|
||||
switch strings.ToLower(c.Type) {
|
||||
case "http":
|
||||
response := http.Response{
|
||||
StatusCode: 403,
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Header: http.Header{
|
||||
"Connection": {"close"},
|
||||
"Cache-Control": {"max-age=3600, public"},
|
||||
},
|
||||
}
|
||||
var data bytes.Buffer
|
||||
common.Must(response.Write(&data))
|
||||
config.Response = data.Bytes()
|
||||
case "custom":
|
||||
data, err := base64.StdEncoding.DecodeString(c.Response)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to decode response").Base(err)
|
||||
}
|
||||
config.Response = data
|
||||
default:
|
||||
return nil, errors.New("unknown responder response type: ", c.Type)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package conf_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/core"
|
||||
. "github.com/xtls/xray-core/infra/conf"
|
||||
"github.com/xtls/xray-core/proxy/responder"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestResponderConfig(t *testing.T) {
|
||||
parser := loadJSON(func() Buildable { return new(ResponderConfig) })
|
||||
httpResponse := []byte("HTTP/1.1 403 Forbidden\r\n" +
|
||||
"Cache-Control: max-age=3600, public\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: 0\r\n\r\n")
|
||||
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{Input: `{"type":"http"}`, Parser: parser, Output: &responder.Config{Response: httpResponse}},
|
||||
{Input: `{"type":"HtTp"}`, Parser: parser, Output: &responder.Config{Response: httpResponse}},
|
||||
{Input: `{"type":"custom","response":"aGVsbG8="}`, Parser: parser, Output: &responder.Config{Response: []byte("hello")}},
|
||||
{Input: `{"type":"CuStOm","response":"aGVsbG8="}`, Parser: parser, Output: &responder.Config{Response: []byte("hello")}},
|
||||
{Input: `{"type":"custom","response":"AP+A"}`, Parser: parser, Output: &responder.Config{Response: []byte{0, 255, 128}}},
|
||||
{Input: `{"type":"custom","response":""}`, Parser: parser, Output: &responder.Config{}},
|
||||
{Input: `{"type":"custom"}`, Parser: parser, Output: &responder.Config{}},
|
||||
{
|
||||
Input: `{
|
||||
"protocol": "ReSpOnDeR",
|
||||
"tag": "reply",
|
||||
"settings": {"type": "custom", "response": "aGVsbG8="}
|
||||
}`,
|
||||
Parser: func(s string) (proto.Message, error) {
|
||||
var config OutboundDetourConfig
|
||||
if err := json.Unmarshal([]byte(s), &config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config.Build()
|
||||
},
|
||||
Output: &core.OutboundHandlerConfig{
|
||||
Tag: "reply",
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{}),
|
||||
ProxySettings: serial.ToTypedMessage(&responder.Config{Response: []byte("hello")}),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestResponderConfigErrors(t *testing.T) {
|
||||
parser := loadJSON(func() Buildable { return new(ResponderConfig) })
|
||||
for _, input := range []string{
|
||||
`{}`,
|
||||
`{"type":""}`,
|
||||
`{"type":"unknown"}`,
|
||||
`{"type":"none"}`,
|
||||
`{"type":"custom","response":"!"}`,
|
||||
} {
|
||||
if _, err := parser(input); err == nil {
|
||||
t.Fatalf("expected error for %s", input)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ var (
|
||||
"block": func() interface{} { return new(BlackholeConfig) },
|
||||
"blackhole": func() interface{} { return new(BlackholeConfig) },
|
||||
"loopback": func() interface{} { return new(LoopbackConfig) },
|
||||
"responder": func() interface{} { return new(ResponderConfig) },
|
||||
"direct": func() interface{} { return new(FreedomConfig) },
|
||||
"freedom": func() interface{} { return new(FreedomConfig) },
|
||||
"http": func() interface{} { return new(HTTPClientConfig) },
|
||||
|
||||
Reference in New Issue
Block a user