Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DetailsMap() to protocol interface #20

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions xray/protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package xray

import (
"errors"
"github.com/xtls/xray-core/infra/conf"
"fmt"
"strings"

"github.com/fatih/color"
"github.com/xtls/xray-core/infra/conf"
)

const (
Expand All @@ -20,9 +23,28 @@ type Protocol interface {
BuildOutboundDetourConfig(allowInsecure bool) (*conf.OutboundDetourConfig, error)
BuildInboundDetourConfig() (*conf.InboundDetourConfig, error)
DetailsStr() string
DetailsMap() map[string]string
ConvertToGeneralConfig() GeneralConfig
}

func detailsToStr(details [][2]string) string {
result := ""
for _, d := range details {
result += fmt.Sprintf("%s: %s\n", color.RedString(d[0]), d[1])
}

return result
}

func detailsToMap(details [][2]string) map[string]string {
result := make(map[string]string, len(details))
for _, d := range details {
result[d[0]] = d[1]
}

return result
}

func CreateProtocol(configLink string) (Protocol, error) {
switch {
case strings.HasPrefix(configLink, vmessIdentifier):
Expand Down Expand Up @@ -82,10 +104,10 @@ type Vmess struct {
TlsFingerprint string `json:"fp"` // TLS fingerprint
Type string `json:"type"` // Used for HTTP Obfuscation

//// It's also possible for Vmess to have REALITY...
//PublicKey string `json:"pbk"`
//ShortIds string `json:"sid"` // Mandatory, the shortId list available to the client, which can be used to distinguish different clients
//SpiderX string `json:"spx"` // Reality path
// // It's also possible for Vmess to have REALITY...
// PublicKey string `json:"pbk"`
// ShortIds string `json:"sid"` // Mandatory, the shortId list available to the client, which can be used to distinguish different clients
// SpiderX string `json:"spx"` // Reality path

OrigLink string `json:"-"` // Original link
}
Expand Down
52 changes: 30 additions & 22 deletions xray/shadowsocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"net/url"
"strings"

"github.com/fatih/color"
"github.com/lilendian0x00/xray-knife/v2/utils"
"github.com/xtls/xray-core/infra/conf"

"github.com/lilendian0x00/xray-knife/v2/utils"
)

func NewShadowsocks() Protocol {
Expand Down Expand Up @@ -44,11 +44,11 @@ func (s *Shadowsocks) Parse(configLink string) error {
return errors.New("invalid config link")
}

//link := "ss://" + string(decoded) + "@" + secondPart[1]
//uri, err := url.Parse(link)
//if err != nil {
// link := "ss://" + string(decoded) + "@" + secondPart[1]
// uri, err := url.Parse(link)
// if err != nil {
// return err
//}
// }
creds := strings.SplitN(string(decoded), ":", 2)
if len(creds) != 2 {
return errors.New("error when decoding secret part")
Expand All @@ -57,7 +57,7 @@ func (s *Shadowsocks) Parse(configLink string) error {
s.Encryption = creds[0] // Encryption Type
s.Password = creds[1] // Encryption Password

//hostPortRemark := strings.SplitN(secondPart[1], ":", 2)
// hostPortRemark := strings.SplitN(secondPart[1], ":", 2)

s.Address, s.Port, err = net.SplitHostPort(uri.Host)
if err != nil {
Expand All @@ -73,31 +73,39 @@ func (s *Shadowsocks) Parse(configLink string) error {
s.Remark = uri.Fragment
}

//s.Address = hostPortRemark[0]
// s.Address = hostPortRemark[0]
//
//PortRemark := strings.SplitN(hostPortRemark[1], "#", 2)
//s.Port = PortRemark[0]
// PortRemark := strings.SplitN(hostPortRemark[1], "#", 2)
// s.Port = PortRemark[0]

//remarkStr, _, _ := strings.Cut(PortRemark[1], "\n")
// remarkStr, _, _ := strings.Cut(PortRemark[1], "\n")

//s.Remark, err = url.PathUnescape(remarkStr)
//if err != nil {
// s.Remark, err = url.PathUnescape(remarkStr)
// if err != nil {
// s.Remark = remarkStr
//}
// }
s.OrigLink = configLink

return nil
}

func (s *Shadowsocks) DetailsStr() string {
info := fmt.Sprintf("%s: %s\n%s: %s\n%s: %s\n%s: %v\n%s: %s\n%s: %s\n",
color.RedString("Protocol"), s.Name(),
color.RedString("Remark"), s.Remark,
color.RedString("IP"), s.Address,
color.RedString("Port"), s.Port,
color.RedString("Encryption"), s.Encryption,
color.RedString("Password"), s.Password)
return info
return detailsToStr(s.details())
}

func (s *Shadowsocks) DetailsMap() map[string]string {
return detailsToMap(s.details())
}

func (s *Shadowsocks) details() [][2]string {
return [][2]string{
{"Protocol", s.Name()},
{"Remark", s.Remark},
{"IP", s.Address},
{"Port", s.Port},
{"Encryption", s.Encryption},
{"Password", s.Password},
}
}

func (s *Shadowsocks) ConvertToGeneralConfig() GeneralConfig {
Expand Down
30 changes: 29 additions & 1 deletion xray/shadowsocks_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
package xray

import "testing"
import (
"reflect"
"testing"
)

func TestShadowSocks_Parse(t *testing.T) {
var ss Shadowsocks
err := ss.Parse("ss://[email protected]:443#exa")
if err != nil {
t.Errorf("Error when parsing: %v", err)
}

expected := `Protocol: shadowsocks
Remark: exa
IP: example.com
Port: 443
Encryption: aes-256-gcm
Password: Example@1234
`

t.Logf("%s\n", ss.DetailsStr())
if expected != ss.DetailsStr() {
t.Fatalf("expected %q, got %q", expected, ss.DetailsStr())
}

expectedMap := map[string]string{
"Protocol": "shadowsocks",
"Remark": "exa",
"IP": "example.com",
"Port": "443",
"Encryption": "aes-256-gcm",
"Password": "Example@1234",
}

if !reflect.DeepEqual(expectedMap, ss.DetailsMap()) {
t.Fatalf("expected %v, got %v", expectedMap, ss.DetailsMap())
}
}
36 changes: 22 additions & 14 deletions xray/socks.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"strconv"
"strings"

"github.com/fatih/color"
"github.com/lilendian0x00/xray-knife/v2/utils"
net2 "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf"

"github.com/lilendian0x00/xray-knife/v2/utils"
)

func NewSocks() Protocol {
Expand Down Expand Up @@ -53,23 +53,31 @@ func (s *Socks) Parse(configLink string) error {
}

func (s *Socks) DetailsStr() string {
copyV := *s
return detailsToStr(s.details())
}

info := fmt.Sprintf("%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %v\n",
color.RedString("Protocol"), s.Name(),
color.RedString("Remark"), copyV.Remark,
color.RedString("Network"), "tcp",
color.RedString("Address"), copyV.Address,
color.RedString("Port"), copyV.Port,
)
func (s *Socks) DetailsMap() map[string]string {
return detailsToMap(s.details())
}

func (s *Socks) details() [][2]string {
copyV := *s
result := [][2]string{
{"Protocol", s.Name()},
{"Remark", copyV.Remark},
{"Network", "tcp"},
{"Address", copyV.Address},
{"Port", copyV.Port},
}

if len(copyV.Username) != 0 && len(copyV.Password) != 0 {
info += color.RedString("Username") + ": " + copyV.Username
info += "\n"
info += color.RedString("Password") + ": " + copyV.Password
result = append(result, [][2]string{
{"Username", copyV.Username},
{"Password", copyV.Password},
}...)
}

return info
return result
}

func (s *Socks) ConvertToGeneralConfig() GeneralConfig {
Expand Down
109 changes: 62 additions & 47 deletions xray/trojan.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package xray
import (
"encoding/json"
"fmt"
"github.com/fatih/color"
"github.com/lilendian0x00/xray-knife/v2/utils"
"github.com/xtls/xray-core/infra/conf"
"net"
"net/url"
"reflect"
"slices"
"strings"

"github.com/xtls/xray-core/infra/conf"

"github.com/lilendian0x00/xray-knife/v2/utils"
)

func NewTrojan() Protocol {
Expand Down Expand Up @@ -91,72 +93,85 @@ func (t *Trojan) Parse(configLink string) error {
}

func (t *Trojan) DetailsStr() string {
return detailsToStr(t.details())
}

func (t *Trojan) DetailsMap() map[string]string {
return detailsToMap(t.details())
}

func (t *Trojan) details() [][2]string {
copyV := *t
if copyV.Flow == "" || copyV.Type == "grpc" {
copyV.Flow = "none"
}
info := fmt.Sprintf("%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %v\n%s: %s\n%s: %s\n",
color.RedString("Protocol"), t.Name(),
color.RedString("Remark"), t.Remark,
color.RedString("Network"), t.Type,
color.RedString("Address"), t.Address,
color.RedString("Port"), t.Port,
color.RedString("Password"), t.Password,
color.RedString("Flow"), copyV.Flow,
)

if copyV.Type == "" {

} else if copyV.Type == "http" || copyV.Type == "httpupgrade" || copyV.Type == "ws" || copyV.Type == "h2" || copyV.Type == "splithttp" {
info += fmt.Sprintf("%s: %s\n%s: %s\n",
color.RedString("Host"), copyV.Host,
color.RedString("Path"), copyV.Path)
} else if copyV.Type == "kcp" {
info += fmt.Sprintf("%s: %s\n", color.RedString("KCP Seed"), copyV.Path)
} else if copyV.Type == "grpc" {
result := make([][2]string, 0, 20)
result = append(result, [][2]string{
{"Protocol", t.Name()},
{"Remark", t.Remark},
{"Network", t.Type},
{"Address", t.Address},
{"Port", t.Port},
{"Password", t.Password},
{"Flow", copyV.Flow},
}...)

// Type
switch {
case slices.Contains([]string{"http", "httpupgrade", "ws", "h2", "splithttp"}, copyV.Type):
result = append(result, [][2]string{
{"Host", copyV.Host},
{"Path", copyV.Path},
}...)
case copyV.Type == "kcp":
result = append(result, [2]string{"KCP Seed", copyV.Path})
case copyV.Type == "grpc":
if copyV.ServiceName == "" {
copyV.ServiceName = "none"
}
info += fmt.Sprintf("%s: %s\n%s: %s\n",
color.RedString("ServiceName"), copyV.ServiceName,
color.RedString("Authority"), copyV.Authority)
result = append(result, [][2]string{
{"ServiceName", copyV.ServiceName},
{"Authority", copyV.Authority},
}...)
}

if copyV.Security == "reality" {
info += fmt.Sprintf("%s: reality\n", color.RedString("TLS"))
switch copyV.Security {
case "reality":
if copyV.SpiderX == "" {
copyV.SpiderX = "none"
}
info += fmt.Sprintf("%s: %s\n%s: %s\n%s: %s\n%s: %s\n%s: %s\n",
color.RedString("Public key"), copyV.PublicKey,
color.RedString("SNI"), copyV.SNI,
color.RedString("ShortID"), copyV.ShortIds,
color.RedString("SpiderX"), copyV.SpiderX,
color.RedString("Fingerprint"), copyV.TlsFingerprint,
)
} else if copyV.Security == "tls" {
info += fmt.Sprintf("%s: tls\n", color.RedString("TLS"))
if len(copyV.SNI) == 0 {
result = append(result, [][2]string{
{"TLS", "reality"},
{"Public key", copyV.PublicKey},
{"SNI", copyV.SNI},
{"ShortID", copyV.ShortIds},
{"SpiderX", copyV.SpiderX},
{"Fingerprint", copyV.TlsFingerprint},
}...)
case "tls":
if copyV.SNI == "" {
gotstanis marked this conversation as resolved.
Show resolved Hide resolved
copyV.SNI = "none"
if copyV.Host != "" {
copyV.SNI = copyV.Host
} else {
copyV.SNI = "none"
}
}
if len(copyV.ALPN) == 0 {
if copyV.ALPN == "" {
copyV.ALPN = "none"
}
if copyV.TlsFingerprint == "" {
copyV.TlsFingerprint = "none"
}
info += fmt.Sprintf("%s: %s\n%s: %s\n%s: %s\n",
color.RedString("SNI"), copyV.SNI,
color.RedString("ALPN"), copyV.ALPN,
color.RedString("Fingerprint"), copyV.TlsFingerprint)
} else {
info += fmt.Sprintf("%s: none\n", color.RedString("TLS"))
result = append(result, [][2]string{
{"TLS", "tls"},
{"SNI", copyV.SNI},
{"ALPN", copyV.ALPN},
{"Fingerprint", copyV.TlsFingerprint},
}...)
default:
result = append(result, [2]string{"TLS", "none"})
}
return info

return result
}

func (t *Trojan) ConvertToGeneralConfig() GeneralConfig {
Expand Down
Loading