移除反向代理代码

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)
[![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)
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远程桌面
![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
1. ~~支持include的yaml配置文件~~
2. ~~通用的connect、connect_response、disconnect消息~~
3. ~~所有隧道的dashboard页面~~
3. ~~dashboard页面~~
4. 文件传输
5. ~web远程桌面~
6. ~~流量监控统计页面server还是client?~~
7. web端管理tunnel
7. web端管理规则
## 免责声明

View File

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

View File

@@ -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",

View File

@@ -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),

View File

@@ -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" {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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 # 监听地址
port: 8080 # 监听端口号
#include conf.d/*.yaml
tunnel: # tunnel列表
#include tunnel.d/*.yaml
rules: # rule列表
#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'"
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/...

View File

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