@@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
- name: Build Client
|
||||
run: |
|
||||
go run contrib/bindata/main.go -pkg shell -o code/client/tunnel/shell/assets.go -prefix html/shell html/shell/...
|
||||
go run contrib/bindata/main.go -pkg vnc -o code/client/tunnel/vnc/assets.go -prefix html/vnc html/vnc/...
|
||||
go run contrib/bindata/main.go -pkg shell -o code/client/rule/shell/assets.go -prefix html/shell html/shell/...
|
||||
go run contrib/bindata/main.go -pkg vnc -o code/client/rule/vnc/assets.go -prefix html/vnc html/vnc/...
|
||||
go run contrib/bindata/main.go -pkg dashboard -o code/client/dashboard/assets.go -prefix html/dashboard html/dashboard/...
|
||||
go build -v code/client/main.go
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
# v0.3.0
|
||||
|
||||
1. 新增shell隧道的支持
|
||||
1. 新增shell规则的支持
|
||||
|
||||
# v0.4.0
|
||||
|
||||
@@ -46,15 +46,21 @@
|
||||
|
||||
# v0.6.0
|
||||
|
||||
1. 新增vnc隧道支持
|
||||
1. 新增vnc规则支持
|
||||
|
||||
# v0.6.1
|
||||
|
||||
1. 修正vnc隧道的fps参数上限不起作用的问题
|
||||
1. 修正vnc规则的fps参数上限不起作用的问题
|
||||
2. vnc页面增加全屏功能
|
||||
|
||||
# v0.6.2
|
||||
|
||||
1. vnc页面支持滚动
|
||||
2. go版本升级到1.17.3
|
||||
3. 文档补全
|
||||
3. 文档补全
|
||||
|
||||
# v0.7.0
|
||||
|
||||
1. bootstrap降版到4.6.1
|
||||
2. dashboard页面支持规则类型筛选
|
||||
3. **为遵守中国法律,移除内网穿透功能**,保留shell和vnc功能不变
|
||||
@@ -7,10 +7,10 @@
|
||||
[](https://github.com/lwch/natpass)
|
||||
[](https://jq.qq.com/?_wv=1027&k=6Fz2vkVE)
|
||||
|
||||
新一代NAT内网穿透工具,支持tcp隧道、shell隧道,[实现原理](docs/desc.md)
|
||||
新一代主机管理工具,支持shell管理,支持远程桌面管理[实现原理](docs/desc.md)
|
||||
|
||||
1. [如何部署](docs/startup.md)
|
||||
2. [隧道配置](docs/tunnel.md)
|
||||
2. [规则配置](docs/rules.md)
|
||||
|
||||
功能与特性:
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
3. 支持多路异步IO
|
||||
4. 支持虚拟链路层
|
||||
5. 支持链路和终端会话监控
|
||||
6. 支持tcp协议反向代理
|
||||
7. 支持web shell
|
||||
8. 支持web vnc
|
||||
9. 支持多种操作系统
|
||||
10. protobuf数据编码
|
||||
6. 支持web shell
|
||||
7. 支持web vnc
|
||||
8. 支持多种操作系统
|
||||
9. protobuf数据编码
|
||||
|
||||
## 效果图
|
||||
|
||||
@@ -51,29 +50,15 @@ windows11远程桌面
|
||||
|
||||

|
||||
|
||||
## iperf3压测对比
|
||||
|
||||
使用相同参数,iperf3压测1分钟
|
||||
|
||||
# natpass10路复用,读写均为1s超时
|
||||
[ ID] Interval Transfer Bitrate Retr
|
||||
[ 5] 0.00-60.00 sec 70.0 MBytes 9.79 Mbits/sec 22 sender
|
||||
[ 5] 0.00-60.02 sec 57.9 MBytes 8.10 Mbits/sec receiver
|
||||
|
||||
# frp10路复用stcp,tls
|
||||
[ ID] Interval Transfer Bitrate Retr
|
||||
[ 5] 0.00-60.00 sec 66.2 MBytes 9.26 Mbits/sec 31 sender
|
||||
[ 5] 0.00-60.10 sec 57.7 MBytes 8.05 Mbits/sec receiver
|
||||
|
||||
## TODO
|
||||
|
||||
1. ~~支持include的yaml配置文件~~
|
||||
2. ~~通用的connect、connect_response、disconnect消息~~
|
||||
3. ~~所有隧道的dashboard页面~~
|
||||
3. ~~dashboard页面~~
|
||||
4. 文件传输
|
||||
5. ~web远程桌面~
|
||||
6. ~~流量监控统计页面,server还是client?~~
|
||||
7. web端管理tunnel
|
||||
7. web端管理规则
|
||||
|
||||
## 免责声明
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
VERSION=0.6.2
|
||||
VERSION=0.7.0
|
||||
|
||||
DOCKER_BUILDKIT=1 docker build -t natpass -f contrib/build/Dockerfile .
|
||||
docker run --rm \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
VERSION=0.6.2
|
||||
VERSION=0.7.0
|
||||
|
||||
DOCKER_BUILDKIT=1 docker build -t natpass -f contrib/build/Dockerfile .
|
||||
docker run --rm \
|
||||
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"natpass/code/client/dashboard"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/tunnel/reverse"
|
||||
"natpass/code/client/tunnel/shell"
|
||||
"natpass/code/client/tunnel/vnc"
|
||||
"natpass/code/client/rule"
|
||||
"natpass/code/client/rule/shell"
|
||||
"natpass/code/client/rule/vnc"
|
||||
"natpass/code/network"
|
||||
rt "runtime"
|
||||
"time"
|
||||
@@ -53,14 +52,10 @@ func (a *App) run() {
|
||||
defer logging.Flush()
|
||||
|
||||
pl := pool.New(a.cfg)
|
||||
mgr := tunnel.New()
|
||||
mgr := rule.New()
|
||||
|
||||
for _, t := range a.cfg.Tunnels {
|
||||
for _, t := range a.cfg.Rules {
|
||||
switch t.Type {
|
||||
case "tcp", "udp":
|
||||
tn := reverse.New(t)
|
||||
mgr.Add(tn)
|
||||
go tn.Handle(pl)
|
||||
case "shell":
|
||||
sh := shell.New(t)
|
||||
mgr.Add(sh)
|
||||
@@ -89,8 +84,6 @@ func (a *App) run() {
|
||||
switch msg.GetXType() {
|
||||
case network.Msg_connect_req:
|
||||
switch msg.GetCreq().GetXType() {
|
||||
case network.ConnectRequest_tcp, network.ConnectRequest_udp:
|
||||
a.connect(mgr, conn, msg)
|
||||
case network.ConnectRequest_shell:
|
||||
a.shellCreate(mgr, conn, msg)
|
||||
case network.ConnectRequest_vnc:
|
||||
|
||||
@@ -1,60 +1,21 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/tunnel/reverse"
|
||||
"natpass/code/client/tunnel/shell"
|
||||
"natpass/code/client/tunnel/vnc"
|
||||
"natpass/code/client/rule"
|
||||
"natpass/code/client/rule/shell"
|
||||
"natpass/code/client/rule/vnc"
|
||||
"natpass/code/network"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/lwch/logging"
|
||||
)
|
||||
|
||||
func (a *App) connect(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
req := msg.GetCreq()
|
||||
// TODO: 创建tcp连接移到reverse包中实现
|
||||
dial := "tcp"
|
||||
if req.GetXType() == network.ConnectRequest_udp {
|
||||
dial = "udp"
|
||||
}
|
||||
addr := req.GetCaddr()
|
||||
link, err := net.Dial(dial, fmt.Sprintf("%s:%d", addr.GetAddr(), addr.GetPort()))
|
||||
if err != nil {
|
||||
logging.Error("connect to %s:%d failed, err=%v", addr.GetAddr(), addr.GetPort(), err)
|
||||
conn.SendConnectError(msg.GetFrom(), msg.GetFromIdx(), msg.GetLinkId(), err.Error())
|
||||
return
|
||||
}
|
||||
host, pt, _ := net.SplitHostPort(link.LocalAddr().String())
|
||||
port, _ := strconv.ParseUint(pt, 10, 16)
|
||||
tn := mgr.Get(req.GetName(), msg.GetFrom())
|
||||
if tn == nil {
|
||||
tn = reverse.New(global.Tunnel{
|
||||
Name: req.GetName(),
|
||||
Target: msg.GetFrom(),
|
||||
Type: dial,
|
||||
LocalAddr: host,
|
||||
LocalPort: uint16(port),
|
||||
RemoteAddr: addr.GetAddr(),
|
||||
RemotePort: uint16(addr.GetPort()),
|
||||
})
|
||||
mgr.Add(tn)
|
||||
}
|
||||
lk := tn.NewLink(msg.GetLinkId(), msg.GetFrom(), msg.GetFromIdx(), link, conn).(*reverse.Link)
|
||||
conn.SendConnectOK(msg.GetFrom(), msg.GetFromIdx(), msg.GetLinkId())
|
||||
lk.Forward()
|
||||
lk.OnWork <- struct{}{}
|
||||
}
|
||||
|
||||
func (a *App) shellCreate(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
func (a *App) shellCreate(mgr *rule.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
create := msg.GetCreq()
|
||||
tn := mgr.Get(create.GetName(), msg.GetFrom())
|
||||
if tn == nil {
|
||||
tn = shell.New(global.Tunnel{
|
||||
tn = shell.New(global.Rule{
|
||||
Name: create.GetName(),
|
||||
Target: msg.GetFrom(),
|
||||
Type: "shell",
|
||||
@@ -74,11 +35,11 @@ func (a *App) shellCreate(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
lk.Forward()
|
||||
}
|
||||
|
||||
func (a *App) vncCreate(confDir string, mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
func (a *App) vncCreate(confDir string, mgr *rule.Mgr, conn *pool.Conn, msg *network.Msg) {
|
||||
create := msg.GetCreq()
|
||||
tn := mgr.Get(create.GetName(), msg.GetFrom())
|
||||
if tn == nil {
|
||||
tn = vnc.New(global.Tunnel{
|
||||
tn = vnc.New(global.Rule{
|
||||
Name: create.GetName(),
|
||||
Target: msg.GetFrom(),
|
||||
Type: "vnc",
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/rule"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
type Dashboard struct {
|
||||
cfg *global.Configure
|
||||
pl *pool.Pool
|
||||
mgr *tunnel.Mgr
|
||||
mgr *rule.Mgr
|
||||
Version string
|
||||
}
|
||||
|
||||
// New create dashboard object
|
||||
func New(cfg *global.Configure, pl *pool.Pool, mgr *tunnel.Mgr, version string) *Dashboard {
|
||||
func New(cfg *global.Configure, pl *pool.Pool, mgr *rule.Mgr, version string) *Dashboard {
|
||||
return &Dashboard{
|
||||
cfg: cfg,
|
||||
pl: pl,
|
||||
@@ -30,7 +30,7 @@ func New(cfg *global.Configure, pl *pool.Pool, mgr *tunnel.Mgr, version string)
|
||||
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("/api/rules", db.Rules)
|
||||
mux.HandleFunc("/", db.Render)
|
||||
svr := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", addr, port),
|
||||
|
||||
@@ -2,21 +2,21 @@ package dashboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/rule"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Info information data
|
||||
func (db *Dashboard) Info(w http.ResponseWriter, r *http.Request) {
|
||||
var ret struct {
|
||||
Tunnels int `json:"tunnels"`
|
||||
Rules int `json:"rules"`
|
||||
PhysicalLinks int `json:"physical_links"`
|
||||
VirtualLinks int `json:"virtual_links"`
|
||||
Session int `json:"sessions"`
|
||||
}
|
||||
ret.Tunnels = len(db.cfg.Tunnels)
|
||||
ret.Rules = len(db.cfg.Rules)
|
||||
ret.PhysicalLinks = db.pl.Size()
|
||||
db.mgr.Range(func(t tunnel.Tunnel) {
|
||||
db.mgr.Range(func(t rule.Rule) {
|
||||
n := len(t.GetLinks())
|
||||
ret.VirtualLinks += n
|
||||
if t.GetTypeName() == "shell" {
|
||||
|
||||
@@ -2,12 +2,12 @@ package dashboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/rule"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Tunnels get tunnels list
|
||||
func (db *Dashboard) Tunnels(w http.ResponseWriter, r *http.Request) {
|
||||
// Rules get rule list
|
||||
func (db *Dashboard) Rules(w http.ResponseWriter, r *http.Request) {
|
||||
type link struct {
|
||||
ID string `json:"id"`
|
||||
SendBytes uint64 `json:"send_bytes"`
|
||||
@@ -23,7 +23,7 @@ func (db *Dashboard) Tunnels(w http.ResponseWriter, r *http.Request) {
|
||||
Links []link `json:"links"`
|
||||
}
|
||||
var ret []item
|
||||
db.mgr.Range(func(t tunnel.Tunnel) {
|
||||
db.mgr.Range(func(t rule.Rule) {
|
||||
var it item
|
||||
it.Name = t.GetName()
|
||||
it.Remote = t.GetRemote()
|
||||
@@ -2,6 +2,7 @@ package global
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"natpass/code/utils"
|
||||
"time"
|
||||
|
||||
@@ -9,8 +10,8 @@ import (
|
||||
"github.com/lwch/yaml"
|
||||
)
|
||||
|
||||
// Tunnel tunnel config
|
||||
type Tunnel struct {
|
||||
// Rule rule config
|
||||
type Rule struct {
|
||||
Name string `yaml:"name"`
|
||||
Target string `yaml:"target"`
|
||||
Type string `yaml:"type"`
|
||||
@@ -39,7 +40,7 @@ type Configure struct {
|
||||
DashboardEnabled bool
|
||||
DashboardListen string
|
||||
DashboardPort uint16
|
||||
Tunnels []Tunnel
|
||||
Rules []Rule
|
||||
}
|
||||
|
||||
// LoadConf load configure file
|
||||
@@ -63,16 +64,16 @@ func LoadConf(dir string) *Configure {
|
||||
Listen string `yaml:"listen"`
|
||||
Port uint16 `yaml:"port"`
|
||||
} `yaml:"dashboard"`
|
||||
Tunnel []Tunnel `yaml:"tunnel"`
|
||||
Rules []Rule `yaml:"rules"`
|
||||
}
|
||||
runtime.Assert(yaml.Decode(dir, &cfg))
|
||||
for i, t := range cfg.Tunnel {
|
||||
for i, t := range cfg.Rules {
|
||||
switch t.Type {
|
||||
case "tcp", "shell", "vnc":
|
||||
case "shell", "vnc":
|
||||
default:
|
||||
t.Type = "udp"
|
||||
panic(fmt.Sprintf("unsupported type: %s", t.Type))
|
||||
}
|
||||
cfg.Tunnel[i] = t
|
||||
cfg.Rules[i] = t
|
||||
}
|
||||
if cfg.Link.Connections <= 0 {
|
||||
cfg.Link.Connections = 3
|
||||
@@ -96,6 +97,6 @@ func LoadConf(dir string) *Configure {
|
||||
DashboardEnabled: cfg.Dashboard.Enabled,
|
||||
DashboardListen: cfg.Dashboard.Listen,
|
||||
DashboardPort: cfg.Dashboard.Port,
|
||||
Tunnels: cfg.Tunnel,
|
||||
Rules: cfg.Rules,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"natpass/code/client/app"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/tunnel/vnc"
|
||||
"natpass/code/client/rule/vnc"
|
||||
"natpass/code/utils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -38,7 +38,7 @@ func main() {
|
||||
conf := flag.String("conf", "", "configure file path")
|
||||
ver := flag.Bool("version", false, "show version info")
|
||||
act := flag.String("action", "", "install or uninstall")
|
||||
name := flag.String("name", "", "tunnel name")
|
||||
name := flag.String("name", "", "rule name")
|
||||
vport := flag.Uint("vport", 6155, "vnc worker listen port")
|
||||
vcursor := flag.Bool("vcursor", false, "vnc show cursor")
|
||||
flag.Parse()
|
||||
|
||||
@@ -9,26 +9,12 @@ import (
|
||||
)
|
||||
|
||||
// SendConnectReq send connect request message
|
||||
func (conn *Conn) SendConnectReq(id string, cfg global.Tunnel) {
|
||||
func (conn *Conn) SendConnectReq(id string, cfg global.Rule) {
|
||||
var msg network.Msg
|
||||
msg.To = cfg.Target
|
||||
msg.XType = network.Msg_connect_req
|
||||
msg.LinkId = id
|
||||
switch cfg.Type {
|
||||
case "tcp":
|
||||
msg.Payload = &network.Msg_Creq{
|
||||
Creq: &network.ConnectRequest{
|
||||
Name: cfg.Name,
|
||||
XType: network.ConnectRequest_tcp,
|
||||
Payload: &network.ConnectRequest_Caddr{
|
||||
Caddr: &network.ConnectAddr{
|
||||
Addr: cfg.RemoteAddr,
|
||||
Port: uint32(cfg.RemotePort),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
case "udp":
|
||||
case "shell":
|
||||
msg.Payload = &network.Msg_Creq{
|
||||
Creq: &network.ConnectRequest{
|
||||
@@ -68,7 +54,7 @@ func (conn *Conn) SendConnectReq(id string, cfg global.Tunnel) {
|
||||
}
|
||||
|
||||
// SendConnectVnc send connect vnc request message
|
||||
func (conn *Conn) SendConnectVnc(id string, cfg global.Tunnel, quality uint64, showCursor bool) {
|
||||
func (conn *Conn) SendConnectVnc(id string, cfg global.Rule, quality uint64, showCursor bool) {
|
||||
var msg network.Msg
|
||||
msg.To = cfg.Target
|
||||
msg.XType = network.Msg_connect_req
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package tunnel
|
||||
package rule
|
||||
|
||||
import (
|
||||
"natpass/code/client/pool"
|
||||
@@ -15,8 +15,8 @@ type Link interface {
|
||||
GetPackets() (uint64, uint64)
|
||||
}
|
||||
|
||||
// Tunnel tunnel interface
|
||||
type Tunnel interface {
|
||||
// Rule rule interface
|
||||
type Rule interface {
|
||||
NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) Link
|
||||
GetName() string
|
||||
GetRemote() string
|
||||
@@ -26,29 +26,29 @@ type Tunnel interface {
|
||||
GetLinks() []Link
|
||||
}
|
||||
|
||||
// Mgr tunnel manager
|
||||
// Mgr rule manager
|
||||
type Mgr struct {
|
||||
sync.RWMutex
|
||||
tunnels []Tunnel
|
||||
rules []Rule
|
||||
}
|
||||
|
||||
// New new tunnel manager
|
||||
// New new rule manager
|
||||
func New() *Mgr {
|
||||
return &Mgr{}
|
||||
}
|
||||
|
||||
// Add add tunnel
|
||||
func (mgr *Mgr) Add(tunnel Tunnel) {
|
||||
// Add add rule
|
||||
func (mgr *Mgr) Add(rule Rule) {
|
||||
mgr.Lock()
|
||||
defer mgr.Unlock()
|
||||
mgr.tunnels = append(mgr.tunnels, tunnel)
|
||||
mgr.rules = append(mgr.rules, rule)
|
||||
}
|
||||
|
||||
// Get get tunnel by name
|
||||
func (mgr *Mgr) Get(name, remote string) Tunnel {
|
||||
// Get get rule by name
|
||||
func (mgr *Mgr) Get(name, remote string) Rule {
|
||||
mgr.RLock()
|
||||
defer mgr.RUnlock()
|
||||
for _, t := range mgr.tunnels {
|
||||
for _, t := range mgr.rules {
|
||||
if t.GetName() == name && t.GetRemote() == remote {
|
||||
return t
|
||||
}
|
||||
@@ -56,11 +56,11 @@ func (mgr *Mgr) Get(name, remote string) Tunnel {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Range range tunnels
|
||||
func (mgr *Mgr) Range(fn func(Tunnel)) {
|
||||
// Range range rules
|
||||
func (mgr *Mgr) Range(fn func(Rule)) {
|
||||
mgr.RLock()
|
||||
defer mgr.RUnlock()
|
||||
for _, t := range mgr.tunnels {
|
||||
for _, t := range mgr.rules {
|
||||
fn(t)
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func (shell *Shell) New(pool *pool.Pool, w http.ResponseWriter, r *http.Request)
|
||||
select {
|
||||
case msg = <-ch:
|
||||
case <-timeout:
|
||||
logging.Error("create shell %s on tunnel %s failed, timtout", link.id, link.parent.Name)
|
||||
logging.Error("create shell %s by rule %s failed, timtout", link.id, link.parent.Name)
|
||||
http.Error(w, "timeout", http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (shell *Shell) New(pool *pool.Pool, w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
rep := msg.GetCrep()
|
||||
if !rep.GetOk() {
|
||||
logging.Error("create shell %s on tunnel %s failed, err=%s",
|
||||
logging.Error("create shell %s by rule %s failed, err=%s",
|
||||
link.id, link.parent.Name, rep.GetMsg())
|
||||
http.Error(w, rep.GetMsg(), http.StatusBadGateway)
|
||||
return
|
||||
@@ -85,7 +85,7 @@ func (shell *Shell) remoteForward(id string, local *websocket.Conn) {
|
||||
logging.Debug("remote read %d bytes: name=%s, id=%s",
|
||||
len(msg.GetSdata().GetData()), shell.Name, id)
|
||||
case network.Msg_disconnect:
|
||||
logging.Info("shell %s on tunnel %s closed by remote",
|
||||
logging.Info("shell %s by rule %s closed by remote",
|
||||
link.id, link.parent.Name)
|
||||
return
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/rule"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -17,12 +17,12 @@ import (
|
||||
type Shell struct {
|
||||
sync.RWMutex
|
||||
Name string
|
||||
cfg global.Tunnel
|
||||
cfg global.Rule
|
||||
links map[string]*Link
|
||||
}
|
||||
|
||||
// New new shell
|
||||
func New(cfg global.Tunnel) *Shell {
|
||||
func New(cfg global.Rule) *Shell {
|
||||
return &Shell{
|
||||
Name: cfg.Name,
|
||||
cfg: cfg,
|
||||
@@ -31,7 +31,7 @@ func New(cfg global.Tunnel) *Shell {
|
||||
}
|
||||
|
||||
// NewLink new link
|
||||
func (shell *Shell) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) tunnel.Link {
|
||||
func (shell *Shell) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) rule.Link {
|
||||
remoteConn.AddLink(id)
|
||||
logging.Info("create link %s for shell %s on connection %d",
|
||||
id, shell.Name, remoteConn.Idx)
|
||||
@@ -48,24 +48,24 @@ func (shell *Shell) NewLink(id, remote string, remoteIdx uint32, localConn net.C
|
||||
return link
|
||||
}
|
||||
|
||||
// GetName get shell tunnel name
|
||||
// GetName get shell rule name
|
||||
func (shell *Shell) GetName() string {
|
||||
return shell.Name
|
||||
}
|
||||
|
||||
// GetTypeName get shell tunnel type name
|
||||
// GetTypeName get shell rule type name
|
||||
func (shell *Shell) GetTypeName() string {
|
||||
return "shell"
|
||||
}
|
||||
|
||||
// GetTarget get target of this tunnel
|
||||
// GetTarget get target of this rule
|
||||
func (shell *Shell) GetTarget() string {
|
||||
return shell.cfg.Target
|
||||
}
|
||||
|
||||
// GetLinks get tunnel links
|
||||
func (shell *Shell) GetLinks() []tunnel.Link {
|
||||
ret := make([]tunnel.Link, 0, len(shell.links))
|
||||
// GetLinks get rule links
|
||||
func (shell *Shell) GetLinks() []rule.Link {
|
||||
ret := make([]rule.Link, 0, len(shell.links))
|
||||
shell.RLock()
|
||||
for _, link := range shell.links {
|
||||
ret = append(ret, link)
|
||||
@@ -88,7 +88,7 @@ func (shell *Shell) GetPort() uint16 {
|
||||
func (shell *Shell) Handle(pl *pool.Pool) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logging.Error("close shell tunnel: %s, err=%v", shell.Name, err)
|
||||
logging.Error("close shell: %s, err=%v", shell.Name, err)
|
||||
}
|
||||
}()
|
||||
pf := func(cb func(*pool.Pool, http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Ctrl change vnc tunnel config
|
||||
// Ctrl change vnc rule config
|
||||
func (v *VNC) Ctrl(pool *pool.Pool, w http.ResponseWriter, r *http.Request) {
|
||||
q := r.FormValue("quality")
|
||||
s := r.FormValue("show_cursor")
|
||||
@@ -50,7 +50,7 @@ func (v *VNC) New(pool *pool.Pool, w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case msg = <-ch:
|
||||
case <-timeout:
|
||||
logging.Error("create vnc %s on tunnel %s failed, timtout", v.link.id, v.link.parent.Name)
|
||||
logging.Error("create vnc %s by rule %s failed, timtout", v.link.id, v.link.parent.Name)
|
||||
http.Error(w, "timeout", http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func (v *VNC) New(pool *pool.Pool, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
rep := msg.GetCrep()
|
||||
if !rep.GetOk() {
|
||||
logging.Error("create vnc %s on tunnel %s failed, err=%s",
|
||||
logging.Error("create vnc %s by rule %s failed, err=%s",
|
||||
v.link.id, v.link.parent.Name, rep.GetMsg())
|
||||
http.Error(w, rep.GetMsg(), http.StatusBadGateway)
|
||||
return
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel/vnc/process"
|
||||
"natpass/code/client/rule/vnc/process"
|
||||
"natpass/code/network"
|
||||
"natpass/code/utils"
|
||||
"time"
|
||||
@@ -1,7 +1,7 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
"natpass/code/network"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"natpass/code/client/tunnel/vnc/define"
|
||||
"natpass/code/client/rule/vnc/define"
|
||||
"syscall"
|
||||
|
||||
"github.com/lwch/logging"
|
||||
@@ -3,7 +3,7 @@ package process
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
"natpass/code/utils"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"natpass/code/client/tunnel/vnc/define"
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/define"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"natpass/code/client/rule"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -17,12 +17,12 @@ import (
|
||||
type VNC struct {
|
||||
sync.RWMutex
|
||||
Name string
|
||||
cfg global.Tunnel
|
||||
cfg global.Rule
|
||||
link *Link
|
||||
}
|
||||
|
||||
// New new vnc
|
||||
func New(cfg global.Tunnel) *VNC {
|
||||
func New(cfg global.Rule) *VNC {
|
||||
return &VNC{
|
||||
Name: cfg.Name,
|
||||
cfg: cfg,
|
||||
@@ -30,9 +30,9 @@ func New(cfg global.Tunnel) *VNC {
|
||||
}
|
||||
|
||||
// NewLink new link
|
||||
func (v *VNC) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) tunnel.Link {
|
||||
func (v *VNC) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) rule.Link {
|
||||
remoteConn.AddLink(id)
|
||||
logging.Info("create link %s for tunnel %s on connection %d",
|
||||
logging.Info("create link %s for rule %s on connection %d",
|
||||
id, v.Name, remoteConn.Idx)
|
||||
link := &Link{
|
||||
parent: v,
|
||||
@@ -48,25 +48,25 @@ func (v *VNC) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, r
|
||||
return link
|
||||
}
|
||||
|
||||
// GetName get vnc tunnel name
|
||||
// GetName get vnc rule name
|
||||
func (v *VNC) GetName() string {
|
||||
return v.Name
|
||||
}
|
||||
|
||||
// GetTypeName get vnc tunnel type name
|
||||
// GetTypeName get vnc rule type name
|
||||
func (v *VNC) GetTypeName() string {
|
||||
return "vnc"
|
||||
}
|
||||
|
||||
// GetTarget get target of this tunnel
|
||||
// GetTarget get target of this rule
|
||||
func (v *VNC) GetTarget() string {
|
||||
return v.cfg.Target
|
||||
}
|
||||
|
||||
// GetLinks get tunnel links
|
||||
func (v *VNC) GetLinks() []tunnel.Link {
|
||||
// GetLinks get rule links
|
||||
func (v *VNC) GetLinks() []rule.Link {
|
||||
if v.link != nil {
|
||||
return []tunnel.Link{v.link}
|
||||
return []rule.Link{v.link}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (v *VNC) GetPort() uint16 {
|
||||
func (v *VNC) Handle(pl *pool.Pool) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logging.Error("close shell tunnel: %s, err=%v", v.Name, err)
|
||||
logging.Error("close shell: %s, err=%v", v.Name, err)
|
||||
}
|
||||
}()
|
||||
pf := func(cb func(*pool.Pool, http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
@@ -2,7 +2,7 @@ package vnc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"natpass/code/client/tunnel/vnc/worker"
|
||||
"natpass/code/client/rule/vnc/worker"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/lwch/runtime"
|
||||
@@ -2,8 +2,8 @@ package worker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"natpass/code/client/tunnel/vnc/define"
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/define"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package worker
|
||||
|
||||
import "natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
import "natpass/code/client/rule/vnc/vncnetwork"
|
||||
|
||||
func (worker *Worker) runCapture() vncnetwork.ImageData {
|
||||
return vncnetwork.ImageData{}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package worker
|
||||
|
||||
import "natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
import "natpass/code/client/rule/vnc/vncnetwork"
|
||||
|
||||
func runMouse(data *vncnetwork.MouseData) {
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/lwch/logging"
|
||||
@@ -3,7 +3,7 @@ package worker
|
||||
import (
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"natpass/code/client/tunnel/vnc/vncnetwork"
|
||||
"natpass/code/client/rule/vnc/vncnetwork"
|
||||
"os"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -2,7 +2,7 @@ package worker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"natpass/code/client/tunnel/vnc/define"
|
||||
"natpass/code/client/rule/vnc/define"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
package reverse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/network"
|
||||
"natpass/code/utils"
|
||||
"net"
|
||||
|
||||
"github.com/lwch/logging"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Link link object
|
||||
type Link struct {
|
||||
parent *Tunnel
|
||||
id string // link id
|
||||
target string // target id
|
||||
targetIdx uint32 // target idx
|
||||
local net.Conn
|
||||
remote *pool.Conn
|
||||
OnWork chan struct{}
|
||||
closeFromRemote bool
|
||||
// runtime
|
||||
recvBytes uint64
|
||||
sendBytes uint64
|
||||
recvPacket uint64
|
||||
sendPacket uint64
|
||||
}
|
||||
|
||||
func (link *Link) close() {
|
||||
logging.Info("close link %s on tunnel %s", link.id, link.parent.Name)
|
||||
link.local.Close()
|
||||
link.remote.RemoveLink(link.id)
|
||||
link.parent.remove(link.id)
|
||||
}
|
||||
|
||||
// GetID get link id
|
||||
func (link *Link) GetID() string {
|
||||
return link.id
|
||||
}
|
||||
|
||||
// GetBytes get send and recv bytes
|
||||
func (link *Link) GetBytes() (uint64, uint64) {
|
||||
return link.recvBytes, link.sendBytes
|
||||
}
|
||||
|
||||
// GetPackets get send and recv packets
|
||||
func (link *Link) GetPackets() (uint64, uint64) {
|
||||
return link.recvPacket, link.sendPacket
|
||||
}
|
||||
|
||||
// Forward forward data
|
||||
func (link *Link) Forward() {
|
||||
go link.remoteRead()
|
||||
go link.localRead()
|
||||
}
|
||||
|
||||
func (link *Link) remoteRead() {
|
||||
defer utils.Recover("remoteRead")
|
||||
defer link.close()
|
||||
ch := link.remote.ChanRead(link.id)
|
||||
for {
|
||||
msg := <-ch
|
||||
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:
|
||||
_, err := io.Copy(link.local, bytes.NewReader(msg.GetXData().GetData()))
|
||||
if err != nil {
|
||||
logging.Error("write data on tunnel %s link %s failed, err=%v", link.parent.Name, link.id, err)
|
||||
return
|
||||
}
|
||||
case network.Msg_connect_rep:
|
||||
if msg.GetCrep().GetOk() {
|
||||
link.OnWork <- struct{}{}
|
||||
continue
|
||||
}
|
||||
logging.Error("create link %s on tunnel %s failed, err=%s",
|
||||
link.id, link.parent.Name, msg.GetCrep().GetMsg())
|
||||
return
|
||||
case network.Msg_disconnect:
|
||||
logging.Info("disconnect link %s on tunnel %s from remote",
|
||||
link.id, link.parent.Name)
|
||||
link.closeFromRemote = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (link *Link) localRead() {
|
||||
defer utils.Recover("localRead")
|
||||
defer link.close()
|
||||
<-link.OnWork
|
||||
buf := make([]byte, 16*1024)
|
||||
for {
|
||||
n, err := link.local.Read(buf)
|
||||
if err != nil {
|
||||
if !link.closeFromRemote {
|
||||
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
|
||||
}
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
logging.Debug("link %s on tunnel %s read from local %d bytes", link.id, link.parent.Name, n)
|
||||
send := link.remote.SendData(link.target, link.targetIdx, link.id, buf[:n])
|
||||
link.sendBytes += send
|
||||
link.sendPacket++
|
||||
}
|
||||
}
|
||||
|
||||
// SetTargetIdx set link remote index
|
||||
func (link *Link) SetTargetIdx(idx uint32) {
|
||||
link.targetIdx = idx
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package reverse
|
||||
|
||||
import (
|
||||
"natpass/code/client/global"
|
||||
"natpass/code/client/pool"
|
||||
"natpass/code/client/tunnel"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/lwch/logging"
|
||||
"github.com/lwch/runtime"
|
||||
)
|
||||
|
||||
// Tunnel tunnel object
|
||||
type Tunnel struct {
|
||||
sync.RWMutex
|
||||
Name string
|
||||
cfg global.Tunnel
|
||||
links map[string]*Link
|
||||
}
|
||||
|
||||
// New new tunnel
|
||||
func New(cfg global.Tunnel) *Tunnel {
|
||||
return &Tunnel{
|
||||
Name: cfg.Name,
|
||||
cfg: cfg,
|
||||
links: make(map[string]*Link),
|
||||
}
|
||||
}
|
||||
|
||||
// NewLink new link
|
||||
func (tn *Tunnel) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) tunnel.Link {
|
||||
remoteConn.AddLink(id)
|
||||
logging.Info("create link %s for reverse %s on connection %d",
|
||||
id, tn.Name, remoteConn.Idx)
|
||||
link := &Link{
|
||||
parent: tn,
|
||||
id: id,
|
||||
target: remote,
|
||||
targetIdx: remoteIdx,
|
||||
local: localConn,
|
||||
remote: remoteConn,
|
||||
OnWork: make(chan struct{}),
|
||||
}
|
||||
tn.Lock()
|
||||
tn.links[link.id] = link
|
||||
tn.Unlock()
|
||||
return link
|
||||
}
|
||||
|
||||
// GetName get reverse tunnel name
|
||||
func (tn *Tunnel) GetName() string {
|
||||
return tn.Name
|
||||
}
|
||||
|
||||
// GetTypeName get reverse tunnel type name
|
||||
func (tn *Tunnel) GetTypeName() string {
|
||||
return "reverse"
|
||||
}
|
||||
|
||||
// GetTarget get target of this tunnel
|
||||
func (tn *Tunnel) GetTarget() string {
|
||||
return tn.cfg.Target
|
||||
}
|
||||
|
||||
// GetLinks get tunnel links
|
||||
func (tn *Tunnel) GetLinks() []tunnel.Link {
|
||||
ret := make([]tunnel.Link, 0, len(tn.links))
|
||||
tn.RLock()
|
||||
for _, link := range tn.links {
|
||||
ret = append(ret, link)
|
||||
}
|
||||
tn.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetRemote get remote target name
|
||||
func (tn *Tunnel) GetRemote() string {
|
||||
return tn.cfg.Target
|
||||
}
|
||||
|
||||
// GetPort get listen port
|
||||
func (tn *Tunnel) GetPort() uint16 {
|
||||
return tn.cfg.LocalPort
|
||||
}
|
||||
|
||||
// Handle handle tunnel
|
||||
func (tn *Tunnel) Handle(pool *pool.Pool) {
|
||||
if tn.cfg.Type == "tcp" {
|
||||
tn.handleTCP(pool)
|
||||
} else {
|
||||
// TODO
|
||||
func() {}()
|
||||
}
|
||||
}
|
||||
|
||||
func (tn *Tunnel) handleTCP(pool *pool.Pool) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logging.Error("close tcp tunnel: %s, err=%v", tn.cfg.Name, err)
|
||||
}
|
||||
}()
|
||||
l, err := net.ListenTCP("tcp", &net.TCPAddr{
|
||||
IP: net.ParseIP(tn.cfg.LocalAddr),
|
||||
Port: int(tn.cfg.LocalPort),
|
||||
})
|
||||
runtime.Assert(err)
|
||||
defer l.Close()
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
logging.Error("accept from %s tunnel, err=%v", tn.cfg.Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
id, err := runtime.UUID(16, "0123456789abcdef")
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
logging.Error("generate link id failed, err=%v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
remote := pool.Get(id)
|
||||
if remote == nil {
|
||||
conn.Close()
|
||||
logging.Error("no connection available")
|
||||
continue
|
||||
}
|
||||
link := tn.NewLink(id, tn.cfg.Target, 0, conn, remote).(*Link)
|
||||
remote.SendConnectReq(id, tn.cfg)
|
||||
link.Forward()
|
||||
}
|
||||
}
|
||||
|
||||
func (tn *Tunnel) remove(id string) {
|
||||
tn.Lock()
|
||||
delete(tn.links, id)
|
||||
tn.Unlock()
|
||||
}
|
||||
@@ -5,5 +5,5 @@ dashboard: # web面板
|
||||
listen: 0.0.0.0 # 监听地址
|
||||
port: 8080 # 监听端口号
|
||||
#include conf.d/*.yaml
|
||||
tunnel: # tunnel列表
|
||||
#include tunnel.d/*.yaml
|
||||
rules: # rule列表
|
||||
#include rule.d/*.yaml
|
||||
@@ -1,7 +0,0 @@
|
||||
- name: rdp # 链路名称
|
||||
target: that # 目标客户端ID
|
||||
type: tcp # 连接类型tcp或udp
|
||||
local_addr: 0.0.0.0 # 本地监听地址
|
||||
local_port: 3389 # 本地监听端口号
|
||||
remote_addr: 127.0.0.1 # 目标客户端连接地址
|
||||
remote_port: 3389 # 目标客户端连接端口号
|
||||
@@ -17,9 +17,9 @@ LDFLAGS="$LDFLAGS
|
||||
--extldflags '-static -fpic -lssp'"
|
||||
fi
|
||||
|
||||
go run contrib/bindata/main.go -pkg shell -o code/client/tunnel/shell/assets.go \
|
||||
go run contrib/bindata/main.go -pkg shell -o code/client/rule/shell/assets.go \
|
||||
-prefix html/shell "$@" html/shell/...
|
||||
go run contrib/bindata/main.go -pkg vnc -o code/client/tunnel/vnc/assets.go \
|
||||
go run contrib/bindata/main.go -pkg vnc -o code/client/rule/vnc/assets.go \
|
||||
-prefix html/vnc "$@" html/vnc/...
|
||||
go run contrib/bindata/main.go -pkg dashboard -o code/client/dashboard/assets.go \
|
||||
-prefix html/dashboard "$@" html/dashboard/...
|
||||
|
||||
@@ -118,7 +118,7 @@ func main() {
|
||||
func bindata() {
|
||||
cmd := exec.Command("go", "run", "contrib/bindata/main.go",
|
||||
"-pkg", "shell",
|
||||
"-o", "code/client/tunnel/shell/assets.go",
|
||||
"-o", "code/client/rule/shell/assets.go",
|
||||
"-prefix", "html/shell",
|
||||
"html/shell/...")
|
||||
cmd.Stdout = os.Stdout
|
||||
@@ -127,7 +127,7 @@ func bindata() {
|
||||
|
||||
cmd = exec.Command("go", "run", "contrib/bindata/main.go",
|
||||
"-pkg", "vnc",
|
||||
"-o", "code/client/tunnel/vnc/assets.go",
|
||||
"-o", "code/client/rule/vnc/assets.go",
|
||||
"-prefix", "html/vnc",
|
||||
"html/vnc/...")
|
||||
cmd.Stdout = os.Stdout
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# 实现原理
|
||||
|
||||
基于tls链接,protobuf进行数据传输,下面举例在办公网络穿透到家庭网络,
|
||||
并通过rdp进行连接家庭网络下的某台windows设备
|
||||
基于tls链接,protobuf进行数据传输,下面举例远程连接服务器集群内的某台主机
|
||||
|
||||

|
||||

|
||||
|
||||
server端配置(10.0.1.1):
|
||||
|
||||
@@ -17,9 +16,9 @@ server端配置(10.0.1.1):
|
||||
key: /dir/to/tls/key/file # tls密钥
|
||||
crt: /dir/to/tls/crt/file # tls证书
|
||||
|
||||
家庭网络client配置(192.168.1.100):
|
||||
服务器client配置(192.168.1.100):
|
||||
|
||||
id: home # 客户端ID
|
||||
id: server # 客户端ID
|
||||
server: 10.0.1.1:6154 # 服务器地址
|
||||
secret: 0123456789 # 预共享密钥,必须与server端相同,否则握手失败
|
||||
log:
|
||||
@@ -36,29 +35,26 @@ server端配置(10.0.1.1):
|
||||
dir: /opt/natpass/logs # 路径
|
||||
size: 50M # 单个文件大小
|
||||
rotate: 7 # 保留数量
|
||||
tunnel: # 远端tunnel列表可为空
|
||||
rules: # 远端rule列表可为空
|
||||
- name: rdp # 链路名称
|
||||
target: home # 目标客户端ID
|
||||
type: tcp # 连接类型tcp或udp
|
||||
target: server # 目标客户端ID
|
||||
type: shell # 连接类型tcp或udp
|
||||
local_addr: 0.0.0.0 # 本地监听地址
|
||||
local_port: 3389 # 本地监听端口号
|
||||
remote_addr: 192.168.1.101 # 目标客户端连接地址
|
||||
remote_port: 3389 # 目标客户端连接端口号
|
||||
|
||||
工作流程如下:
|
||||
|
||||
1. 办公网络与家庭网络中的np-cli创建tls连接到np-svr
|
||||
2. np-cli服务发送握手包,并将配置文件中的secret字段进行md5哈希
|
||||
3. np-svr等待握手报文,若等待超时则为非法链接,直接断开
|
||||
4. 办公网络客户机创建新连接到172.16.1.100的3389端口
|
||||
5. 172.16.1.100上的np-cli接收到新请求后创建新的link并生成链接id
|
||||
6. 172.16.1.100上的np-cli发送connect_request消息,告知连接类型和链接目标地址和端口
|
||||
7. np-svr转发connect_request消息至192.168.1.100上的np-cli
|
||||
8. 192.168.1.100上的np-cli接收到connect_request消息,根据请求信息创建链接到目标地址和端口
|
||||
9. 192.168.1.100上的np-cli根据链接创建结果返回connect_response消息
|
||||
10. np-svr转发connect_response消息至172.16.1.100上的np-cli
|
||||
11. 172.168.1.100上的np-cli接收到connect_response消息后根据是否成功来决定是否需要断开rdp客户端链接
|
||||
12. 链路打通,两端各自发送data消息到对应链路
|
||||
4. 用户打开办公网络主机172.16.1.100上的终端页面,并连接到服务器集群中的主机server
|
||||
5. 172.16.1.100上的np-cli发送connect_request消息,并将连接类型设置为shell
|
||||
6. np-svr转发connect_request消息至192.168.1.100上的np-cli
|
||||
7. 192.168.1.100上的np-cli接收到connect_request消息,创建/bin/bash进程
|
||||
8. 192.168.1.100上的np-cli根据链接创建结果返回connect_response消息
|
||||
9. np-svr转发connect_response消息至172.16.1.100上的np-cli
|
||||
10. 172.168.1.100上的np-cli接收connect_response消息
|
||||
11. 开始转发网页上的输入输出内容
|
||||
|
||||
## 软件架构
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
<mxfile host="Chrome" modified="2021-11-15T16:37:12.268Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" etag="TKZKltqgxWfshnQa0pVI" version="15.5.6" type="device"><diagram id="LZ-Lv04eS_hwo8OXVvyP" name="第 1 页">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</diagram></mxfile>
|
||||
<mxfile host="Chrome" modified="2021-11-18T16:09:14.322Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" etag="I6b9FnXFCRl5Ulcx4P_B" version="15.5.6" type="device"><diagram id="LZ-Lv04eS_hwo8OXVvyP" name="第 1 页">5V1bc6JIFP41PI5FN7fmERRnandnHyZbNbP7skWUKBUCDpJJsr9++7SAQp94iVxEfZjpNIj4nUufy9eoaOOn18+pv1p+TeZBpFB1/qpoE4VSQqjG/4OZt82MpVqbiUUazvOTthN34X9BPqnms8/hPFhXTsySJMrCVXVylsRxMMsqc36aJi/V0x6SqPqpK38RSBN3Mz+SZ7+H82y5mWXU2s5/CcLFsvhkYtqbI09+cXL+TdZLf5687ExpnqKN0yTJNqOn13EQAXgFLpv3Td85Wt5YGsTZMW94eL1bkufs291P+sM00iT6Ov/xKb/KLz96zr9wfrPZW4FAmjzH8wAuoiqa+7IMs+Bu5c/g6AuXOZ9bZk8R/4vw4UMYReMkSlLxXm0qXnxevtnik4M0C153pvKb/xwkT0GWvvFT8qNajmOuSAWsL1upmHo+t9yViMryWT9XhUV56S1afJADdgJ4lnUYvQWHb3X8ty8V2b8vrqDuRYXVUNFlWEpb2oVFt9tCpZBTczqVxFnuGCjDdGzMX6iO7ZfaYc3rEUSKgGhGWQ5HBU3z53NSHPi0FkA5/ASir163B/loAf+vl/DpnqEwR7GniscUpinupLg4v9nN9TdnS4LjiGVV6aQB/8hcW0GY/nOWbG5CHPajcBHz8YwLJeAScwH2kPtXJz/wFM7n8GZ3lYRxJnA0XMWY1AQdJzGctM7S5DGoTVa1qa4uzatFftSiI6NifLohG5+FqU1bWmOYstZ4puKoimvDgE0Ux4OBrcHY00Hy9ljxLMXlWuCKgcv14sEPo3t/9igUhSmuKt49VpgFM/watgMDm8AF4DKu4uh7rJycZOVEP2klaUicpCpMDVlgCOtUmkcsLzyoWMFwHcaLKHAg4OEYzcOULyFhEgsbSeH2Lx5+u25NlOnyUmbI+Gut4c8Qa+LGMFVsXWg/txQvX67/5W5wlcTrAAzFNcFowGKI4kyvyyxKERwyC6M1sdiSWKKELyh8Kg38+XXBTRAv1CnaphzNpcFTkgVXArd6GG+7U7yPyMiux+nrdadfupK+nL6JBd4n479OngeBP9GsixOAjqy6Igrl6y0f8FDTdYLXYHZ7IalO+g5JTeOWvJNdywisnk3DQnwT6L6u8FCZp258oWKmCFE9yPDAang+51yXERR1sr4CIku7JRMoPMlbFeneLKAR/zPc1bl3/LEC034PxI8aQ/dA6kEX1GmOQDAXdFpxmDKsOCxKg2NRGhQFYoeAUB1XVDGOKxCfJtmqJD0TavnNdIsMKbNQkejJYKWF7UrObEBy3x1zvAj/sb9R6+/Y+/J79vab+Uk/Irtru2MkIcMQYCy1NWDwwFLC5a8/7hTPBi/CfQl4FAu0EBIAojAZtXP0bjx+14Psl+JJHaSytNAJoEfUjs9p7LYIWbn4yVqpm11CKJd/hU5uKsCijcI8vriR84BtD0CjGrthySOmkq0lj3LdFsXzTEVtDc96q713PIsb2AF0NBrxCfFvDcMBNG5bk5yuSr0lxLcgoqOtiU6OA1Bb+PNCbUE3pLphh9aAfwmkW9d1aFX2jAtQLFtCBU8VilWkeSJJ4wyvQ2ycd2P4/WI7jY3TMYjnJ1w4G+dXPLtxLs65SlESTauWZxA5R++UimMhdie1MV6S9JELInf7gn7jcCXgg6nijqG7AWfaQCjYvBeaHRsaDy2pOetgvQ6TWJX0o6MiS2MSHDFL3XnVeh+WOpKZB9Rko6Ia0skqg0mVQfcJklQLjBcIVoIb4ooBt2g2Ff2oMfCwtqUxPtBB2jzH5VKFc7jwJwqzxbumkONCNcYA8tXAJauOTPq+ZDWGS9YeaaxLyR4RP1xAXb8pmWh0xFR7+6pZmya7z7YKzbg05GRxSNyrbiyHR0GXYDlUzkOv2nK0kU7ftRxN79lyqLxEXQI9rin0jf0WoWIW0RZFAsef3pI16NqI7JOHgXqoTu1hGP36buRBzP7lgfG76nsUHlZrJAze8rz4jCWyIrHaO07RFxr8gr/fvfEst3f3NgwGWDfmZBq9WxNOyGCeqCJYIuu0d6oI9RAayVWv3IJ6Nh85y7wIOn1LZTg8HiNtVeLQb3HMftQL4Iw1JQEm9br6j8GwJgRCG7PBMzmikAbOiRWF8Pt0l6B0XRl+zWAuYIXHth6jwsormiJ2Y9YtCMu+uHAM60xJwprBunJz0kFTnW6Fg29lqVuSKfZcOwXn8hbd3gXIahjM8taihAuoDOjYwmOK9EQXAzMvAtSba1Ir7bqMA8lZSLFLrhtqDdKMqUPcOWvZQp500zVrmWAayxTbzotUzBW8jpLFnLO62mExm+aJimm/I5sLYjEf05T9KHuJIOylFjG8GFoz2q47kcxE8d0jomJrE+GIeWxDtg3an8/BOsPCmFN3lZwv45Md+Oky1vtkR+JC//BjBU4Am/YBNrXqYFOKRDIagnaxs7R5tJHAvzkTq1DIln48j4L0Og1JI9rIOmhJne6A/3j/49INSVcv0JCQ9kZjhlQ2QCAhn0hkoqOy8Gu0Ov2o5QvTg9YyEAOLWTrOQIha2wtvy6gY2KJevrH58LjTZux5eliK8PgwypQBxiLlFvHF3E9rRaGu8aX944vtUj3RvaMb2eMgA2493NR6MVqlSZZc0a6K5jWioP0ifh7TiPb2xWG0XxOySngUgQnseObu0H/qCScMHCrK6yVXSAfuw4ZWz1fsvM9IsadSDED09eCgNedQ38qGlC2oiqhGa48e0ZG1blNHsw1opjAvrw43UVnbXwL2DNj+jqJ/+nMqqjBjFojGFKQ1nI9Y8z4cz7YMJmHaITT14qm6HaEpO7SX4H6dzB6DTTnMAK/VJr574ogPPIK/tssO0VbVlPFt7xHJcl4w8+Nf/HPyJ1mzbb9oKCDrRKulXyjMXRY9DKR6uGXr7DBB2ER4Yya8sTUYyGlNr0t0K4i3tKcGRxzjdYgWKGwBFU+3hPiHDxiQBsr9hXRaTLqiLzoR+4kHIgaDHnYv6M8wtCaFd55FagvKuWg7563pCfBqh2sA0oMLUAPoEnpTTg0FNBDgE1g2wf+IfdBDwbjuZBDtxp5q0B7jBf+xiBoXabg6rWvd6TT/c/tDTuLYzs9had7/</diagram></mxfile>
|
||||
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 80 KiB |
@@ -1,158 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2021-08-19T03:29:42.029Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" etag="kKNkbF7So22PkGp4eWOc" version="14.9.7" type="github">
|
||||
<diagram id="Kjf8sS8rRDm6eebZkxfj" name="第 1 页">
|
||||
<mxGraphModel dx="1038" dy="579" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="290" y="219" as="sourcePoint" />
|
||||
<mxPoint x="390" y="130" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="290" y="219" />
|
||||
<mxPoint x="290" y="130" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.71;exitY=1.066;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WTAgDNwTBJ27G1_lSc48-3" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="320" y="356" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-3" value="" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/security/Router_VPN.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="280" y="220" width="55.800000000000004" height="39.6" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.694;entryY=-0.054;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.717;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WTAgDNwTBJ27G1_lSc48-4" target="WTAgDNwTBJ27G1_lSc48-8" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="WTAgDNwTBJ27G1_lSc48-4" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="436" y="150" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="500" y="150" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-4" value="" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/security/Router_VPN.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="490" y="221" width="55.800000000000004" height="39.6" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="WTAgDNwTBJ27G1_lSc48-5" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="290" y="260" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="290" y="330" />
|
||||
<mxPoint x="290" y="330" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=-0.005;exitY=0.676;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WTAgDNwTBJ27G1_lSc48-5" target="WTAgDNwTBJ27G1_lSc48-18" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="230" y="402" />
|
||||
<mxPoint x="230" y="402" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-5" value="内网设备<br>172.16.1.100" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/computer_and_terminals/Personal_Computer_with_Server.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="276.7" y="360" width="62.400000000000006" height="62.400000000000006" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="440" y="130" as="sourcePoint" />
|
||||
<mxPoint x="530" y="222" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="530" y="130" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.681;entryY=0.015;entryDx=0;entryDy=0;entryPerimeter=0;exitX=-0.014;exitY=0.759;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WTAgDNwTBJ27G1_lSc48-6" target="WTAgDNwTBJ27G1_lSc48-3" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-6" value="np-svr<br>公网服务<br>10.0.1.1" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/computer_and_terminals/Server_Desktop.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="393" y="110" width="42.599999999999994" height="54" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="500" y="357" as="sourcePoint" />
|
||||
<mxPoint x="500" y="250" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1.053;exitY=0.33;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WTAgDNwTBJ27G1_lSc48-8" target="WTAgDNwTBJ27G1_lSc48-28" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="590" y="381" />
|
||||
<mxPoint x="590" y="381" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-8" value="内网设备<br>192.168.1.100" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/computer_and_terminals/Personal_Computer_with_Server.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="486.7" y="360" width="62.400000000000006" height="62.400000000000006" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-16" value="办公网络<br>172.16.1.1/24" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="221" width="90" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-17" value="家庭网络<br>192.168.1.1/24" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="224.8" width="100" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="WTAgDNwTBJ27G1_lSc48-18" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="276" y="380" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="276" y="380" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="200" y="410" as="sourcePoint" />
|
||||
<mxPoint x="200" y="480" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-18" value="" style="pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;aspect=fixed;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.vvd.cloud_computing;fillColor=#066A90;" parent="1" vertex="1">
|
||||
<mxGeometry x="160" y="375" width="50" height="32" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="170" y="410" as="targetPoint" />
|
||||
<mxPoint x="170" y="470" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-19" value="rdp客户端" style="pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#434445;aspect=fixed;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.vvd.administrator;" parent="1" vertex="1">
|
||||
<mxGeometry x="174.25" y="480" width="21.5" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-21" value="np-cli<br>监听3389端口" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="70" y="375" width="90" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="650" y="410" as="sourcePoint" />
|
||||
<mxPoint x="650" y="480" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="WTAgDNwTBJ27G1_lSc48-28" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="550" y="400" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="560" y="400" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-28" value="" style="pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;aspect=fixed;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.vvd.cloud_computing;fillColor=#066A90;" parent="1" vertex="1">
|
||||
<mxGeometry x="610" y="375" width="50" height="32" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="620" y="410" as="targetPoint" />
|
||||
<mxPoint x="620" y="470" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-31" value="np-cli<br>连接到3389端口" style="text;html=1;resizable=0;autosize=1;align=center;verticalAlign=middle;points=[];fillColor=none;strokeColor=none;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="665" y="377" width="100" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WTAgDNwTBJ27G1_lSc48-32" value="内网设备<br>192.168.1.101" style="points=[];aspect=fixed;html=1;align=center;shadow=0;dashed=0;image;image=img/lib/allied_telesis/computer_and_terminals/Personal_Computer_with_Server.svg;" parent="1" vertex="1">
|
||||
<mxGeometry x="603.8" y="480" width="62.400000000000006" height="62.400000000000006" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
<mxfile host="Chrome" modified="2021-11-18T15:55:23.638Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" etag="KKjYPjoS9srZirTPQqsC" version="15.5.6" type="device"><diagram id="Kjf8sS8rRDm6eebZkxfj" name="第 1 页">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</diagram></mxfile>
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 283 KiB After Width: | Height: | Size: 260 KiB |
|
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 393 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 102 KiB |
@@ -1,30 +1,10 @@
|
||||
# 隧道配置
|
||||
# 规则配置
|
||||
|
||||
所有隧道均为正向隧道,由连接发起方进行配置
|
||||
所有链接均为正向配置,由连接发起方进行配置
|
||||
|
||||
## tcp隧道
|
||||
## shell规则
|
||||
|
||||
tcp隧道用于反向代理远程的任意服务,如rdp、ssh、http等
|
||||
|
||||
- name: rdp # 链路名称
|
||||
target: that # 目标客户端ID
|
||||
type: tcp # 连接类型tcp或udp
|
||||
local_addr: 0.0.0.0 # 本地监听地址
|
||||
local_port: 3389 # 本地监听端口号
|
||||
remote_addr: 127.0.0.1 # 目标客户端连接地址
|
||||
remote_port: 3389 # 目标客户端连接端口号
|
||||
|
||||
1. `name`: 该隧道名称,必须全局唯一
|
||||
2. `target`: 对端客户端ID
|
||||
3. `type`: tcp
|
||||
4. `local_addr`: 本地监听地址,如只允许局域网访问可绑定在局域网IP地址上
|
||||
5. `local_port`: 本地监听端口号
|
||||
6. `remote_addr`: 目标客户端连接地址,该地址为127.0.0.1时表示连接本机服务,也可连接局域网或广域网上的其他地址
|
||||
7. `remote_port`: 目标客户端连接端口号
|
||||
|
||||
## shell隧道
|
||||
|
||||
shell隧道用于创建一个网页端的命令行操作页面
|
||||
shell规则用于创建一个网页端的命令行操作页面
|
||||
|
||||
- name: shell # 链路名称
|
||||
target: that # 目标客户端ID
|
||||
@@ -37,7 +17,7 @@ shell隧道用于创建一个网页端的命令行操作页面
|
||||
env: # 环境变量设置
|
||||
- TERM=xterm
|
||||
|
||||
1. `name`: 该隧道名称,必须全局唯一
|
||||
1. `name`: 该规则名称,必须全局唯一
|
||||
2. `target`: 对端客户端ID
|
||||
3. `type`: shell
|
||||
4. `local_addr`: 本地监听地址,如只允许局域网访问可绑定在局域网IP地址上
|
||||
@@ -48,11 +28,11 @@ shell隧道用于创建一个网页端的命令行操作页面
|
||||
- windows系统:优先查找powershell命令,若没有则查找cmd命令,否则报错
|
||||
7. `env`: 进程启动时的环境变量设置
|
||||
|
||||
连接成功后即可使用浏览器访问`local_port`所对应的端口来创建shell隧道,如http://127.0.0.1:8080
|
||||
连接成功后即可使用浏览器访问`local_port`所对应的端口来创建shell,如http://127.0.0.1:8080
|
||||
|
||||
## vnc隧道
|
||||
## vnc规则
|
||||
|
||||
vnc隧道用于创建一个网页端的远程桌面操作页面,目前仅支持*windows*操作系统
|
||||
vnc规则用于创建一个网页端的远程桌面操作页面,目前仅支持*windows*操作系统
|
||||
|
||||
- name: vnc # 链路名称
|
||||
target: that # 目标客户端ID
|
||||
@@ -61,14 +41,14 @@ vnc隧道用于创建一个网页端的远程桌面操作页面,目前仅支
|
||||
local_port: 5900 # 本地监听端口号
|
||||
fps: 10 # 刷新频率
|
||||
|
||||
1. `name`: 该隧道名称,必须全局唯一
|
||||
1. `name`: 该规则名称,必须全局唯一
|
||||
2. `target`: 对端客户端ID
|
||||
3. `type`: shell
|
||||
4. `local_addr`: 本地监听地址,如只允许局域网访问可绑定在局域网IP地址上
|
||||
5. `local_port`: 本地监听端口号
|
||||
6. `fps`: 每秒钟截屏多少次,最高50
|
||||
|
||||
连接成功后即可使用浏览器访问`local_port`所对应的端口来创建vnc隧道,如http://127.0.0.1:5900
|
||||
连接成功后即可使用浏览器访问`local_port`所对应的端口来创建vnc,如http://127.0.0.1:5900
|
||||
|
||||
注意:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
1. 在远端机器上[下载](https://github.com/lwch/natpass/releases)并解压到任意目录
|
||||
2. 修改client.yaml配置文件,设置*id*为remote,设置*server*地址,并删除以下配置
|
||||
|
||||
#include tunnel.d/*.yaml
|
||||
#include rule.d/*.yaml
|
||||
3. 修改conf.d/conn.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致
|
||||
4. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
1. 在本地机器上[下载](https://github.com/lwch/natpass/releases)并解压到任意目录
|
||||
2. 修改client.yaml配置文件,设置*id*为local,设置*server*地址
|
||||
3. 修改conf.d/conn.yaml配置文件,修改*secret*密钥,该密钥必须与服务器端保持一致
|
||||
4. 修改tunnel.d目录下的tunnel配置文件,[tunnel配置方法](tunnel.md)
|
||||
4. 修改rule.d目录下的规则配置文件,[rule配置方法](rules.md)
|
||||
5. 使用以下命令将np-cli注册为系统服务,其中-conf参数后跟配置文件所在路径,-user参数后为程序启动身份(建议使用nobody身份启动)
|
||||
|
||||
sudo ./np-cli -conf server.yaml -action install -user nobody
|
||||
|
||||
@@ -7,7 +7,7 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/go-bindata/go-bindata/v3 v3.1.3
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-vgo/robotgo v0.100.7
|
||||
github.com/go-vgo/robotgo v0.100.8
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/kardianos/service v1.2.0
|
||||
github.com/kisielk/errcheck v1.6.0 // indirect
|
||||
@@ -18,7 +18,7 @@ require (
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/tools v0.1.7 // indirect
|
||||
google.golang.org/protobuf v1.27.1
|
||||
|
||||
@@ -14,8 +14,8 @@ github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7N
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-vgo/robotgo v0.100.7 h1:tkb/Sd2Drz3uyKGzlhjhNIbLEtV7nkzyGK0RxsuG418=
|
||||
github.com/go-vgo/robotgo v0.100.7/go.mod h1:GCjwxRFoUkuekzm02WexYBV0paDLCbrrlKEfxt/CB10=
|
||||
github.com/go-vgo/robotgo v0.100.8 h1:fBcmqPoQq/0vOr0C45T6SSScKwuYgAEJr9+T1PulHOA=
|
||||
github.com/go-vgo/robotgo v0.100.8/go.mod h1:GCjwxRFoUkuekzm02WexYBV0paDLCbrrlKEfxt/CB10=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -100,8 +100,8 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 h1:7NCfEGl0sfUojmX78nK9pBJuUlSZWEJA/TwASvfiPLo=
|
||||
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
||||
@@ -1 +1 @@
|
||||
../bootstrap-5.1.3
|
||||
../bootstrap-4.6.1
|
||||
@@ -3,6 +3,15 @@
|
||||
<script src="/js/index.js"></script>
|
||||
{{template "aside" .}}
|
||||
<script>aside.active_dashboard();</script>
|
||||
<style>
|
||||
#label-rule-type {
|
||||
margin-right: 5px;
|
||||
}
|
||||
#rule-type {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header">
|
||||
<div class="container-fluid">
|
||||
@@ -23,10 +32,18 @@
|
||||
<div class="row"><div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">隧道列表</h3>
|
||||
<h3 class="card-title">终端列表</h3>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<table id="tunnels" class="table table-hover">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label id="label-rule-type" for="rule-type">类型:</label>
|
||||
<select id="rule-type" class="form-control">
|
||||
<option value="all">全部</option>
|
||||
<option value="shell">shell</option>
|
||||
<option value="vnc">vnc</option>
|
||||
</select>
|
||||
</div>
|
||||
<table id="rules" class="table table-hover">
|
||||
<thead><tr>
|
||||
<th>名称</th>
|
||||
<th style="width:200px">对端</th>
|
||||
@@ -34,7 +51,7 @@
|
||||
<th style="width:120px">虚拟连接数</th>
|
||||
<th style="width:200px">接收/发送(字节数)</th>
|
||||
<th style="width:200px">接收/发送(数据包)</th>
|
||||
<th style="width:200px">操作</th>
|
||||
<th style="width:120px">操作</th>
|
||||
</tr></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
@@ -43,7 +60,7 @@
|
||||
</div>
|
||||
<!-- card -->
|
||||
</div></div>
|
||||
<!-- 隧道列表 -->
|
||||
<!-- 终端列表 -->
|
||||
</div>
|
||||
<!-- container -->
|
||||
</section>
|
||||
|
||||
@@ -1,58 +1,63 @@
|
||||
var page = {
|
||||
init: function() {
|
||||
$('#rule-type').change(page.render);
|
||||
page.render();
|
||||
setInterval(page.render, 5000);
|
||||
},
|
||||
render: function() {
|
||||
page.render_cards();
|
||||
page.render_tunnels();
|
||||
page.render_rules();
|
||||
},
|
||||
render_cards: function() {
|
||||
$.get('/api/info', function(ret) {
|
||||
$('#cards').empty();
|
||||
page.add_card('隧道总数', ret.tunnels);
|
||||
page.add_card('规则总数', ret.rules);
|
||||
page.add_card('物理连接数', ret.physical_links);
|
||||
page.add_card('虚拟连接数', ret.virtual_links);
|
||||
page.add_card('终端会话', ret.sessions);
|
||||
});
|
||||
},
|
||||
render_tunnels: function() {
|
||||
$.get('/api/tunnels', function(ret) {
|
||||
$('#tunnels tbody').empty();
|
||||
$.each(ret, function(_, tunnel) {
|
||||
render_rules: function() {
|
||||
$.get('/api/rules', function(ret) {
|
||||
$('#rules tbody').empty();
|
||||
var type = $('#rule-type').val();
|
||||
$.each(ret, function(_, rule) {
|
||||
if (type != 'all' && rule.type != type) {
|
||||
return;
|
||||
}
|
||||
var send_bytes = 0;
|
||||
var send_packet = 0;
|
||||
var recv_bytes = 0;
|
||||
var recv_packet = 0;
|
||||
$.each(tunnel.links, function(_, link) {
|
||||
$.each(rule.links, function(_, link) {
|
||||
send_bytes += link.send_bytes;
|
||||
send_packet += link.send_packet;
|
||||
recv_bytes += link.recv_bytes;
|
||||
recv_packet += link.recv_packet;
|
||||
});
|
||||
var op = '';
|
||||
switch (tunnel.type) {
|
||||
switch (rule.type) {
|
||||
case 'reverse':
|
||||
op = `
|
||||
<a href="http://${location.hostname}:${tunnel.port}" target="_blank">http</a>
|
||||
<a href="https://${location.hostname}:${tunnel.port}" target="_blank">https</a>`;
|
||||
<a href="http://${location.hostname}:${rule.port}" target="_blank">http</a>
|
||||
<a href="https://${location.hostname}:${rule.port}" target="_blank">https</a>`;
|
||||
break;
|
||||
case 'shell':
|
||||
case 'vnc':
|
||||
op = `<a href="http://${location.host}/terminal.html?name=${tunnel.name}" target="_blank">连接</a>`;
|
||||
op = `<a href="http://${location.host}/terminal.html?name=${rule.name}" target="_blank">连接</a>`;
|
||||
break;
|
||||
}
|
||||
var str = `
|
||||
<tr>
|
||||
<td>${tunnel.name}</td>
|
||||
<td>${tunnel.remote}</td>
|
||||
<td>${tunnel.type}</td>
|
||||
<td>${tunnel.links?tunnel.links.length:0}</td>
|
||||
<td>${rule.name}</td>
|
||||
<td>${rule.remote}</td>
|
||||
<td>${rule.type}</td>
|
||||
<td>${rule.links?rule.links.length:0}</td>
|
||||
<td>${humanize.bytes(recv_bytes)}/${humanize.bytes(send_bytes)}</td>
|
||||
<td>${recv_packet}/${send_packet}</td>
|
||||
<td>${op}</td>
|
||||
</tr>`;
|
||||
$('#tunnels tbody').append($(str));
|
||||
$('#rules tbody').append($(str));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -11,14 +11,14 @@ var page = {
|
||||
},
|
||||
load: function(cb) {
|
||||
if (!cb) cb = function(){};
|
||||
$.get('/api/tunnels', function(ret) {
|
||||
$.get('/api/rules', function(ret) {
|
||||
$('#terms').empty();
|
||||
$.each(ret, function(_, tunnel) {
|
||||
if (tunnel.type != 'shell' &&
|
||||
tunnel.type != 'vnc') {
|
||||
$.each(ret, function(_, rule) {
|
||||
if (rule.type != 'shell' &&
|
||||
rule.type != 'vnc') {
|
||||
return;
|
||||
}
|
||||
$('#terms').append($(`<option value="${tunnel.port}">${tunnel.name}</option>`));
|
||||
$('#terms').append($(`<option value="${rule.port}">${rule.name}</option>`));
|
||||
});
|
||||
cb();
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row"><div class="col-12">
|
||||
<div class="input-group mb-3">
|
||||
<select id="terms" class="form-select"></select>
|
||||
<select id="terms" class="form-control"></select>
|
||||
<div class="input-group-append">
|
||||
<button id="connect" class="btn btn-primary" type="button">连接</button>
|
||||
</div>
|
||||
|
||||
@@ -1 +1 @@
|
||||
../bootstrap-5.1.3
|
||||
../bootstrap-4.6.1
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="container-fluid">
|
||||
<div>
|
||||
<label>图像质量:</label>
|
||||
<select id="quality" class="form-select">
|
||||
<select id="quality" class="form-control">
|
||||
<option value="100">原始</option>
|
||||
<option value="90" selected>高</option>
|
||||
<option value="70">中</option>
|
||||
|
||||