隧道列表
+| 名称 | +类型 | +虚拟连接数 | +接收/发送(字节数) | +接收/发送(数据包) | +操作 | +
|---|
diff --git a/code/client/dashboard/dashboard.go b/code/client/dashboard/dashboard.go index b988f8b..f7e83e6 100644 --- a/code/client/dashboard/dashboard.go +++ b/code/client/dashboard/dashboard.go @@ -2,22 +2,33 @@ package dashboard import ( "fmt" + "natpass/code/client/global" + "natpass/code/client/pool" + "natpass/code/client/tunnel" "net/http" ) // Dashboard dashboard object type Dashboard struct { + cfg *global.Configure + pl *pool.Pool + mgr *tunnel.Mgr Version string } -func New(version string) *Dashboard { +func New(cfg *global.Configure, pl *pool.Pool, mgr *tunnel.Mgr, version string) *Dashboard { return &Dashboard{ + cfg: cfg, + pl: pl, + mgr: mgr, Version: version, } } func (db *Dashboard) ListenAndServe(addr string, port uint16) error { mux := http.NewServeMux() + mux.HandleFunc("/api/info", db.Info) + mux.HandleFunc("/api/tunnels", db.Tunnels) mux.HandleFunc("/", db.Render) svr := &http.Server{ Addr: fmt.Sprintf("%s:%d", addr, port), diff --git a/code/client/dashboard/h_info.go b/code/client/dashboard/h_info.go new file mode 100644 index 0000000..246522f --- /dev/null +++ b/code/client/dashboard/h_info.go @@ -0,0 +1,28 @@ +package dashboard + +import ( + "encoding/json" + "natpass/code/client/tunnel" + "net/http" +) + +// Info information data +func (db *Dashboard) Info(w http.ResponseWriter, r *http.Request) { + var ret struct { + Tunnels int `json:"tunnels"` + PhysicalLinks int `json:"physical_links"` + VirtualLinks int `json:"virtual_links"` + Session int `json:"sessions"` + } + ret.Tunnels = len(db.cfg.Tunnels) + ret.PhysicalLinks = db.pl.Size() + db.mgr.Range(func(t tunnel.Tunnel) { + n := len(t.GetLinks()) + ret.VirtualLinks += n + if t.GetTypeName() == "shell" { + ret.Session += n + } + }) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(ret) +} diff --git a/code/client/dashboard/h_tunnels.go b/code/client/dashboard/h_tunnels.go new file mode 100644 index 0000000..dcfdb57 --- /dev/null +++ b/code/client/dashboard/h_tunnels.go @@ -0,0 +1,40 @@ +package dashboard + +import ( + "encoding/json" + "natpass/code/client/tunnel" + "net/http" +) + +func (db *Dashboard) Tunnels(w http.ResponseWriter, r *http.Request) { + type link struct { + ID string `json:"id"` + SendBytes uint64 `json:"send_bytes"` + SendPacket uint64 `json:"send_packet"` + RecvBytes uint64 `json:"recv_bytes"` + RecvPacket uint64 `json:"recv_packet"` + } + type item struct { + Name string `json:"name"` + Port uint16 `json:"port"` + Type string `json:"type"` + Links []link `json:"links"` + } + var ret []item + db.mgr.Range(func(t tunnel.Tunnel) { + var it item + it.Name = t.GetName() + it.Port = t.GetPort() + it.Type = t.GetTypeName() + for _, l := range t.GetLinks() { + var lk link + lk.ID = l.GetID() + lk.RecvBytes, lk.SendBytes = l.GetBytes() + lk.RecvPacket, lk.SendPacket = l.GetPackets() + it.Links = append(it.Links, lk) + } + ret = append(ret, it) + }) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(ret) +} diff --git a/code/client/main.go b/code/client/main.go index 4778c58..d80e310 100644 --- a/code/client/main.go +++ b/code/client/main.go @@ -108,7 +108,7 @@ func (a *app) run() { } if a.cfg.DashboardEnabled { - db := dashboard.New(_VERSION) + db := dashboard.New(a.cfg, pl, mgr, _VERSION) runtime.Assert(db.ListenAndServe(a.cfg.DashboardListen, a.cfg.DashboardPort)) } else { select {} diff --git a/code/client/pool/send.go b/code/client/pool/send.go index 7818f4e..119aa9d 100644 --- a/code/client/pool/send.go +++ b/code/client/pool/send.go @@ -3,10 +3,12 @@ package pool import ( "natpass/code/network" "time" + + "google.golang.org/protobuf/proto" ) // SendData send forward data -func (conn *Conn) SendData(to string, toIdx uint32, id string, data []byte) { +func (conn *Conn) SendData(to string, toIdx uint32, id string, data []byte) uint64 { dup := func(data []byte) []byte { ret := make([]byte, len(data)) copy(ret, data) @@ -24,7 +26,10 @@ func (conn *Conn) SendData(to string, toIdx uint32, id string, data []byte) { } select { case conn.write <- &msg: + data, _ := proto.Marshal(&msg) + return uint64(len(data)) case <-time.After(conn.parent.cfg.WriteTimeout): + return 0 } } diff --git a/code/client/pool/send_conn.go b/code/client/pool/send_conn.go index 6e9608a..d92162a 100644 --- a/code/client/pool/send_conn.go +++ b/code/client/pool/send_conn.go @@ -4,6 +4,8 @@ import ( "natpass/code/client/global" "natpass/code/network" "time" + + "google.golang.org/protobuf/proto" ) // SendConnectReq send connect request message @@ -85,7 +87,7 @@ func (conn *Conn) SendConnectOK(to string, toIdx uint32, id string) { } // SendDisconnect send disconnect message -func (conn *Conn) SendDisconnect(to string, toIdx uint32, id string) { +func (conn *Conn) SendDisconnect(to string, toIdx uint32, id string) uint64 { var msg network.Msg msg.To = to msg.ToIdx = toIdx @@ -93,6 +95,9 @@ func (conn *Conn) SendDisconnect(to string, toIdx uint32, id string) { msg.LinkId = id select { case conn.write <- &msg: + data, _ := proto.Marshal(&msg) + return uint64(len(data)) case <-time.After(conn.parent.cfg.WriteTimeout): + return 0 } } diff --git a/code/client/pool/send_shell.go b/code/client/pool/send_shell.go index 65b0fcb..8232545 100644 --- a/code/client/pool/send_shell.go +++ b/code/client/pool/send_shell.go @@ -3,10 +3,12 @@ package pool import ( "natpass/code/network" "time" + + "google.golang.org/protobuf/proto" ) // SendShellData send shell data -func (conn *Conn) SendShellData(to string, toIdx uint32, id string, data []byte) { +func (conn *Conn) SendShellData(to string, toIdx uint32, id string, data []byte) uint64 { dup := func(data []byte) []byte { ret := make([]byte, len(data)) copy(ret, data) @@ -24,7 +26,10 @@ func (conn *Conn) SendShellData(to string, toIdx uint32, id string, data []byte) } select { case conn.write <- &msg: + data, _ := proto.Marshal(&msg) + return uint64(len(data)) case <-time.After(conn.parent.cfg.WriteTimeout): + return 0 } } diff --git a/code/client/tunnel/mgr.go b/code/client/tunnel/mgr.go index a827af5..786873a 100644 --- a/code/client/tunnel/mgr.go +++ b/code/client/tunnel/mgr.go @@ -4,15 +4,16 @@ import "sync" type Link interface { GetID() string - // GetBytes tx, rx + // GetBytes rx, tx GetBytes() (uint64, uint64) - // GetPackets tx, rx + // GetPackets rx, tx GetPackets() (uint64, uint64) } // Tunnel tunnel interface type Tunnel interface { GetName() string + GetPort() uint16 GetTypeName() string GetTarget() string GetLinks() []Link @@ -35,3 +36,12 @@ func (mgr *Mgr) Add(tunnel Tunnel) { defer mgr.Unlock() mgr.tunnels = append(mgr.tunnels, tunnel) } + +// Range range tunnels +func (mgr *Mgr) Range(fn func(Tunnel)) { + mgr.RLock() + defer mgr.RUnlock() + for _, t := range mgr.tunnels { + fn(t) + } +} diff --git a/code/client/tunnel/reverse/link.go b/code/client/tunnel/reverse/link.go index 13492b9..30c0425 100644 --- a/code/client/tunnel/reverse/link.go +++ b/code/client/tunnel/reverse/link.go @@ -9,6 +9,7 @@ import ( "net" "github.com/lwch/logging" + "google.golang.org/protobuf/proto" ) // Link link object @@ -21,6 +22,11 @@ type Link struct { remote *pool.Conn OnWork chan struct{} closeFromRemote bool + // runtime + recvBytes uint64 + sendBytes uint64 + recvPacket uint64 + sendPacket uint64 } // NewLink create link @@ -52,14 +58,12 @@ func (link *Link) GetID() string { // GetBytes get send and recv bytes func (link *Link) GetBytes() (uint64, uint64) { - // TODO - return 0, 0 + return link.recvBytes, link.sendBytes } // GetPackets get send and recv packets func (link *Link) GetPackets() (uint64, uint64) { - // TODO - return 0, 0 + return link.recvPacket, link.sendPacket } // Forward forward data @@ -77,6 +81,9 @@ func (link *Link) remoteRead() { if msg == nil { return } + data, _ := proto.Marshal(msg) + link.recvBytes += uint64(len(data)) + link.recvPacket++ link.targetIdx = msg.GetFromIdx() switch msg.GetXType() { case network.Msg_forward: @@ -111,7 +118,9 @@ func (link *Link) localRead() { n, err := link.local.Read(buf) if err != nil { if !link.closeFromRemote { - link.remote.SendDisconnect(link.target, link.targetIdx, link.id) + n := link.remote.SendDisconnect(link.target, link.targetIdx, link.id) + link.sendBytes += n + link.sendPacket++ } logging.Error("read data on tunnel %s link %s failed, err=%v", link.parent.Name, link.id, err) return @@ -120,7 +129,9 @@ func (link *Link) localRead() { continue } logging.Debug("link %s on tunnel %s read from local %d bytes", link.id, link.parent.Name, n) - link.remote.SendData(link.target, link.targetIdx, link.id, buf[:n]) + send := link.remote.SendData(link.target, link.targetIdx, link.id, buf[:n]) + link.sendBytes += send + link.sendPacket++ } } diff --git a/code/client/tunnel/reverse/tunnel.go b/code/client/tunnel/reverse/tunnel.go index 65979bc..1bf295c 100644 --- a/code/client/tunnel/reverse/tunnel.go +++ b/code/client/tunnel/reverse/tunnel.go @@ -22,8 +22,9 @@ type Tunnel struct { // New new tunnel func New(cfg global.Tunnel) *Tunnel { return &Tunnel{ - Name: cfg.Name, - cfg: cfg, + Name: cfg.Name, + cfg: cfg, + links: make(map[string]*Link), } } @@ -53,6 +54,11 @@ func (t *Tunnel) GetLinks() []tunnel.Link { return ret } +// GetPort get listen port +func (t *Tunnel) GetPort() uint16 { + return t.cfg.LocalPort +} + // Handle handle tunnel func (tunnel *Tunnel) Handle(pool *pool.Pool) { if tunnel.cfg.Type == "tcp" { diff --git a/code/client/tunnel/shell/link.go b/code/client/tunnel/shell/link.go index f294b4a..fae01a0 100644 --- a/code/client/tunnel/shell/link.go +++ b/code/client/tunnel/shell/link.go @@ -9,6 +9,7 @@ import ( "github.com/lwch/logging" "golang.org/x/text/encoding/simplifiedchinese" + "google.golang.org/protobuf/proto" ) // Link shell link @@ -22,6 +23,11 @@ type Link struct { pid int stdin io.WriteCloser stdout io.ReadCloser + // runtime + sendBytes uint64 + recvBytes uint64 + sendPacket uint64 + recvPacket uint64 } // NewLink create link @@ -44,14 +50,12 @@ func (link *Link) GetID() string { // GetBytes get send and recv bytes func (link *Link) GetBytes() (uint64, uint64) { - // TODO - return 0, 0 + return link.recvBytes, link.sendBytes } // GetPackets get send and recv packets func (link *Link) GetPackets() (uint64, uint64) { - // TODO - return 0, 0 + return link.recvPacket, link.sendPacket } // SetTargetIdx set link remote index @@ -85,6 +89,9 @@ func (link *Link) remoteRead() { if msg == nil { return } + data, _ := proto.Marshal(msg) + link.recvBytes += uint64(len(data)) + link.recvPacket++ link.targetIdx = msg.GetFromIdx() switch msg.GetXType() { case network.Msg_shell_resize: @@ -131,7 +138,9 @@ func (link *Link) localRead() { } logging.Debug("link %s on shell %s read from local %d bytes", link.id, link.parent.Name, n) - link.remote.SendShellData(link.target, link.targetIdx, link.id, data) + send := link.remote.SendShellData(link.target, link.targetIdx, link.id, data) + link.sendBytes += send + link.sendPacket++ } } diff --git a/code/client/tunnel/shell/shell.go b/code/client/tunnel/shell/shell.go index 6c6079d..1e15a01 100644 --- a/code/client/tunnel/shell/shell.go +++ b/code/client/tunnel/shell/shell.go @@ -55,6 +55,11 @@ func (shell *Shell) GetLinks() []tunnel.Link { return ret } +// GetPort get listen port +func (shell *Shell) GetPort() uint16 { + return shell.cfg.LocalPort +} + // Handle handle shell func (shell *Shell) Handle(pl *pool.Pool) { defer func() { diff --git a/html/dashboard/index.html b/html/dashboard/index.html index ad400c2..0b4ab99 100644 --- a/html/dashboard/index.html +++ b/html/dashboard/index.html @@ -1,5 +1,7 @@ {{define "all"}} {{template "header" .}} + + {{template "aside" .}}
| 名称 | +类型 | +虚拟连接数 | +接收/发送(字节数) | +接收/发送(数据包) | +操作 | +
|---|
+ ${count} +
+文件
+ +