移除反向代理代码

This commit is contained in:
lwch
2021-11-18 23:17:44 +08:00
parent 4ce221eeae
commit d30b27367f
59 changed files with 93 additions and 439 deletions

View File

@@ -7,7 +7,7 @@
[![platform](https://img.shields.io/badge/platform-linux%20%7C%20windows%20%7C%20macos-lightgrey.svg)](https://github.com/lwch/natpass) [![platform](https://img.shields.io/badge/platform-linux%20%7C%20windows%20%7C%20macos-lightgrey.svg)](https://github.com/lwch/natpass)
[![QQ群711086098](https://img.shields.io/badge/QQ%E7%BE%A4-711086098-success)](https://jq.qq.com/?_wv=1027&k=6Fz2vkVE) [![QQ群711086098](https://img.shields.io/badge/QQ%E7%BE%A4-711086098-success)](https://jq.qq.com/?_wv=1027&k=6Fz2vkVE)
新一代NAT内网穿透工具支持tcp隧道、shell隧道[实现原理](docs/desc.md) 新一代主机管理工具支持shell管理支持远程桌面管理[实现原理](docs/desc.md)
1. [如何部署](docs/startup.md) 1. [如何部署](docs/startup.md)
2. [隧道配置](docs/tunnel.md) 2. [隧道配置](docs/tunnel.md)
@@ -19,11 +19,10 @@
3. 支持多路异步IO 3. 支持多路异步IO
4. 支持虚拟链路层 4. 支持虚拟链路层
5. 支持链路和终端会话监控 5. 支持链路和终端会话监控
6. 支持tcp协议反向代理 6. 支持web shell
7. 支持web shell 7. 支持web vnc
8. 支持web vnc 8. 支持多种操作系统
9. 支持多种操作系统 9. protobuf数据编码
10. protobuf数据编码
## 效果图 ## 效果图
@@ -51,29 +50,15 @@ windows11远程桌面
![win11-vnc](docs/imgs/vnc_win11.png) ![win11-vnc](docs/imgs/vnc_win11.png)
## 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路复用stcptls
[ 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 ## TODO
1. ~~支持include的yaml配置文件~~ 1. ~~支持include的yaml配置文件~~
2. ~~通用的connect、connect_response、disconnect消息~~ 2. ~~通用的connect、connect_response、disconnect消息~~
3. ~~所有隧道的dashboard页面~~ 3. ~~dashboard页面~~
4. 文件传输 4. 文件传输
5. ~web远程桌面~ 5. ~web远程桌面~
6. ~~流量监控统计页面server还是client?~~ 6. ~~流量监控统计页面server还是client?~~
7. web端管理tunnel 7. web端管理规则
## 免责声明 ## 免责声明

View File

@@ -4,10 +4,9 @@ import (
"natpass/code/client/dashboard" "natpass/code/client/dashboard"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel" tunnel "natpass/code/client/rule"
"natpass/code/client/tunnel/reverse" "natpass/code/client/rule/shell"
"natpass/code/client/tunnel/shell" "natpass/code/client/rule/vnc"
"natpass/code/client/tunnel/vnc"
"natpass/code/network" "natpass/code/network"
rt "runtime" rt "runtime"
"time" "time"
@@ -55,12 +54,8 @@ func (a *App) run() {
pl := pool.New(a.cfg) pl := pool.New(a.cfg)
mgr := tunnel.New() mgr := tunnel.New()
for _, t := range a.cfg.Tunnels { for _, t := range a.cfg.Rules {
switch t.Type { switch t.Type {
case "tcp", "udp":
tn := reverse.New(t)
mgr.Add(tn)
go tn.Handle(pl)
case "shell": case "shell":
sh := shell.New(t) sh := shell.New(t)
mgr.Add(sh) mgr.Add(sh)
@@ -89,8 +84,6 @@ func (a *App) run() {
switch msg.GetXType() { switch msg.GetXType() {
case network.Msg_connect_req: case network.Msg_connect_req:
switch msg.GetCreq().GetXType() { switch msg.GetCreq().GetXType() {
case network.ConnectRequest_tcp, network.ConnectRequest_udp:
a.connect(mgr, conn, msg)
case network.ConnectRequest_shell: case network.ConnectRequest_shell:
a.shellCreate(mgr, conn, msg) a.shellCreate(mgr, conn, msg)
case network.ConnectRequest_vnc: case network.ConnectRequest_vnc:

View File

@@ -1,60 +1,21 @@
package app package app
import ( import (
"fmt"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"natpass/code/client/tunnel/reverse" "natpass/code/client/rule/shell"
"natpass/code/client/tunnel/shell" "natpass/code/client/rule/vnc"
"natpass/code/client/tunnel/vnc"
"natpass/code/network" "natpass/code/network"
"net"
"strconv"
"github.com/lwch/logging" "github.com/lwch/logging"
) )
func (a *App) connect(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) { func (a *App) shellCreate(mgr *rule.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) {
create := msg.GetCreq() create := msg.GetCreq()
tn := mgr.Get(create.GetName(), msg.GetFrom()) tn := mgr.Get(create.GetName(), msg.GetFrom())
if tn == nil { if tn == nil {
tn = shell.New(global.Tunnel{ tn = shell.New(global.Rule{
Name: create.GetName(), Name: create.GetName(),
Target: msg.GetFrom(), Target: msg.GetFrom(),
Type: "shell", Type: "shell",
@@ -74,11 +35,11 @@ func (a *App) shellCreate(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) {
lk.Forward() 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() create := msg.GetCreq()
tn := mgr.Get(create.GetName(), msg.GetFrom()) tn := mgr.Get(create.GetName(), msg.GetFrom())
if tn == nil { if tn == nil {
tn = vnc.New(global.Tunnel{ tn = vnc.New(global.Rule{
Name: create.GetName(), Name: create.GetName(),
Target: msg.GetFrom(), Target: msg.GetFrom(),
Type: "vnc", Type: "vnc",

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"net/http" "net/http"
) )
@@ -12,12 +12,12 @@ import (
type Dashboard struct { type Dashboard struct {
cfg *global.Configure cfg *global.Configure
pl *pool.Pool pl *pool.Pool
mgr *tunnel.Mgr mgr *rule.Mgr
Version string Version string
} }
// New create dashboard object // 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{ return &Dashboard{
cfg: cfg, cfg: cfg,
pl: pl, 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 { func (db *Dashboard) ListenAndServe(addr string, port uint16) error {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/api/info", db.Info) mux.HandleFunc("/api/info", db.Info)
mux.HandleFunc("/api/tunnels", db.Tunnels) mux.HandleFunc("/api/rules", db.Rules)
mux.HandleFunc("/", db.Render) mux.HandleFunc("/", db.Render)
svr := &http.Server{ svr := &http.Server{
Addr: fmt.Sprintf("%s:%d", addr, port), Addr: fmt.Sprintf("%s:%d", addr, port),

View File

@@ -2,21 +2,21 @@ package dashboard
import ( import (
"encoding/json" "encoding/json"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"net/http" "net/http"
) )
// Info information data // Info information data
func (db *Dashboard) Info(w http.ResponseWriter, r *http.Request) { func (db *Dashboard) Info(w http.ResponseWriter, r *http.Request) {
var ret struct { var ret struct {
Tunnels int `json:"tunnels"` Rules int `json:"rules"`
PhysicalLinks int `json:"physical_links"` PhysicalLinks int `json:"physical_links"`
VirtualLinks int `json:"virtual_links"` VirtualLinks int `json:"virtual_links"`
Session int `json:"sessions"` Session int `json:"sessions"`
} }
ret.Tunnels = len(db.cfg.Tunnels) ret.Rules = len(db.cfg.Rules)
ret.PhysicalLinks = db.pl.Size() ret.PhysicalLinks = db.pl.Size()
db.mgr.Range(func(t tunnel.Tunnel) { db.mgr.Range(func(t rule.Rule) {
n := len(t.GetLinks()) n := len(t.GetLinks())
ret.VirtualLinks += n ret.VirtualLinks += n
if t.GetTypeName() == "shell" { if t.GetTypeName() == "shell" {

View File

@@ -2,12 +2,12 @@ package dashboard
import ( import (
"encoding/json" "encoding/json"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"net/http" "net/http"
) )
// Tunnels get tunnels list // Rules get rule list
func (db *Dashboard) Tunnels(w http.ResponseWriter, r *http.Request) { func (db *Dashboard) Rules(w http.ResponseWriter, r *http.Request) {
type link struct { type link struct {
ID string `json:"id"` ID string `json:"id"`
SendBytes uint64 `json:"send_bytes"` SendBytes uint64 `json:"send_bytes"`
@@ -23,7 +23,7 @@ func (db *Dashboard) Tunnels(w http.ResponseWriter, r *http.Request) {
Links []link `json:"links"` Links []link `json:"links"`
} }
var ret []item var ret []item
db.mgr.Range(func(t tunnel.Tunnel) { db.mgr.Range(func(t rule.Rule) {
var it item var it item
it.Name = t.GetName() it.Name = t.GetName()
it.Remote = t.GetRemote() it.Remote = t.GetRemote()

View File

@@ -2,6 +2,7 @@ package global
import ( import (
"crypto/md5" "crypto/md5"
"fmt"
"natpass/code/utils" "natpass/code/utils"
"time" "time"
@@ -9,8 +10,8 @@ import (
"github.com/lwch/yaml" "github.com/lwch/yaml"
) )
// Tunnel tunnel config // Rule rule config
type Tunnel struct { type Rule struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Target string `yaml:"target"` Target string `yaml:"target"`
Type string `yaml:"type"` Type string `yaml:"type"`
@@ -39,7 +40,7 @@ type Configure struct {
DashboardEnabled bool DashboardEnabled bool
DashboardListen string DashboardListen string
DashboardPort uint16 DashboardPort uint16
Tunnels []Tunnel Rules []Rule
} }
// LoadConf load configure file // LoadConf load configure file
@@ -63,16 +64,16 @@ func LoadConf(dir string) *Configure {
Listen string `yaml:"listen"` Listen string `yaml:"listen"`
Port uint16 `yaml:"port"` Port uint16 `yaml:"port"`
} `yaml:"dashboard"` } `yaml:"dashboard"`
Tunnel []Tunnel `yaml:"tunnel"` Rules []Rule `yaml:"rules"`
} }
runtime.Assert(yaml.Decode(dir, &cfg)) runtime.Assert(yaml.Decode(dir, &cfg))
for i, t := range cfg.Tunnel { for i, t := range cfg.Rules {
switch t.Type { switch t.Type {
case "tcp", "shell", "vnc": case "shell", "vnc":
default: 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 { if cfg.Link.Connections <= 0 {
cfg.Link.Connections = 3 cfg.Link.Connections = 3
@@ -96,6 +97,6 @@ func LoadConf(dir string) *Configure {
DashboardEnabled: cfg.Dashboard.Enabled, DashboardEnabled: cfg.Dashboard.Enabled,
DashboardListen: cfg.Dashboard.Listen, DashboardListen: cfg.Dashboard.Listen,
DashboardPort: cfg.Dashboard.Port, DashboardPort: cfg.Dashboard.Port,
Tunnels: cfg.Tunnel, Rules: cfg.Rules,
} }
} }

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"natpass/code/client/app" "natpass/code/client/app"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/tunnel/vnc" "natpass/code/client/rule/vnc"
"natpass/code/utils" "natpass/code/utils"
"os" "os"
"path/filepath" "path/filepath"

View File

@@ -9,26 +9,12 @@ import (
) )
// SendConnectReq send connect request message // 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 var msg network.Msg
msg.To = cfg.Target msg.To = cfg.Target
msg.XType = network.Msg_connect_req msg.XType = network.Msg_connect_req
msg.LinkId = id msg.LinkId = id
switch cfg.Type { 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": case "shell":
msg.Payload = &network.Msg_Creq{ msg.Payload = &network.Msg_Creq{
Creq: &network.ConnectRequest{ Creq: &network.ConnectRequest{
@@ -68,7 +54,7 @@ func (conn *Conn) SendConnectReq(id string, cfg global.Tunnel) {
} }
// SendConnectVnc send connect vnc request message // 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 var msg network.Msg
msg.To = cfg.Target msg.To = cfg.Target
msg.XType = network.Msg_connect_req msg.XType = network.Msg_connect_req

View File

@@ -1,4 +1,4 @@
package tunnel package rule
import ( import (
"natpass/code/client/pool" "natpass/code/client/pool"
@@ -15,8 +15,8 @@ type Link interface {
GetPackets() (uint64, uint64) GetPackets() (uint64, uint64)
} }
// Tunnel tunnel interface // Rule rule interface
type Tunnel interface { type Rule interface {
NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) Link NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, remoteConn *pool.Conn) Link
GetName() string GetName() string
GetRemote() string GetRemote() string
@@ -26,29 +26,29 @@ type Tunnel interface {
GetLinks() []Link GetLinks() []Link
} }
// Mgr tunnel manager // Mgr rule manager
type Mgr struct { type Mgr struct {
sync.RWMutex sync.RWMutex
tunnels []Tunnel rules []Rule
} }
// New new tunnel manager // New new rule manager
func New() *Mgr { func New() *Mgr {
return &Mgr{} return &Mgr{}
} }
// Add add tunnel // Add add rule
func (mgr *Mgr) Add(tunnel Tunnel) { func (mgr *Mgr) Add(rule Rule) {
mgr.Lock() mgr.Lock()
defer mgr.Unlock() defer mgr.Unlock()
mgr.tunnels = append(mgr.tunnels, tunnel) mgr.rules = append(mgr.rules, rule)
} }
// Get get tunnel by name // Get get rule by name
func (mgr *Mgr) Get(name, remote string) Tunnel { func (mgr *Mgr) Get(name, remote string) Rule {
mgr.RLock() mgr.RLock()
defer mgr.RUnlock() defer mgr.RUnlock()
for _, t := range mgr.tunnels { for _, t := range mgr.rules {
if t.GetName() == name && t.GetRemote() == remote { if t.GetName() == name && t.GetRemote() == remote {
return t return t
} }
@@ -56,11 +56,11 @@ func (mgr *Mgr) Get(name, remote string) Tunnel {
return nil return nil
} }
// Range range tunnels // Range range rules
func (mgr *Mgr) Range(fn func(Tunnel)) { func (mgr *Mgr) Range(fn func(Rule)) {
mgr.RLock() mgr.RLock()
defer mgr.RUnlock() defer mgr.RUnlock()
for _, t := range mgr.tunnels { for _, t := range mgr.rules {
fn(t) fn(t)
} }
} }

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"net" "net"
"net/http" "net/http"
"sync" "sync"
@@ -17,12 +17,12 @@ import (
type Shell struct { type Shell struct {
sync.RWMutex sync.RWMutex
Name string Name string
cfg global.Tunnel cfg global.Rule
links map[string]*Link links map[string]*Link
} }
// New new shell // New new shell
func New(cfg global.Tunnel) *Shell { func New(cfg global.Rule) *Shell {
return &Shell{ return &Shell{
Name: cfg.Name, Name: cfg.Name,
cfg: cfg, cfg: cfg,
@@ -31,7 +31,7 @@ func New(cfg global.Tunnel) *Shell {
} }
// NewLink new link // 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) remoteConn.AddLink(id)
logging.Info("create link %s for shell %s on connection %d", logging.Info("create link %s for shell %s on connection %d",
id, shell.Name, remoteConn.Idx) id, shell.Name, remoteConn.Idx)
@@ -48,24 +48,24 @@ func (shell *Shell) NewLink(id, remote string, remoteIdx uint32, localConn net.C
return link return link
} }
// GetName get shell tunnel name // GetName get shell rule name
func (shell *Shell) GetName() string { func (shell *Shell) GetName() string {
return shell.Name return shell.Name
} }
// GetTypeName get shell tunnel type name // GetTypeName get shell rule type name
func (shell *Shell) GetTypeName() string { func (shell *Shell) GetTypeName() string {
return "shell" return "shell"
} }
// GetTarget get target of this tunnel // GetTarget get target of this rule
func (shell *Shell) GetTarget() string { func (shell *Shell) GetTarget() string {
return shell.cfg.Target return shell.cfg.Target
} }
// GetLinks get tunnel links // GetLinks get rule links
func (shell *Shell) GetLinks() []tunnel.Link { func (shell *Shell) GetLinks() []rule.Link {
ret := make([]tunnel.Link, 0, len(shell.links)) ret := make([]rule.Link, 0, len(shell.links))
shell.RLock() shell.RLock()
for _, link := range shell.links { for _, link := range shell.links {
ret = append(ret, link) ret = append(ret, link)
@@ -88,7 +88,7 @@ func (shell *Shell) GetPort() uint16 {
func (shell *Shell) Handle(pl *pool.Pool) { func (shell *Shell) Handle(pl *pool.Pool) {
defer func() { defer func() {
if err := recover(); err != nil { 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 { pf := func(cb func(*pool.Pool, http.ResponseWriter, *http.Request)) http.HandlerFunc {

View File

@@ -5,7 +5,7 @@ import (
"image" "image"
"image/jpeg" "image/jpeg"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel/vnc/process" "natpass/code/client/rule/vnc/process"
"natpass/code/network" "natpass/code/network"
"natpass/code/utils" "natpass/code/utils"
"time" "time"

View File

@@ -1,7 +1,7 @@
package process package process
import ( import (
"natpass/code/client/tunnel/vnc/vncnetwork" "natpass/code/client/rule/vnc/vncnetwork"
"natpass/code/network" "natpass/code/network"
) )

View File

@@ -3,7 +3,7 @@ package process
import ( import (
"errors" "errors"
"fmt" "fmt"
"natpass/code/client/tunnel/vnc/vncnetwork" "natpass/code/client/rule/vnc/vncnetwork"
"natpass/code/utils" "natpass/code/utils"
"net" "net"
"net/http" "net/http"

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"natpass/code/client/global" "natpass/code/client/global"
"natpass/code/client/pool" "natpass/code/client/pool"
"natpass/code/client/tunnel" "natpass/code/client/rule"
"net" "net"
"net/http" "net/http"
"sync" "sync"
@@ -17,12 +17,12 @@ import (
type VNC struct { type VNC struct {
sync.RWMutex sync.RWMutex
Name string Name string
cfg global.Tunnel cfg global.Rule
link *Link link *Link
} }
// New new vnc // New new vnc
func New(cfg global.Tunnel) *VNC { func New(cfg global.Rule) *VNC {
return &VNC{ return &VNC{
Name: cfg.Name, Name: cfg.Name,
cfg: cfg, cfg: cfg,
@@ -30,9 +30,9 @@ func New(cfg global.Tunnel) *VNC {
} }
// NewLink new link // 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) 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) id, v.Name, remoteConn.Idx)
link := &Link{ link := &Link{
parent: v, parent: v,
@@ -48,25 +48,25 @@ func (v *VNC) NewLink(id, remote string, remoteIdx uint32, localConn net.Conn, r
return link return link
} }
// GetName get vnc tunnel name // GetName get vnc rule name
func (v *VNC) GetName() string { func (v *VNC) GetName() string {
return v.Name return v.Name
} }
// GetTypeName get vnc tunnel type name // GetTypeName get vnc rule type name
func (v *VNC) GetTypeName() string { func (v *VNC) GetTypeName() string {
return "vnc" return "vnc"
} }
// GetTarget get target of this tunnel // GetTarget get target of this rule
func (v *VNC) GetTarget() string { func (v *VNC) GetTarget() string {
return v.cfg.Target return v.cfg.Target
} }
// GetLinks get tunnel links // GetLinks get rule links
func (v *VNC) GetLinks() []tunnel.Link { func (v *VNC) GetLinks() []rule.Link {
if v.link != nil { if v.link != nil {
return []tunnel.Link{v.link} return []rule.Link{v.link}
} }
return nil return nil
} }
@@ -85,7 +85,7 @@ func (v *VNC) GetPort() uint16 {
func (v *VNC) Handle(pl *pool.Pool) { func (v *VNC) Handle(pl *pool.Pool) {
defer func() { defer func() {
if err := recover(); err != nil { 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 { pf := func(cb func(*pool.Pool, http.ResponseWriter, *http.Request)) http.HandlerFunc {

View File

@@ -2,7 +2,7 @@ package vnc
import ( import (
"fmt" "fmt"
"natpass/code/client/tunnel/vnc/worker" "natpass/code/client/rule/vnc/worker"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/lwch/runtime" "github.com/lwch/runtime"

View File

@@ -3,7 +3,7 @@
package worker package worker
import "natpass/code/client/tunnel/vnc/vncnetwork" import "natpass/code/client/rule/vnc/vncnetwork"
func (worker *Worker) runCapture() vncnetwork.ImageData { func (worker *Worker) runCapture() vncnetwork.ImageData {
return vncnetwork.ImageData{} return vncnetwork.ImageData{}

View File

@@ -3,7 +3,7 @@
package worker package worker
import "natpass/code/client/tunnel/vnc/vncnetwork" import "natpass/code/client/rule/vnc/vncnetwork"
func runMouse(data *vncnetwork.MouseData) { func runMouse(data *vncnetwork.MouseData) {
} }

View File

@@ -3,7 +3,7 @@ package worker
import ( import (
"image" "image"
"image/jpeg" "image/jpeg"
"natpass/code/client/tunnel/vnc/vncnetwork" "natpass/code/client/rule/vnc/vncnetwork"
"os" "os"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -5,5 +5,5 @@ dashboard: # web面板
listen: 0.0.0.0 # 监听地址 listen: 0.0.0.0 # 监听地址
port: 8080 # 监听端口号 port: 8080 # 监听端口号
#include conf.d/*.yaml #include conf.d/*.yaml
tunnel: # tunnel列表 rules: # rule列表
#include tunnel.d/*.yaml #include rule.d/*.yaml

View File

@@ -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 # 目标客户端连接端口号

View File

@@ -17,9 +17,9 @@ LDFLAGS="$LDFLAGS
--extldflags '-static -fpic -lssp'" --extldflags '-static -fpic -lssp'"
fi 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/... -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/... -prefix html/vnc "$@" html/vnc/...
go run contrib/bindata/main.go -pkg dashboard -o code/client/dashboard/assets.go \ go run contrib/bindata/main.go -pkg dashboard -o code/client/dashboard/assets.go \
-prefix html/dashboard "$@" html/dashboard/... -prefix html/dashboard "$@" html/dashboard/...

View File

@@ -36,7 +36,7 @@ server端配置(10.0.1.1)
dir: /opt/natpass/logs # 路径 dir: /opt/natpass/logs # 路径
size: 50M # 单个文件大小 size: 50M # 单个文件大小
rotate: 7 # 保留数量 rotate: 7 # 保留数量
tunnel: # 远端tunnel列表可为空 rules: # 远端rule列表可为空
- name: rdp # 链路名称 - name: rdp # 链路名称
target: home # 目标客户端ID target: home # 目标客户端ID
type: tcp # 连接类型tcp或udp type: tcp # 连接类型tcp或udp