From bd1e9a30108783b960e2eee555836c641fd2e49c Mon Sep 17 00:00:00 2001 From: fatedier Date: Tue, 5 Dec 2017 01:34:33 +0800 Subject: [PATCH] update doc and fix vistor -> visitor --- README.md | 56 +++++++++++++++++- README_zh.md | 60 ++++++++++++++++++- client/admin_api.go | 4 +- client/control.go | 94 +++++++++++++++--------------- client/proxy.go | 10 ++-- client/service.go | 4 +- client/{vistor.go => visitor.go} | 98 ++++++++++++++++---------------- cmd/frpc/main.go | 4 +- conf/frpc_full.ini | 20 +++---- models/config/proxy.go | 22 +++---- models/msg/msg.go | 52 ++++++++--------- server/manager.go | 32 +++++------ server/nathole.go | 28 ++++----- server/proxy.go | 4 +- server/service.go | 22 +++---- 15 files changed, 308 insertions(+), 202 deletions(-) rename client/{vistor.go => visitor.go} (71%) diff --git a/README.md b/README.md index e065971..a61c980 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi ## Table of Contents + * [What can I do with frp?](#what-can-i-do-with-frp) * [Status](#status) * [Architecture](#architecture) @@ -20,6 +21,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi * [Forward DNS query request](#forward-dns-query-request) * [Forward unix domain socket](#forward-unix-domain-socket) * [Expose your service in security](#expose-your-service-in-security) + * [P2P Mode](#p2p-mode) * [Connect website through frpc's network](#connect-website-through-frpcs-network) * [Features](#features) * [Configuration File](#configuration-file) @@ -242,9 +244,9 @@ Configure frps same as above. server_addr = x.x.x.x server_port = 7000 - [secret_ssh_vistor] + [secret_ssh_visitor] type = stcp - role = vistor + role = visitor server_name = secret_ssh sk = abcdefg bind_addr = 127.0.0.1 @@ -255,6 +257,54 @@ Configure frps same as above. `ssh -oPort=6000 test@127.0.0.1` +### P2P Mode + +**xtcp** is designed for transmitting a large amount of data directly between two client. + +Now it can't penetrate all types of NAT devices. You can try **stcp** if **xtcp** doesn't work. + +1. Configure a udp port for xtcp: + + ```ini + bind_udp_port = 7001 + ``` + +2. Start frpc, forward ssh port and `remote_port` is useless: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh] + type = xtcp + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +3. Start another frpc in which you want to connect this ssh server: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh_visitor] + type = xtcp + role = visitor + server_name = p2p_ssh + sk = abcdefg + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +4. Connect to server in LAN by ssh assuming that username is test: + + `ssh -oPort=6000 test@127.0.0.1` + ### Connect website through frpc's network Configure frps same as above. @@ -550,7 +600,7 @@ plugin_http_passwd = abc * Direct reverse proxy, like haproxy. * Load balance to different service in frpc. * Frpc can directly be a webserver for static files. -* P2p communicate by make udp hole to penetrate NAT. +* P2p communicate by making udp hole to penetrate NAT. * kubernetes ingress support. diff --git a/README_zh.md b/README_zh.md index 1d12d87..9335dc8 100644 --- a/README_zh.md +++ b/README_zh.md @@ -9,6 +9,7 @@ frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp ## 目录 + * [frp 的作用](#frp-的作用) * [开发状态](#开发状态) * [架构](#架构) @@ -18,6 +19,7 @@ frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp * [转发 DNS 查询请求](#转发-dns-查询请求) * [转发 Unix域套接字](#转发-unix域套接字) * [安全地暴露内网服务](#安全地暴露内网服务) + * [点对点内网穿透](#点对点内网穿透) * [通过 frpc 所在机器访问外网](#通过-frpc-所在机器访问外网) * [功能说明](#功能说明) * [配置文件](#配置文件) @@ -246,10 +248,10 @@ frps 的部署步骤同上。 server_addr = x.x.x.x server_port = 7000 - [secret_ssh_vistor] + [secret_ssh_visitor] type = stcp # stcp 的访问者 - role = vistor + role = visitor # 要访问的 stcp 代理的名字 server_name = secret_ssh sk = abcdefg @@ -262,6 +264,60 @@ frps 的部署步骤同上。 `ssh -oPort=6000 test@127.0.0.1` +### 点对点内网穿透 + +frp 提供了一种新的代理类型 **xtcp** 用于应对在希望传输大量数据且流量不经过服务器的场景。 + +使用方式同 **stcp** 类似,需要在两边都部署上 frpc 用于建立直接的连接。 + +目前处于开发的初级阶段,并不能穿透所有类型的 NAT 设备,所以穿透成功率较低。穿透失败时可以尝试 **stcp** 的方式。 + +1. frps 除正常配置外需要额外配置一个 udp 端口用于支持该类型的客户端: + + ```ini + bind_udp_port = 7001 + ``` + +2. 启动 frpc,转发内网的 ssh 服务,配置如下,不需要指定远程端口: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh] + type = xtcp + # 只有 sk 一致的用户才能访问到此服务 + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +3. 在要访问这个服务的机器上启动另外一个 frpc,配置如下: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh_visitor] + type = xtcp + # xtcp 的访问者 + role = visitor + # 要访问的 xtcp 代理的名字 + server_name = p2p_ssh + sk = abcdefg + # 绑定本地端口用于访问 ssh 服务 + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +4. 通过 ssh 访问内网机器,假设用户名为 test: + + `ssh -oPort=6000 test@127.0.0.1` + ### 通过 frpc 所在机器访问外网 frpc 内置了 http proxy 和 socks5 插件,可以使其他机器通过 frpc 的网络访问互联网。 diff --git a/client/admin_api.go b/client/admin_api.go index 5523302..70842e6 100644 --- a/client/admin_api.go +++ b/client/admin_api.go @@ -64,7 +64,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout return } - pxyCfgs, vistorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, newCommonCfg.Start) + pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, newCommonCfg.Start) if err != nil { res.Code = 3 res.Msg = err.Error() @@ -72,7 +72,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout return } - svr.ctl.reloadConf(pxyCfgs, vistorCfgs) + svr.ctl.reloadConf(pxyCfgs, visitorCfgs) log.Info("success reload conf") return } diff --git a/client/control.go b/client/control.go index b6c4d48..788621c 100644 --- a/client/control.go +++ b/client/control.go @@ -49,11 +49,11 @@ type Control struct { // proxies proxies map[string]Proxy - // vistor configures - vistorCfgs map[string]config.ProxyConf + // visitor configures + visitorCfgs map[string]config.ProxyConf - // vistors - vistors map[string]Vistor + // visitors + visitors map[string]Visitor // control connection conn frpNet.Conn @@ -84,7 +84,7 @@ type Control struct { log.Logger } -func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, vistorCfgs map[string]config.ProxyConf) *Control { +func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.ProxyConf) *Control { loginMsg := &msg.Login{ Arch: runtime.GOARCH, Os: runtime.GOOS, @@ -93,16 +93,16 @@ func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, vistorCfgs ma Version: version.Full(), } return &Control{ - svr: svr, - loginMsg: loginMsg, - pxyCfgs: pxyCfgs, - vistorCfgs: vistorCfgs, - proxies: make(map[string]Proxy), - vistors: make(map[string]Vistor), - sendCh: make(chan msg.Message, 10), - readCh: make(chan msg.Message, 10), - closedCh: make(chan int), - Logger: log.NewPrefixLogger(""), + svr: svr, + loginMsg: loginMsg, + pxyCfgs: pxyCfgs, + visitorCfgs: visitorCfgs, + proxies: make(map[string]Proxy), + visitors: make(map[string]Visitor), + sendCh: make(chan msg.Message, 10), + readCh: make(chan msg.Message, 10), + closedCh: make(chan int), + Logger: log.NewPrefixLogger(""), } } @@ -137,16 +137,16 @@ func (ctl *Control) Run() (err error) { go ctl.writer() go ctl.reader() - // start all local vistors - for _, cfg := range ctl.vistorCfgs { - vistor := NewVistor(ctl, cfg) - err = vistor.Run() + // start all local visitors + for _, cfg := range ctl.visitorCfgs { + visitor := NewVisitor(ctl, cfg) + err = visitor.Run() if err != nil { - vistor.Warn("start error: %v", err) + visitor.Warn("start error: %v", err) continue } - ctl.vistors[cfg.GetName()] = vistor - vistor.Info("start vistor success") + ctl.visitors[cfg.GetName()] = visitor + visitor.Info("start visitor success") } // send NewProxy message for all configured proxies @@ -441,17 +441,17 @@ func (ctl *Control) controler() { } } - for _, cfg := range ctl.vistorCfgs { - if _, exist := ctl.vistors[cfg.GetName()]; !exist { - ctl.Info("try to start vistor [%s]", cfg.GetName()) - vistor := NewVistor(ctl, cfg) - err = vistor.Run() + for _, cfg := range ctl.visitorCfgs { + if _, exist := ctl.visitors[cfg.GetName()]; !exist { + ctl.Info("try to start visitor [%s]", cfg.GetName()) + visitor := NewVisitor(ctl, cfg) + err = visitor.Run() if err != nil { - vistor.Warn("start error: %v", err) + visitor.Warn("start error: %v", err) continue } - ctl.vistors[cfg.GetName()] = vistor - vistor.Info("start vistor success") + ctl.visitors[cfg.GetName()] = visitor + visitor.Info("start visitor success") } } ctl.mu.RUnlock() @@ -549,7 +549,7 @@ func (ctl *Control) getProxyConf(name string) (conf config.ProxyConf, ok bool) { return } -func (ctl *Control) reloadConf(pxyCfgs map[string]config.ProxyConf, vistorCfgs map[string]config.ProxyConf) { +func (ctl *Control) reloadConf(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.ProxyConf) { ctl.mu.Lock() defer ctl.mu.Unlock() @@ -588,35 +588,35 @@ func (ctl *Control) reloadConf(pxyCfgs map[string]config.ProxyConf, vistorCfgs m } ctl.Info("proxy added: %v", addedPxyNames) - removedVistorName := make([]string, 0) - for name, oldVistorCfg := range ctl.vistorCfgs { + removedVisitorName := make([]string, 0) + for name, oldVisitorCfg := range ctl.visitorCfgs { del := false - cfg, ok := vistorCfgs[name] + cfg, ok := visitorCfgs[name] if !ok { del = true } else { - if !oldVistorCfg.Compare(cfg) { + if !oldVisitorCfg.Compare(cfg) { del = true } } if del { - removedVistorName = append(removedVistorName, name) - delete(ctl.vistorCfgs, name) - if vistor, ok := ctl.vistors[name]; ok { - vistor.Close() + removedVisitorName = append(removedVisitorName, name) + delete(ctl.visitorCfgs, name) + if visitor, ok := ctl.visitors[name]; ok { + visitor.Close() } - delete(ctl.vistors, name) + delete(ctl.visitors, name) } } - ctl.Info("vistor removed: %v", removedVistorName) + ctl.Info("visitor removed: %v", removedVisitorName) - addedVistorName := make([]string, 0) - for name, vistorCfg := range vistorCfgs { - if _, ok := ctl.vistorCfgs[name]; !ok { - ctl.vistorCfgs[name] = vistorCfg - addedVistorName = append(addedVistorName, name) + addedVisitorName := make([]string, 0) + for name, visitorCfg := range visitorCfgs { + if _, ok := ctl.visitorCfgs[name]; !ok { + ctl.visitorCfgs[name] = visitorCfg + addedVisitorName = append(addedVisitorName, name) } } - ctl.Info("vistor added: %v", addedVistorName) + ctl.Info("visitor added: %v", addedVisitorName) } diff --git a/client/proxy.go b/client/proxy.go index c2d7bf6..0b26bf4 100644 --- a/client/proxy.go +++ b/client/proxy.go @@ -273,23 +273,23 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) { clientConn.Close() pxy.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr) - // Send sid to vistor udp address. + // Send sid to visitor udp address. time.Sleep(time.Second) laddr, _ := net.ResolveUDPAddr("udp", clientConn.LocalAddr().String()) - daddr, err := net.ResolveUDPAddr("udp", natHoleRespMsg.VistorAddr) + daddr, err := net.ResolveUDPAddr("udp", natHoleRespMsg.VisitorAddr) if err != nil { - pxy.Error("resolve vistor udp address error: %v", err) + pxy.Error("resolve visitor udp address error: %v", err) return } lConn, err := net.DialUDP("udp", laddr, daddr) if err != nil { - pxy.Error("dial vistor udp address error: %v", err) + pxy.Error("dial visitor udp address error: %v", err) return } lConn.Write([]byte(natHoleRespMsg.Sid)) - kcpConn, err := frpNet.NewKcpConnFromUdp(lConn, true, natHoleRespMsg.VistorAddr) + kcpConn, err := frpNet.NewKcpConnFromUdp(lConn, true, natHoleRespMsg.VisitorAddr) if err != nil { pxy.Error("create kcp connection from udp connection error: %v", err) return diff --git a/client/service.go b/client/service.go index 241a435..49c7848 100644 --- a/client/service.go +++ b/client/service.go @@ -26,11 +26,11 @@ type Service struct { closedCh chan int } -func NewService(pxyCfgs map[string]config.ProxyConf, vistorCfgs map[string]config.ProxyConf) (svr *Service) { +func NewService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.ProxyConf) (svr *Service) { svr = &Service{ closedCh: make(chan int), } - ctl := NewControl(svr, pxyCfgs, vistorCfgs) + ctl := NewControl(svr, pxyCfgs, visitorCfgs) svr.ctl = ctl return } diff --git a/client/vistor.go b/client/visitor.go similarity index 71% rename from client/vistor.go rename to client/visitor.go index a2ac9d4..76f28d9 100644 --- a/client/vistor.go +++ b/client/visitor.go @@ -35,34 +35,34 @@ import ( "github.com/fatedier/frp/utils/util" ) -// Vistor is used for forward traffics from local port tot remote service. -type Vistor interface { +// Visitor is used for forward traffics from local port tot remote service. +type Visitor interface { Run() error Close() log.Logger } -func NewVistor(ctl *Control, pxyConf config.ProxyConf) (vistor Vistor) { - baseVistor := BaseVistor{ +func NewVisitor(ctl *Control, pxyConf config.ProxyConf) (visitor Visitor) { + baseVisitor := BaseVisitor{ ctl: ctl, Logger: log.NewPrefixLogger(pxyConf.GetName()), } switch cfg := pxyConf.(type) { case *config.StcpProxyConf: - vistor = &StcpVistor{ - BaseVistor: baseVistor, - cfg: cfg, + visitor = &StcpVisitor{ + BaseVisitor: baseVisitor, + cfg: cfg, } case *config.XtcpProxyConf: - vistor = &XtcpVistor{ - BaseVistor: baseVistor, - cfg: cfg, + visitor = &XtcpVisitor{ + BaseVisitor: baseVisitor, + cfg: cfg, } } return } -type BaseVistor struct { +type BaseVisitor struct { ctl *Control l frpNet.Listener closed bool @@ -70,13 +70,13 @@ type BaseVistor struct { log.Logger } -type StcpVistor struct { - BaseVistor +type StcpVisitor struct { + BaseVisitor cfg *config.StcpProxyConf } -func (sv *StcpVistor) Run() (err error) { +func (sv *StcpVisitor) Run() (err error) { sv.l, err = frpNet.ListenTcp(sv.cfg.BindAddr, int64(sv.cfg.BindPort)) if err != nil { return @@ -86,11 +86,11 @@ func (sv *StcpVistor) Run() (err error) { return } -func (sv *StcpVistor) Close() { +func (sv *StcpVisitor) Close() { sv.l.Close() } -func (sv *StcpVistor) worker() { +func (sv *StcpVisitor) worker() { for { conn, err := sv.l.Accept() if err != nil { @@ -102,46 +102,46 @@ func (sv *StcpVistor) worker() { } } -func (sv *StcpVistor) handleConn(userConn frpNet.Conn) { +func (sv *StcpVisitor) handleConn(userConn frpNet.Conn) { defer userConn.Close() sv.Debug("get a new stcp user connection") - vistorConn, err := sv.ctl.connectServer() + visitorConn, err := sv.ctl.connectServer() if err != nil { return } - defer vistorConn.Close() + defer visitorConn.Close() now := time.Now().Unix() - newVistorConnMsg := &msg.NewVistorConn{ + newVisitorConnMsg := &msg.NewVisitorConn{ ProxyName: sv.cfg.ServerName, SignKey: util.GetAuthKey(sv.cfg.Sk, now), Timestamp: now, UseEncryption: sv.cfg.UseEncryption, UseCompression: sv.cfg.UseCompression, } - err = msg.WriteMsg(vistorConn, newVistorConnMsg) + err = msg.WriteMsg(visitorConn, newVisitorConnMsg) if err != nil { - sv.Warn("send newVistorConnMsg to server error: %v", err) + sv.Warn("send newVisitorConnMsg to server error: %v", err) return } - var newVistorConnRespMsg msg.NewVistorConnResp - vistorConn.SetReadDeadline(time.Now().Add(10 * time.Second)) - err = msg.ReadMsgInto(vistorConn, &newVistorConnRespMsg) + var newVisitorConnRespMsg msg.NewVisitorConnResp + visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second)) + err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg) if err != nil { - sv.Warn("get newVistorConnRespMsg error: %v", err) + sv.Warn("get newVisitorConnRespMsg error: %v", err) return } - vistorConn.SetReadDeadline(time.Time{}) + visitorConn.SetReadDeadline(time.Time{}) - if newVistorConnRespMsg.Error != "" { - sv.Warn("start new vistor connection error: %s", newVistorConnRespMsg.Error) + if newVisitorConnRespMsg.Error != "" { + sv.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error) return } var remote io.ReadWriteCloser - remote = vistorConn + remote = visitorConn if sv.cfg.UseEncryption { remote, err = frpIo.WithEncryption(remote, []byte(sv.cfg.Sk)) if err != nil { @@ -157,13 +157,13 @@ func (sv *StcpVistor) handleConn(userConn frpNet.Conn) { frpIo.Join(userConn, remote) } -type XtcpVistor struct { - BaseVistor +type XtcpVisitor struct { + BaseVisitor cfg *config.XtcpProxyConf } -func (sv *XtcpVistor) Run() (err error) { +func (sv *XtcpVisitor) Run() (err error) { sv.l, err = frpNet.ListenTcp(sv.cfg.BindAddr, int64(sv.cfg.BindPort)) if err != nil { return @@ -173,11 +173,11 @@ func (sv *XtcpVistor) Run() (err error) { return } -func (sv *XtcpVistor) Close() { +func (sv *XtcpVisitor) Close() { sv.l.Close() } -func (sv *XtcpVistor) worker() { +func (sv *XtcpVisitor) worker() { for { conn, err := sv.l.Accept() if err != nil { @@ -189,7 +189,7 @@ func (sv *XtcpVistor) worker() { } } -func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { +func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) { defer userConn.Close() sv.Debug("get a new xtcp user connection") @@ -200,26 +200,26 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { raddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort)) - vistorConn, err := net.DialUDP("udp", nil, raddr) - defer vistorConn.Close() + visitorConn, err := net.DialUDP("udp", nil, raddr) + defer visitorConn.Close() now := time.Now().Unix() - natHoleVistorMsg := &msg.NatHoleVistor{ + natHoleVisitorMsg := &msg.NatHoleVisitor{ ProxyName: sv.cfg.ServerName, SignKey: util.GetAuthKey(sv.cfg.Sk, now), Timestamp: now, } - err = msg.WriteMsg(vistorConn, natHoleVistorMsg) + err = msg.WriteMsg(visitorConn, natHoleVisitorMsg) if err != nil { - sv.Warn("send natHoleVistorMsg to server error: %v", err) + sv.Warn("send natHoleVisitorMsg to server error: %v", err) return } // Wait for client address at most 10 seconds. var natHoleRespMsg msg.NatHoleResp - vistorConn.SetReadDeadline(time.Now().Add(10 * time.Second)) + visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second)) buf := pool.GetBuf(1024) - n, err := vistorConn.Read(buf) + n, err := visitorConn.Read(buf) if err != nil { sv.Warn("get natHoleRespMsg error: %v", err) return @@ -230,13 +230,13 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { sv.Warn("get natHoleRespMsg error: %v", err) return } - vistorConn.SetReadDeadline(time.Time{}) + visitorConn.SetReadDeadline(time.Time{}) pool.PutBuf(buf) sv.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr) - // Close vistorConn, so we can use it's local address. - vistorConn.Close() + // Close visitorConn, so we can use it's local address. + visitorConn.Close() // Send detect message. array := strings.Split(natHoleRespMsg.ClientAddr, ":") @@ -244,7 +244,7 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { sv.Error("get natHoleResp client address error: %s", natHoleRespMsg.ClientAddr) return } - laddr, _ := net.ResolveUDPAddr("udp", vistorConn.LocalAddr().String()) + laddr, _ := net.ResolveUDPAddr("udp", visitorConn.LocalAddr().String()) /* for i := 1000; i < 65000; i++ { sv.sendDetectMsg(array[0], int64(i), laddr, "a") @@ -258,7 +258,7 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { sv.sendDetectMsg(array[0], int64(port), laddr, []byte(natHoleRespMsg.Sid)) sv.Trace("send all detect msg done") - // Listen for vistorConn's address and wait for client connection. + // Listen for visitorConn's address and wait for client connection. lConn, _ := net.ListenUDP("udp", laddr) lConn.SetReadDeadline(time.Now().Add(5 * time.Second)) sidBuf := pool.GetBuf(1024) @@ -298,7 +298,7 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) { sv.Debug("join connections closed") } -func (sv *XtcpVistor) sendDetectMsg(addr string, port int64, laddr *net.UDPAddr, content []byte) (err error) { +func (sv *XtcpVisitor) sendDetectMsg(addr string, port int64, laddr *net.UDPAddr, content []byte) (err error) { daddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", addr, port)) if err != nil { return err diff --git a/cmd/frpc/main.go b/cmd/frpc/main.go index 93642c8..f0d438f 100644 --- a/cmd/frpc/main.go +++ b/cmd/frpc/main.go @@ -156,7 +156,7 @@ func main() { } } - pxyCfgs, vistorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, config.ClientCommonCfg.Start) + pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, config.ClientCommonCfg.Start) if err != nil { fmt.Println(err) os.Exit(1) @@ -165,7 +165,7 @@ func main() { log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile, config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays) - svr := client.NewService(pxyCfgs, vistorCfgs) + svr := client.NewService(pxyCfgs, visitorCfgs) // Capture the exit signal if we use kcp. if config.ClientCommonCfg.Protocol == "kcp" { diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini index 44a89df..a0988e3 100644 --- a/conf/frpc_full.ini +++ b/conf/frpc_full.ini @@ -119,24 +119,24 @@ plugin_http_passwd = abc [secret_tcp] # If the type is secret tcp, remote_port is useless -# Who want to connect local port should deploy another frpc with stcp proxy and role is vistor +# Who want to connect local port should deploy another frpc with stcp proxy and role is visitor type = stcp -# sk used for authentication for vistors +# sk used for authentication for visitors sk = abcdefg local_ip = 127.0.0.1 local_port = 22 use_encryption = false use_compression = false -# user of frpc should be same in both stcp server and stcp vistor -[secret_tcp_vistor] -# frpc role vistor -> frps -> frpc role server -role = vistor +# user of frpc should be same in both stcp server and stcp visitor +[secret_tcp_visitor] +# frpc role visitor -> frps -> frpc role server +role = visitor type = stcp -# the server name you want to vistor +# the server name you want to visitor server_name = secret_tcp sk = abcdefg -# connect this address to vistor stcp server +# connect this address to visitor stcp server bind_addr = 127.0.0.1 bind_port = 9000 use_encryption = false @@ -150,8 +150,8 @@ local_port = 22 use_encryption = false use_compression = false -[p2p_tcp_vistor] -role = vistor +[p2p_tcp_visitor] +role = visitor type = xtcp server_name = p2p_tcp sk = abcdefg diff --git a/models/config/proxy.go b/models/config/proxy.go index 2246a84..75eb138 100644 --- a/models/config/proxy.go +++ b/models/config/proxy.go @@ -595,7 +595,7 @@ type StcpProxyConf struct { LocalSvrConf PluginConf - // used in role vistor + // used in role visitor ServerName string `json:"server_name"` BindAddr string `json:"bind_addr"` BindPort int `json:"bind_port"` @@ -632,7 +632,7 @@ func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err er } tmpStr := section["role"] - if tmpStr == "server" || tmpStr == "vistor" { + if tmpStr == "server" || tmpStr == "visitor" { cfg.Role = tmpStr } else { cfg.Role = "server" @@ -640,7 +640,7 @@ func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err er cfg.Sk = section["sk"] - if tmpStr == "vistor" { + if tmpStr == "visitor" { prefix := section["prefix"] cfg.ServerName = prefix + section["server_name"] if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" { @@ -684,7 +684,7 @@ type XtcpProxyConf struct { LocalSvrConf PluginConf - // used in role vistor + // used in role visitor ServerName string `json:"server_name"` BindAddr string `json:"bind_addr"` BindPort int `json:"bind_port"` @@ -721,7 +721,7 @@ func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err er } tmpStr := section["role"] - if tmpStr == "server" || tmpStr == "vistor" { + if tmpStr == "server" || tmpStr == "visitor" { cfg.Role = tmpStr } else { cfg.Role = "server" @@ -729,7 +729,7 @@ func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err er cfg.Sk = section["sk"] - if tmpStr == "vistor" { + if tmpStr == "visitor" { prefix := section["prefix"] cfg.ServerName = prefix + section["server_name"] if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" { @@ -765,7 +765,7 @@ func (cfg *XtcpProxyConf) Check() (err error) { // if len(startProxy) is 0, start all // otherwise just start proxies in startProxy map func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]struct{}) ( - proxyConfs map[string]ProxyConf, vistorConfs map[string]ProxyConf, err error) { + proxyConfs map[string]ProxyConf, visitorConfs map[string]ProxyConf, err error) { if prefix != "" { prefix += "." @@ -776,7 +776,7 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s startAll = false } proxyConfs = make(map[string]ProxyConf) - vistorConfs = make(map[string]ProxyConf) + visitorConfs = make(map[string]ProxyConf) for name, section := range conf { _, shouldStart := startProxy[name] if name != "common" && (startAll || shouldStart) { @@ -784,12 +784,12 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s section["prefix"] = prefix cfg, err := NewProxyConfFromFile(name, section) if err != nil { - return proxyConfs, vistorConfs, err + return proxyConfs, visitorConfs, err } role := section["role"] - if role == "vistor" { - vistorConfs[prefix+name] = cfg + if role == "visitor" { + visitorConfs[prefix+name] = cfg } else { proxyConfs[prefix+name] = cfg } diff --git a/models/msg/msg.go b/models/msg/msg.go index fc2ab2f..22bf5f6 100644 --- a/models/msg/msg.go +++ b/models/msg/msg.go @@ -20,23 +20,23 @@ import ( ) const ( - TypeLogin = 'o' - TypeLoginResp = '1' - TypeNewProxy = 'p' - TypeNewProxyResp = '2' - TypeCloseProxy = 'c' - TypeNewWorkConn = 'w' - TypeReqWorkConn = 'r' - TypeStartWorkConn = 's' - TypeNewVistorConn = 'v' - TypeNewVistorConnResp = '3' - TypePing = 'h' - TypePong = '4' - TypeUdpPacket = 'u' - TypeNatHoleVistor = 'i' - TypeNatHoleClient = 'n' - TypeNatHoleResp = 'm' - TypeNatHoleSid = '5' + TypeLogin = 'o' + TypeLoginResp = '1' + TypeNewProxy = 'p' + TypeNewProxyResp = '2' + TypeCloseProxy = 'c' + TypeNewWorkConn = 'w' + TypeReqWorkConn = 'r' + TypeStartWorkConn = 's' + TypeNewVisitorConn = 'v' + TypeNewVisitorConnResp = '3' + TypePing = 'h' + TypePong = '4' + TypeUdpPacket = 'u' + TypeNatHoleVisitor = 'i' + TypeNatHoleClient = 'n' + TypeNatHoleResp = 'm' + TypeNatHoleSid = '5' ) var ( @@ -56,12 +56,12 @@ func init() { TypeMap[TypeNewWorkConn] = reflect.TypeOf(NewWorkConn{}) TypeMap[TypeReqWorkConn] = reflect.TypeOf(ReqWorkConn{}) TypeMap[TypeStartWorkConn] = reflect.TypeOf(StartWorkConn{}) - TypeMap[TypeNewVistorConn] = reflect.TypeOf(NewVistorConn{}) - TypeMap[TypeNewVistorConnResp] = reflect.TypeOf(NewVistorConnResp{}) + TypeMap[TypeNewVisitorConn] = reflect.TypeOf(NewVisitorConn{}) + TypeMap[TypeNewVisitorConnResp] = reflect.TypeOf(NewVisitorConnResp{}) TypeMap[TypePing] = reflect.TypeOf(Ping{}) TypeMap[TypePong] = reflect.TypeOf(Pong{}) TypeMap[TypeUdpPacket] = reflect.TypeOf(UdpPacket{}) - TypeMap[TypeNatHoleVistor] = reflect.TypeOf(NatHoleVistor{}) + TypeMap[TypeNatHoleVisitor] = reflect.TypeOf(NatHoleVisitor{}) TypeMap[TypeNatHoleClient] = reflect.TypeOf(NatHoleClient{}) TypeMap[TypeNatHoleResp] = reflect.TypeOf(NatHoleResp{}) TypeMap[TypeNatHoleSid] = reflect.TypeOf(NatHoleSid{}) @@ -138,7 +138,7 @@ type StartWorkConn struct { ProxyName string `json:"proxy_name"` } -type NewVistorConn struct { +type NewVisitorConn struct { ProxyName string `json:"proxy_name"` SignKey string `json:"sign_key"` Timestamp int64 `json:"timestamp"` @@ -146,7 +146,7 @@ type NewVistorConn struct { UseCompression bool `json:"use_compression"` } -type NewVistorConnResp struct { +type NewVisitorConnResp struct { ProxyName string `json:"proxy_name"` Error string `json:"error"` } @@ -163,7 +163,7 @@ type UdpPacket struct { RemoteAddr *net.UDPAddr `json:"r"` } -type NatHoleVistor struct { +type NatHoleVisitor struct { ProxyName string `json:"proxy_name"` SignKey string `json:"sign_key"` Timestamp int64 `json:"timestamp"` @@ -175,9 +175,9 @@ type NatHoleClient struct { } type NatHoleResp struct { - Sid string `json:"sid"` - VistorAddr string `json:"vistor_addr"` - ClientAddr string `json:"client_addr"` + Sid string `json:"sid"` + VisitorAddr string `json:"visitor_addr"` + ClientAddr string `json:"client_addr"` } type NatHoleSid struct { diff --git a/server/manager.go b/server/manager.go index c78037d..c023d18 100644 --- a/server/manager.go +++ b/server/manager.go @@ -93,46 +93,46 @@ func (pm *ProxyManager) GetByName(name string) (pxy Proxy, ok bool) { return } -// Manager for vistor listeners. -type VistorManager struct { - vistorListeners map[string]*frpNet.CustomListener - skMap map[string]string +// Manager for visitor listeners. +type VisitorManager struct { + visitorListeners map[string]*frpNet.CustomListener + skMap map[string]string mu sync.RWMutex } -func NewVistorManager() *VistorManager { - return &VistorManager{ - vistorListeners: make(map[string]*frpNet.CustomListener), - skMap: make(map[string]string), +func NewVisitorManager() *VisitorManager { + return &VisitorManager{ + visitorListeners: make(map[string]*frpNet.CustomListener), + skMap: make(map[string]string), } } -func (vm *VistorManager) Listen(name string, sk string) (l *frpNet.CustomListener, err error) { +func (vm *VisitorManager) Listen(name string, sk string) (l *frpNet.CustomListener, err error) { vm.mu.Lock() defer vm.mu.Unlock() - if _, ok := vm.vistorListeners[name]; ok { + if _, ok := vm.visitorListeners[name]; ok { err = fmt.Errorf("custom listener for [%s] is repeated", name) return } l = frpNet.NewCustomListener() - vm.vistorListeners[name] = l + vm.visitorListeners[name] = l vm.skMap[name] = sk return } -func (vm *VistorManager) NewConn(name string, conn frpNet.Conn, timestamp int64, signKey string, +func (vm *VisitorManager) NewConn(name string, conn frpNet.Conn, timestamp int64, signKey string, useEncryption bool, useCompression bool) (err error) { vm.mu.RLock() defer vm.mu.RUnlock() - if l, ok := vm.vistorListeners[name]; ok { + if l, ok := vm.visitorListeners[name]; ok { var sk string if sk = vm.skMap[name]; util.GetAuthKey(sk, timestamp) != signKey { - err = fmt.Errorf("vistor connection of [%s] auth failed", name) + err = fmt.Errorf("visitor connection of [%s] auth failed", name) return } @@ -154,10 +154,10 @@ func (vm *VistorManager) NewConn(name string, conn frpNet.Conn, timestamp int64, return } -func (vm *VistorManager) CloseListener(name string) { +func (vm *VisitorManager) CloseListener(name string) { vm.mu.Lock() defer vm.mu.Unlock() - delete(vm.vistorListeners, name) + delete(vm.visitorListeners, name) delete(vm.skMap, name) } diff --git a/server/nathole.go b/server/nathole.go index 933d077..08f9365 100644 --- a/server/nathole.go +++ b/server/nathole.go @@ -78,8 +78,8 @@ func (nc *NatHoleController) Run() { } switch m := rawMsg.(type) { - case *msg.NatHoleVistor: - go nc.HandleVistor(m, raddr) + case *msg.NatHoleVisitor: + go nc.HandleVisitor(m, raddr) case *msg.NatHoleClient: go nc.HandleClient(m, raddr) default: @@ -96,12 +96,12 @@ func (nc *NatHoleController) GenSid() string { return fmt.Sprintf("%d%s", t, id) } -func (nc *NatHoleController) HandleVistor(m *msg.NatHoleVistor, raddr *net.UDPAddr) { +func (nc *NatHoleController) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) { sid := nc.GenSid() session := &NatHoleSession{ - Sid: sid, - VistorAddr: raddr, - NotifyCh: make(chan struct{}, 0), + Sid: sid, + VisitorAddr: raddr, + NotifyCh: make(chan struct{}, 0), } nc.mu.Lock() clientCfg, ok := nc.clientCfgs[m.ProxyName] @@ -111,7 +111,7 @@ func (nc *NatHoleController) HandleVistor(m *msg.NatHoleVistor, raddr *net.UDPAd } nc.sessions[sid] = session nc.mu.Unlock() - log.Trace("handle vistor message, sid [%s]", sid) + log.Trace("handle visitor message, sid [%s]", sid) defer func() { nc.mu.Lock() @@ -130,7 +130,7 @@ func (nc *NatHoleController) HandleVistor(m *msg.NatHoleVistor, raddr *net.UDPAd select { case <-session.NotifyCh: resp := nc.GenNatHoleResponse(raddr, session) - log.Trace("send nat hole response to vistor") + log.Trace("send nat hole response to visitor") nc.listener.WriteToUDP(resp, raddr) case <-time.After(time.Duration(NatHoleTimeout) * time.Second): return @@ -155,9 +155,9 @@ func (nc *NatHoleController) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAd func (nc *NatHoleController) GenNatHoleResponse(raddr *net.UDPAddr, session *NatHoleSession) []byte { m := &msg.NatHoleResp{ - Sid: session.Sid, - VistorAddr: session.VistorAddr.String(), - ClientAddr: session.ClientAddr.String(), + Sid: session.Sid, + VisitorAddr: session.VisitorAddr.String(), + ClientAddr: session.ClientAddr.String(), } b := bytes.NewBuffer(nil) err := msg.WriteMsg(b, m) @@ -168,9 +168,9 @@ func (nc *NatHoleController) GenNatHoleResponse(raddr *net.UDPAddr, session *Nat } type NatHoleSession struct { - Sid string - VistorAddr *net.UDPAddr - ClientAddr *net.UDPAddr + Sid string + VisitorAddr *net.UDPAddr + ClientAddr *net.UDPAddr NotifyCh chan struct{} } diff --git a/server/proxy.go b/server/proxy.go index a4fdcd2..d76358c 100644 --- a/server/proxy.go +++ b/server/proxy.go @@ -290,7 +290,7 @@ type StcpProxy struct { } func (pxy *StcpProxy) Run() error { - listener, err := pxy.ctl.svr.vistorManager.Listen(pxy.GetName(), pxy.cfg.Sk) + listener, err := pxy.ctl.svr.visitorManager.Listen(pxy.GetName(), pxy.cfg.Sk) if err != nil { return err } @@ -308,7 +308,7 @@ func (pxy *StcpProxy) GetConf() config.ProxyConf { func (pxy *StcpProxy) Close() { pxy.BaseProxy.Close() - pxy.ctl.svr.vistorManager.CloseListener(pxy.GetName()) + pxy.ctl.svr.visitorManager.CloseListener(pxy.GetName()) } type XtcpProxy struct { diff --git a/server/service.go b/server/service.go index fb99008..7799d3e 100644 --- a/server/service.go +++ b/server/service.go @@ -56,8 +56,8 @@ type Service struct { // Manage all proxies. pxyManager *ProxyManager - // Manage all vistor listeners. - vistorManager *VistorManager + // Manage all visitor listeners. + visitorManager *VisitorManager // Controller for nat hole connections. natHoleController *NatHoleController @@ -65,9 +65,9 @@ type Service struct { func NewService() (svr *Service, err error) { svr = &Service{ - ctlManager: NewControlManager(), - pxyManager: NewProxyManager(), - vistorManager: NewVistorManager(), + ctlManager: NewControlManager(), + pxyManager: NewProxyManager(), + visitorManager: NewVisitorManager(), } cfg := config.ServerCommonCfg @@ -200,16 +200,16 @@ func (svr *Service) HandleListener(l frpNet.Listener) { } case *msg.NewWorkConn: svr.RegisterWorkConn(conn, m) - case *msg.NewVistorConn: - if err = svr.RegisterVistorConn(conn, m); err != nil { + case *msg.NewVisitorConn: + if err = svr.RegisterVisitorConn(conn, m); err != nil { conn.Warn("%v", err) - msg.WriteMsg(conn, &msg.NewVistorConnResp{ + msg.WriteMsg(conn, &msg.NewVisitorConnResp{ ProxyName: m.ProxyName, Error: err.Error(), }) conn.Close() } else { - msg.WriteMsg(conn, &msg.NewVistorConnResp{ + msg.WriteMsg(conn, &msg.NewVisitorConnResp{ ProxyName: m.ProxyName, Error: "", }) @@ -300,8 +300,8 @@ func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkCo return } -func (svr *Service) RegisterVistorConn(vistorConn frpNet.Conn, newMsg *msg.NewVistorConn) error { - return svr.vistorManager.NewConn(newMsg.ProxyName, vistorConn, newMsg.Timestamp, newMsg.SignKey, +func (svr *Service) RegisterVisitorConn(visitorConn frpNet.Conn, newMsg *msg.NewVisitorConn) error { + return svr.visitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey, newMsg.UseEncryption, newMsg.UseCompression) }