mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
feature:api server 添加 热加载url功能;添加sa参数,配置api server的监听地址;
允许api server 在不设置密码时运行
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/tlsLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -17,16 +18,18 @@ var (
|
||||
apiServerRunning bool
|
||||
apiServerPathPrefix string
|
||||
apiServerAdminPass string
|
||||
apiServerAddr string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&enableApiServer, "ea", false, "enable api server")
|
||||
flag.StringVar(&apiServerPathPrefix, "spp", "/api", "api Server Path Prefix, must start with '/' ")
|
||||
flag.StringVar(&apiServerAdminPass, "sap", "", "api Server admin password, but won't be used if it's empty")
|
||||
flag.StringVar(&apiServerAddr, "sa", "127.0.0.1:48345", "api Server listen address")
|
||||
|
||||
}
|
||||
|
||||
//非阻塞,如果运行成功则 apiServerRunning 会被设为 true
|
||||
// 非阻塞,如果运行成功则 apiServerRunning 会被设为 true
|
||||
func tryRunApiServer() {
|
||||
|
||||
var thepass string
|
||||
@@ -39,27 +42,67 @@ func tryRunApiServer() {
|
||||
thepass = apiServerAdminPass
|
||||
}
|
||||
|
||||
if thepass != "" {
|
||||
apiServerRunning = true
|
||||
apiServerRunning = true
|
||||
|
||||
go runApiServer(thepass)
|
||||
|
||||
go runApiServer(thepass)
|
||||
}
|
||||
}
|
||||
|
||||
//阻塞
|
||||
// 阻塞
|
||||
func runApiServer(adminUUID string) {
|
||||
|
||||
utils.Info("Start Api Server")
|
||||
utils.Info("Start Api Server at " + apiServerAddr)
|
||||
|
||||
ser := newApiServer("admin", adminUUID)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc(apiServerPathPrefix+"/allstate", ser.basicAuth(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ser.addServerHandle(mux, "allstate", func(w http.ResponseWriter, r *http.Request) {
|
||||
printAllState(w, false)
|
||||
}))
|
||||
})
|
||||
ser.addServerHandle(mux, "hotLoadUrl", func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
|
||||
listenStr := q.Get("listen")
|
||||
dialStr := q.Get("dial")
|
||||
|
||||
f := r.Form
|
||||
|
||||
if listenStr == "" {
|
||||
listenStr = f.Get("listen")
|
||||
}
|
||||
if dialStr == "" {
|
||||
dialStr = f.Get("dial")
|
||||
}
|
||||
|
||||
var resultStr string = "result:"
|
||||
if listenStr != "" {
|
||||
if ce := utils.CanLogInfo("api server got hot load listen request"); ce != nil {
|
||||
ce.Write(zap.String("listenUrl", listenStr))
|
||||
}
|
||||
e := hotLoadListenUrl(listenStr)
|
||||
if e == nil {
|
||||
resultStr += "\nhot load listen Url Success for " + listenStr
|
||||
} else {
|
||||
resultStr += "\nhot load listen Url Failed for " + listenStr
|
||||
}
|
||||
}
|
||||
if dialStr != "" {
|
||||
if ce := utils.CanLogInfo("api server got hot load dial request"); ce != nil {
|
||||
ce.Write(zap.String("dialUrl", dialStr))
|
||||
}
|
||||
e := hotLoadDialUrl(dialStr)
|
||||
if e == nil {
|
||||
resultStr += "\nhot load dial Url Success for " + dialStr
|
||||
} else {
|
||||
resultStr += "\nhot load dial Url Failed for " + dialStr
|
||||
}
|
||||
}
|
||||
w.Write([]byte(resultStr))
|
||||
})
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: "127.0.0.1:48345",
|
||||
Addr: apiServerAddr,
|
||||
Handler: mux,
|
||||
IdleTimeout: time.Minute,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
@@ -81,18 +124,34 @@ type auth struct {
|
||||
|
||||
type apiServer struct {
|
||||
admin_auth auth
|
||||
nopass bool
|
||||
}
|
||||
|
||||
func newApiServer(user, pass string) *apiServer {
|
||||
s := new(apiServer)
|
||||
|
||||
s.admin_auth.expectedUsernameHash = sha256.Sum256([]byte(user))
|
||||
s.admin_auth.expectedPasswordHash = sha256.Sum256([]byte(pass))
|
||||
if pass != "" {
|
||||
s.admin_auth.expectedUsernameHash = sha256.Sum256([]byte(user))
|
||||
s.admin_auth.expectedPasswordHash = sha256.Sum256([]byte(pass))
|
||||
|
||||
} else {
|
||||
s.nopass = true
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (ser *apiServer) addServerHandle(mux *http.ServeMux, name string, f func(w http.ResponseWriter, r *http.Request)) {
|
||||
mux.HandleFunc(apiServerPathPrefix+"/"+name, ser.basicAuth(f))
|
||||
}
|
||||
|
||||
func (ser *apiServer) basicAuth(realfunc http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if ser.nopass {
|
||||
realfunc.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
thisun, thispass, ok := r.BasicAuth()
|
||||
if ok {
|
||||
usernameHash := sha256.Sum256([]byte(thisun))
|
||||
|
||||
@@ -251,12 +251,12 @@ func generateConfigFileInteractively() {
|
||||
switch ihot {
|
||||
case 0:
|
||||
|
||||
hotLoadDialConfForRuntime("", confServer.Dial)
|
||||
hotLoadListenConfForRuntime(confServer.Listen)
|
||||
hotLoadDialConf("", confServer.Dial)
|
||||
hotLoadListenConf(confServer.Listen)
|
||||
|
||||
case 1:
|
||||
hotLoadDialConfForRuntime("", confClient.Dial)
|
||||
hotLoadListenConfForRuntime(confClient.Listen)
|
||||
hotLoadDialConf("", confClient.Dial)
|
||||
hotLoadListenConf(confClient.Listen)
|
||||
}
|
||||
|
||||
utils.PrintStr("加载成功!你可以回退(ctrl+c)到上级来使用 【查询当前状态】来查询新增的配置\n")
|
||||
@@ -430,52 +430,11 @@ func interactively_hotLoadUrlConfig() {
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
dc := &proxy.DialConf{}
|
||||
dc.Protocol = sn
|
||||
|
||||
dc.TLS = okTls
|
||||
err = proxy.URLToDialConf(u, dc)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
dc, err = creator.URLToDialConf(u, dc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
hotLoadDialConfForRuntime("", []*proxy.DialConf{dc})
|
||||
hotLoadDialUrl(theUrlStr)
|
||||
|
||||
} else {
|
||||
hotLoadListenUrl(theUrlStr)
|
||||
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
lc := &proxy.ListenConf{}
|
||||
lc.Protocol = sn
|
||||
|
||||
lc.TLS = okTls
|
||||
|
||||
err = proxy.URLToListenConf(u, lc)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return
|
||||
}
|
||||
lc, err = creator.URLToListenConf(u, lc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return
|
||||
}
|
||||
hotLoadListenConfForRuntime([]*proxy.ListenConf{lc})
|
||||
}
|
||||
return
|
||||
|
||||
@@ -536,12 +495,12 @@ func interactively_hotLoadConfigFile() {
|
||||
switch confMode {
|
||||
case proxy.StandardMode:
|
||||
if len(standardConf.Dial) > 0 {
|
||||
hotLoadDialConfForRuntime("", standardConf.Dial)
|
||||
hotLoadDialConf("", standardConf.Dial)
|
||||
|
||||
}
|
||||
|
||||
if len(standardConf.Listen) > 0 {
|
||||
hotLoadListenConfForRuntime(standardConf.Listen)
|
||||
hotLoadListenConf(standardConf.Listen)
|
||||
|
||||
}
|
||||
case proxy.SimpleMode:
|
||||
|
||||
@@ -276,7 +276,9 @@ func tryDownloadGeositeSource() {
|
||||
|
||||
}
|
||||
|
||||
func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) {
|
||||
func hotLoadDialConf(Default_uuid string, conf []*proxy.DialConf) (ok bool) {
|
||||
ok = true
|
||||
|
||||
for _, d := range conf {
|
||||
|
||||
if d.Uuid == "" && Default_uuid != "" {
|
||||
@@ -288,6 +290,7 @@ func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) {
|
||||
if ce := utils.CanLogErr("can not create outClient: "); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
ok = false
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -307,9 +310,11 @@ func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) {
|
||||
defaultOutClient = vs.DirectClient
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) {
|
||||
func hotLoadListenConf(conf []*proxy.ListenConf) (ok bool) {
|
||||
ok = true
|
||||
|
||||
if defaultOutClient == nil {
|
||||
defaultOutClient = vs.DirectClient
|
||||
@@ -319,7 +324,8 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) {
|
||||
inServer, err := proxy.NewServer(l)
|
||||
if err != nil {
|
||||
log.Println("can not create inServer: ", i, err)
|
||||
return
|
||||
ok = false
|
||||
continue
|
||||
}
|
||||
lis := vs.ListenSer(inServer, defaultOutClient, &routingEnv)
|
||||
if lis != nil {
|
||||
@@ -330,6 +336,63 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) {
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func hotLoadDialUrl(theUrlStr string) error {
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
dc := &proxy.DialConf{}
|
||||
dc.Protocol = sn
|
||||
|
||||
dc.TLS = okTls
|
||||
err = proxy.URLToDialConf(u, dc)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
dc, err = creator.URLToDialConf(u, dc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !hotLoadDialConf("", []*proxy.DialConf{dc}) {
|
||||
return utils.ErrFailed
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func hotLoadListenUrl(theUrlStr string) error {
|
||||
u, sn, creator, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
lc := &proxy.ListenConf{}
|
||||
lc.Protocol = sn
|
||||
|
||||
lc.TLS = okTls
|
||||
|
||||
err = proxy.URLToListenConf(u, lc)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
lc, err = creator.URLToListenConf(u, lc, proxy.UrlStandardFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("parse url step 2 failed %v\n", err)
|
||||
return err
|
||||
}
|
||||
if !hotLoadListenConf([]*proxy.ListenConf{lc}) {
|
||||
return utils.ErrFailed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadSimpleServer() (result int, server proxy.Server) {
|
||||
|
||||
@@ -362,7 +362,7 @@ func mainFunc() (result int) {
|
||||
break
|
||||
}
|
||||
|
||||
hotLoadDialConfForRuntime(Default_uuid, standardConf.Dial)
|
||||
hotLoadDialConf(Default_uuid, standardConf.Dial)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,11 +44,16 @@ func AnyToBool(a any) (v bool, ok bool) {
|
||||
v = true
|
||||
}
|
||||
case string:
|
||||
if StrNegative(value) {
|
||||
v = false
|
||||
} else if StrPositive(value) {
|
||||
v = true
|
||||
if b, e := strconv.ParseBool(value); e == nil {
|
||||
v = b
|
||||
} else {
|
||||
if StrNegative(value) {
|
||||
v = false
|
||||
} else if StrPositive(value) {
|
||||
v = true
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
var i64 int64
|
||||
i64, ok = AnyToInt64(a)
|
||||
|
||||
Reference in New Issue
Block a user