mirror of
https://github.com/lwch/natpass
synced 2025-10-05 13:26:50 +08:00
移除反向代理代码
This commit is contained in:
29
README.md
29
README.md
@@ -7,7 +7,7 @@
|
||||
[](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)
|
||||
@@ -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端管理规则
|
||||
|
||||
## 免责声明
|
||||
|
||||
|
@@ -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"
|
||||
tunnel "natpass/code/client/rule"
|
||||
"natpass/code/client/rule/shell"
|
||||
"natpass/code/client/rule/vnc"
|
||||
"natpass/code/network"
|
||||
rt "runtime"
|
||||
"time"
|
||||
@@ -55,12 +54,8 @@ func (a *App) run() {
|
||||
pl := pool.New(a.cfg)
|
||||
mgr := tunnel.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"
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
@@ -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 {
|
@@ -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"
|
||||
)
|
||||
|
@@ -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"
|
@@ -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"
|
@@ -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) {
|
||||
}
|
@@ -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"
|
@@ -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/...
|
||||
|
@@ -36,7 +36,7 @@ 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
|
||||
|
Reference in New Issue
Block a user