mirror of
https://github.com/v2fly/v2ray-core
synced 2024-02-27 03:18:06 +00:00
Allow the use of scripting to generate V2Fly shadowsockets outbound based on SIP008
This commit is contained in:
@@ -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())
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package templates
|
||||
|
||||
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
|
||||
@@ -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{}))
|
||||
}
|
||||
Reference in New Issue
Block a user