1
0
forked from x/ContextOS
This commit is contained in:
shaoying 2019-02-12 08:18:49 +08:00
parent 84b27c3d17
commit 75e93fc315
12 changed files with 490 additions and 271 deletions

View File

@ -5,9 +5,6 @@ export ctx_root="/usr/local/context"
export ctx_home=~/context
export ctx_bin="bench"
export user_cert=etc/user/cert.pem
export user_key=etc/user/key.pem
log() {
echo -e $*
}

View File

@ -5,9 +5,6 @@ export ctx_root="/usr/local/context"
export ctx_home=~/context
export ctx_bin="bench"
export user_cert=etc/user/cert.pem
export user_key=etc/user/key.pem
log() {
echo -e $*
}

View File

@ -1,3 +1,5 @@
source common.shy
~ssh
remote auto
source local.shy

View File

@ -126,6 +126,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
"auth_type": &ctx.Config{Name: "auth_type", Value: map[string]interface{}{
"session": map[string]interface{}{"unique": true},
"bench": map[string]interface{}{"unique": true},
"cert": map[string]interface{}{"public": true},
"username": map[string]interface{}{"public": true},
"userrole": map[string]interface{}{"public": true},
"password": map[string]interface{}{"secrete": true, "single": true},
@ -141,6 +142,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
},
Commands: map[string]*ctx.Command{
"init": &ctx.Command{Name: "init", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Conf("runtime", "node.cert", m.Cmdx("nfs.load", os.Getenv("node_cert")))
m.Conf("runtime", "node.key", m.Cmdx("nfs.load", os.Getenv("node_key")))
m.Conf("runtime", "user.cert", m.Cmdx("nfs.load", os.Getenv("user_cert")))
m.Conf("runtime", "user.key", m.Cmdx("nfs.load", os.Getenv("user_key")))
return
@ -508,7 +511,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
case 2: // 查看会话
m.Cmdy("aaa.auth", "ship", "username", arg[0], "session", arg[1])
case 3: // 用户认证
if m.Cmds("aaa.auth", "ship", "username", arg[0]) && (arg[1] == "password" || arg[1] == "uuid") {
if (arg[1] == "password" || arg[1] == "uuid") && m.Cmds("aaa.auth", "ship", "username", arg[0]) {
m.Cmdy("aaa.auth", "username", arg[0], arg[1], arg[2])
break
}
@ -697,8 +700,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
template := x509.Certificate{
SerialNumber: big.NewInt(1),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign,
Subject: pkix.Name{CommonName: kit.Format(common)},
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign,
Subject: pkix.Name{CommonName: kit.Format(common)},
}
cert, e := x509.CreateCertificate(crand.Reader, &template, &template, &keys.PublicKey, keys)
m.Assert(e)
@ -797,26 +801,36 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
var common interface{}
json.Unmarshal([]byte(cert.Subject.CommonName), &common)
m.Put("option", "common", common).Cmdy("ctx.trans", "common", "format", "object")
case "grant":
private, e := x509.ParsePKCS1PrivateKey(aaa.Decode(arg[1]))
m.Assert(e)
parent, e := x509.ParseCertificate(aaa.Decode(arg[2]))
m.Assert(e)
for _, v := range arg[3:] {
template, e := x509.ParseCertificate(aaa.Decode(v))
m.Assert(e)
cert, e := x509.CreateCertificate(crand.Reader, template, parent, template.PublicKey, private)
m.Assert(e)
certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert}))
m.Echo(certificate)
}
case "check":
defer func() {
recover()
}()
root, e := x509.ParseCertificate(aaa.Decode(arg[1]))
parent, e := x509.ParseCertificate(aaa.Decode(arg[1]))
m.Assert(e)
cert, e := x509.ParseCertificate(aaa.Decode(arg[2]))
m.Assert(e)
for _, v := range arg[2:] {
template, e := x509.ParseCertificate(aaa.Decode(v))
m.Assert(e)
// ee := cert.CheckSignatureFrom(root)
// m.Echo("%v", ee)
//
pool := &x509.CertPool{}
m.Echo("%c", pool)
pool.AddCert(root)
c, e := cert.Verify(x509.VerifyOptions{Roots: pool})
m.Echo("%c", c)
if e = template.CheckSignatureFrom(parent); e != nil {
m.Echo("error: ").Echo("%v", e)
}
}
m.Echo("true")
}
}
return

View File

@ -149,16 +149,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Confm("runtime", "init_env", func(index int, key string) {
m.Conf("runtime", key, os.Getenv(key))
})
if m.Confs("runtime", "ctx_box") {
m.Conf("runtime", "node.type", "worker")
m.Conf("runtime", "node.name", m.Conf("runtime", "pathname"))
} else {
m.Conf("runtime", "node.type", "server")
m.Conf("runtime", "node.name", strings.Replace(m.Conf("runtime", "hostname"), ".", "_", -1))
}
m.Conf("runtime", "node.route", m.Conf("runtime", "node.name"))
return
}},
"source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {

View File

@ -90,7 +90,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
},
Commands: map[string]*Command{
"init": &Command{Name: "init", Help: "启动", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
for _, x := range []string{"cli", "yac", "nfs", "aaa", "log", "web", "gdb"} {
for _, x := range []string{"cli", "yac", "nfs", "aaa", "log", "ssh", "web", "gdb"} {
m.Cmd(x + ".init")
}
return

View File

@ -1323,7 +1323,12 @@ func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg
})
m.Log("sync", m.Format("wait", "result", "append"))
return <-wait
select {
case <-time.After(kit.Duration("30s")):
m.Log("sync", m.Format("timeout", "result", "append"))
case <-wait:
}
return m
}
func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
if len(cbs) == 0 {
@ -1364,6 +1369,7 @@ func (m *Message) Cmd(args ...interface{}) *Message {
if strings.Contains(key, ".") {
arg := strings.Split(key, ".")
m, key = m.Sess(arg[0]), arg[1]
m.Option("remote_code", "")
}
if m == nil {
return m
@ -1454,7 +1460,6 @@ func (m *Message) Confm(key string, args ...interface{}) map[string]interface{}
if len(args) == 0 {
return value
}
switch fun := args[0].(type) {
case func(int, string):
for i, v := range table {
@ -1477,6 +1482,9 @@ func (m *Message) Confm(key string, args ...interface{}) map[string]interface{}
}
}
case func(map[string]interface{}):
if len(value) == 0 {
return nil
}
fun(value)
case func(string, map[string]interface{}):
for k, v := range value {

View File

@ -128,12 +128,13 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
"call": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}},
"back": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}},
"right": map[string]interface{}{"value": map[string]interface{}{"file": "right.log", "meta": []interface{}{"time", "ship"}}},
"bench": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}}},
"begin": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"start": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"close": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"warn": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[33m", "color_end": "\033[0m"}},
"right": map[string]interface{}{"value": map[string]interface{}{"file": "right.log", "meta": []interface{}{"time", "ship"}}},
"cmd": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"},
"lex": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}},

View File

@ -150,8 +150,12 @@ func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) {
flag = arg[0]
}
m.Log("info", "open %s", name)
f, e := os.OpenFile(name, flag, 0660)
if e == nil {
m.Log("info", "open %s", name)
return name, f, e
}
m.Log("warn", "%v", e)
return name, f, e
}
func Format(args ...interface{}) string {
@ -929,14 +933,14 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
nfs.echo = make(chan *ctx.Message, 10)
nfs.hand = map[int]*ctx.Message{}
// 消息发送队列
m.GoLoop(m, func(m *ctx.Message) {
msg, code, meta, body := m, 0, "detail", "option"
select {
case msg = <-nfs.send:
case msg = <-nfs.send: // 发送请求
code = msg.Code()
nfs.hand[code] = msg
msg.Option("username", m.Conf("runtime", "USER"))
case msg = <-nfs.echo:
case msg = <-nfs.echo: // 发送响应
code, meta, body = msg.Optioni("remote_code"), "result", "append"
}
@ -952,7 +956,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
nfs.Send("")
})
//接收消息队列
// 消息接收队列
msg, code, head, body := m, "0", "result", "append"
for bio := bufio.NewScanner(nfs.io); bio.Scan(); {
@ -971,16 +975,20 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
msg.Add(field, value)
case "":
m.Log("recv", "time %v", time.Now().Format(m.Conf("time_format")))
if head == "detail" { // 接收请求
msg.Detail(-1, "remote")
msg.Option("remote_code", code)
msg.Call(func(msg *ctx.Message) *ctx.Message {
go msg.Call(func(msg *ctx.Message) *ctx.Message {
nfs.echo <- msg
return nil
})
} else { // 接收响应
h := nfs.hand[kit.Int(code)]
h.Copy(msg, "result").Copy(msg, "append").Back(h)
h.Copy(msg, "result").Copy(msg, "append")
go func() {
h.Back(h)
}()
}
msg, code, head, body = nil, "0", "result", "append"
@ -1269,7 +1277,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
return
}},
"load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if p, f, e := open(m, arg[0]); m.Assert(e) {
if p, f, e := open(m, arg[0]); e == nil {
defer f.Close()
pos := kit.Int(kit.Select("0", arg, 2))
@ -1518,7 +1526,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"remote": &ctx.Command{Name: "remote listen|dial args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{
m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message {
if sub.Has("hostport") {
if sub.Has("node.port") {
return sub
}
sub.Sess("ms_source", sub)

View File

@ -34,270 +34,448 @@ func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
Caches: map[string]*ctx.Cache{
"nnode": &ctx.Cache{Name: "nnode", Value: "0", Help: "节点数量"},
"nodename": &ctx.Cache{Name: "nodename", Value: "dev", Help: "本机域名"},
"nnode": &ctx.Cache{Name: "nnode", Value: "0", Help: "节点数量"},
},
Configs: map[string]*ctx.Config{
"node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "主机信息"},
"hostport": &ctx.Config{Name: "hostport", Value: "", Help: "主机域名"},
"current": &ctx.Config{Name: "current", Value: "", Help: "当前主机"},
"timer": &ctx.Config{Name: "timer", Value: "", Help: "当前主机"},
"node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "主机信息"},
"current": &ctx.Config{Name: "current", Value: "", Help: "当前主机"},
"timer": &ctx.Config{Name: "timer", Value: "", Help: "断线重连"},
"timer_interval": &ctx.Config{Name: "timer_interval", Value: "10s", Help: "断线重连"},
},
Commands: map[string]*ctx.Command{
"remote": &ctx.Command{Name: "remote listen|dial args...", Help: "远程连接", Form: map[string]int{"right": 1, "nodename": 1, "nodetype": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 { // 查看主机
"init": &ctx.Command{Name: "init", Help: "启动", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Confs("runtime", "ctx_box") {
m.Conf("runtime", "node.type", "worker")
m.Conf("runtime", "node.name", m.Conf("runtime", "pathname"))
} else {
m.Conf("runtime", "node.type", "server")
m.Conf("runtime", "node.name", strings.Replace(strings.TrimSuffix(m.Conf("runtime", "hostname"), ".local"), ".", "_", -1))
}
m.Conf("runtime", "node.route", m.Conf("runtime", "node.name"))
m.Conf("runtime", "user.name", m.Conf("runtime", "USER"))
return
}},
"remote": &ctx.Command{Name: "remote auto|dial|listen args...", Help: "远程连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ctx.config", "node")
return
}
if !m.Confs("runtime", "node.cert") { // 设备证书
// 设备证书
if !m.Confs("runtime", "node.cert") || !m.Confs("runtime", "node.key") {
msg := m.Cmd("aaa.rsa", "gen", "common", m.Confv("runtime", "node"))
m.Conf("runtime", "node.cert", msg.Append("certificate"))
m.Conf("runtime", "node.key", msg.Append("private"))
}
if !m.Confs("runtime", "user.cert") { // 用户证书
msg := m.Cmd("aaa.rsa", "gen", "common", m.Confv("runtime", "user"))
m.Conf("runtime", "user.cert", msg.Append("certificate"))
m.Conf("runtime", "user.key", msg.Append("private"))
}
switch arg[0] {
case "auto":
case "auto": // 自动连接
if m.Cmd("ssh.remote", "dial", "consul", "/shadow"); !m.Confs("runtime", "ctx_box") {
m.Cmd("ssh.remote", "listen", m.Conf("runtime", "ssh_port"))
m.Cmd("web.serve", "usr", m.Conf("runtime", "web_port"))
}
case "listen":
case "listen": // 监听连接
m.Call(func(nfs *ctx.Message) *ctx.Message {
if nfs.Has("hostport") {
m.Log("info", "ssh_ports %v", nfs.Optionv("hostport"))
m.Conf("runtime", "ssh_ports", nfs.Optionv("hostport"))
if !m.Confs("runtime", "node.sess") { // 注册设备
m.Conf("runtime", "node.sess", m.Cmdx("web.get", "dev", "/login", "cert", m.Confv("runtime", "node.cert"), "temp", "sess.0"))
}
if nfs.Has("node.port") {
m.Log("info", "node.port %v", nfs.Optionv("node.port"))
m.Conf("runtime", "node.port", nfs.Optionv("node.port"))
}
// 创建会话
sess := m.Cmd("aaa.auth", "nodes", m.Conf("runtime", "node.route"), "session", "nodes").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "nodes", "nodes", m.Conf("runtime", "node.route"))
m.Cmd("aaa.auth", "nodes", m.Conf("runtime", "node.route"), "cert", m.Conf("runtime", "node.cert"))
}
m.Cmd("aaa.auth", "username", m.Conf("runtime", "USER"), "userrole", "root")
m.Cmdx("aaa.sess", sess, m.Conf("runtime", "USER"), "cert", m.Conf("runtime", "user.cert"))
return nil
}, "nfs.remote", arg)
case "redial": // 断线重连
if !m.Caps("nodename") {
if !m.Caps("stream") {
m.Cmdx("remote", "dial", arg[1:])
}
case "dial":
case "dial": // 连接主机
m.Call(func(nfs *ctx.Message) *ctx.Message {
if m.Confs("timer") { // 断线重连
// 断线重连
if m.Confs("timer") {
m.Conf("timer", m.Cmdx("cli.timer", "delete", m.Conf("timer")))
}
msg := m.Spawn(nfs.Target())
msg.Option("node.cert", m.Conf("runtime", "node.cert"))
msg.Option("user.cert", m.Conf("runtime", "user.cert"))
if m.Confs("runtime", "user.cert") {
msg.Option("user.route", kit.Select(m.Conf("runtime", "user.route"), m.Conf("runtime", "user.route")))
}
msg.Call(func(node *ctx.Message) *ctx.Message {
m.Confv("node", node.Result(1), map[string]interface{}{ // 添加主机
// 添加主机
m.Confv("node", node.Append("node.name"), map[string]interface{}{
"module": m.Cap("stream", nfs.Format("target")),
"create_time": m.Time(),
"access_time": m.Time(),
"nodename": node.Result(1),
"nodetype": "master",
"module": nfs.Format("target"),
"username": m.Option("right"),
"cm_target": "ctx.web.code",
"node": map[string]interface{}{
"name": node.Append("node.name"),
"type": "master",
},
})
m.Conf("runtime", "node.route", node.Result(2)+"."+node.Result(0))
if !m.Confs("runtime", "node.sess") { // 设备注册
if !m.Confs("runtime", "node.cert") {
msg := m.Cmd("aaa.rsa", "gen", "common", m.Confv("runtime", "node"))
m.Conf("runtime", "node.cert", msg.Append("certificate"))
m.Conf("runtime", "node.key", msg.Append("private"))
m.Log("fuck", "what %v", node.Meta)
// 主机路由
m.Conf("runtime", "node.route", node.Append("node.route")+"."+node.Result(0))
if !m.Confs("runtime", "user.route") {
if m.Confs("runtime", "user.cert") && m.Confs("runtime", "user.key") {
m.Cmd("ssh.share", "root", m.Conf("runtime", "node.route"))
m.Log("fuck", "what %v", 123)
m.Log("fuck", "what %v", node.Meta)
if !node.Appends("user.route") {
m.Log("fuck", "what %v", 123)
m.Cmd("ssh.share", node.Append("node.route"), "root", m.Conf("runtime", "node.route"))
}
} else if node.Appends("user.route") {
m.Cmd("ssh.share", "root", node.Append("user.route"))
}
m.Conf("runtime", "node.sess", m.Cmdx("web.get", "dev", "/login",
"cert", m.Confv("runtime", "node.cert"), "temp", "sess.0"))
}
if !m.Confs("runtime", "user.name") && m.Confs("runtime", "user.key") { // 用户注册
user := m.Cmd("web.get", "dev", "/login", "username", m.Conf("runtime", "USER"),
"user.cert", m.Conf("runtime", "user.cert"), "temp", "data", "format", "object")
m.Conf("runtime", "user.name", user.Append("username"))
}
if m.Confs("runtime", "user.name") { // 绑定用户
msg := m.Cmd("web.get", "dev", "/login", "username", m.Conf("runtime", "user.name"),
"bind", m.Conf("runtime", "node.route"), "code", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), m.Conf("runtime", "node.route")), "temp", "data", "format", "object")
m.Cmd("aaa.auth", "username", m.Conf("runtime", "user.name"), "userrole", msg.Append("userrole"))
}
m.Cap("stream", nfs.Format("target"))
// 默认节点
if !m.Confs("current") {
m.Conf("current", node.Result(1))
m.Conf("current", node.Append("node.name"))
}
nfs.Free(func(nfs *ctx.Message) bool { // 连接中断
m.Conf("timer", m.Cmdx("cli.timer", "repeat", "10s", "context", "ssh", "remote", "redial", arg[1:]))
// 清理主机
nfs.Free(func(nfs *ctx.Message) bool {
m.Conf("timer", m.Cmdx("cli.timer", "repeat", m.Conf("timer_interval"), "context", "ssh", "remote", "redial", arg[1:]))
m.Log("info", "delete node %s", node.Result(1))
delete(m.Confm("node"), node.Result(1))
m.Cap("nodename", "")
m.Log("info", "delete node %s", node.Append("node.name"))
delete(m.Confm("node"), node.Append("node.name"))
m.Cap("stream", "")
return true
})
return nil
}, "send", "recv", "add", m.Conf("runtime", "node.name"), m.Conf("runtime", "node.type"))
}, "send", "recv", "add", m.Conf("runtime", "node.name"), m.Conf("runtime", "node.type"), m.Conf("runtime", "node.cert"))
return nil
}, "nfs.remote", arg)
case "recv":
switch arg[1] {
case "add":
if node := m.Confm("node", arg[2]); node == nil { // 添加主机
m.Confv("node", arg[2], map[string]interface{}{
"create_time": m.Time(),
"access_time": m.Time(),
"nodename": arg[2],
"nodetype": arg[3],
"module": m.Format("source"),
"username": m.Option("right"),
"cm_target": "ctx.web.code",
})
} else if len(arg) > 3 && arg[3] == kit.Format(node["token"]) { // 断线重连
node["access_time"] = m.Time()
node["module"] = m.Format("source")
} else { // 域名冲突
arg[2] = fmt.Sprintf("%s_%d", arg[2], m.Capi("nnode", 1))
m.Confv("node", arg[2], map[string]interface{}{
"create_time": m.Time(),
"access_time": m.Time(),
"nodename": arg[2],
"nodetype": arg[3],
"module": m.Format("source"),
"username": m.Option("right"),
"cm_target": "ctx.web.code",
})
// 节点命名
name := arg[2]
for node := m.Confm("node", name); node != nil; node = m.Confm("node", name) {
name = fmt.Sprintf("%s_%d", arg[2], m.Capi("nnode", 1))
}
info := map[string]string{}
if len(arg) > 4 && m.Cmds("aaa.rsa", "check", m.Conf("runtime", "node.cert"), arg[4]) {
m.Cmd("aaa.rsa", "info", arg[4]).Table(func(line map[string]string) {
for k, v := range line {
info[k] = v
}
})
}
m.Log("info", "info--- %v", info)
// 添加节点
m.Confv("node", name, map[string]interface{}{
"module": m.Format("source"),
"create_time": m.Time(),
"node": map[string]interface{}{
"name": name,
"type": arg[3],
},
})
// 节点路由
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Append("user.route", m.Conf("runtime", "user.route"))
m.Append("node.route", m.Conf("runtime", "node.route"))
m.Append("node.name", m.Conf("runtime", "node.name"))
m.Echo(name).Back(m)
// 默认节点
if !m.Confs("current") {
m.Conf("current", arg[2])
m.Conf("current", name)
}
m.Echo(arg[2]).Echo(m.Conf("runtime", "node.name")).Echo(m.Conf("runtime", "node.route")).Back(m)
m.Sess("ms_source", false).Free(func(msg *ctx.Message) bool { // 断线清理
m.Log("info", "delete node %s", arg[2])
delete(m.Confm("node"), arg[2])
// 清理节点
m.Sess("ms_source", false).Free(func(msg *ctx.Message) bool {
m.Log("info", "delete node %s", name)
delete(m.Confm("node"), name)
return true
})
}
default:
if !m.Options("sign_source") { // 数字签名
hash, meta := kit.Hash("rand",
m.Option("sign_time", m.Time("stamp")),
m.Option("sign_username", m.Option("username")),
m.Option("sign_source", m.Conf("runtime", "node.route")),
m.Option("sign_target", arg[0]),
m.Option("sign_cmd", strings.Join(arg[1:], " ")),
)
m.Option("sign_rand", meta[0])
m.Option("sign_code", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "node.key"), m.Option("sign_hash", hash)))
// 拆分路由
if arg[0] == m.Conf("runtime", "node.name") || arg[0] == m.Conf("runtime", "node.route") {
arg[0] = ""
}
arg[0] = strings.TrimPrefix(arg[0], m.Conf("runtime", "node.route")+".")
route, names, arg := arg[0], strings.SplitN(arg[0], ".", 2), arg[1:]
if len(names) > 1 && names[0] == "" && names[1] != "" {
names[0], names[1] = names[1], names[0]
}
names, arg := strings.SplitN(arg[0], ".", 2), arg[1:]
if names[0] == "" { // 本地执行
hash, _ := kit.Hash(
m.Option("sign_rand"),
m.Option("sign_time"),
m.Option("sign_username"),
m.Option("sign_source"),
m.Option("sign_target"),
m.Option("sign_cmd"),
)
// 创建会话
if m.Option("sessid", m.Cmd("aaa.auth", "nodes", m.Option("sign_source"), "session").Append("key")); !m.Options("sessid") {
m.Option("sessid", m.Cmdx("aaa.sess", "nodes", "nodes", m.Option("sign_source")))
}
// 绑定设备
m.Option("username", m.Cmd("aaa.sess", m.Option("sessid"), "username").Append("meta"))
if !m.Options("username") || !m.Cmds("aaa.auth", "nodes", m.Option("sign_source"), "cert") {
msg := m.Cmd("web.get", "dev", "/login", "pull", m.Option("sign_source"), "temp", "data", "format", "object")
if m.Cmds("aaa.auth", "nodes", m.Option("sign_source"), "cert", msg.Append("cert")); m.Appends("username") {
m.Cmds("aaa.auth", m.Option("sessid"), "username", m.Option("username", msg.Append("username")))
} else {
m.Log("fuck", "no username")
}
}
// 验证签名
if !m.Cmds("aaa.rsa", "verify", m.Cmd("aaa.auth", "nodes", m.Option("sign_source"), "cert").Append("meta"), m.Option("sign_code"), hash) {
m.Log("fuck", "sign failure")
return
}
// 创建空间
if m.Option("bench", m.Cmd("aaa.sess", m.Option("sessid"), "bench").Append("key")); !m.Options("bench") {
m.Option("bench", m.Cmdx("aaa.work", m.Option("sessid"), "nodes"))
}
m.Option("current_ctx", kit.Select("ssh", m.Cmdx("aaa.auth", m.Option("bench"), "data", "target")))
if m.Cmds("aaa.work", m.Option("bench"), "right", m.Option("username"), "remote", arg[0]) { // 执行命令
msg := m.Find(m.Option("current_ctx")).Cmd(arg).CopyTo(m)
m.Cmd("aaa.auth", m.Option("bench"), "data", "target", msg.Cap("module"))
} else {
m.Echo("no right %s %s", "remote", arg[0])
}
// 返回结果
m.Back(m)
return
}
//同步或异步
// 同步异步
sync := !m.Options("remote_code")
switch arg[0] {
case "async", "sync":
sync, arg = arg[0] == "sync", arg[1:]
}
rest := kit.Select("", names, 1)
m.Option("username", m.Option("username"))
m.Option("nodename", m.Conf("runtime", "node.name"))
// 路由转发
if rest := kit.Select("", names, 1); names[0] != "" {
// 数字签名
if !m.Options("remote_code") {
// 用户路由
m.Option("user.route", kit.Select(m.Conf("runtime", "node.route"), m.Conf("runtime", "user.route")))
m.Cmd("aaa.auth", "username", m.Option("username"), "session", "login").Table(func(line map[string]string) {
m.Option("user.route", m.Cmd("aaa.auth", line["key"], "login").Append("meta"))
})
if names[0] == "*" { // 广播命令
m.Confm("node", func(name string, node map[string]interface{}) {
// 数据哈希
hash, meta := kit.Hash("rand",
m.Option("text.time", m.Time("stamp")),
m.Option("text.cmd", strings.Join(arg, " ")),
m.Option("text.route", route),
m.Option("node.route", m.Conf("runtime", "node.route")),
m.Option("user.route"),
m.Option("user.name", m.Option("username")),
)
m.Option("text.rand", meta[0])
// 设备签名
m.Option("node.sign", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "node.key"), m.Option("text.hash", hash)))
// 用户签名
if m.Options("user.sign") && m.Confs("runtime", "user.key") {
m.Option("user.sign", m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), m.Option("text.hash", hash)))
}
}
if names[0] == "*" { // 广播命令
m.Confm("node", func(name string, node map[string]interface{}) {
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", "", arg)
})
} else if m.Confm("node", names[0], func(node map[string]interface{}) { // 单播命令
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", "", arg)
})
}, "send", rest, arg)
} else if m.Confm("node", names[0], func(node map[string]interface{}) { // 单播命令
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", rest, arg)
}) == nil { // 回溯命令
m.Find(m.Cap("stream"), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", strings.Join(names, "."), arg)
}
return
}
}) == nil { // 回溯命令
m.Find(m.Cap("stream"), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", strings.Join(names, "."), arg)
// 返回结果
defer func() { m.Back(m) }()
// 查看证书
switch arg[0] {
case "check":
switch arg[1] {
case "node": // 设备证书
m.Echo(m.Conf("runtime", "node.cert"))
case "user":
if len(arg) == 2 { // 用户证书
m.Append("user.cert", m.Conf("runtime", "user.cert"))
m.Append("user.name", m.Conf("runtime", "user.name"))
m.Append("user.route", kit.Select(m.Conf("runtime", "node.route"), m.Conf("runtime", "user.route")))
} else { // 代理验证
if arg[2] == m.Conf("runtime", "node.route") || m.Cmds("aaa.auth", "proxy", arg[2]) {
m.Echo(m.Cmdx("aaa.rsa", "sign", m.Conf("runtime", "user.key"), arg[3]))
}
}
}
return
}
if m.Options("remote_code") {
// 检查数据
hash, _ := kit.Hash(
m.Option("text.rand"),
m.Option("text.time"),
m.Option("text.cmd"),
m.Option("text.route"),
m.Option("node.route"),
m.Option("user.route"),
m.Option("user.name"),
)
if m.Option("text.hash") != hash {
m.Log("warning", "text error")
return
}
// 设备证书
m.Option("node.cert", m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert").Append("meta"))
if !m.Options("node.cert") {
m.Option("node.cert", m.Spawn().Cmdx("ssh.remote", m.Option("node.route"), "sync", "check", "node"))
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "cert", m.Option("node.cert"))
}
// 设备验签
if !m.Cmds("aaa.rsa", "verify", m.Option("node.cert"), m.Option("node.sign"), m.Option("text.hash", hash)) {
m.Log("warning", "node error")
return
}
} else {
m.Option("user.name", m.Conf("runtime", "user.name"))
}
switch arg[0] {
case "login": // 用户代理
if !m.Cmds("aaa.auth", "proxy", m.Option("node.route")) {
return
}
sess := m.Cmd("aaa.auth", "username", m.Option("user.name"), "session", "proxy").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "proxy", "username", m.Option("user.name"))
}
m.Cmd("aaa.auth", sess, "proxy", m.Option("node.route"))
m.Echo(sess)
return
case "share": // 设备权限
// 默认用户
if !m.Confs("runtime", "user.route") {
user := m.Spawn().Cmd("ssh.remote", m.Option("user.route"), "sync", "check", "user")
m.Conf("runtime", "user.route", user.Append("user.route"))
m.Conf("runtime", "user.name", user.Append("user.name"))
m.Conf("runtime", "user.cert", user.Append("user.cert"))
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
m.Cmd("aaa.user", "root", user.Append("user.name"), "what")
return
}
// 共享用户
if !m.Options("remote_code") || (m.Options("user.sign") && m.Conf("runtime", "user.name") == m.Option("user.name")) {
if !m.Options("remote_code") || m.Cmds("aaa.rsa", "verify", m.Conf("runtime", "user.cert"), m.Option("user.sign"), m.Option("text.hash")) {
for _, v := range arg[2:] {
user := m.Spawn().Cmd("ssh.remote", v, "sync", "check", "user")
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
m.Cmd("aaa.user", arg[1], user.Append("user.name"), "what")
}
return
}
}
// 申请权限
m.Spawn().Set("option", "remote_code", "").Cmds("ssh.remote", m.Conf("runtime", "user.route"), "sync", "apply", arg[1:])
return
case "apply": // 权限申请
for _, v := range arg[2:] {
user := m.Spawn().Cmd("ssh.remote", v, "sync", "check", "user")
m.Cmd("aaa.auth", "username", user.Append("user.name"), "cert", user.Append("user.cert"))
sess := m.Cmd("aaa.auth", "username", user.Append("user.name"), "session", "apply").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "apply", "username", arg[2])
}
m.Cmd("aaa.auth", sess, "apply", m.Option("node.route"))
m.Cmd("aaa.auth", sess, "share", user.Append("user.route"))
}
return
}
// 检查会话
m.Option("sessid", "")
m.Cmd("aaa.auth", "nodes", m.Option("node.route"), "session").Table(func(line map[string]string) {
if m.Cmds("aaa.auth", line["key"], "username", m.Option("user.name")) {
m.Option("sessid", line["key"])
}
})
if m.Options("remote_code") {
if !m.Options("sessid") {
// 用户签名
hash, _ := kit.Hash("rand", m.Option("text.time", m.Time("stamp")), m.Option("node.route"))
m.Option("user.cert", m.Cmd("aaa.auth", "username", m.Option("user.name"), "cert").Append("meta"))
m.Option("user.sign", m.Spawn().Cmdx("ssh.remote", m.Option("user.route"), "sync", "check", "user", m.Option("node.route"), hash))
// 代理验签
if !m.Options("user.cert") || !m.Options("user.sign") || !m.Cmds("aaa.rsa", "verify", m.Option("user.cert"), m.Option("user.sign"), hash) {
m.Log("warn", "user error")
return
}
// 创建会话
m.Option("sessid", m.Cmdx("aaa.sess", "nodes", "username", m.Option("user.name")))
m.Cmd("aaa.auth", m.Option("sessid"), "nodes", m.Option("node.route"))
}
// 创建空间
if m.Option("bench", m.Cmd("aaa.sess", m.Option("sessid"), "bench").Append("key")); !m.Options("bench") {
m.Option("bench", m.Cmdx("aaa.work", m.Option("sessid"), "nodes"))
}
}
if !m.Options("remote_code") || m.Cmds("aaa.work", m.Option("bench"), "right", m.Option("user.name"), "remote", arg[0]) {
m.Option("username", m.Option("user.name"))
m.Option("current_ctx", kit.Select("ssh", m.Cmdx("aaa.auth", m.Option("bench"), "data", "target")))
// 执行命令
msg := m.Find(m.Option("current_ctx")).Cmd(arg).CopyTo(m)
m.Cmd("aaa.auth", m.Option("bench"), "data", "target", msg.Cap("module"))
} else {
m.Echo("no right %s %s", "remote", arg[0])
}
}
return
}},
"proxy": &ctx.Command{Name: "proxy [proxy.route]", Help: "代理节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmd("aaa.auth", "proxy")
return
}
m.Cmd("aaa.auth", "proxy", arg[0])
return
}},
"login": &ctx.Command{Name: "login client.route", Help: "用户节点", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmd("aaa.auth", "login")
return
}
if !m.Cmds("ssh.remote", arg[0], "login") {
m.Echo("error: ").Echo("login failure")
return
}
sess := m.Cmd("aaa.auth", "username", m.Option("username"), "session", "login").Append("key")
if sess == "" {
sess = m.Cmdx("aaa.sess", "login", "username", m.Option("username"))
}
m.Cmd("aaa.auth", sess, "login", arg[0])
m.Echo(sess)
return
}},
"share": &ctx.Command{Name: "share serve.route role client.route...", Help: "共享权限", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmd("aaa.auth", "apply").Table(func(node map[string]string) {
m.Cmd("aaa.auth", node["key"], "session", "apply").Table(func(sess map[string]string) {
m.Cmd("aaa.auth", sess["key"], "username").Table(func(user map[string]string) {
m.Add("append", "time", sess["create_time"])
m.Add("append", "user", user["meta"])
m.Add("append", "node", node["meta"])
})
})
})
m.Table()
return
}
if len(arg) == 2 {
m.Option("user.route", arg[1])
m.Cmd("ssh.remote", "", "share", arg[1:])
return
}
m.Option("user.sign", "yes")
m.Cmd("ssh.remote", arg[0], "sync", "share", arg[1:])
return
}},
"check": &ctx.Command{Name: "check proxy.route client.route", Help: "权限检查", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
return
}},
"sh": &ctx.Command{Name: "sh [[node] name] cmd...", Help: "发送命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Echo(m.Conf("current"))

View File

@ -18,6 +18,37 @@ type TCP struct {
*ctx.Context
}
func (tcp *TCP) Fuck(address []string, action func(address string) (net.Conn, error)) {
m := tcp.Message()
fuck := make(chan bool, 3)
for _, p := range address {
m.Cap("address", p)
for i := 0; i < m.Confi("retry", "counts"); i++ {
go func() {
p := m.Cap("address")
if c, e := action(p); e == nil {
tcp.Conn = c
fuck <- true
} else {
m.Log("info", "dial %s:%s %s", m.Cap("protocol"), p, e)
fuck <- false
}
}()
select {
case ok := <-fuck:
if ok {
return
}
case <-time.After(kit.Duration(m.Conf("retry", "interval"))):
m.Log("info", "dial %s:%s timeout", m.Cap("protocol"), p)
}
time.Sleep(kit.Duration(m.Conf("retry", "interval")))
}
}
}
func (tcp *TCP) Read(b []byte) (n int, e error) {
m := tcp.Context.Message()
m.Assert(tcp.Conn != nil)
@ -59,9 +90,13 @@ func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server {
func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool {
address := []string{}
if arg[1] == "consul" {
m.Cmd("web.get", "dev", arg[2], "temp", "hostport").Table(func(line map[string]string) {
m.Cmd("web.get", "dev", arg[2], "temp", "ports", "format", "object").Table(func(line map[string]string) {
address = append(address, line["value"])
})
if len(address) == 0 {
m.Log("warn", "dial failure %v", arg)
return true
}
for i := 2; i < len(arg)-1; i++ {
arg[i] = arg[i+1]
}
@ -78,33 +113,17 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool {
switch arg[0] {
case "dial":
if m.Caps("security") {
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
m.Assert(e)
conf := &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
for _, p := range address {
for i := 0; i < m.Confi("retry", "counts"); i++ {
if c, e := tls.Dial(m.Cap("protocol"), p, conf); e == nil {
m.Cap("address", p)
tcp.Conn = c
break
} else {
m.Log("info", "dial %s:%s %s", m.Cap("protocol"), m.Cap("address"), e)
}
time.Sleep(kit.Duration(m.Conf("retry", "interval")))
}
}
tcp.Fuck(address, func(p string) (net.Conn, error) {
return tls.Dial(m.Cap("protocol"), p, conf)
})
} else {
for i := 0; i < m.Confi("retry", "counts"); i++ {
if c, e := net.Dial(m.Cap("protocol"), m.Cap("address")); e == nil {
tcp.Conn = c
break
} else {
m.Log("info", "dial %s:%s %s", m.Cap("protocol"), m.Cap("address"), e)
}
time.Sleep(kit.Duration(m.Conf("retry", "interval")))
}
tcp.Fuck(address, func(p string) (net.Conn, error) {
return net.Dial(m.Cap("protocol"), p)
})
}
m.Log("info", "%s dial %s", m.Cap("nclient"),
@ -153,7 +172,7 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool {
m.Cmd("tcp.ifconfig").Table(func(line map[string]string) {
ports = append(ports, fmt.Sprintf("%s:%s", line["ip"], addr[len(addr)-1]))
})
m.Back(m.Spawn(m.Source()).Put("option", "hostport", ports))
m.Back(m.Spawn(m.Source()).Put("option", "node.port", ports))
}
for {
@ -195,7 +214,7 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
"security": &ctx.Config{Name: "security(true/false)", Value: "false", Help: "加密通信"},
"protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"},
"retry": &ctx.Config{Name: "retry", Value: map[string]interface{}{
"interval": "3s", "counts": 5,
"interval": "3s", "counts": 3,
}, Help: "网络协议"},
},
Commands: map[string]*ctx.Command{
@ -231,20 +250,21 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
"ifconfig": &ctx.Command{Name: "ifconfig [name]", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if ifs, e := net.Interfaces(); m.Assert(e) {
for _, v := range ifs {
if len(arg) > 0 && !strings.Contains(v.Name, arg[0]) {
continue
}
if ips, e := v.Addrs(); m.Assert(e) {
for _, x := range ips {
ip := strings.Split(x.String(), "/")
if !strings.Contains(ip[0], ":") && len(ip) > 0 && len(v.HardwareAddr) > 0 {
if len(arg) > 0 && !strings.Contains(v.Name, arg[0]) {
continue
}
m.Add("append", "index", v.Index)
m.Add("append", "name", v.Name)
m.Add("append", "hard", v.HardwareAddr)
m.Add("append", "ip", ip[0])
if strings.Contains(ip[0], ":") || len(ip) == 0 {
continue
}
m.Add("append", "index", v.Index)
m.Add("append", "name", v.Name)
m.Add("append", "ip", ip[0])
m.Add("append", "mask", ip[1])
m.Add("append", "hard", v.HardwareAddr.String())
}
}
}

View File

@ -554,7 +554,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
}
res, e := web.Client.Do(req)
if m.Assert(e); kit.Right(client["logheaders"]) {
if e != nil {
m.Log("warn", "%v", e)
return e
}
if kit.Right(client["logheaders"]) {
for k, v := range res.Header {
m.Log("info", "%s: %v", k, v)
}
@ -1025,8 +1029,8 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
return
}},
"/shadow": &ctx.Command{Name: "/shadow", Help: "暗网", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Confm("runtime", "ssh_ports", func(index int, value string) {
m.Add("append", "hostport", value)
m.Confm("runtime", "node.port", func(index int, value string) {
m.Add("append", "ports", value)
})
return
}},