mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2026-04-22 22:47:04 +08:00
改进代码; 添加按不同格式解析url的特性
This commit is contained in:
@@ -140,10 +140,7 @@ verysimple -c server.json
|
||||
|
||||
verysimple 继承 v2simple的一个优点,就是服务端的配置也可以用url做到。谁规定url只能用于分享客户端配置了?一条url肯定比json更容易配置,不容易出错。
|
||||
|
||||
|
||||
另外,极简模式所使用的 url并不是正规的 各个协议所规定的 分享链接格式,而是我们自己的格式,所以链接看起来会略有区别。
|
||||
|
||||
以后可以考虑 推出一个 选项,选择 到底是 使用协议所规定的格式, 还是 使用我们verysimple自己的通用链接格式。
|
||||
关于url格式,见: https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
|
||||
### 命令行模式
|
||||
|
||||
|
||||
+14
-24
@@ -23,17 +23,17 @@ import (
|
||||
|
||||
var (
|
||||
cmdPrintSupportedProtocols bool
|
||||
cmdPrintVer bool
|
||||
|
||||
interactive_mode bool
|
||||
download bool
|
||||
cmdPrintVer bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&cmdPrintSupportedProtocols, "sp", false, "print supported protocols")
|
||||
flag.BoolVar(&cmdPrintVer, "v", false, "print the version string then exit")
|
||||
flag.BoolVar(&interactive_mode, "i", false, "enable interactive commandline mode")
|
||||
flag.BoolVar(&download, "d", false, " automatically download required mmdb file")
|
||||
flag.BoolVar(&cmdPrintVer, "v", false, "print the version string then exit")
|
||||
|
||||
//本文件 中定义的 CliCmd都是直接返回运行结果的、无需进一步交互的命令
|
||||
|
||||
@@ -41,27 +41,19 @@ func init() {
|
||||
"生成一个随机的uuid供你参考", func() {
|
||||
generateAndPrintUUID()
|
||||
},
|
||||
})
|
||||
|
||||
cliCmdList = append(cliCmdList, CliCmd{
|
||||
}, CliCmd{
|
||||
"下载geosite文件夹", func() {
|
||||
tryDownloadGeositeSource()
|
||||
},
|
||||
})
|
||||
|
||||
cliCmdList = append(cliCmdList, CliCmd{
|
||||
}, CliCmd{
|
||||
"下载geoip文件(GeoLite2-Country.mmdb)", func() {
|
||||
tryDownloadMMDB()
|
||||
},
|
||||
})
|
||||
|
||||
cliCmdList = append(cliCmdList, CliCmd{
|
||||
}, CliCmd{
|
||||
"打印当前版本所支持的所有协议", func() {
|
||||
printSupportedProtocols()
|
||||
},
|
||||
})
|
||||
|
||||
cliCmdList = append(cliCmdList, CliCmd{
|
||||
}, CliCmd{
|
||||
"查询当前状态", func() {
|
||||
printAllState(os.Stdout, false)
|
||||
},
|
||||
@@ -285,12 +277,11 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) {
|
||||
}
|
||||
|
||||
func loadSimpleServer() (result int, server proxy.Server) {
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
server, hase, eie = proxy.ServerFromURL(simpleConf.ListenUrl)
|
||||
if hase {
|
||||
var e error
|
||||
server, e = proxy.ServerFromURL(simpleConf.ListenUrl)
|
||||
if e != nil {
|
||||
if ce := utils.CanLogErr("can not create local server"); ce != nil {
|
||||
ce.Write(zap.String("error", eie.Error()))
|
||||
ce.Write(zap.String("error", e.Error()))
|
||||
}
|
||||
result = -1
|
||||
return
|
||||
@@ -313,12 +304,11 @@ func loadSimpleServer() (result int, server proxy.Server) {
|
||||
}
|
||||
|
||||
func loadSimpleClient() (result int, client proxy.Client) {
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
client, hase, eie = proxy.ClientFromURL(simpleConf.DialUrl)
|
||||
if hase {
|
||||
var e error
|
||||
client, e = proxy.ClientFromURL(simpleConf.DialUrl)
|
||||
if e != nil {
|
||||
if ce := utils.CanLogErr("can not create remote client"); ce != nil {
|
||||
ce.Write(zap.String("error", eie.Error()))
|
||||
ce.Write(zap.String("error", e.Error()))
|
||||
}
|
||||
result = -1
|
||||
return
|
||||
|
||||
+42
-34
@@ -24,11 +24,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
configFileName string
|
||||
startPProf bool
|
||||
startMProf bool
|
||||
listenURL string //用于命令行模式
|
||||
dialURL string //用于命令行模式
|
||||
configFileName string
|
||||
useNativeUrlFormat bool
|
||||
startPProf bool
|
||||
startMProf bool
|
||||
listenURL string //用于命令行模式
|
||||
dialURL string //用于命令行模式
|
||||
//jsonMode int
|
||||
|
||||
standardConf proxy.StandardConf
|
||||
@@ -57,22 +58,22 @@ const (
|
||||
func init() {
|
||||
routingEnv.ClientsTagMap = make(map[string]proxy.Client)
|
||||
|
||||
flag.StringVar(&configFileName, "c", defaultConfFn, "config file name")
|
||||
flag.IntVar(&utils.LogLevel, "ll", utils.DefaultLL, "log level,0=debug, 1=info, 2=warning, 3=error, 4=dpanic, 5=panic, 6=fatal")
|
||||
|
||||
flag.BoolVar(&startPProf, "pp", false, "pprof")
|
||||
flag.BoolVar(&startMProf, "mp", false, "memory pprof")
|
||||
//flag.IntVar(&jsonMode, "jm", 0, "json mode, 0:verysimple mode; 1: v2ray mode(not implemented yet)")
|
||||
flag.BoolVar(&useNativeUrlFormat, "sn", false, "use the proxy-defined url format, instead of the standard verysimple one.")
|
||||
|
||||
flag.BoolVar(&netLayer.UseReadv, "readv", netLayer.DefaultReadvOption, "toggle the use of 'readv' syscall")
|
||||
|
||||
flag.StringVar(&configFileName, "c", defaultConfFn, "config file name")
|
||||
|
||||
flag.StringVar(&listenURL, "L", "", "listen URL, only used when no config file is provided.")
|
||||
flag.StringVar(&dialURL, "D", "", "dial URL, only used when no config file is provided.")
|
||||
|
||||
//other packages
|
||||
|
||||
flag.IntVar(&utils.LogLevel, "ll", utils.DefaultLL, "log level,0=debug, 1=info, 2=warning, 3=error, 4=dpanic, 5=panic, 6=fatal")
|
||||
|
||||
flag.StringVar(&utils.LogOutFileName, "lf", defaultLogFile, "output file for log; If empty, no log file will be used.")
|
||||
|
||||
flag.BoolVar(&netLayer.UseReadv, "readv", netLayer.DefaultReadvOption, "toggle the use of 'readv' syscall")
|
||||
|
||||
flag.StringVar(&netLayer.GeoipFileName, "geoip", defaultGeoipFn, "geoip maxmind file name")
|
||||
flag.StringVar(&utils.ExtraSearchPath, "path", "", "search path for mmdb, geosite and other required files")
|
||||
|
||||
@@ -143,32 +144,39 @@ func mainFunc() (result int) {
|
||||
|
||||
}
|
||||
|
||||
if startPProf {
|
||||
const pprofFN = "cpu.pprof"
|
||||
f, err := os.OpenFile(pprofFN, os.O_CREATE|os.O_RDWR, 0644)
|
||||
// config by bool params
|
||||
{
|
||||
if startPProf {
|
||||
const pprofFN = "cpu.pprof"
|
||||
f, err := os.OpenFile(pprofFN, os.O_CREATE|os.O_RDWR, 0644)
|
||||
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
err = pprof.StartCPUProfile(f)
|
||||
if err == nil {
|
||||
defer pprof.StopCPUProfile()
|
||||
} else {
|
||||
log.Println("pprof.StartCPUProfile failed", err)
|
||||
defer f.Close()
|
||||
err = pprof.StartCPUProfile(f)
|
||||
if err == nil {
|
||||
defer pprof.StopCPUProfile()
|
||||
} else {
|
||||
log.Println("pprof.StartCPUProfile failed", err)
|
||||
|
||||
}
|
||||
} else {
|
||||
log.Println(pprofFN, "can't be created,", err)
|
||||
}
|
||||
} else {
|
||||
log.Println(pprofFN, "can't be created,", err)
|
||||
|
||||
}
|
||||
if startMProf {
|
||||
//若不使用 NoShutdownHook, 则 我们ctrl+c退出时不会产生 pprof文件
|
||||
p := profile.Start(profile.MemProfile, profile.MemProfileRate(1), profile.NoShutdownHook)
|
||||
|
||||
defer p.Stop()
|
||||
}
|
||||
|
||||
}
|
||||
if startMProf {
|
||||
//若不使用 NoShutdownHook, 则 我们ctrl+c退出时不会产生 pprof文件
|
||||
p := profile.Start(profile.MemProfile, profile.MemProfileRate(1), profile.NoShutdownHook)
|
||||
|
||||
defer p.Stop()
|
||||
if useNativeUrlFormat {
|
||||
proxy.UrlFormat = proxy.UrlNativeFormat
|
||||
}
|
||||
}
|
||||
|
||||
var mode int
|
||||
var configMode int
|
||||
var mainFallback *httpLayer.ClassicFallback
|
||||
|
||||
var loadConfigErr error
|
||||
@@ -186,7 +194,7 @@ func mainFunc() (result int) {
|
||||
|
||||
}
|
||||
|
||||
standardConf, simpleConf, mode, mainFallback, loadConfigErr = proxy.LoadConfig(configFileName, listenURL, dialURL, 0)
|
||||
standardConf, simpleConf, configMode, mainFallback, loadConfigErr = proxy.LoadConfig(configFileName, listenURL, dialURL, 0)
|
||||
|
||||
if loadConfigErr == nil {
|
||||
|
||||
@@ -273,7 +281,7 @@ func mainFunc() (result int) {
|
||||
var tproxyConfs []*proxy.ListenConf
|
||||
|
||||
//load inServers and RoutingEnv
|
||||
switch mode {
|
||||
switch configMode {
|
||||
case proxy.SimpleMode:
|
||||
result, defaultInServer = loadSimpleServer()
|
||||
if result < 0 {
|
||||
@@ -341,7 +349,7 @@ func mainFunc() (result int) {
|
||||
}
|
||||
|
||||
// load outClients
|
||||
switch mode {
|
||||
switch configMode {
|
||||
case proxy.SimpleMode:
|
||||
result, defaultOutClient = loadSimpleClient()
|
||||
if result < 0 {
|
||||
@@ -368,7 +376,7 @@ func mainFunc() (result int) {
|
||||
|
||||
if (defaultOutClient != nil) && (defaultInServer != nil || len(allServers) > 0 || len(tproxyConfs) > 0) {
|
||||
|
||||
if mode == proxy.SimpleMode {
|
||||
if configMode == proxy.SimpleMode {
|
||||
lis := vs.ListenSer(defaultInServer, defaultOutClient, &routingEnv)
|
||||
if lis != nil {
|
||||
listenCloserList = append(listenCloserList, lis)
|
||||
|
||||
@@ -43,7 +43,7 @@ var (
|
||||
var (
|
||||
|
||||
//一个默认的 非 fullcone 的 direct Client
|
||||
DirectClient, _, _ = proxy.ClientFromURL(proxy.DirectURL)
|
||||
DirectClient, _ = proxy.ClientFromURL(proxy.DirectURL)
|
||||
)
|
||||
|
||||
//用于回落到h2c
|
||||
|
||||
+15
-10
@@ -35,16 +35,21 @@ func PrintAllClientNames() {
|
||||
}
|
||||
}
|
||||
|
||||
//可通过两种配置方式来初始化。
|
||||
//可通过标准配置或url 来初始化。
|
||||
type ClientCreator interface {
|
||||
NewClient(*DialConf) (Client, error)
|
||||
NewClientFromURL(url *url.URL) (Client, error)
|
||||
//大部分通用内容都会被proxy包解析,方法只需要处理proxy包未知的内容
|
||||
NewClient(*DialConf) (Client, error) //标准配置
|
||||
|
||||
URLToDialConf(url *url.URL, format int) (*DialConf, error)
|
||||
//DialConfToURL(url *DialConf, format int) (*url.URL, error)
|
||||
}
|
||||
|
||||
//可通过两种配置方式来初始化。
|
||||
type ServerCreator interface {
|
||||
NewServer(*ListenConf) (Server, error)
|
||||
NewServerFromURL(url *url.URL) (Server, error)
|
||||
|
||||
URLToListenConf(url *url.URL, format int) (*ListenConf, error)
|
||||
//ListenConfToURL(url *ListenConf, format int) (*url.URL, error)
|
||||
}
|
||||
|
||||
// 规定,每个 实现Client的包必须使用本函数进行注册。
|
||||
@@ -68,19 +73,19 @@ func NewClient(dc *DialConf) (Client, error) {
|
||||
creator, ok := clientCreatorMap[protocol]
|
||||
if ok {
|
||||
|
||||
return newclient(creator, dc, false)
|
||||
return newClient(creator, dc, false)
|
||||
} else {
|
||||
realScheme := strings.TrimSuffix(protocol, "s")
|
||||
creator, ok = clientCreatorMap[realScheme]
|
||||
if ok {
|
||||
return newclient(creator, dc, true)
|
||||
return newClient(creator, dc, true)
|
||||
}
|
||||
}
|
||||
return nil, utils.ErrInErr{ErrDesc: "Unknown client protocol ", Data: protocol}
|
||||
|
||||
}
|
||||
|
||||
func newclient(creator ClientCreator, dc *DialConf, knownTls bool) (Client, error) {
|
||||
func newClient(creator ClientCreator, dc *DialConf, knownTls bool) (Client, error) {
|
||||
c, e := creator.NewClient(dc)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
@@ -136,19 +141,19 @@ func NewServer(lc *ListenConf) (Server, error) {
|
||||
protocol := lc.Protocol
|
||||
creator, ok := serverCreatorMap[protocol]
|
||||
if ok {
|
||||
return newserver(creator, lc, false)
|
||||
return newServer(creator, lc, false)
|
||||
} else {
|
||||
realScheme := strings.TrimSuffix(protocol, "s")
|
||||
creator, ok = serverCreatorMap[realScheme]
|
||||
if ok {
|
||||
return newserver(creator, lc, true)
|
||||
return newServer(creator, lc, true)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, utils.ErrInErr{ErrDesc: "Unknown server protocol ", Data: protocol}
|
||||
}
|
||||
|
||||
func newserver(creator ServerCreator, lc *ListenConf, knownTls bool) (Server, error) {
|
||||
func newServer(creator ServerCreator, lc *ListenConf, knownTls bool) (Server, error) {
|
||||
ser, err := creator.NewServer(lc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+85
-66
@@ -1,79 +1,84 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
UrlNativeMode = iota //proxy对应的标准文档所定义的url模式,一般散布于对应github的文档上
|
||||
UrlStandardMode //VS定义的 供 所有proxy 使用的 标准 url模式
|
||||
UrlNativeFormat = iota //proxy对应的标准文档所定义的url模式,一般散布于对应github的文档上
|
||||
UrlStandardFormat //VS定义的 供 所有proxy 使用的 标准 url模式
|
||||
|
||||
)
|
||||
|
||||
var (
|
||||
//关于url模式, 见 https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
UrlMode = UrlNativeMode
|
||||
// Url格式 设置以何种方式解析 命令行模式/极简模式 中出现的url配置
|
||||
//
|
||||
//关于url格式的详细, 见 https://github.com/e1732a364fed/v2ray_simple/discussions/163
|
||||
UrlFormat = UrlStandardFormat
|
||||
)
|
||||
|
||||
// ClientFromURL calls the registered creator to create client. The returned bool is true if has err.
|
||||
func ClientFromURL(s string) (Client, bool, utils.ErrInErr) {
|
||||
func ClientFromURL(s string) (Client, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
|
||||
return nil, true, utils.ErrInErr{ErrDesc: "Can't parse client url", ErrDetail: err, Data: s}
|
||||
return nil, utils.ErrInErr{ErrDesc: "Can't parse client url", ErrDetail: err, Data: s}
|
||||
}
|
||||
|
||||
schemeName := strings.ToLower(u.Scheme)
|
||||
|
||||
creator, ok := clientCreatorMap[schemeName]
|
||||
if ok {
|
||||
return clientFromURL(creator, u, false)
|
||||
} else {
|
||||
|
||||
//尝试判断是否套tls, 比如vlesss实际上是vless+tls,https实际上是http+tls
|
||||
var okTls bool
|
||||
|
||||
if !ok {
|
||||
realScheme := strings.TrimSuffix(schemeName, "s")
|
||||
creator, ok = clientCreatorMap[realScheme]
|
||||
if ok {
|
||||
return clientFromURL(creator, u, true)
|
||||
creator, okTls = clientCreatorMap[realScheme]
|
||||
}
|
||||
//尝试判断是否套tls, 比如vlesss实际上是vless+tls,https实际上是http+tls
|
||||
|
||||
if okTls {
|
||||
ok = true
|
||||
}
|
||||
|
||||
if ok {
|
||||
|
||||
dc, e := creator.URLToDialConf(u, UrlStandardFormat)
|
||||
if e != nil {
|
||||
|
||||
return nil, e
|
||||
}
|
||||
if UrlFormat == UrlStandardFormat {
|
||||
setConfByStandardURL(&dc.CommonConf, u)
|
||||
|
||||
if okTls {
|
||||
dc.TLS = true
|
||||
prepareTLS_forConf_withStandardURL(u, &dc.CommonConf, nil, dc)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
c, e := newClient(creator, dc, false)
|
||||
|
||||
return nil, false, utils.ErrInErr{ErrDesc: "Unknown client protocol ", Data: u.Scheme}
|
||||
}
|
||||
if e != nil {
|
||||
|
||||
func clientFromURL(creator ClientCreator, u *url.URL, knownTLS bool) (Client, bool, utils.ErrInErr) {
|
||||
c, e := creator.NewClientFromURL(u)
|
||||
if e != nil {
|
||||
return nil, true, utils.ErrInErr{ErrDesc: "Err, creator.NewClientFromURL", ErrDetail: e}
|
||||
}
|
||||
configCommonByURL(c, u)
|
||||
|
||||
cc := c.GetBase()
|
||||
|
||||
if cc != nil {
|
||||
cc.Tag = u.Fragment
|
||||
|
||||
if knownTLS {
|
||||
cc.TLS = true
|
||||
prepareTLS_forProxyCommon_withURL(u, true, c)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
return c, false, utils.ErrInErr{}
|
||||
return nil, utils.ErrInErr{ErrDesc: "Unknown client protocol ", Data: u.Scheme}
|
||||
}
|
||||
|
||||
// ServerFromURL calls the registered creator to create proxy servers.
|
||||
func ServerFromURL(s string) (Server, bool, utils.ErrInErr) {
|
||||
func ServerFromURL(s string) (Server, error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return nil, true, utils.ErrInErr{
|
||||
return nil, utils.ErrInErr{
|
||||
ErrDesc: "Can't parse server url ",
|
||||
ErrDetail: err,
|
||||
Data: s,
|
||||
@@ -82,39 +87,50 @@ func ServerFromURL(s string) (Server, bool, utils.ErrInErr) {
|
||||
|
||||
schemeName := strings.ToLower(u.Scheme)
|
||||
creator, ok := serverCreatorMap[schemeName]
|
||||
if ok {
|
||||
return serverFromURL(creator, u, false)
|
||||
|
||||
} else {
|
||||
var okTls bool
|
||||
|
||||
if !ok {
|
||||
realScheme := strings.TrimSuffix(schemeName, "s")
|
||||
creator, ok = serverCreatorMap[realScheme]
|
||||
if ok {
|
||||
return serverFromURL(creator, u, true)
|
||||
creator, okTls = serverCreatorMap[realScheme]
|
||||
|
||||
}
|
||||
|
||||
if okTls {
|
||||
ok = true
|
||||
}
|
||||
|
||||
if ok {
|
||||
|
||||
sConf, err := creator.URLToListenConf(u, UrlFormat)
|
||||
if err != nil {
|
||||
return nil, utils.ErrInErr{
|
||||
ErrDesc: "URLToListenConf err ",
|
||||
ErrDetail: err,
|
||||
Data: s,
|
||||
}
|
||||
}
|
||||
|
||||
if UrlFormat == UrlStandardFormat {
|
||||
confQueryForServer(sConf, u)
|
||||
|
||||
if okTls {
|
||||
sConf.TLS = true
|
||||
|
||||
prepareTLS_forConf_withStandardURL(u, &sConf.CommonConf, sConf, nil)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newServer(creator, sConf, false)
|
||||
|
||||
}
|
||||
|
||||
return nil, true, utils.ErrInErr{ErrDesc: "Unknown server protocol ", Data: u.Scheme}
|
||||
}
|
||||
|
||||
func serverFromURL(creator ServerCreator, u *url.URL, knownTLS bool) (Server, bool, utils.ErrInErr) {
|
||||
server, err := creator.NewServerFromURL(u)
|
||||
if err != nil {
|
||||
return nil, true, utils.ErrInErr{
|
||||
ErrDesc: "Err, creator.NewServerFromURL",
|
||||
ErrDetail: err,
|
||||
}
|
||||
}
|
||||
configCommonURLQueryForServer(server, u)
|
||||
|
||||
if knownTLS {
|
||||
server.GetBase().TLS = true
|
||||
prepareTLS_forProxyCommon_withURL(u, false, server)
|
||||
|
||||
}
|
||||
return server, false, utils.ErrInErr{}
|
||||
return nil, utils.ErrInErr{ErrDesc: "Unknown server protocol ", Data: u.Scheme}
|
||||
}
|
||||
|
||||
/*
|
||||
//set Tag, cantRoute,FallbackAddr, call configCommonByURL
|
||||
func configCommonURLQueryForServer(ser BaseInterface, u *url.URL) {
|
||||
nr := false
|
||||
@@ -122,7 +138,7 @@ func configCommonURLQueryForServer(ser BaseInterface, u *url.URL) {
|
||||
if q.Get("noroute") != "" {
|
||||
nr = true
|
||||
}
|
||||
configCommonByURL(ser, u)
|
||||
configCommonByStandardURL(ser, u)
|
||||
|
||||
serc := ser.GetBase()
|
||||
if serc == nil {
|
||||
@@ -148,9 +164,11 @@ func configCommonURLQueryForServer(ser BaseInterface, u *url.URL) {
|
||||
serc.FallbackAddr = &fa
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//SetAddrStr, setNetwork, Isfullcone
|
||||
func configCommonByURL(baseI BaseInterface, u *url.URL) {
|
||||
func configCommonByStandardURL(baseI BaseInterface, u *url.URL) {
|
||||
if u.Scheme != DirectName {
|
||||
baseI.SetAddrStr(u.Host) //若不给出port,那就只有host名,这样不好,我们 默认 配置里肯定给了port
|
||||
|
||||
@@ -161,11 +179,12 @@ func configCommonByURL(baseI BaseInterface, u *url.URL) {
|
||||
}
|
||||
base.setNetwork(u.Query().Get("network"))
|
||||
|
||||
base.IsFullcone = GetFullconeFromUrl(u)
|
||||
base.IsFullcone = getFullconeFromUrl(u)
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
func GetFullconeFromUrl(url *url.URL) bool {
|
||||
func getFullconeFromUrl(url *url.URL) bool {
|
||||
nStr := url.Query().Get("fullcone")
|
||||
return nStr == "true" || nStr == "1"
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@ const (
|
||||
//implements ClientCreator for direct
|
||||
type DirectCreator struct{}
|
||||
|
||||
func (DirectCreator) NewClientFromURL(url *url.URL) (Client, error) {
|
||||
d := &DirectClient{}
|
||||
func (DirectCreator) URLToDialConf(url *url.URL, format int) (*DialConf, error) {
|
||||
d := &DialConf{}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
+30
-20
@@ -39,13 +39,6 @@ func tryRejectWithHttpRespAndClose(rejectType string, underlay net.Conn) {
|
||||
//implements ClientCreator for reject
|
||||
type RejectCreator struct{}
|
||||
|
||||
func (RejectCreator) NewClientFromURL(url *url.URL) (Client, error) {
|
||||
r := &RejectClient{}
|
||||
r.initWithUrl(url)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (RejectCreator) NewClient(dc *DialConf) (Client, error) {
|
||||
r := &RejectClient{}
|
||||
|
||||
@@ -54,11 +47,36 @@ func (RejectCreator) NewClient(dc *DialConf) (Client, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (RejectCreator) NewServerFromURL(url *url.URL) (Server, error) {
|
||||
r := &RejectServer{}
|
||||
r.initWithUrl(url)
|
||||
func (RejectCreator) initCommonConfByURL(url *url.URL, lc *CommonConf, format int) {
|
||||
|
||||
return r, nil
|
||||
if format != UrlStandardFormat {
|
||||
return
|
||||
}
|
||||
|
||||
nStr := url.Query().Get("type")
|
||||
|
||||
if nStr != "" {
|
||||
|
||||
lc.Extra = make(map[string]any)
|
||||
lc.Extra["type"] = nStr
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (rc RejectCreator) URLToDialConf(url *url.URL, format int) (*DialConf, error) {
|
||||
dc := &DialConf{}
|
||||
rc.initCommonConfByURL(url, &dc.CommonConf, format)
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
func (rc RejectCreator) URLToListenConf(url *url.URL, format int) (*ListenConf, error) {
|
||||
|
||||
lc := &ListenConf{}
|
||||
rc.initCommonConfByURL(url, &lc.CommonConf, format)
|
||||
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
func (RejectCreator) NewServer(lc *ListenConf) (Server, error) {
|
||||
@@ -72,19 +90,11 @@ func (RejectCreator) NewServer(lc *ListenConf) (Server, error) {
|
||||
type rejectCommon struct {
|
||||
Base
|
||||
|
||||
theType string
|
||||
theType string //拒绝响应的类型, 可为空、http或nginx
|
||||
}
|
||||
|
||||
func (*rejectCommon) Name() string { return RejectName }
|
||||
|
||||
func (rc *rejectCommon) initWithUrl(url *url.URL) {
|
||||
nStr := url.Query().Get("type")
|
||||
if nStr != "" {
|
||||
rc.theType = nStr
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (rc *rejectCommon) initWithCommonConf(cc *CommonConf) {
|
||||
if cc.Extra != nil {
|
||||
if thing := cc.Extra["type"]; thing != nil {
|
||||
|
||||
@@ -9,13 +9,13 @@ https://github.com/shadowsocks/shadowsocks-org/wiki/AEAD-Ciphers
|
||||
|
||||
这里vs参考了gost的实现。gost中,Connector就相当于 client,Handler就相当于 Server
|
||||
|
||||
但是发现,似乎没法一个server同时处理tcp和udp? 也就是说,只能预先指定服务端要处理的协议;
|
||||
但是发现,没法一个server同时处理tcp和udp? 也就是说,只能预先指定服务端要处理的协议;
|
||||
|
||||
而且我看ss的标准,也没有提及哪一项 可以指定 tcp/udp
|
||||
看ss的标准,也没有提及哪一项 可以指定 tcp/udp
|
||||
|
||||
后重新阅读上面Protocol页面,参考阅读 http://overtalk.site/2020/02/25/network-shadowsocks/
|
||||
重新阅读上面Protocol页面,参考阅读 http://overtalk.site/2020/02/25/network-shadowsocks/
|
||||
|
||||
似乎意识到,ss好似不像vmess等协议一样,只使用一种传输层协议来传输 tcp和udp数据;而是:用tcp传tcp,用udp传udp。
|
||||
ss不像vmess等协议一样,只使用一种传输层协议来传输 tcp和udp数据;而是:用tcp传tcp,用udp传udp。
|
||||
如此的话,特征必很明显。
|
||||
|
||||
还有一个重要的问题,就是,我们vs的架构,在设计之初,就是为vmess/vless/trojan等 只需要一种传输层协议 来获取 多种传输层协议的客户端等数据的;
|
||||
|
||||
+8
-8
@@ -21,13 +21,13 @@ func TestTCP(protocol string, version int, port string, t *testing.T) {
|
||||
utils.InitLog("")
|
||||
|
||||
url := protocol + "://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:" + port + "?version=" + strconv.Itoa(version)
|
||||
server, hase, _ := ServerFromURL(url)
|
||||
if hase {
|
||||
server, e := ServerFromURL(url)
|
||||
if e != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
defer server.Stop()
|
||||
client, hase, _ := ClientFromURL(url)
|
||||
if hase {
|
||||
client, e := ClientFromURL(url)
|
||||
if e != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
@@ -132,14 +132,14 @@ func TestUDP(protocol string, version int, proxyPort string, use_multi int, t *t
|
||||
fmtStr := protocol + "://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:%s?version=%d&vless1_udp_multi=%d"
|
||||
|
||||
url := fmt.Sprintf(fmtStr, proxyPort, version, use_multi)
|
||||
fakeServerEndLocalServer, hase, errx := ServerFromURL(url)
|
||||
if hase {
|
||||
fakeServerEndLocalServer, errx := ServerFromURL(url)
|
||||
if errx != nil {
|
||||
t.Log("fakeClientEndLocalServer parse err", errx)
|
||||
t.FailNow()
|
||||
}
|
||||
defer fakeServerEndLocalServer.Stop()
|
||||
fakeClientEndRemoteClient, hase, errx := ClientFromURL(url)
|
||||
if hase {
|
||||
fakeClientEndRemoteClient, errx := ClientFromURL(url)
|
||||
if errx != nil {
|
||||
t.Log("fakeClientEndRemoteClient parse err", errx)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ func prepareTLS_forServer(com BaseInterface, lc *ListenConf) error {
|
||||
}
|
||||
|
||||
//给 ProxyCommon 的tls做一些配置上的准备,从url读取配置
|
||||
func prepareTLS_forProxyCommon_withURL(u *url.URL, isclient bool, com BaseInterface) error {
|
||||
func prepareTLS_forProxyCommon_withStandardURL(u *url.URL, isclient bool, com BaseInterface) error {
|
||||
q := u.Query()
|
||||
insecureStr := q.Get("insecure")
|
||||
insecure := false
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
//SetAddrStr, setNetwork, Isfullcone
|
||||
func setConfByStandardURL(conf *CommonConf, u *url.URL) error {
|
||||
if u.Scheme != DirectName {
|
||||
|
||||
hn := u.Hostname()
|
||||
|
||||
ip := net.ParseIP(hn)
|
||||
if ip != nil {
|
||||
conf.IP = hn
|
||||
} else {
|
||||
conf.Host = hn
|
||||
}
|
||||
|
||||
if hn != u.Host { //给出了port
|
||||
|
||||
p, err := strconv.Atoi(u.Host[strings.LastIndexByte(u.Host, ':'):])
|
||||
if err != nil {
|
||||
return err
|
||||
} else if p < 0 || p > 65535 {
|
||||
return utils.ErrInvalidData
|
||||
}
|
||||
conf.Port = p
|
||||
|
||||
}
|
||||
}
|
||||
conf.Network = u.Query().Get("network")
|
||||
|
||||
conf.Fullcone = getFullconeFromUrl(u)
|
||||
conf.Tag = u.Fragment
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//set Tag, NoRoute,Fallback, call setConfByStandardURL
|
||||
func confQueryForServer(conf *ListenConf, u *url.URL) {
|
||||
nr := false
|
||||
q := u.Query()
|
||||
if q.Get("noroute") != "" {
|
||||
nr = true
|
||||
}
|
||||
setConfByStandardURL(&conf.CommonConf, u)
|
||||
|
||||
conf.NoRoute = nr
|
||||
|
||||
conf.Tag = u.Fragment
|
||||
|
||||
fallbackStr := q.Get("fallback")
|
||||
|
||||
conf.Fallback = fallbackStr
|
||||
}
|
||||
|
||||
//给 ProxyCommon 的tls做一些配置上的准备,从url读取配置
|
||||
func prepareTLS_forConf_withStandardURL(u *url.URL, com *CommonConf, lc *ListenConf, dc *DialConf) error {
|
||||
q := u.Query()
|
||||
insecureStr := q.Get("insecure")
|
||||
if insecureStr != "" && insecureStr != "false" && insecureStr != "0" {
|
||||
|
||||
com.Insecure = true
|
||||
}
|
||||
|
||||
if dc != nil {
|
||||
utlsStr := q.Get("utls")
|
||||
useUtls := utlsStr != "" && utlsStr != "false" && utlsStr != "0"
|
||||
|
||||
dc.Utls = useUtls
|
||||
|
||||
} else {
|
||||
certFile := q.Get("cert")
|
||||
keyFile := q.Get("key")
|
||||
|
||||
lc.TLSCert = certFile
|
||||
lc.TLSKey = keyFile
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,10 @@
|
||||
// Package vless implements vless v0/v1 for proxy.Client and proxy.Server
|
||||
/* Package vless implements vless v0/v1 for proxy.Client and proxy.Server.
|
||||
|
||||
|
||||
vless的客户端配置 分享url文档:
|
||||
https://github.com/XTLS/Xray-core/discussions/716
|
||||
|
||||
*/
|
||||
package vless
|
||||
|
||||
import (
|
||||
@@ -35,7 +41,6 @@ func WriteAddrTo(writeBuf utils.ByteWriter, raddr netLayer.Addr) {
|
||||
|
||||
}
|
||||
|
||||
//https://github.com/XTLS/Xray-core/discussions/716
|
||||
func GenerateXrayShareURL(dialconf *proxy.DialConf) string {
|
||||
|
||||
var u url.URL
|
||||
|
||||
@@ -17,6 +17,15 @@ vmess 协议是一个很老旧的协议,有很多向前兼容的代码,很
|
||||
|
||||
我们所实现的vmess 服务端 力求简单、最新,不求兼容所有老旧客户端。
|
||||
|
||||
Share URL
|
||||
|
||||
v2fly只有一个草案
|
||||
https://github.com/v2fly/v2fly-github-io/issues/26
|
||||
|
||||
似乎v2fly社区对于这个URL标准的制定并不注重,而且看起来这个草案也不太美观
|
||||
|
||||
而xray社区的则美观得多,见 https://github.com/XTLS/Xray-core/discussions/716
|
||||
|
||||
*/
|
||||
package vmess
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ func testTls(protocol string, t *testing.T) {
|
||||
port := netLayer.RandPortStr(true, false)
|
||||
|
||||
url := protocol + "://a684455c-b14f-11ea-bf0d-42010aaa0003@localhost:" + port + "?alterID=4&cert=../cert.pem&key=../cert.key&insecure=1"
|
||||
server, hase, errx := proxy.ServerFromURL(url)
|
||||
if hase {
|
||||
server, errx := proxy.ServerFromURL(url)
|
||||
if errx != nil {
|
||||
t.Log("fail1", errx)
|
||||
t.FailNow()
|
||||
}
|
||||
defer server.Stop()
|
||||
client, hase, errx := proxy.ClientFromURL(url)
|
||||
if hase {
|
||||
client, errx := proxy.ClientFromURL(url)
|
||||
if errx != nil {
|
||||
t.Log("fail2", errx)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
+5
-5
@@ -22,8 +22,8 @@ type UserWithPass interface {
|
||||
GetPassword() []byte
|
||||
}
|
||||
|
||||
//判断用户是否存在并取出
|
||||
type UserHaser interface {
|
||||
//用户集合,判断用户是否存在并取出
|
||||
type UserSet interface {
|
||||
HasUserByBytes(bs []byte) User
|
||||
IDBytesLen() int //用户名bytes的最小长度
|
||||
}
|
||||
@@ -35,9 +35,9 @@ type UserAuther interface {
|
||||
AuthBytesLen() int
|
||||
}
|
||||
|
||||
//可判断是否存在,也可以验证
|
||||
//用户容器,可判断是否存在,也可以验证
|
||||
type UserContainer interface {
|
||||
UserHaser
|
||||
UserSet
|
||||
|
||||
UserAuther
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func (ph *UserPass) InitWithStr(str string) (ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
//implements UserBus, UserHaser, UserGetter; 只能存储同一类型的User.
|
||||
//implements UserBus, UserSet, UserGetter; 只能存储同一类型的User.
|
||||
// 通过 bytes存储用户id,而不是 str。
|
||||
type MultiUserMap struct {
|
||||
IDMap map[string]User
|
||||
|
||||
Reference in New Issue
Block a user