mirror of
https://github.com/fatedier/frp.git
synced 2024-12-14 02:31:21 +01:00
update doc and fix vistor -> visitor
This commit is contained in:
parent
92fff5c191
commit
bd1e9a3010
56
README.md
56
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
|
## Table of Contents
|
||||||
|
|
||||||
<!-- vim-markdown-toc GFM -->
|
<!-- vim-markdown-toc GFM -->
|
||||||
|
|
||||||
* [What can I do with frp?](#what-can-i-do-with-frp)
|
* [What can I do with frp?](#what-can-i-do-with-frp)
|
||||||
* [Status](#status)
|
* [Status](#status)
|
||||||
* [Architecture](#architecture)
|
* [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 DNS query request](#forward-dns-query-request)
|
||||||
* [Forward unix domain socket](#forward-unix-domain-socket)
|
* [Forward unix domain socket](#forward-unix-domain-socket)
|
||||||
* [Expose your service in security](#expose-your-service-in-security)
|
* [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)
|
* [Connect website through frpc's network](#connect-website-through-frpcs-network)
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
* [Configuration File](#configuration-file)
|
* [Configuration File](#configuration-file)
|
||||||
@ -242,9 +244,9 @@ Configure frps same as above.
|
|||||||
server_addr = x.x.x.x
|
server_addr = x.x.x.x
|
||||||
server_port = 7000
|
server_port = 7000
|
||||||
|
|
||||||
[secret_ssh_vistor]
|
[secret_ssh_visitor]
|
||||||
type = stcp
|
type = stcp
|
||||||
role = vistor
|
role = visitor
|
||||||
server_name = secret_ssh
|
server_name = secret_ssh
|
||||||
sk = abcdefg
|
sk = abcdefg
|
||||||
bind_addr = 127.0.0.1
|
bind_addr = 127.0.0.1
|
||||||
@ -255,6 +257,54 @@ Configure frps same as above.
|
|||||||
|
|
||||||
`ssh -oPort=6000 test@127.0.0.1`
|
`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
|
### Connect website through frpc's network
|
||||||
|
|
||||||
Configure frps same as above.
|
Configure frps same as above.
|
||||||
@ -550,7 +600,7 @@ plugin_http_passwd = abc
|
|||||||
* Direct reverse proxy, like haproxy.
|
* Direct reverse proxy, like haproxy.
|
||||||
* Load balance to different service in frpc.
|
* Load balance to different service in frpc.
|
||||||
* Frpc can directly be a webserver for static files.
|
* 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.
|
* kubernetes ingress support.
|
||||||
|
|
||||||
|
|
||||||
|
60
README_zh.md
60
README_zh.md
@ -9,6 +9,7 @@ frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp
|
|||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
<!-- vim-markdown-toc GFM -->
|
<!-- vim-markdown-toc GFM -->
|
||||||
|
|
||||||
* [frp 的作用](#frp-的作用)
|
* [frp 的作用](#frp-的作用)
|
||||||
* [开发状态](#开发状态)
|
* [开发状态](#开发状态)
|
||||||
* [架构](#架构)
|
* [架构](#架构)
|
||||||
@ -18,6 +19,7 @@ frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp
|
|||||||
* [转发 DNS 查询请求](#转发-dns-查询请求)
|
* [转发 DNS 查询请求](#转发-dns-查询请求)
|
||||||
* [转发 Unix域套接字](#转发-unix域套接字)
|
* [转发 Unix域套接字](#转发-unix域套接字)
|
||||||
* [安全地暴露内网服务](#安全地暴露内网服务)
|
* [安全地暴露内网服务](#安全地暴露内网服务)
|
||||||
|
* [点对点内网穿透](#点对点内网穿透)
|
||||||
* [通过 frpc 所在机器访问外网](#通过-frpc-所在机器访问外网)
|
* [通过 frpc 所在机器访问外网](#通过-frpc-所在机器访问外网)
|
||||||
* [功能说明](#功能说明)
|
* [功能说明](#功能说明)
|
||||||
* [配置文件](#配置文件)
|
* [配置文件](#配置文件)
|
||||||
@ -246,10 +248,10 @@ frps 的部署步骤同上。
|
|||||||
server_addr = x.x.x.x
|
server_addr = x.x.x.x
|
||||||
server_port = 7000
|
server_port = 7000
|
||||||
|
|
||||||
[secret_ssh_vistor]
|
[secret_ssh_visitor]
|
||||||
type = stcp
|
type = stcp
|
||||||
# stcp 的访问者
|
# stcp 的访问者
|
||||||
role = vistor
|
role = visitor
|
||||||
# 要访问的 stcp 代理的名字
|
# 要访问的 stcp 代理的名字
|
||||||
server_name = secret_ssh
|
server_name = secret_ssh
|
||||||
sk = abcdefg
|
sk = abcdefg
|
||||||
@ -262,6 +264,60 @@ frps 的部署步骤同上。
|
|||||||
|
|
||||||
`ssh -oPort=6000 test@127.0.0.1`
|
`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 所在机器访问外网
|
||||||
|
|
||||||
frpc 内置了 http proxy 和 socks5 插件,可以使其他机器通过 frpc 的网络访问互联网。
|
frpc 内置了 http proxy 和 socks5 插件,可以使其他机器通过 frpc 的网络访问互联网。
|
||||||
|
@ -64,7 +64,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout
|
|||||||
return
|
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 {
|
if err != nil {
|
||||||
res.Code = 3
|
res.Code = 3
|
||||||
res.Msg = err.Error()
|
res.Msg = err.Error()
|
||||||
@ -72,7 +72,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svr.ctl.reloadConf(pxyCfgs, vistorCfgs)
|
svr.ctl.reloadConf(pxyCfgs, visitorCfgs)
|
||||||
log.Info("success reload conf")
|
log.Info("success reload conf")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,11 @@ type Control struct {
|
|||||||
// proxies
|
// proxies
|
||||||
proxies map[string]Proxy
|
proxies map[string]Proxy
|
||||||
|
|
||||||
// vistor configures
|
// visitor configures
|
||||||
vistorCfgs map[string]config.ProxyConf
|
visitorCfgs map[string]config.ProxyConf
|
||||||
|
|
||||||
// vistors
|
// visitors
|
||||||
vistors map[string]Vistor
|
visitors map[string]Visitor
|
||||||
|
|
||||||
// control connection
|
// control connection
|
||||||
conn frpNet.Conn
|
conn frpNet.Conn
|
||||||
@ -84,7 +84,7 @@ type Control struct {
|
|||||||
log.Logger
|
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{
|
loginMsg := &msg.Login{
|
||||||
Arch: runtime.GOARCH,
|
Arch: runtime.GOARCH,
|
||||||
Os: runtime.GOOS,
|
Os: runtime.GOOS,
|
||||||
@ -93,16 +93,16 @@ func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, vistorCfgs ma
|
|||||||
Version: version.Full(),
|
Version: version.Full(),
|
||||||
}
|
}
|
||||||
return &Control{
|
return &Control{
|
||||||
svr: svr,
|
svr: svr,
|
||||||
loginMsg: loginMsg,
|
loginMsg: loginMsg,
|
||||||
pxyCfgs: pxyCfgs,
|
pxyCfgs: pxyCfgs,
|
||||||
vistorCfgs: vistorCfgs,
|
visitorCfgs: visitorCfgs,
|
||||||
proxies: make(map[string]Proxy),
|
proxies: make(map[string]Proxy),
|
||||||
vistors: make(map[string]Vistor),
|
visitors: make(map[string]Visitor),
|
||||||
sendCh: make(chan msg.Message, 10),
|
sendCh: make(chan msg.Message, 10),
|
||||||
readCh: make(chan msg.Message, 10),
|
readCh: make(chan msg.Message, 10),
|
||||||
closedCh: make(chan int),
|
closedCh: make(chan int),
|
||||||
Logger: log.NewPrefixLogger(""),
|
Logger: log.NewPrefixLogger(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,16 +137,16 @@ func (ctl *Control) Run() (err error) {
|
|||||||
go ctl.writer()
|
go ctl.writer()
|
||||||
go ctl.reader()
|
go ctl.reader()
|
||||||
|
|
||||||
// start all local vistors
|
// start all local visitors
|
||||||
for _, cfg := range ctl.vistorCfgs {
|
for _, cfg := range ctl.visitorCfgs {
|
||||||
vistor := NewVistor(ctl, cfg)
|
visitor := NewVisitor(ctl, cfg)
|
||||||
err = vistor.Run()
|
err = visitor.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vistor.Warn("start error: %v", err)
|
visitor.Warn("start error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctl.vistors[cfg.GetName()] = vistor
|
ctl.visitors[cfg.GetName()] = visitor
|
||||||
vistor.Info("start vistor success")
|
visitor.Info("start visitor success")
|
||||||
}
|
}
|
||||||
|
|
||||||
// send NewProxy message for all configured proxies
|
// send NewProxy message for all configured proxies
|
||||||
@ -441,17 +441,17 @@ func (ctl *Control) controler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cfg := range ctl.vistorCfgs {
|
for _, cfg := range ctl.visitorCfgs {
|
||||||
if _, exist := ctl.vistors[cfg.GetName()]; !exist {
|
if _, exist := ctl.visitors[cfg.GetName()]; !exist {
|
||||||
ctl.Info("try to start vistor [%s]", cfg.GetName())
|
ctl.Info("try to start visitor [%s]", cfg.GetName())
|
||||||
vistor := NewVistor(ctl, cfg)
|
visitor := NewVisitor(ctl, cfg)
|
||||||
err = vistor.Run()
|
err = visitor.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vistor.Warn("start error: %v", err)
|
visitor.Warn("start error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctl.vistors[cfg.GetName()] = vistor
|
ctl.visitors[cfg.GetName()] = visitor
|
||||||
vistor.Info("start vistor success")
|
visitor.Info("start visitor success")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctl.mu.RUnlock()
|
ctl.mu.RUnlock()
|
||||||
@ -549,7 +549,7 @@ func (ctl *Control) getProxyConf(name string) (conf config.ProxyConf, ok bool) {
|
|||||||
return
|
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()
|
ctl.mu.Lock()
|
||||||
defer ctl.mu.Unlock()
|
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)
|
ctl.Info("proxy added: %v", addedPxyNames)
|
||||||
|
|
||||||
removedVistorName := make([]string, 0)
|
removedVisitorName := make([]string, 0)
|
||||||
for name, oldVistorCfg := range ctl.vistorCfgs {
|
for name, oldVisitorCfg := range ctl.visitorCfgs {
|
||||||
del := false
|
del := false
|
||||||
cfg, ok := vistorCfgs[name]
|
cfg, ok := visitorCfgs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
del = true
|
del = true
|
||||||
} else {
|
} else {
|
||||||
if !oldVistorCfg.Compare(cfg) {
|
if !oldVisitorCfg.Compare(cfg) {
|
||||||
del = true
|
del = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if del {
|
if del {
|
||||||
removedVistorName = append(removedVistorName, name)
|
removedVisitorName = append(removedVisitorName, name)
|
||||||
delete(ctl.vistorCfgs, name)
|
delete(ctl.visitorCfgs, name)
|
||||||
if vistor, ok := ctl.vistors[name]; ok {
|
if visitor, ok := ctl.visitors[name]; ok {
|
||||||
vistor.Close()
|
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)
|
addedVisitorName := make([]string, 0)
|
||||||
for name, vistorCfg := range vistorCfgs {
|
for name, visitorCfg := range visitorCfgs {
|
||||||
if _, ok := ctl.vistorCfgs[name]; !ok {
|
if _, ok := ctl.visitorCfgs[name]; !ok {
|
||||||
ctl.vistorCfgs[name] = vistorCfg
|
ctl.visitorCfgs[name] = visitorCfg
|
||||||
addedVistorName = append(addedVistorName, name)
|
addedVisitorName = append(addedVisitorName, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctl.Info("vistor added: %v", addedVistorName)
|
ctl.Info("visitor added: %v", addedVisitorName)
|
||||||
}
|
}
|
||||||
|
@ -273,23 +273,23 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) {
|
|||||||
clientConn.Close()
|
clientConn.Close()
|
||||||
pxy.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr)
|
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)
|
time.Sleep(time.Second)
|
||||||
laddr, _ := net.ResolveUDPAddr("udp", clientConn.LocalAddr().String())
|
laddr, _ := net.ResolveUDPAddr("udp", clientConn.LocalAddr().String())
|
||||||
daddr, err := net.ResolveUDPAddr("udp", natHoleRespMsg.VistorAddr)
|
daddr, err := net.ResolveUDPAddr("udp", natHoleRespMsg.VisitorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pxy.Error("resolve vistor udp address error: %v", err)
|
pxy.Error("resolve visitor udp address error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lConn, err := net.DialUDP("udp", laddr, daddr)
|
lConn, err := net.DialUDP("udp", laddr, daddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pxy.Error("dial vistor udp address error: %v", err)
|
pxy.Error("dial visitor udp address error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lConn.Write([]byte(natHoleRespMsg.Sid))
|
lConn.Write([]byte(natHoleRespMsg.Sid))
|
||||||
|
|
||||||
kcpConn, err := frpNet.NewKcpConnFromUdp(lConn, true, natHoleRespMsg.VistorAddr)
|
kcpConn, err := frpNet.NewKcpConnFromUdp(lConn, true, natHoleRespMsg.VisitorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pxy.Error("create kcp connection from udp connection error: %v", err)
|
pxy.Error("create kcp connection from udp connection error: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -26,11 +26,11 @@ type Service struct {
|
|||||||
closedCh chan int
|
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{
|
svr = &Service{
|
||||||
closedCh: make(chan int),
|
closedCh: make(chan int),
|
||||||
}
|
}
|
||||||
ctl := NewControl(svr, pxyCfgs, vistorCfgs)
|
ctl := NewControl(svr, pxyCfgs, visitorCfgs)
|
||||||
svr.ctl = ctl
|
svr.ctl = ctl
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -35,34 +35,34 @@ import (
|
|||||||
"github.com/fatedier/frp/utils/util"
|
"github.com/fatedier/frp/utils/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Vistor is used for forward traffics from local port tot remote service.
|
// Visitor is used for forward traffics from local port tot remote service.
|
||||||
type Vistor interface {
|
type Visitor interface {
|
||||||
Run() error
|
Run() error
|
||||||
Close()
|
Close()
|
||||||
log.Logger
|
log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVistor(ctl *Control, pxyConf config.ProxyConf) (vistor Vistor) {
|
func NewVisitor(ctl *Control, pxyConf config.ProxyConf) (visitor Visitor) {
|
||||||
baseVistor := BaseVistor{
|
baseVisitor := BaseVisitor{
|
||||||
ctl: ctl,
|
ctl: ctl,
|
||||||
Logger: log.NewPrefixLogger(pxyConf.GetName()),
|
Logger: log.NewPrefixLogger(pxyConf.GetName()),
|
||||||
}
|
}
|
||||||
switch cfg := pxyConf.(type) {
|
switch cfg := pxyConf.(type) {
|
||||||
case *config.StcpProxyConf:
|
case *config.StcpProxyConf:
|
||||||
vistor = &StcpVistor{
|
visitor = &StcpVisitor{
|
||||||
BaseVistor: baseVistor,
|
BaseVisitor: baseVisitor,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
case *config.XtcpProxyConf:
|
case *config.XtcpProxyConf:
|
||||||
vistor = &XtcpVistor{
|
visitor = &XtcpVisitor{
|
||||||
BaseVistor: baseVistor,
|
BaseVisitor: baseVisitor,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseVistor struct {
|
type BaseVisitor struct {
|
||||||
ctl *Control
|
ctl *Control
|
||||||
l frpNet.Listener
|
l frpNet.Listener
|
||||||
closed bool
|
closed bool
|
||||||
@ -70,13 +70,13 @@ type BaseVistor struct {
|
|||||||
log.Logger
|
log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type StcpVistor struct {
|
type StcpVisitor struct {
|
||||||
BaseVistor
|
BaseVisitor
|
||||||
|
|
||||||
cfg *config.StcpProxyConf
|
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))
|
sv.l, err = frpNet.ListenTcp(sv.cfg.BindAddr, int64(sv.cfg.BindPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -86,11 +86,11 @@ func (sv *StcpVistor) Run() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *StcpVistor) Close() {
|
func (sv *StcpVisitor) Close() {
|
||||||
sv.l.Close()
|
sv.l.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *StcpVistor) worker() {
|
func (sv *StcpVisitor) worker() {
|
||||||
for {
|
for {
|
||||||
conn, err := sv.l.Accept()
|
conn, err := sv.l.Accept()
|
||||||
if err != nil {
|
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()
|
defer userConn.Close()
|
||||||
|
|
||||||
sv.Debug("get a new stcp user connection")
|
sv.Debug("get a new stcp user connection")
|
||||||
vistorConn, err := sv.ctl.connectServer()
|
visitorConn, err := sv.ctl.connectServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer vistorConn.Close()
|
defer visitorConn.Close()
|
||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
newVistorConnMsg := &msg.NewVistorConn{
|
newVisitorConnMsg := &msg.NewVisitorConn{
|
||||||
ProxyName: sv.cfg.ServerName,
|
ProxyName: sv.cfg.ServerName,
|
||||||
SignKey: util.GetAuthKey(sv.cfg.Sk, now),
|
SignKey: util.GetAuthKey(sv.cfg.Sk, now),
|
||||||
Timestamp: now,
|
Timestamp: now,
|
||||||
UseEncryption: sv.cfg.UseEncryption,
|
UseEncryption: sv.cfg.UseEncryption,
|
||||||
UseCompression: sv.cfg.UseCompression,
|
UseCompression: sv.cfg.UseCompression,
|
||||||
}
|
}
|
||||||
err = msg.WriteMsg(vistorConn, newVistorConnMsg)
|
err = msg.WriteMsg(visitorConn, newVisitorConnMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sv.Warn("send newVistorConnMsg to server error: %v", err)
|
sv.Warn("send newVisitorConnMsg to server error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var newVistorConnRespMsg msg.NewVistorConnResp
|
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||||
vistorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
err = msg.ReadMsgInto(vistorConn, &newVistorConnRespMsg)
|
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sv.Warn("get newVistorConnRespMsg error: %v", err)
|
sv.Warn("get newVisitorConnRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vistorConn.SetReadDeadline(time.Time{})
|
visitorConn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
if newVistorConnRespMsg.Error != "" {
|
if newVisitorConnRespMsg.Error != "" {
|
||||||
sv.Warn("start new vistor connection error: %s", newVistorConnRespMsg.Error)
|
sv.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var remote io.ReadWriteCloser
|
var remote io.ReadWriteCloser
|
||||||
remote = vistorConn
|
remote = visitorConn
|
||||||
if sv.cfg.UseEncryption {
|
if sv.cfg.UseEncryption {
|
||||||
remote, err = frpIo.WithEncryption(remote, []byte(sv.cfg.Sk))
|
remote, err = frpIo.WithEncryption(remote, []byte(sv.cfg.Sk))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -157,13 +157,13 @@ func (sv *StcpVistor) handleConn(userConn frpNet.Conn) {
|
|||||||
frpIo.Join(userConn, remote)
|
frpIo.Join(userConn, remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
type XtcpVistor struct {
|
type XtcpVisitor struct {
|
||||||
BaseVistor
|
BaseVisitor
|
||||||
|
|
||||||
cfg *config.XtcpProxyConf
|
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))
|
sv.l, err = frpNet.ListenTcp(sv.cfg.BindAddr, int64(sv.cfg.BindPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -173,11 +173,11 @@ func (sv *XtcpVistor) Run() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *XtcpVistor) Close() {
|
func (sv *XtcpVisitor) Close() {
|
||||||
sv.l.Close()
|
sv.l.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *XtcpVistor) worker() {
|
func (sv *XtcpVisitor) worker() {
|
||||||
for {
|
for {
|
||||||
conn, err := sv.l.Accept()
|
conn, err := sv.l.Accept()
|
||||||
if err != nil {
|
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()
|
defer userConn.Close()
|
||||||
|
|
||||||
sv.Debug("get a new xtcp user connection")
|
sv.Debug("get a new xtcp user connection")
|
||||||
@ -200,26 +200,26 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) {
|
|||||||
|
|
||||||
raddr, err := net.ResolveUDPAddr("udp",
|
raddr, err := net.ResolveUDPAddr("udp",
|
||||||
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort))
|
fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort))
|
||||||
vistorConn, err := net.DialUDP("udp", nil, raddr)
|
visitorConn, err := net.DialUDP("udp", nil, raddr)
|
||||||
defer vistorConn.Close()
|
defer visitorConn.Close()
|
||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
natHoleVistorMsg := &msg.NatHoleVistor{
|
natHoleVisitorMsg := &msg.NatHoleVisitor{
|
||||||
ProxyName: sv.cfg.ServerName,
|
ProxyName: sv.cfg.ServerName,
|
||||||
SignKey: util.GetAuthKey(sv.cfg.Sk, now),
|
SignKey: util.GetAuthKey(sv.cfg.Sk, now),
|
||||||
Timestamp: now,
|
Timestamp: now,
|
||||||
}
|
}
|
||||||
err = msg.WriteMsg(vistorConn, natHoleVistorMsg)
|
err = msg.WriteMsg(visitorConn, natHoleVisitorMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sv.Warn("send natHoleVistorMsg to server error: %v", err)
|
sv.Warn("send natHoleVisitorMsg to server error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for client address at most 10 seconds.
|
// Wait for client address at most 10 seconds.
|
||||||
var natHoleRespMsg msg.NatHoleResp
|
var natHoleRespMsg msg.NatHoleResp
|
||||||
vistorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
buf := pool.GetBuf(1024)
|
buf := pool.GetBuf(1024)
|
||||||
n, err := vistorConn.Read(buf)
|
n, err := visitorConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sv.Warn("get natHoleRespMsg error: %v", err)
|
sv.Warn("get natHoleRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
@ -230,13 +230,13 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) {
|
|||||||
sv.Warn("get natHoleRespMsg error: %v", err)
|
sv.Warn("get natHoleRespMsg error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vistorConn.SetReadDeadline(time.Time{})
|
visitorConn.SetReadDeadline(time.Time{})
|
||||||
pool.PutBuf(buf)
|
pool.PutBuf(buf)
|
||||||
|
|
||||||
sv.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr)
|
sv.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr)
|
||||||
|
|
||||||
// Close vistorConn, so we can use it's local address.
|
// Close visitorConn, so we can use it's local address.
|
||||||
vistorConn.Close()
|
visitorConn.Close()
|
||||||
|
|
||||||
// Send detect message.
|
// Send detect message.
|
||||||
array := strings.Split(natHoleRespMsg.ClientAddr, ":")
|
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)
|
sv.Error("get natHoleResp client address error: %s", natHoleRespMsg.ClientAddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
laddr, _ := net.ResolveUDPAddr("udp", vistorConn.LocalAddr().String())
|
laddr, _ := net.ResolveUDPAddr("udp", visitorConn.LocalAddr().String())
|
||||||
/*
|
/*
|
||||||
for i := 1000; i < 65000; i++ {
|
for i := 1000; i < 65000; i++ {
|
||||||
sv.sendDetectMsg(array[0], int64(i), laddr, "a")
|
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.sendDetectMsg(array[0], int64(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||||
sv.Trace("send all detect msg done")
|
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, _ := net.ListenUDP("udp", laddr)
|
||||||
lConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
lConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||||
sidBuf := pool.GetBuf(1024)
|
sidBuf := pool.GetBuf(1024)
|
||||||
@ -298,7 +298,7 @@ func (sv *XtcpVistor) handleConn(userConn frpNet.Conn) {
|
|||||||
sv.Debug("join connections closed")
|
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))
|
daddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", addr, port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
@ -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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -165,7 +165,7 @@ func main() {
|
|||||||
log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile,
|
log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile,
|
||||||
config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays)
|
config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays)
|
||||||
|
|
||||||
svr := client.NewService(pxyCfgs, vistorCfgs)
|
svr := client.NewService(pxyCfgs, visitorCfgs)
|
||||||
|
|
||||||
// Capture the exit signal if we use kcp.
|
// Capture the exit signal if we use kcp.
|
||||||
if config.ClientCommonCfg.Protocol == "kcp" {
|
if config.ClientCommonCfg.Protocol == "kcp" {
|
||||||
|
@ -119,24 +119,24 @@ plugin_http_passwd = abc
|
|||||||
|
|
||||||
[secret_tcp]
|
[secret_tcp]
|
||||||
# If the type is secret tcp, remote_port is useless
|
# 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
|
type = stcp
|
||||||
# sk used for authentication for vistors
|
# sk used for authentication for visitors
|
||||||
sk = abcdefg
|
sk = abcdefg
|
||||||
local_ip = 127.0.0.1
|
local_ip = 127.0.0.1
|
||||||
local_port = 22
|
local_port = 22
|
||||||
use_encryption = false
|
use_encryption = false
|
||||||
use_compression = false
|
use_compression = false
|
||||||
|
|
||||||
# user of frpc should be same in both stcp server and stcp vistor
|
# user of frpc should be same in both stcp server and stcp visitor
|
||||||
[secret_tcp_vistor]
|
[secret_tcp_visitor]
|
||||||
# frpc role vistor -> frps -> frpc role server
|
# frpc role visitor -> frps -> frpc role server
|
||||||
role = vistor
|
role = visitor
|
||||||
type = stcp
|
type = stcp
|
||||||
# the server name you want to vistor
|
# the server name you want to visitor
|
||||||
server_name = secret_tcp
|
server_name = secret_tcp
|
||||||
sk = abcdefg
|
sk = abcdefg
|
||||||
# connect this address to vistor stcp server
|
# connect this address to visitor stcp server
|
||||||
bind_addr = 127.0.0.1
|
bind_addr = 127.0.0.1
|
||||||
bind_port = 9000
|
bind_port = 9000
|
||||||
use_encryption = false
|
use_encryption = false
|
||||||
@ -150,8 +150,8 @@ local_port = 22
|
|||||||
use_encryption = false
|
use_encryption = false
|
||||||
use_compression = false
|
use_compression = false
|
||||||
|
|
||||||
[p2p_tcp_vistor]
|
[p2p_tcp_visitor]
|
||||||
role = vistor
|
role = visitor
|
||||||
type = xtcp
|
type = xtcp
|
||||||
server_name = p2p_tcp
|
server_name = p2p_tcp
|
||||||
sk = abcdefg
|
sk = abcdefg
|
||||||
|
@ -595,7 +595,7 @@ type StcpProxyConf struct {
|
|||||||
LocalSvrConf
|
LocalSvrConf
|
||||||
PluginConf
|
PluginConf
|
||||||
|
|
||||||
// used in role vistor
|
// used in role visitor
|
||||||
ServerName string `json:"server_name"`
|
ServerName string `json:"server_name"`
|
||||||
BindAddr string `json:"bind_addr"`
|
BindAddr string `json:"bind_addr"`
|
||||||
BindPort int `json:"bind_port"`
|
BindPort int `json:"bind_port"`
|
||||||
@ -632,7 +632,7 @@ func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmpStr := section["role"]
|
tmpStr := section["role"]
|
||||||
if tmpStr == "server" || tmpStr == "vistor" {
|
if tmpStr == "server" || tmpStr == "visitor" {
|
||||||
cfg.Role = tmpStr
|
cfg.Role = tmpStr
|
||||||
} else {
|
} else {
|
||||||
cfg.Role = "server"
|
cfg.Role = "server"
|
||||||
@ -640,7 +640,7 @@ func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err er
|
|||||||
|
|
||||||
cfg.Sk = section["sk"]
|
cfg.Sk = section["sk"]
|
||||||
|
|
||||||
if tmpStr == "vistor" {
|
if tmpStr == "visitor" {
|
||||||
prefix := section["prefix"]
|
prefix := section["prefix"]
|
||||||
cfg.ServerName = prefix + section["server_name"]
|
cfg.ServerName = prefix + section["server_name"]
|
||||||
if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" {
|
if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" {
|
||||||
@ -684,7 +684,7 @@ type XtcpProxyConf struct {
|
|||||||
LocalSvrConf
|
LocalSvrConf
|
||||||
PluginConf
|
PluginConf
|
||||||
|
|
||||||
// used in role vistor
|
// used in role visitor
|
||||||
ServerName string `json:"server_name"`
|
ServerName string `json:"server_name"`
|
||||||
BindAddr string `json:"bind_addr"`
|
BindAddr string `json:"bind_addr"`
|
||||||
BindPort int `json:"bind_port"`
|
BindPort int `json:"bind_port"`
|
||||||
@ -721,7 +721,7 @@ func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmpStr := section["role"]
|
tmpStr := section["role"]
|
||||||
if tmpStr == "server" || tmpStr == "vistor" {
|
if tmpStr == "server" || tmpStr == "visitor" {
|
||||||
cfg.Role = tmpStr
|
cfg.Role = tmpStr
|
||||||
} else {
|
} else {
|
||||||
cfg.Role = "server"
|
cfg.Role = "server"
|
||||||
@ -729,7 +729,7 @@ func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err er
|
|||||||
|
|
||||||
cfg.Sk = section["sk"]
|
cfg.Sk = section["sk"]
|
||||||
|
|
||||||
if tmpStr == "vistor" {
|
if tmpStr == "visitor" {
|
||||||
prefix := section["prefix"]
|
prefix := section["prefix"]
|
||||||
cfg.ServerName = prefix + section["server_name"]
|
cfg.ServerName = prefix + section["server_name"]
|
||||||
if cfg.BindAddr = section["bind_addr"]; cfg.BindAddr == "" {
|
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
|
// if len(startProxy) is 0, start all
|
||||||
// otherwise just start proxies in startProxy map
|
// otherwise just start proxies in startProxy map
|
||||||
func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]struct{}) (
|
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 != "" {
|
if prefix != "" {
|
||||||
prefix += "."
|
prefix += "."
|
||||||
@ -776,7 +776,7 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s
|
|||||||
startAll = false
|
startAll = false
|
||||||
}
|
}
|
||||||
proxyConfs = make(map[string]ProxyConf)
|
proxyConfs = make(map[string]ProxyConf)
|
||||||
vistorConfs = make(map[string]ProxyConf)
|
visitorConfs = make(map[string]ProxyConf)
|
||||||
for name, section := range conf {
|
for name, section := range conf {
|
||||||
_, shouldStart := startProxy[name]
|
_, shouldStart := startProxy[name]
|
||||||
if name != "common" && (startAll || shouldStart) {
|
if name != "common" && (startAll || shouldStart) {
|
||||||
@ -784,12 +784,12 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s
|
|||||||
section["prefix"] = prefix
|
section["prefix"] = prefix
|
||||||
cfg, err := NewProxyConfFromFile(name, section)
|
cfg, err := NewProxyConfFromFile(name, section)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return proxyConfs, vistorConfs, err
|
return proxyConfs, visitorConfs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
role := section["role"]
|
role := section["role"]
|
||||||
if role == "vistor" {
|
if role == "visitor" {
|
||||||
vistorConfs[prefix+name] = cfg
|
visitorConfs[prefix+name] = cfg
|
||||||
} else {
|
} else {
|
||||||
proxyConfs[prefix+name] = cfg
|
proxyConfs[prefix+name] = cfg
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeLogin = 'o'
|
TypeLogin = 'o'
|
||||||
TypeLoginResp = '1'
|
TypeLoginResp = '1'
|
||||||
TypeNewProxy = 'p'
|
TypeNewProxy = 'p'
|
||||||
TypeNewProxyResp = '2'
|
TypeNewProxyResp = '2'
|
||||||
TypeCloseProxy = 'c'
|
TypeCloseProxy = 'c'
|
||||||
TypeNewWorkConn = 'w'
|
TypeNewWorkConn = 'w'
|
||||||
TypeReqWorkConn = 'r'
|
TypeReqWorkConn = 'r'
|
||||||
TypeStartWorkConn = 's'
|
TypeStartWorkConn = 's'
|
||||||
TypeNewVistorConn = 'v'
|
TypeNewVisitorConn = 'v'
|
||||||
TypeNewVistorConnResp = '3'
|
TypeNewVisitorConnResp = '3'
|
||||||
TypePing = 'h'
|
TypePing = 'h'
|
||||||
TypePong = '4'
|
TypePong = '4'
|
||||||
TypeUdpPacket = 'u'
|
TypeUdpPacket = 'u'
|
||||||
TypeNatHoleVistor = 'i'
|
TypeNatHoleVisitor = 'i'
|
||||||
TypeNatHoleClient = 'n'
|
TypeNatHoleClient = 'n'
|
||||||
TypeNatHoleResp = 'm'
|
TypeNatHoleResp = 'm'
|
||||||
TypeNatHoleSid = '5'
|
TypeNatHoleSid = '5'
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -56,12 +56,12 @@ func init() {
|
|||||||
TypeMap[TypeNewWorkConn] = reflect.TypeOf(NewWorkConn{})
|
TypeMap[TypeNewWorkConn] = reflect.TypeOf(NewWorkConn{})
|
||||||
TypeMap[TypeReqWorkConn] = reflect.TypeOf(ReqWorkConn{})
|
TypeMap[TypeReqWorkConn] = reflect.TypeOf(ReqWorkConn{})
|
||||||
TypeMap[TypeStartWorkConn] = reflect.TypeOf(StartWorkConn{})
|
TypeMap[TypeStartWorkConn] = reflect.TypeOf(StartWorkConn{})
|
||||||
TypeMap[TypeNewVistorConn] = reflect.TypeOf(NewVistorConn{})
|
TypeMap[TypeNewVisitorConn] = reflect.TypeOf(NewVisitorConn{})
|
||||||
TypeMap[TypeNewVistorConnResp] = reflect.TypeOf(NewVistorConnResp{})
|
TypeMap[TypeNewVisitorConnResp] = reflect.TypeOf(NewVisitorConnResp{})
|
||||||
TypeMap[TypePing] = reflect.TypeOf(Ping{})
|
TypeMap[TypePing] = reflect.TypeOf(Ping{})
|
||||||
TypeMap[TypePong] = reflect.TypeOf(Pong{})
|
TypeMap[TypePong] = reflect.TypeOf(Pong{})
|
||||||
TypeMap[TypeUdpPacket] = reflect.TypeOf(UdpPacket{})
|
TypeMap[TypeUdpPacket] = reflect.TypeOf(UdpPacket{})
|
||||||
TypeMap[TypeNatHoleVistor] = reflect.TypeOf(NatHoleVistor{})
|
TypeMap[TypeNatHoleVisitor] = reflect.TypeOf(NatHoleVisitor{})
|
||||||
TypeMap[TypeNatHoleClient] = reflect.TypeOf(NatHoleClient{})
|
TypeMap[TypeNatHoleClient] = reflect.TypeOf(NatHoleClient{})
|
||||||
TypeMap[TypeNatHoleResp] = reflect.TypeOf(NatHoleResp{})
|
TypeMap[TypeNatHoleResp] = reflect.TypeOf(NatHoleResp{})
|
||||||
TypeMap[TypeNatHoleSid] = reflect.TypeOf(NatHoleSid{})
|
TypeMap[TypeNatHoleSid] = reflect.TypeOf(NatHoleSid{})
|
||||||
@ -138,7 +138,7 @@ type StartWorkConn struct {
|
|||||||
ProxyName string `json:"proxy_name"`
|
ProxyName string `json:"proxy_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewVistorConn struct {
|
type NewVisitorConn struct {
|
||||||
ProxyName string `json:"proxy_name"`
|
ProxyName string `json:"proxy_name"`
|
||||||
SignKey string `json:"sign_key"`
|
SignKey string `json:"sign_key"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
@ -146,7 +146,7 @@ type NewVistorConn struct {
|
|||||||
UseCompression bool `json:"use_compression"`
|
UseCompression bool `json:"use_compression"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewVistorConnResp struct {
|
type NewVisitorConnResp struct {
|
||||||
ProxyName string `json:"proxy_name"`
|
ProxyName string `json:"proxy_name"`
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ type UdpPacket struct {
|
|||||||
RemoteAddr *net.UDPAddr `json:"r"`
|
RemoteAddr *net.UDPAddr `json:"r"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NatHoleVistor struct {
|
type NatHoleVisitor struct {
|
||||||
ProxyName string `json:"proxy_name"`
|
ProxyName string `json:"proxy_name"`
|
||||||
SignKey string `json:"sign_key"`
|
SignKey string `json:"sign_key"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
@ -175,9 +175,9 @@ type NatHoleClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NatHoleResp struct {
|
type NatHoleResp struct {
|
||||||
Sid string `json:"sid"`
|
Sid string `json:"sid"`
|
||||||
VistorAddr string `json:"vistor_addr"`
|
VisitorAddr string `json:"visitor_addr"`
|
||||||
ClientAddr string `json:"client_addr"`
|
ClientAddr string `json:"client_addr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NatHoleSid struct {
|
type NatHoleSid struct {
|
||||||
|
@ -93,46 +93,46 @@ func (pm *ProxyManager) GetByName(name string) (pxy Proxy, ok bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager for vistor listeners.
|
// Manager for visitor listeners.
|
||||||
type VistorManager struct {
|
type VisitorManager struct {
|
||||||
vistorListeners map[string]*frpNet.CustomListener
|
visitorListeners map[string]*frpNet.CustomListener
|
||||||
skMap map[string]string
|
skMap map[string]string
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVistorManager() *VistorManager {
|
func NewVisitorManager() *VisitorManager {
|
||||||
return &VistorManager{
|
return &VisitorManager{
|
||||||
vistorListeners: make(map[string]*frpNet.CustomListener),
|
visitorListeners: make(map[string]*frpNet.CustomListener),
|
||||||
skMap: make(map[string]string),
|
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()
|
vm.mu.Lock()
|
||||||
defer vm.mu.Unlock()
|
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)
|
err = fmt.Errorf("custom listener for [%s] is repeated", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l = frpNet.NewCustomListener()
|
l = frpNet.NewCustomListener()
|
||||||
vm.vistorListeners[name] = l
|
vm.visitorListeners[name] = l
|
||||||
vm.skMap[name] = sk
|
vm.skMap[name] = sk
|
||||||
return
|
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) {
|
useEncryption bool, useCompression bool) (err error) {
|
||||||
|
|
||||||
vm.mu.RLock()
|
vm.mu.RLock()
|
||||||
defer vm.mu.RUnlock()
|
defer vm.mu.RUnlock()
|
||||||
|
|
||||||
if l, ok := vm.vistorListeners[name]; ok {
|
if l, ok := vm.visitorListeners[name]; ok {
|
||||||
var sk string
|
var sk string
|
||||||
if sk = vm.skMap[name]; util.GetAuthKey(sk, timestamp) != signKey {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +154,10 @@ func (vm *VistorManager) NewConn(name string, conn frpNet.Conn, timestamp int64,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VistorManager) CloseListener(name string) {
|
func (vm *VisitorManager) CloseListener(name string) {
|
||||||
vm.mu.Lock()
|
vm.mu.Lock()
|
||||||
defer vm.mu.Unlock()
|
defer vm.mu.Unlock()
|
||||||
|
|
||||||
delete(vm.vistorListeners, name)
|
delete(vm.visitorListeners, name)
|
||||||
delete(vm.skMap, name)
|
delete(vm.skMap, name)
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ func (nc *NatHoleController) Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch m := rawMsg.(type) {
|
switch m := rawMsg.(type) {
|
||||||
case *msg.NatHoleVistor:
|
case *msg.NatHoleVisitor:
|
||||||
go nc.HandleVistor(m, raddr)
|
go nc.HandleVisitor(m, raddr)
|
||||||
case *msg.NatHoleClient:
|
case *msg.NatHoleClient:
|
||||||
go nc.HandleClient(m, raddr)
|
go nc.HandleClient(m, raddr)
|
||||||
default:
|
default:
|
||||||
@ -96,12 +96,12 @@ func (nc *NatHoleController) GenSid() string {
|
|||||||
return fmt.Sprintf("%d%s", t, id)
|
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()
|
sid := nc.GenSid()
|
||||||
session := &NatHoleSession{
|
session := &NatHoleSession{
|
||||||
Sid: sid,
|
Sid: sid,
|
||||||
VistorAddr: raddr,
|
VisitorAddr: raddr,
|
||||||
NotifyCh: make(chan struct{}, 0),
|
NotifyCh: make(chan struct{}, 0),
|
||||||
}
|
}
|
||||||
nc.mu.Lock()
|
nc.mu.Lock()
|
||||||
clientCfg, ok := nc.clientCfgs[m.ProxyName]
|
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.sessions[sid] = session
|
||||||
nc.mu.Unlock()
|
nc.mu.Unlock()
|
||||||
log.Trace("handle vistor message, sid [%s]", sid)
|
log.Trace("handle visitor message, sid [%s]", sid)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
nc.mu.Lock()
|
nc.mu.Lock()
|
||||||
@ -130,7 +130,7 @@ func (nc *NatHoleController) HandleVistor(m *msg.NatHoleVistor, raddr *net.UDPAd
|
|||||||
select {
|
select {
|
||||||
case <-session.NotifyCh:
|
case <-session.NotifyCh:
|
||||||
resp := nc.GenNatHoleResponse(raddr, session)
|
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)
|
nc.listener.WriteToUDP(resp, raddr)
|
||||||
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
||||||
return
|
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 {
|
func (nc *NatHoleController) GenNatHoleResponse(raddr *net.UDPAddr, session *NatHoleSession) []byte {
|
||||||
m := &msg.NatHoleResp{
|
m := &msg.NatHoleResp{
|
||||||
Sid: session.Sid,
|
Sid: session.Sid,
|
||||||
VistorAddr: session.VistorAddr.String(),
|
VisitorAddr: session.VisitorAddr.String(),
|
||||||
ClientAddr: session.ClientAddr.String(),
|
ClientAddr: session.ClientAddr.String(),
|
||||||
}
|
}
|
||||||
b := bytes.NewBuffer(nil)
|
b := bytes.NewBuffer(nil)
|
||||||
err := msg.WriteMsg(b, m)
|
err := msg.WriteMsg(b, m)
|
||||||
@ -168,9 +168,9 @@ func (nc *NatHoleController) GenNatHoleResponse(raddr *net.UDPAddr, session *Nat
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NatHoleSession struct {
|
type NatHoleSession struct {
|
||||||
Sid string
|
Sid string
|
||||||
VistorAddr *net.UDPAddr
|
VisitorAddr *net.UDPAddr
|
||||||
ClientAddr *net.UDPAddr
|
ClientAddr *net.UDPAddr
|
||||||
|
|
||||||
NotifyCh chan struct{}
|
NotifyCh chan struct{}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ type StcpProxy struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pxy *StcpProxy) Run() error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ func (pxy *StcpProxy) GetConf() config.ProxyConf {
|
|||||||
|
|
||||||
func (pxy *StcpProxy) Close() {
|
func (pxy *StcpProxy) Close() {
|
||||||
pxy.BaseProxy.Close()
|
pxy.BaseProxy.Close()
|
||||||
pxy.ctl.svr.vistorManager.CloseListener(pxy.GetName())
|
pxy.ctl.svr.visitorManager.CloseListener(pxy.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
type XtcpProxy struct {
|
type XtcpProxy struct {
|
||||||
|
@ -56,8 +56,8 @@ type Service struct {
|
|||||||
// Manage all proxies.
|
// Manage all proxies.
|
||||||
pxyManager *ProxyManager
|
pxyManager *ProxyManager
|
||||||
|
|
||||||
// Manage all vistor listeners.
|
// Manage all visitor listeners.
|
||||||
vistorManager *VistorManager
|
visitorManager *VisitorManager
|
||||||
|
|
||||||
// Controller for nat hole connections.
|
// Controller for nat hole connections.
|
||||||
natHoleController *NatHoleController
|
natHoleController *NatHoleController
|
||||||
@ -65,9 +65,9 @@ type Service struct {
|
|||||||
|
|
||||||
func NewService() (svr *Service, err error) {
|
func NewService() (svr *Service, err error) {
|
||||||
svr = &Service{
|
svr = &Service{
|
||||||
ctlManager: NewControlManager(),
|
ctlManager: NewControlManager(),
|
||||||
pxyManager: NewProxyManager(),
|
pxyManager: NewProxyManager(),
|
||||||
vistorManager: NewVistorManager(),
|
visitorManager: NewVisitorManager(),
|
||||||
}
|
}
|
||||||
cfg := config.ServerCommonCfg
|
cfg := config.ServerCommonCfg
|
||||||
|
|
||||||
@ -200,16 +200,16 @@ func (svr *Service) HandleListener(l frpNet.Listener) {
|
|||||||
}
|
}
|
||||||
case *msg.NewWorkConn:
|
case *msg.NewWorkConn:
|
||||||
svr.RegisterWorkConn(conn, m)
|
svr.RegisterWorkConn(conn, m)
|
||||||
case *msg.NewVistorConn:
|
case *msg.NewVisitorConn:
|
||||||
if err = svr.RegisterVistorConn(conn, m); err != nil {
|
if err = svr.RegisterVisitorConn(conn, m); err != nil {
|
||||||
conn.Warn("%v", err)
|
conn.Warn("%v", err)
|
||||||
msg.WriteMsg(conn, &msg.NewVistorConnResp{
|
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||||
ProxyName: m.ProxyName,
|
ProxyName: m.ProxyName,
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
})
|
})
|
||||||
conn.Close()
|
conn.Close()
|
||||||
} else {
|
} else {
|
||||||
msg.WriteMsg(conn, &msg.NewVistorConnResp{
|
msg.WriteMsg(conn, &msg.NewVisitorConnResp{
|
||||||
ProxyName: m.ProxyName,
|
ProxyName: m.ProxyName,
|
||||||
Error: "",
|
Error: "",
|
||||||
})
|
})
|
||||||
@ -300,8 +300,8 @@ func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkCo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svr *Service) RegisterVistorConn(vistorConn frpNet.Conn, newMsg *msg.NewVistorConn) error {
|
func (svr *Service) RegisterVisitorConn(visitorConn frpNet.Conn, newMsg *msg.NewVisitorConn) error {
|
||||||
return svr.vistorManager.NewConn(newMsg.ProxyName, vistorConn, newMsg.Timestamp, newMsg.SignKey,
|
return svr.visitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
|
||||||
newMsg.UseEncryption, newMsg.UseCompression)
|
newMsg.UseEncryption, newMsg.UseCompression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user