Allow the use of scripting to generate V2Fly shadowsockets outbound based on SIP008

This commit is contained in:
Shelikhoo
2021-03-06 04:40:40 +00:00
parent e22cf451f4
commit 8a33291c8c
9 changed files with 185 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
package securedload
const allowedHashes = `SHA256 (!#project==v2fly) = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
SHA256 (!#version==embedded) = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
SHA256 (subscriptions/subscriptionsDefinition.v2flyTemplate) = 3f165dba7de0d7c506fbdff3275ea64b76f307df435316a3ea0914ee957793ab
`
@@ -0,0 +1,47 @@
package securedload
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"github.com/v2fly/VSign/insmgr"
"github.com/v2fly/VSign/signerVerify"
"github.com/v2fly/v2ray-core/v4/common/platform"
"github.com/v2fly/v2ray-core/v4/common/platform/filesystem"
"strings"
)
type EmbeddedHashProtectedLoader struct {
checkedFile map[string]string
}
func (e EmbeddedHashProtectedLoader) VerifyAndLoad(filename string) ([]byte, error) {
filecontent, err := filesystem.ReadFile(platform.GetAssetLocation(filename))
if err != nil {
return nil, newError("Cannot find file", filename).Base(err)
}
fileHash := sha256.Sum256(filecontent)
fileHashAsString := hex.EncodeToString(fileHash[:])
if filenameverified, ok := e.checkedFile[fileHashAsString]; ok {
for _, filenameVerifiedIndividual := range strings.Split(filenameverified, ";") {
if strings.HasSuffix(filenameVerifiedIndividual, filename) {
return filecontent, nil
}
}
}
return nil, newError("Unrecognized file at ", filename, " can not be loaded for execution")
}
func NewEmbeddedHashProtectedLoader() *EmbeddedHashProtectedLoader {
instructions := insmgr.ReadAllIns(bytes.NewReader([]byte(allowedHashes)))
checkedFile, _, ok := signerVerify.CheckAsClient(instructions, "v2fly", true)
if !ok {
panic("Embedded Hash data is invalid")
}
return &EmbeddedHashProtectedLoader{checkedFile: checkedFile}
}
func init() {
RegisterProtectedLoader("embedded", NewEmbeddedHashProtectedLoader())
}
+13
View File
@@ -0,0 +1,13 @@
package securedload
func GetAssetSecured(name string) ([]byte, error) {
var err error
for k, v := range knownProtectedLoader {
if loadedData, errLoad := v.VerifyAndLoad(name); errLoad == nil {
return loadedData, nil
} else {
err = newError(k, " is not loading executable file").Base(errLoad)
}
}
return nil, err
}
@@ -0,0 +1,3 @@
package securedload
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
+14
View File
@@ -0,0 +1,14 @@
package securedload
type ProtectedLoader interface {
VerifyAndLoad(filename string) ([]byte, error)
}
var knownProtectedLoader map[string]ProtectedLoader
func RegisterProtectedLoader(name string, sv ProtectedLoader) {
if knownProtectedLoader == nil {
knownProtectedLoader = map[string]ProtectedLoader{}
}
knownProtectedLoader[name] = sv
}
+20
View File
@@ -0,0 +1,20 @@
package templates
import "encoding/json"
type UniversalDot struct {
Content []byte
AsJson interface{}
}
func NewUniversalDot(content []byte) *UniversalDot {
return &UniversalDot{Content: content}
}
func (ud *UniversalDot) IsJson() bool {
if nil == json.Unmarshal(ud.Content, &ud.AsJson) {
return true
}
return false
}
+25
View File
@@ -0,0 +1,25 @@
package templates
import "text/template"
var AssistFunctions template.FuncMap
func RegisterFunction(name string, function interface{}) {
if AssistFunctions == nil {
AssistFunctions = map[string]interface{}{}
}
AssistFunctions[name] = function
}
func Dec(val int) int {
return val - 1
}
func ShortHand(val string) string {
return val[:6]
}
func init() {
RegisterFunction("dec", Dec)
RegisterFunction("shorthand", ShortHand)
}
+3
View File
@@ -0,0 +1,3 @@
package templates
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
+54
View File
@@ -0,0 +1,54 @@
package control
import (
"github.com/v2fly/v2ray-core/v4/common"
"github.com/v2fly/v2ray-core/v4/common/platform/filesystem"
"github.com/v2fly/v2ray-core/v4/common/platform/securedload"
"github.com/v2fly/v2ray-core/v4/common/templates"
"os"
"text/template"
)
type SubscriptionParseCommand struct {
}
func (s SubscriptionParseCommand) Name() string {
return "subscriptionParse"
}
func (s SubscriptionParseCommand) Description() Description {
return Description{
Short: "a tool to parse all kind of subscription into V2Ray outbound",
Usage: []string{
"v2ctl subscriptionParse <subscription file>",
},
}
}
func (s SubscriptionParseCommand) Execute(args []string) error {
templatedef, err := securedload.GetAssetSecured("subscriptions/subscriptionsDefinition.v2flyTemplate")
if err != nil {
return newError("Cannot load subscription template file").Base(err)
}
templatedata, errtempl := template.New("").Funcs(templates.AssistFunctions).Parse(string(templatedef))
if errtempl != nil {
return newError("Cannot parse subscription template file").Base(errtempl)
}
subscription, errsubscription := filesystem.ReadFile(args[0])
if errsubscription != nil {
return newError("cannot read subscriptions file")
}
dot := templates.NewUniversalDot(subscription)
if errtemp := templatedata.Execute(os.Stdout, dot); errtemp != nil {
return newError("Cannot load execute template file").Base(errtemp)
}
return nil
}
func init() {
common.Must(RegisterCommand(SubscriptionParseCommand{}))
}