改进代码; 添加按不同格式解析url的特性

This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent 23dea929f4
commit b79fb62629
16 changed files with 315 additions and 185 deletions
+1 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -43,7 +43,7 @@ var (
var (
//一个默认的 非 fullcone 的 direct Client
DirectClient, _, _ = proxy.ClientFromURL(proxy.DirectURL)
DirectClient, _ = proxy.ClientFromURL(proxy.DirectURL)
)
//用于回落到h2c
+15 -10
View File
@@ -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
View File
@@ -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+tlshttps实际上是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+tlshttps实际上是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
View File
@@ -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
View File
@@ -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 {
+4 -4
View File
@@ -9,13 +9,13 @@ https://github.com/shadowsocks/shadowsocks-org/wiki/AEAD-Ciphers
这里vs参考了gost的实现gost中Connector就相当于 clientHandler就相当于 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
View File
@@ -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
View File
@@ -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
+87
View File
@@ -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
}
+7 -2
View File
@@ -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
+9
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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