mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
Update On Sun Apr 7 20:25:36 CEST 2024
This commit is contained in:
9
echo/.github/workflows/cd.yaml
vendored
9
echo/.github/workflows/cd.yaml
vendored
@@ -166,9 +166,12 @@ jobs:
|
||||
echo "Creating manifest list..."
|
||||
AMD64_DIGEST=$(ls amd64/)
|
||||
ARM64_DIGEST=$(ls arm64/)
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
--append ${{ env.REGISTRY_IMAGE }}@sha256:$AMD64_DIGEST \
|
||||
--append ${{ env.REGISTRY_IMAGE }}@sha256:$ARM64_DIGEST
|
||||
echo "AMD64_DIGEST: $AMD64_DIGEST"
|
||||
echo "ARM64_DIGEST: $ARM64_DIGEST"
|
||||
docker buildx imagetools create \
|
||||
--tag ${{ env.REGISTRY_IMAGE }}:latest \
|
||||
${{ env.REGISTRY_IMAGE }}@sha256:$AMD64_DIGEST \
|
||||
${{ env.REGISTRY_IMAGE }}@sha256:$ARM64_DIGEST
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
|
||||
300
echo/README.md
300
echo/README.md
@@ -8,126 +8,11 @@
|
||||
|
||||
## Ehco Relay - 让流量转发更简单
|
||||
|
||||
我们很高兴地宣布,ehco 现在提供 SaaS(软件即服务)版本!这是一个全托管的解决方案,旨在为那些希望在不搭建和管理自己的服务器的情况下享受 ehco 强大流量转发能力的用户提供服务。
|
||||
ehco 现在提供 SaaS(软件即服务)版本!这是一个全托管的解决方案,旨在为那些希望在不搭建和管理自己的服务器的情况下享受 ehco 强大流量转发能力的用户提供服务。
|
||||
|
||||
- [Ehco Relay 官方网站](https://ehco-relay.cc)
|
||||
- [Ehco Relay 文档](https://docs.ehco-relay.cc/)
|
||||
|
||||
### 为什么选择 Ehco Relay?
|
||||
|
||||
- **即刻启动**:无需复杂的配置或服务器管理,立即获得高性能的流量转发服务。
|
||||
- **全面托管**:我们的团队会处理所有后端事务,包括维护、更新和故障排除,让您可以专注于您的主要业务。
|
||||
- **灵活的计划**:无论您是个人开发者还是大型企业,我们都提供多种计划来满足您的需求。
|
||||
- **安全可靠**:利用最先进的加密技术,确保您的数据传输安全无忧。
|
||||
|
||||
欢迎访问官网来了解更多信息,并开始您的免费试用。只需几个简单的步骤,您就可以轻松地设置并运行 ehco,享受无缝的流量转发服务。
|
||||
|
||||
## 使用场景
|
||||
|
||||
<details> <summary>连接内网服务</summary>
|
||||
|
||||
本地无法链接集群内的服务,可以通过 ehco 将本地流量转发到集群内,方便本地开发和调试
|
||||
|
||||
e.g. 本地开发调试连接内网服务 db, db host: xxx-rds.xxx.us-east-1.rds.amazonaws.com
|
||||
|
||||
1. 在 k8s 内 启动一个 ehco pod. 启动命令如下:
|
||||
`ehco -l 0.0.0.0:3306 -r xxx-rds.xxx.us-east-1.rds.amazonaws.com:3306`
|
||||
|
||||
2. 使用 kube port-forward 将本地的 3306 端口转发到 ehco pod 的 3306 端口
|
||||
`kubectl port-forward pod/ehco-pod 3306:3306`
|
||||
|
||||
3. 本地使用客户端连接
|
||||
`mysql -h 127.0.0.1:3306 -u root -p`
|
||||
</details>
|
||||
|
||||
<details> <summary>中转 proxy 客户端,提供负载均衡功能</summary>
|
||||
|
||||
从 **v1.1.4-dev(nightly)** 开始, ehco 支持了从 clash proxy provider 读取 proxy 配置并复写成 ehco 的 relay 配置
|
||||
从而实现了 ehco 作为代理客户端的前置代理,提供负载均衡,流量监控等功能
|
||||
|
||||
e.g.
|
||||
|
||||
1. 配置 ehco 的 config.json 并启动
|
||||
|
||||
```json
|
||||
{
|
||||
"web_host": "12.0.0.1",
|
||||
"web_port": 9000,
|
||||
"sub_configs": [
|
||||
{
|
||||
"name": "nas",
|
||||
"url": "your url"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`ehco -c config.json`
|
||||
|
||||
2. 访问 ehco 的 web 界面 获取 ehco 的 proxy provider url
|
||||
|
||||
`http://<web_host>:<web_port>`
|
||||
|
||||

|
||||
|
||||
ehco 会将每个 clash proxy provider 转换成两个新 clash provider
|
||||
|
||||
- 会将每个的 proxy 转换成一个 relay
|
||||
- 会将 proxy 按最长前缀**分组**,并将每个分组转换成开启负载均衡的 relay
|
||||
|
||||
举个例子
|
||||
|
||||
```yaml
|
||||
proxies:
|
||||
- name: us-1
|
||||
server: s1
|
||||
password:
|
||||
port: 1
|
||||
- name: us-2
|
||||
server: s2
|
||||
port: 2
|
||||
- name: jb-1
|
||||
server: s3
|
||||
password: pass
|
||||
port: 3
|
||||
```
|
||||
|
||||
上面这个包含 3 个 proxy 的会被转换成 5 个 relay:
|
||||
|
||||
- us-1 relay to s1:1
|
||||
- us-2 relay to s2:2
|
||||
- jb-1 relay to s3:3
|
||||
us-lb relay to s1:1,s2:2
|
||||
- jb-1-lb relay to s3:3
|
||||
|
||||
3. 将 ehco 的 proxy provider url 配置到 clash 的配置文件中
|
||||
|
||||
```yaml
|
||||
proxy-providers:
|
||||
ehco:
|
||||
type: http
|
||||
url: http://<web_host>:<web_port>/clash_proxy_provider/?sub_name=<name>
|
||||
ehco-lb:
|
||||
type: http
|
||||
url: http://<web_host>:<web_port>/clash_proxy_provider/?sub_name=name&grouped=true
|
||||
```
|
||||
|
||||
你就能得到一个支持负载均衡的 clash proxy client 了,并且还能在 dashboard 上看到流量监控哟
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details> <summary>WIP: 隧道连接到 proxy 集群</summary>
|
||||
</details>
|
||||
|
||||
## 安装
|
||||
|
||||
- ehco 提供预编译的的二进制 [release](https://github.com/Ehco1996/ehco/releases) 页面下载
|
||||
|
||||
- ehco 提供 [nightly build](https://github.com/Ehco1996/ehco/releases/tag/v0.0.0-nightly)
|
||||
|
||||
- ehco 提供 docker 镜像 `docker pull ehco1996/ehco`
|
||||
|
||||
## 主要功能
|
||||
|
||||
- tcp/udp relay
|
||||
@@ -135,185 +20,4 @@ proxy-providers:
|
||||
- proxy server (内嵌了完整班版本的 xray)
|
||||
- 监控报警 (prometheus/grafana)
|
||||
- WebAPI (http://web_host:web_port)
|
||||
|
||||
## 中转使用介绍
|
||||
|
||||
使用隧道需要至少两台主机, 并且在两台主机上都安装了 ehco
|
||||
|
||||
- 中转机器 A 假设机器 A 的 IP 是 1.1.1.1
|
||||
- 落地机器 B 假设机器 B 的 IP 是 2.2.2.2 并且落地机器 B 的 5555 端口跑着一个 SS/v2ray/任意 tcp/udp 服务
|
||||
|
||||
<details> <summary>案例一 不用隧道直接通过中转机器中转用户流量</summary>
|
||||
直接在中转机器 A 上输入: `ehco -l 0.0.0.0:1234 -r 2.2.2.2:5555`
|
||||
|
||||
> 该命令表示将所有从中转机器 A 的 1234 端口进入的流量直接转发到落地机器 B 的 5555 端口
|
||||
|
||||
用户即可通过 中转机器 A 的 1234 端口访问到落地机器 B 的 5555 端口的 SS/v2ray 服务了
|
||||
|
||||
</details>
|
||||
|
||||
<details> <summary>案例二 用 mwss 隧道中转用户流量</summary>
|
||||
在落地机器 B 上输入: `ehco -l 0.0.0.0:443 -lt mwss -r 127.0.0.1:5555`
|
||||
|
||||
> 该命令表示将所有从落地机器 B 的 443 端口进入的 wss 流量解密后转发到落地机器 B 的 5555 端口
|
||||
|
||||
在中转机器 A 上输入: `ehco -l 0.0.0.0:1234 -r wss://2.2.2.2:443 -tt mwss`
|
||||
|
||||
> 该命令表示将所有从 A 的 1234 端口进入的流量通过 wss 加密后转发到落地机器 B 的 443 端口
|
||||
|
||||
用户即可通过 中转机器 A 的 1234 端口访问到落地机器 B 的 5555 端口的 SS/v2ray 服务了
|
||||
|
||||
</details>
|
||||
|
||||
## 内嵌 Xray 功能介绍
|
||||
|
||||
<details> <summary>ehco 内的 xray 服务端</summary>
|
||||
从 `v1.1.2` 开始,ehco 内置了完整版本的 [xray](https://github.com/XTLS/Xray-core) 后端,可以通过标准的 xray 配置文件来启动内置的 xray server, 配置的 key 为 `xray_config`:
|
||||
|
||||
- 单端口多用户的 ss [xray_ss.json](examples/xray_ss.json)
|
||||
- 单端口多用户的 trojan [xray_trojan.json](examples/xray_trojan.json)
|
||||
</details>
|
||||
|
||||
<details> <summary>用户流量统计</summary>
|
||||
|
||||
从 `v1.1.2` 开始,ehco 支持通过 api 下方用户配置和上报用户流量,配置的 key 为 `sync_traffic_endpoint`:
|
||||
|
||||
ehco 会每隔 60s 发送一次 GET 请求,从 `sync_traffic_endpoint` 同步一次用户配置,到 xray server 里,期望的 API 返回格式如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"method": "user1",
|
||||
"password": 1024,
|
||||
"level": 1024,
|
||||
"upload_traffic": 1024,
|
||||
"download_traffic": 1024,
|
||||
"protocol": "trojan/ss"
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"method": "user1",
|
||||
"password": 1024,
|
||||
"level": 1024,
|
||||
"upload_traffic": 1024,
|
||||
"download_traffic": 1024,
|
||||
"protocol": "trojan/ss"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
ehco 会每隔 60s 发送一次 POST 请求至 `sync_traffic_endpoint` ,上报当前 xray server 所有用户的流量使用情况,发送的请求格式如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"upload_traffic": 1024,
|
||||
"download_traffic": 1024
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"upload_traffic": 1024,
|
||||
"download_traffic": 1024
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
需要注意的是,如果想使用此功能,对 xray 的完整配置文件有如下限制
|
||||
|
||||
- 的配置文件必须包开启 `stats` 和 `api` 功能
|
||||
- ss inbound 的 `tag` 必须为 `ss_proxy`
|
||||
- trojan inbound 的 `tag` 必须为 `trojan_proxy`
|
||||
|
||||
一个完整的例子可以参考 [xray_ss.json](examples/xray_ss.json) 和 [xray_trojan.json](examples/xray_trojan.json)
|
||||
|
||||
</details>
|
||||
|
||||
## 配置文件格式
|
||||
|
||||
> ehco 支持从 `配置文件` / `http接口` 里读取 `json` 格式的配置并启动
|
||||
> (更多例子可以参考项目里的 [config.json](examples/config.json) 文件):
|
||||
|
||||
<details> <summary>热重载配置</summary>
|
||||
|
||||
- 大于 1.1.0 版本的 ehco 支持热重载配置
|
||||
- 通过 `kill -HUP pid` 信号来热重载配置
|
||||
- 通过配置 `reload_interval` 来指定配置文件的路径
|
||||
- 通过访问 POST `http://web_host:web_port/reload/` 接口来热重载配置
|
||||
</details>
|
||||
|
||||
## 监控报警
|
||||
|
||||
- dashboard 和 prometheus 规则可以从`monitor`文件夹下找到,可以自行导入
|
||||
|
||||
- 类似 Smoking Ping 的延迟监控
|
||||
|
||||

|
||||
|
||||
- 流量监控
|
||||
|
||||

|
||||
|
||||
## Benchmark(Apple m1)
|
||||
|
||||
iperf:
|
||||
|
||||
```sh
|
||||
# run iperf server on 5201
|
||||
iperf3 -s
|
||||
|
||||
# 直接转发
|
||||
# run relay server listen 1234 to 9001 (raw)
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1234 -r 0.0.0.0:5201
|
||||
|
||||
# 直接转发END
|
||||
|
||||
# 通过ws隧道转发
|
||||
# listen 1235 relay over ws to 1236
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1235 -r ws://0.0.0.0:1236 -tt ws
|
||||
|
||||
# listen 1236 through ws relay to 5201
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1236 -lt ws -r 0.0.0.0:5201
|
||||
# 通过ws隧道转发END
|
||||
|
||||
# 通过wss隧道转发
|
||||
# listen 1234 relay over wss to 1236
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1235 -r wss://0.0.0.0:1236 -tt wss
|
||||
|
||||
# listen 1236 through wss relay to 5201
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1236 -lt wss -r 0.0.0.0:5201
|
||||
# 通过wss隧道转发END
|
||||
|
||||
# 通过mwss隧道转发 和wss相比 速度会慢,但是能减少延迟
|
||||
# listen 1237 relay over mwss to 1238
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1237 -r wss://0.0.0.0:1238 -tt mwss
|
||||
|
||||
# listen 1238 through mwss relay to 5201
|
||||
go run cmd/ehco/main.go -l 0.0.0.0:1238 -lt mwss -r 0.0.0.0:5201
|
||||
# 通过mwss隧道转发END
|
||||
|
||||
# run through file
|
||||
go run cmd/ehco/main.go -c config.json
|
||||
|
||||
# benchmark tcp
|
||||
iperf3 -c 0.0.0.0 -p 1234
|
||||
|
||||
# benchmark tcp through wss
|
||||
iperf3 -c 0.0.0.0 -p 1235
|
||||
|
||||
# benchmark upd
|
||||
iperf3 -c 0.0.0.0 -p 1234 -u -b 1G --length 1024
|
||||
```
|
||||
|
||||
```
|
||||
| iperf | raw | relay(raw) | relay(ws) | relay(wss) | relay(mwss) | relay(mtcp) |
|
||||
| ----- | -------------- | ------------- | ------------ | ------------ | -------------- | -------------- |
|
||||
| tcp | 123 Gbits/sec | 55 Gbits/sec | 41 Gbits/sec | 10 Gbits/sec | 5.78 Gbits/sec | 22.2 Gbits/sec |
|
||||
| udp | 14.5 Gbits/sec | 3.3 Gbits/sec | 直接转发 | 直接转发 | 直接转发 | 直接转发 |
|
||||
|
||||
```
|
||||
- [更多功能请探索文档](https://docs.ehco-relay.cc/)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
cli "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var cliLogger = log.MustNewLogger("info").Sugar().Named("cli-app")
|
||||
var cliLogger = log.MustNewLogger("info").Sugar().Named("cli")
|
||||
|
||||
func startAction(ctx *cli.Context) error {
|
||||
cfg, err := InitConfigAndComponents()
|
||||
|
||||
@@ -49,10 +49,10 @@ func loadConfig() (cfg *config.Config, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// init tls
|
||||
// init tls when need
|
||||
for _, cfg := range cfg.RelayConfigs {
|
||||
if cfg.ListenType == constant.Listen_WSS || cfg.ListenType == constant.Listen_MWSS ||
|
||||
cfg.TransportType == constant.Transport_WSS || cfg.TransportType == constant.Transport_MWSS {
|
||||
if cfg.ListenType == constant.RelayTypeWSS || cfg.ListenType == constant.RelayTypeMWSS ||
|
||||
cfg.TransportType == constant.RelayTypeWSS || cfg.TransportType == constant.RelayTypeMWSS {
|
||||
if err := tls.InitTlsCfg(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -20,19 +20,16 @@ const (
|
||||
SmuxMaxAliveDuration = 10 * time.Minute
|
||||
SmuxMaxStreamCnt = 5
|
||||
|
||||
Listen_RAW = "raw"
|
||||
Listen_WS = "ws"
|
||||
Listen_WSS = "wss"
|
||||
Listen_MWSS = "mwss"
|
||||
Listen_MTCP = "mtcp"
|
||||
|
||||
Transport_RAW = "raw"
|
||||
Transport_WS = "ws"
|
||||
Transport_WSS = "wss"
|
||||
Transport_MWSS = "mwss"
|
||||
Transport_MTCP = "mtcp"
|
||||
|
||||
// todo add udp buffer size
|
||||
BUFFER_POOL_SIZE = 1024 // support 512 connections
|
||||
BUFFER_SIZE = 20 * 1024 // 20KB the maximum packet size of shadowsocks is about 16 KiB
|
||||
)
|
||||
|
||||
// relay type
|
||||
const (
|
||||
RelayTypeRaw = "raw"
|
||||
RelayTypeWS = "ws"
|
||||
RelayTypeWSS = "wss"
|
||||
RelayTypeMWSS = "mwss"
|
||||
RelayTypeMTCP = "mtcp"
|
||||
)
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -22,19 +24,19 @@ func (r *Config) Validate() error {
|
||||
if r.Adjust() != nil {
|
||||
return errors.New("adjust config failed")
|
||||
}
|
||||
if r.ListenType != constant.Listen_RAW &&
|
||||
r.ListenType != constant.Listen_WS &&
|
||||
r.ListenType != constant.Listen_WSS &&
|
||||
r.ListenType != constant.Listen_MTCP &&
|
||||
r.ListenType != constant.Listen_MWSS {
|
||||
if r.ListenType != constant.RelayTypeRaw &&
|
||||
r.ListenType != constant.RelayTypeWS &&
|
||||
r.ListenType != constant.RelayTypeWSS &&
|
||||
r.ListenType != constant.RelayTypeMTCP &&
|
||||
r.ListenType != constant.RelayTypeMWSS {
|
||||
return fmt.Errorf("invalid listen type:%s", r.ListenType)
|
||||
}
|
||||
|
||||
if r.TransportType != constant.Transport_RAW &&
|
||||
r.TransportType != constant.Transport_WS &&
|
||||
r.TransportType != constant.Transport_WSS &&
|
||||
r.TransportType != constant.Transport_MTCP &&
|
||||
r.TransportType != constant.Transport_MWSS {
|
||||
if r.TransportType != constant.RelayTypeRaw &&
|
||||
r.TransportType != constant.RelayTypeWS &&
|
||||
r.TransportType != constant.RelayTypeWSS &&
|
||||
r.TransportType != constant.RelayTypeMTCP &&
|
||||
r.TransportType != constant.RelayTypeMWSS {
|
||||
return fmt.Errorf("invalid transport type:%s", r.ListenType)
|
||||
}
|
||||
|
||||
@@ -106,16 +108,31 @@ func (r *Config) Different(new *Config) bool {
|
||||
}
|
||||
|
||||
// todo make this shorter and more readable
|
||||
func (r *Config) defaultLabel() string {
|
||||
defaultLabel := fmt.Sprintf("<At=%s Over=%s TCP-To=%s UDP-To=%s Through=%s>",
|
||||
r.Listen, r.ListenType, r.TCPRemotes, r.UDPRemotes, r.TransportType)
|
||||
func (r *Config) DefaultLabel() string {
|
||||
defaultLabel := fmt.Sprintf("<At=%s TCP-To=%s TP=%s>",
|
||||
r.Listen, r.TCPRemotes, r.TransportType)
|
||||
return defaultLabel
|
||||
}
|
||||
|
||||
func (r *Config) Adjust() error {
|
||||
if r.Label == "" {
|
||||
r.Label = r.defaultLabel()
|
||||
r.Label = r.DefaultLabel()
|
||||
zap.S().Debugf("label is empty, set default label:%s", r.Label)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Config) ToTCPRemotes() lb.RoundRobin {
|
||||
tcpNodeList := make([]*lb.Node, len(r.TCPRemotes))
|
||||
for idx, addr := range r.TCPRemotes {
|
||||
tcpNodeList[idx] = &lb.Node{
|
||||
Address: addr,
|
||||
Label: fmt.Sprintf("%s-%s", r.Label, addr),
|
||||
}
|
||||
}
|
||||
return lb.NewRoundRobin(tcpNodeList)
|
||||
}
|
||||
|
||||
func (r *Config) GetLoggerName() string {
|
||||
return fmt.Sprintf("%s(%s<->%s)", r.Label, r.ListenType, r.TransportType)
|
||||
}
|
||||
|
||||
@@ -1,138 +1,50 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/cmgr"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/relay/conf"
|
||||
"github.com/Ehco1996/ehco/internal/transporter"
|
||||
)
|
||||
|
||||
type Relay struct {
|
||||
Name string // unique name for all relay
|
||||
TransportType string
|
||||
ListenType string
|
||||
|
||||
TP transporter.RelayTransporter
|
||||
|
||||
LocalTCPAddr *net.TCPAddr
|
||||
closeTcpF func() error
|
||||
|
||||
cfg *conf.Config
|
||||
l *zap.SugaredLogger
|
||||
|
||||
relayServer transporter.RelayServer
|
||||
}
|
||||
|
||||
func (r *Relay) UniqueID() string {
|
||||
return r.cfg.Label
|
||||
}
|
||||
|
||||
func NewRelay(cfg *conf.Config, connMgr cmgr.Cmgr) (*Relay, error) {
|
||||
localTCPAddr, err := net.ResolveTCPAddr("tcp", cfg.Listen)
|
||||
base := transporter.NewBaseTransporter(cfg, connMgr)
|
||||
s, err := transporter.NewRelayServer(cfg.ListenType, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := &Relay{
|
||||
cfg: cfg,
|
||||
l: zap.S().Named("relay"),
|
||||
|
||||
Name: cfg.Label,
|
||||
LocalTCPAddr: localTCPAddr,
|
||||
ListenType: cfg.ListenType,
|
||||
TransportType: cfg.TransportType,
|
||||
TP: transporter.NewRelayTransporter(cfg, connMgr),
|
||||
relayServer: s,
|
||||
cfg: cfg,
|
||||
l: zap.S().Named("relay"),
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Relay) ListenAndServe() error {
|
||||
errCh := make(chan error)
|
||||
|
||||
if len(r.cfg.TCPRemotes) > 0 {
|
||||
switch r.ListenType {
|
||||
case constant.Listen_RAW:
|
||||
go func() {
|
||||
errCh <- r.RunLocalTCPServer()
|
||||
}()
|
||||
case constant.Listen_MTCP:
|
||||
go func() {
|
||||
errCh <- r.RunLocalMTCPServer()
|
||||
}()
|
||||
case constant.Listen_WS:
|
||||
go func() {
|
||||
errCh <- r.RunLocalWSServer()
|
||||
}()
|
||||
case constant.Listen_WSS:
|
||||
go func() {
|
||||
errCh <- r.RunLocalWSSServer()
|
||||
}()
|
||||
case constant.Listen_MWSS:
|
||||
go func() {
|
||||
errCh <- r.RunLocalMWSSServer()
|
||||
}()
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
r.l.Infof("Start TCP Relay Server:%s", r.cfg.DefaultLabel())
|
||||
errCh <- r.relayServer.ListenAndServe()
|
||||
}()
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func (r *Relay) Close() {
|
||||
r.l.Infof("Close relay label: %s", r.Name)
|
||||
if r.closeTcpF != nil {
|
||||
err := r.closeTcpF()
|
||||
if err != nil {
|
||||
r.l.Errorf(err.Error())
|
||||
}
|
||||
r.l.Infof("Close TCP Relay Server:%s", r.cfg.DefaultLabel())
|
||||
if err := r.relayServer.Close(); err != nil {
|
||||
r.l.Errorf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Relay) RunLocalTCPServer() error {
|
||||
rawServer, err := transporter.NewRawServer(r.LocalTCPAddr.String(), r.TP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.closeTcpF = func() error {
|
||||
return rawServer.Close()
|
||||
}
|
||||
r.l.Infof("Start TCP relay Server: %s", r.Name)
|
||||
return rawServer.ListenAndServe()
|
||||
}
|
||||
|
||||
func (r *Relay) RunLocalMTCPServer() error {
|
||||
tp := r.TP.(*transporter.RawClient)
|
||||
mTCPServer := transporter.NewMTCPServer(r.LocalTCPAddr.String(), tp, r.l.Named("MTCPServer"))
|
||||
r.closeTcpF = func() error {
|
||||
return mTCPServer.Close()
|
||||
}
|
||||
r.l.Infof("Start MTCP relay Server: %s", r.Name)
|
||||
return mTCPServer.ListenAndServe()
|
||||
}
|
||||
|
||||
func (r *Relay) RunLocalWSServer() error {
|
||||
tp := r.TP.(*transporter.RawClient)
|
||||
wsServer := transporter.NewWSServer(r.LocalTCPAddr.String(), tp, r.l.Named("WSServer"))
|
||||
r.closeTcpF = func() error {
|
||||
return wsServer.Close()
|
||||
}
|
||||
r.l.Infof("Start WS relay Server: %s", r.Name)
|
||||
return wsServer.ListenAndServe()
|
||||
}
|
||||
|
||||
func (r *Relay) RunLocalWSSServer() error {
|
||||
tp := r.TP.(*transporter.RawClient)
|
||||
wssServer := transporter.NewWSSServer(r.LocalTCPAddr.String(), tp, r.l.Named("WSSServer"))
|
||||
r.closeTcpF = func() error {
|
||||
return wssServer.Close()
|
||||
}
|
||||
r.l.Infof("Start WSS relay Server: %s", r.Name)
|
||||
return wssServer.ListenAndServe()
|
||||
}
|
||||
|
||||
func (r *Relay) RunLocalMWSSServer() error {
|
||||
tp := r.TP.(*transporter.RawClient)
|
||||
mwssServer := transporter.NewMWSSServer(r.LocalTCPAddr.String(), tp, r.l.Named("MWSSServer"))
|
||||
r.closeTcpF = func() error {
|
||||
return mwssServer.Close()
|
||||
}
|
||||
r.l.Infof("Start MWSS relay Server: %s", r.Name)
|
||||
return mwssServer.ListenAndServe()
|
||||
}
|
||||
|
||||
@@ -46,18 +46,18 @@ func NewServer(cfg *config.Config) (*Server, error) {
|
||||
}
|
||||
|
||||
func (s *Server) startOneRelay(r *Relay) {
|
||||
s.relayM.Store(r.Name, r)
|
||||
s.relayM.Store(r.UniqueID(), r)
|
||||
// mute closed network error for tcp server and mute http.ErrServerClosed for http server when config reload
|
||||
if err := r.ListenAndServe(); err != nil &&
|
||||
!errors.Is(err, net.ErrClosed) && !errors.Is(err, http.ErrServerClosed) {
|
||||
s.l.Errorf("start relay %s meet error: %s", r.Name, err)
|
||||
s.l.Errorf("start relay %s meet error: %s", r.UniqueID(), err)
|
||||
s.errCH <- err
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) stopOneRelay(r *Relay) {
|
||||
r.Close()
|
||||
s.relayM.Delete(r.Name)
|
||||
s.relayM.Delete(r.UniqueID())
|
||||
}
|
||||
|
||||
func (s *Server) Start(ctx context.Context) error {
|
||||
|
||||
55
echo/internal/transporter/base.go
Normal file
55
echo/internal/transporter/base.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package transporter
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/cmgr"
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
"github.com/Ehco1996/ehco/internal/relay/conf"
|
||||
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type baseTransporter struct {
|
||||
cmgr cmgr.Cmgr
|
||||
cfg *conf.Config
|
||||
tCPRemotes lb.RoundRobin
|
||||
l *zap.SugaredLogger
|
||||
}
|
||||
|
||||
func NewBaseTransporter(cfg *conf.Config, cmgr cmgr.Cmgr) *baseTransporter {
|
||||
return &baseTransporter{
|
||||
cfg: cfg,
|
||||
cmgr: cmgr,
|
||||
tCPRemotes: cfg.ToTCPRemotes(),
|
||||
l: zap.S().Named(cfg.GetLoggerName()),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *baseTransporter) GetTCPListenAddr() (*net.TCPAddr, error) {
|
||||
return net.ResolveTCPAddr("tcp", b.cfg.Listen)
|
||||
}
|
||||
|
||||
func (b *baseTransporter) GetRemote() *lb.Node {
|
||||
return b.tCPRemotes.Next()
|
||||
}
|
||||
|
||||
func (b *baseTransporter) RelayTCPConn(c net.Conn, handshakeF TCPHandShakeF) error {
|
||||
remote := b.GetRemote()
|
||||
metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Inc()
|
||||
defer metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Dec()
|
||||
|
||||
clonedRemote := remote.Clone()
|
||||
rc, err := handshakeF(clonedRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.l.Infof("RelayTCPConn from %s to %s", c.LocalAddr(), remote.Address)
|
||||
relayConn := conn.NewRelayConn(
|
||||
b.cfg.Label, c, rc, conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
b.cmgr.AddConnection(relayConn)
|
||||
defer b.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
}
|
||||
@@ -1,42 +1,54 @@
|
||||
package transporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/cmgr"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/relay/conf"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
// RelayTransporter
|
||||
type RelayTransporter interface {
|
||||
dialRemote(remote *lb.Node) (net.Conn, error)
|
||||
HandleTCPConn(c net.Conn, remote *lb.Node) error
|
||||
GetRemote() *lb.Node
|
||||
type TCPHandShakeF func(remote *lb.Node) (net.Conn, error)
|
||||
|
||||
type RelayClient interface {
|
||||
TCPHandShake(remote *lb.Node) (net.Conn, error)
|
||||
RelayTCPConn(c net.Conn, handshakeF TCPHandShakeF) error
|
||||
}
|
||||
|
||||
func NewRelayTransporter(cfg *conf.Config, connMgr cmgr.Cmgr) RelayTransporter {
|
||||
tcpNodeList := make([]*lb.Node, len(cfg.TCPRemotes))
|
||||
for idx, addr := range cfg.TCPRemotes {
|
||||
tcpNodeList[idx] = &lb.Node{
|
||||
Address: addr,
|
||||
Label: fmt.Sprintf("%s-%s", cfg.Label, addr),
|
||||
}
|
||||
func NewRelayClient(relayType string, base *baseTransporter) (RelayClient, error) {
|
||||
switch relayType {
|
||||
case constant.RelayTypeRaw:
|
||||
return newRawClient(base)
|
||||
case constant.RelayTypeWS:
|
||||
return newWsClient(base)
|
||||
case constant.RelayTypeWSS:
|
||||
return newWssClient(base)
|
||||
case constant.RelayTypeMWSS:
|
||||
return newMwssClient(base)
|
||||
case constant.RelayTypeMTCP:
|
||||
return newMtcpClient(base)
|
||||
default:
|
||||
panic("unsupported transport type")
|
||||
}
|
||||
}
|
||||
|
||||
type RelayServer interface {
|
||||
ListenAndServe() error
|
||||
Close() error
|
||||
}
|
||||
|
||||
func NewRelayServer(relayType string, base *baseTransporter) (RelayServer, error) {
|
||||
switch relayType {
|
||||
case constant.RelayTypeRaw:
|
||||
return newRawServer(base)
|
||||
case constant.RelayTypeWS:
|
||||
return newWsServer(base)
|
||||
case constant.RelayTypeWSS:
|
||||
return newWssServer(base)
|
||||
case constant.RelayTypeMWSS:
|
||||
return newMwssServer(base)
|
||||
case constant.RelayTypeMTCP:
|
||||
return newMtcpServer(base)
|
||||
default:
|
||||
panic("unsupported transport type")
|
||||
}
|
||||
raw := newRawClient(cfg.Label, lb.NewRoundRobin(tcpNodeList), connMgr)
|
||||
switch cfg.TransportType {
|
||||
case constant.Transport_RAW:
|
||||
return raw
|
||||
case constant.Transport_WS:
|
||||
return newWsClient(raw)
|
||||
case constant.Transport_WSS:
|
||||
return newWSSClient(raw)
|
||||
case constant.Transport_MWSS:
|
||||
return newMWSSClient(raw)
|
||||
case constant.Transport_MTCP:
|
||||
return newMTCPClient(raw)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -136,3 +136,66 @@ func (tr *smuxTransporter) Dial(ctx context.Context, addr string) (conn net.Conn
|
||||
curSM.streamList = append(curSM.streamList, stream)
|
||||
return stream, nil
|
||||
}
|
||||
|
||||
type muxServer interface {
|
||||
ListenAndServe() error
|
||||
Accept() (net.Conn, error)
|
||||
Close() error
|
||||
mux(net.Conn)
|
||||
}
|
||||
|
||||
func newMuxServer(listenAddr string, l *zap.SugaredLogger) *muxServerImpl {
|
||||
return &muxServerImpl{
|
||||
errChan: make(chan error, 1),
|
||||
connChan: make(chan net.Conn, 1024),
|
||||
listenAddr: listenAddr,
|
||||
l: l,
|
||||
}
|
||||
}
|
||||
|
||||
type muxServerImpl struct {
|
||||
errChan chan error
|
||||
connChan chan net.Conn
|
||||
|
||||
listenAddr string
|
||||
l *zap.SugaredLogger
|
||||
}
|
||||
|
||||
func (s *muxServerImpl) Accept() (net.Conn, error) {
|
||||
select {
|
||||
case conn := <-s.connChan:
|
||||
return conn, nil
|
||||
case err := <-s.errChan:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (s *muxServerImpl) mux(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
cfg := smux.DefaultConfig()
|
||||
cfg.KeepAliveDisabled = true
|
||||
session, err := smux.Server(conn, cfg)
|
||||
if err != nil {
|
||||
s.l.Debugf("server err %s - %s : %s", conn.RemoteAddr(), s.listenAddr, err)
|
||||
return
|
||||
}
|
||||
defer session.Close() // nolint: errcheck
|
||||
|
||||
s.l.Debugf("session init %s %s", conn.RemoteAddr(), s.listenAddr)
|
||||
defer s.l.Debugf("session close %s >-< %s", conn.RemoteAddr(), s.listenAddr)
|
||||
|
||||
for {
|
||||
stream, err := session.AcceptStream()
|
||||
if err != nil {
|
||||
s.l.Errorf("accept stream err: %s", err)
|
||||
break
|
||||
}
|
||||
select {
|
||||
case s.connChan <- stream:
|
||||
default:
|
||||
stream.Close() // nolint: errcheck
|
||||
s.l.Infof("%s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,40 +5,33 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/cmgr"
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
var (
|
||||
_ RelayClient = &RawClient{}
|
||||
_ RelayServer = &RawServer{}
|
||||
)
|
||||
|
||||
type RawClient struct {
|
||||
relayLabel string
|
||||
cmgr cmgr.Cmgr
|
||||
tCPRemotes lb.RoundRobin
|
||||
l *zap.SugaredLogger
|
||||
*baseTransporter
|
||||
|
||||
dialer *net.Dialer
|
||||
}
|
||||
|
||||
func newRawClient(relayLabel string, tcpRemotes lb.RoundRobin, cmgr cmgr.Cmgr) *RawClient {
|
||||
func newRawClient(base *baseTransporter) (*RawClient, error) {
|
||||
r := &RawClient{
|
||||
cmgr: cmgr,
|
||||
relayLabel: relayLabel,
|
||||
tCPRemotes: tcpRemotes,
|
||||
l: zap.S().Named(relayLabel),
|
||||
baseTransporter: base,
|
||||
dialer: &net.Dialer{Timeout: constant.DialTimeOut},
|
||||
}
|
||||
return r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (raw *RawClient) GetRemote() *lb.Node {
|
||||
return raw.tCPRemotes.Next()
|
||||
}
|
||||
|
||||
func (raw *RawClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
func (raw *RawClient) TCPHandShake(remote *lb.Node) (net.Conn, error) {
|
||||
t1 := time.Now()
|
||||
d := net.Dialer{Timeout: constant.DialTimeOut}
|
||||
rc, err := d.Dial("tcp", remote.Address)
|
||||
rc, err := raw.dialer.Dial("tcp", remote.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -48,38 +41,32 @@ func (raw *RawClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
func (raw *RawClient) HandleTCPConn(c net.Conn, remote *lb.Node) error {
|
||||
metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Inc()
|
||||
defer metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Dec()
|
||||
|
||||
clonedRemote := remote.Clone()
|
||||
rc, err := raw.dialRemote(clonedRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
raw.l.Infof("HandleTCPConn from %s to %s", c.LocalAddr(), remote.Address)
|
||||
relayConn := conn.NewRelayConn(raw.relayLabel, c, rc, conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
raw.cmgr.AddConnection(relayConn)
|
||||
defer raw.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
}
|
||||
|
||||
type RawServer struct {
|
||||
rtp RelayTransporter
|
||||
lis *net.TCPListener
|
||||
l *zap.SugaredLogger
|
||||
*baseTransporter
|
||||
localTCPAddr *net.TCPAddr
|
||||
lis *net.TCPListener
|
||||
relayer RelayClient
|
||||
}
|
||||
|
||||
func NewRawServer(addr string, rtp RelayTransporter) (*RawServer, error) {
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
func newRawServer(base *baseTransporter) (*RawServer, error) {
|
||||
addr, err := base.GetTCPListenAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lis, err := net.ListenTCP("tcp", tcpAddr)
|
||||
lis, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RawServer{lis: lis, rtp: rtp}, nil
|
||||
relayer, err := NewRelayClient(base.cfg.TransportType, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RawServer{
|
||||
lis: lis,
|
||||
baseTransporter: base,
|
||||
localTCPAddr: addr,
|
||||
relayer: relayer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *RawServer) Close() error {
|
||||
@@ -93,13 +80,8 @@ func (s *RawServer) ListenAndServe() error {
|
||||
return err
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
remote := s.rtp.GetRemote()
|
||||
metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Inc()
|
||||
defer metrics.CurConnectionCount.WithLabelValues(remote.Label, metrics.METRIC_CONN_TYPE_TCP).Dec()
|
||||
if err := s.rtp.HandleTCPConn(c, remote); err != nil {
|
||||
s.l.Errorf("HandleTCPConn meet error tp:%s from:%s to:%s err:%s",
|
||||
s.rtp,
|
||||
c.RemoteAddr(), remote.Address, err)
|
||||
if err := s.RelayTCPConn(c, s.relayer.TCPHandShake); err != nil {
|
||||
s.l.Errorf("RelayTCPConn error: %s", err.Error())
|
||||
}
|
||||
}(c)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// nolint: errcheck
|
||||
package transporter
|
||||
|
||||
import (
|
||||
@@ -7,29 +6,32 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xtaci/smux"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
type MTCPClient struct {
|
||||
var (
|
||||
_ RelayClient = &MtcpClient{}
|
||||
_ RelayServer = &MtcpServer{}
|
||||
)
|
||||
|
||||
type MtcpClient struct {
|
||||
*RawClient
|
||||
dialer *net.Dialer
|
||||
mtp *smuxTransporter
|
||||
muxTP *smuxTransporter
|
||||
}
|
||||
|
||||
func newMTCPClient(raw *RawClient) *MTCPClient {
|
||||
dialer := &net.Dialer{Timeout: constant.DialTimeOut}
|
||||
c := &MTCPClient{dialer: dialer, RawClient: raw}
|
||||
mtp := NewSmuxTransporter(raw.l.Named("mtcp"), c.initNewSession)
|
||||
c.mtp = mtp
|
||||
return c
|
||||
func newMtcpClient(base *baseTransporter) (*MtcpClient, error) {
|
||||
raw, err := newRawClient(base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &MtcpClient{RawClient: raw}
|
||||
c.muxTP = NewSmuxTransporter(raw.l.Named("mtcp"), c.initNewSession)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *MTCPClient) initNewSession(ctx context.Context, addr string) (*smux.Session, error) {
|
||||
func (c *MtcpClient) initNewSession(ctx context.Context, addr string) (*smux.Session, error) {
|
||||
rc, err := c.dialer.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -45,9 +47,9 @@ func (c *MTCPClient) initNewSession(ctx context.Context, addr string) (*smux.Ses
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (s *MTCPClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
func (s *MtcpClient) TCPHandShake(remote *lb.Node) (net.Conn, error) {
|
||||
t1 := time.Now()
|
||||
mtcpc, err := s.mtp.Dial(context.TODO(), remote.Address)
|
||||
mtcpc, err := s.muxTP.Dial(context.TODO(), remote.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -57,87 +59,28 @@ func (s *MTCPClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
return mtcpc, nil
|
||||
}
|
||||
|
||||
func (s *MTCPClient) HandleTCPConn(c net.Conn, remote *lb.Node) error {
|
||||
clonedRemote := remote.Clone()
|
||||
mtcpc, err := s.dialRemote(clonedRemote)
|
||||
type MtcpServer struct {
|
||||
*RawServer
|
||||
*muxServerImpl
|
||||
}
|
||||
|
||||
func newMtcpServer(base *baseTransporter) (*MtcpServer, error) {
|
||||
raw, err := newRawServer(base)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
s.l.Infof("HandleTCPConn from:%s to:%s", c.LocalAddr(), remote.Address)
|
||||
relayConn := conn.NewRelayConn(s.relayLabel, c, mtcpc, conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
s.cmgr.AddConnection(relayConn)
|
||||
defer s.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
s := &MtcpServer{
|
||||
RawServer: raw,
|
||||
muxServerImpl: newMuxServer(base.cfg.Listen, base.l.Named("mtcp")),
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type MTCPServer struct {
|
||||
raw *RawClient
|
||||
listenAddr string
|
||||
listener net.Listener
|
||||
l *zap.SugaredLogger
|
||||
|
||||
errChan chan error
|
||||
connChan chan net.Conn
|
||||
}
|
||||
|
||||
func NewMTCPServer(listenAddr string, raw *RawClient, l *zap.SugaredLogger) *MTCPServer {
|
||||
return &MTCPServer{
|
||||
l: l,
|
||||
raw: raw,
|
||||
listenAddr: listenAddr,
|
||||
errChan: make(chan error, 1),
|
||||
connChan: make(chan net.Conn, 1024),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MTCPServer) mux(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
cfg := smux.DefaultConfig()
|
||||
cfg.KeepAliveDisabled = true
|
||||
session, err := smux.Server(conn, cfg)
|
||||
if err != nil {
|
||||
s.l.Debugf("server err %s - %s : %s", conn.RemoteAddr(), s.listenAddr, err)
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
s.l.Debugf("session init %s %s", conn.RemoteAddr(), s.listenAddr)
|
||||
defer s.l.Debugf("session close %s >-< %s", conn.RemoteAddr(), s.listenAddr)
|
||||
|
||||
for {
|
||||
stream, err := session.AcceptStream()
|
||||
if err != nil {
|
||||
s.l.Errorf("accept stream err: %s", err)
|
||||
break
|
||||
}
|
||||
select {
|
||||
case s.connChan <- stream:
|
||||
default:
|
||||
stream.Close()
|
||||
s.l.Infof("%s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MTCPServer) Accept() (conn net.Conn, err error) {
|
||||
select {
|
||||
case conn = <-s.connChan:
|
||||
case err = <-s.errChan:
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *MTCPServer) ListenAndServe() error {
|
||||
lis, err := net.Listen("tcp", s.listenAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.listener = lis
|
||||
|
||||
func (s *MtcpServer) ListenAndServe() error {
|
||||
go func() {
|
||||
for {
|
||||
c, err := lis.Accept()
|
||||
c, err := s.lis.Accept()
|
||||
if err != nil {
|
||||
s.errChan <- err
|
||||
continue
|
||||
@@ -152,14 +95,13 @@ func (s *MTCPServer) ListenAndServe() error {
|
||||
return e
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
remote := s.raw.GetRemote()
|
||||
if err := s.raw.HandleTCPConn(c, remote); err != nil {
|
||||
s.l.Errorf("HandleTCPConn meet error from:%s to:%s err:%s", c.RemoteAddr(), remote.Address, err)
|
||||
if err := s.RelayTCPConn(c, s.relayer.TCPHandShake); err != nil {
|
||||
s.l.Errorf("RelayTCPConn error: %s", err.Error())
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MTCPServer) Close() error {
|
||||
return s.listener.Close()
|
||||
func (s *MtcpServer) Close() error {
|
||||
return s.lis.Close()
|
||||
}
|
||||
|
||||
@@ -8,27 +8,35 @@ import (
|
||||
|
||||
"github.com/gobwas/ws"
|
||||
"github.com/labstack/echo/v4"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
"github.com/Ehco1996/ehco/internal/web"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
var (
|
||||
_ RelayClient = &WsClient{}
|
||||
_ RelayServer = &WsServer{}
|
||||
)
|
||||
|
||||
type WsClient struct {
|
||||
*RawClient
|
||||
*baseTransporter
|
||||
|
||||
dialer *ws.Dialer
|
||||
}
|
||||
|
||||
func newWsClient(raw *RawClient) *WsClient {
|
||||
return &WsClient{RawClient: raw}
|
||||
func newWsClient(base *baseTransporter) (*WsClient, error) {
|
||||
s := &WsClient{
|
||||
baseTransporter: base,
|
||||
dialer: &ws.Dialer{Timeout: constant.DialTimeOut},
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *WsClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
func (s *WsClient) TCPHandShake(remote *lb.Node) (net.Conn, error) {
|
||||
t1 := time.Now()
|
||||
d := ws.Dialer{Timeout: constant.DialTimeOut}
|
||||
wsc, _, _, err := d.Dial(context.TODO(), remote.Address+"/handshake/")
|
||||
wsc, _, _, err := s.dialer.Dial(context.TODO(), remote.Address+"/handshake/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -38,57 +46,51 @@ func (s *WsClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
return wsc, nil
|
||||
}
|
||||
|
||||
func (s *WsClient) HandleTCPConn(c net.Conn, remote *lb.Node) error {
|
||||
clonedRemote := remote.Clone()
|
||||
wsc, err := s.dialRemote(clonedRemote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.l.Infof("HandleTCPConn from %s to %s", c.LocalAddr(), remote.Address)
|
||||
relayConn := conn.NewRelayConn(
|
||||
s.relayLabel, c, wsc,
|
||||
conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
s.cmgr.AddConnection(relayConn)
|
||||
defer s.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
}
|
||||
type WsServer struct {
|
||||
*baseTransporter
|
||||
|
||||
type WSServer struct {
|
||||
raw *RawClient
|
||||
e *echo.Echo
|
||||
httpServer *http.Server
|
||||
l *zap.SugaredLogger
|
||||
relayer RelayClient
|
||||
}
|
||||
|
||||
func NewWSServer(listenAddr string, raw *RawClient, l *zap.SugaredLogger) *WSServer {
|
||||
s := &WSServer{
|
||||
l: l,
|
||||
raw: raw,
|
||||
httpServer: &http.Server{Addr: listenAddr, ReadHeaderTimeout: 30 * time.Second},
|
||||
func newWsServer(base *baseTransporter) (*WsServer, error) {
|
||||
localTCPAddr, err := base.GetTCPListenAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &WsServer{
|
||||
baseTransporter: base,
|
||||
httpServer: &http.Server{
|
||||
Addr: localTCPAddr.String(), ReadHeaderTimeout: 30 * time.Second,
|
||||
},
|
||||
}
|
||||
e := web.NewEchoServer()
|
||||
e.GET("/", echo.WrapHandler(web.MakeIndexF()))
|
||||
e.GET("/handshake/", echo.WrapHandler(http.HandlerFunc(s.HandleRequest)))
|
||||
s.e = e
|
||||
s.httpServer.Handler = e
|
||||
return s
|
||||
relayer, err := NewRelayClient(base.cfg.TransportType, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.relayer = relayer
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *WSServer) ListenAndServe() error {
|
||||
func (s *WsServer) ListenAndServe() error {
|
||||
return s.e.StartServer(s.httpServer)
|
||||
}
|
||||
|
||||
func (s *WSServer) Close() error {
|
||||
func (s *WsServer) Close() error {
|
||||
return s.e.Close()
|
||||
}
|
||||
|
||||
func (s *WSServer) HandleRequest(w http.ResponseWriter, req *http.Request) {
|
||||
func (s *WsServer) HandleRequest(w http.ResponseWriter, req *http.Request) {
|
||||
wsc, _, _, err := ws.UpgradeHTTP(req, w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
remote := s.raw.GetRemote()
|
||||
if err := s.raw.HandleTCPConn(wsc, remote); err != nil {
|
||||
s.l.Errorf("HandleTCPConn meet error from:%s to:%s err:%s", wsc.RemoteAddr(), remote.Address, err)
|
||||
if err := s.RelayTCPConn(wsc, s.relayer.TCPHandShake); err != nil {
|
||||
s.l.Errorf("RelayTCPConn error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,38 @@
|
||||
// nolint: errcheck
|
||||
package transporter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/gobwas/ws"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
mytls "github.com/Ehco1996/ehco/internal/tls"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
type WSSClient struct {
|
||||
WsClient
|
||||
var (
|
||||
_ RelayClient = &WssClient{}
|
||||
_ RelayServer = &WssServer{}
|
||||
)
|
||||
|
||||
type WssClient struct {
|
||||
*WsClient
|
||||
}
|
||||
|
||||
func newWSSClient(raw *RawClient) *WSSClient {
|
||||
return &WSSClient{*newWsClient(raw)}
|
||||
}
|
||||
|
||||
func (s *WSSClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
t1 := time.Now()
|
||||
d := ws.Dialer{TLSConfig: mytls.DefaultTLSConfig}
|
||||
wssc, _, _, err := d.Dial(context.TODO(), remote.Address+"/handshake/")
|
||||
func newWssClient(base *baseTransporter) (*WssClient, error) {
|
||||
wc, err := newWsClient(base)
|
||||
if err != nil {
|
||||
println("wss called", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
latency := time.Since(t1)
|
||||
metrics.HandShakeDuration.WithLabelValues(remote.Label).Observe(float64(latency.Milliseconds()))
|
||||
remote.HandShakeDuration = latency
|
||||
return wssc, nil
|
||||
// insert tls config
|
||||
wc.dialer.TLSConfig = mytls.DefaultTLSConfig
|
||||
return &WssClient{WsClient: wc}, nil
|
||||
}
|
||||
|
||||
func (s *WSSClient) HandleTCPConn(c net.Conn, remote *lb.Node) error {
|
||||
clonedRemote := remote.Clone()
|
||||
wssc, err := s.dialRemote(clonedRemote)
|
||||
type WssServer struct {
|
||||
*WsServer
|
||||
}
|
||||
|
||||
func newWssServer(base *baseTransporter) (*WssServer, error) {
|
||||
wsServer, err := newWsServer(base)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
s.l.Infof("HandleTCPConn from %s to %s", c.RemoteAddr(), remote.Address)
|
||||
|
||||
relayConn := conn.NewRelayConn(s.relayLabel, c, wssc, conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
s.cmgr.AddConnection(relayConn)
|
||||
defer s.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
}
|
||||
|
||||
type WSSServer struct{ WSServer }
|
||||
|
||||
func NewWSSServer(listenAddr string, raw *RawClient, l *zap.SugaredLogger) *WSSServer {
|
||||
wsServer := NewWSServer(listenAddr, raw, l)
|
||||
return &WSSServer{WSServer: *wsServer}
|
||||
}
|
||||
|
||||
func (s *WSSServer) ListenAndServe() error {
|
||||
s.httpServer.TLSConfig = mytls.DefaultTLSConfig
|
||||
return s.WSServer.ListenAndServe()
|
||||
// insert tls config
|
||||
wsServer.httpServer.TLSConfig = mytls.DefaultTLSConfig
|
||||
return &WssServer{WsServer: wsServer}, nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// nolint: errcheck
|
||||
package transporter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -11,31 +9,34 @@ import (
|
||||
"github.com/gobwas/ws"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/xtaci/smux"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/Ehco1996/ehco/internal/conn"
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
"github.com/Ehco1996/ehco/internal/metrics"
|
||||
mytls "github.com/Ehco1996/ehco/internal/tls"
|
||||
"github.com/Ehco1996/ehco/internal/web"
|
||||
"github.com/Ehco1996/ehco/pkg/lb"
|
||||
)
|
||||
|
||||
type MWSSClient struct {
|
||||
*RawClient
|
||||
dialer *ws.Dialer
|
||||
mtp *smuxTransporter
|
||||
var (
|
||||
_ RelayClient = &MwssClient{}
|
||||
_ RelayServer = &MwssServer{}
|
||||
_ muxServer = &MwssServer{}
|
||||
)
|
||||
|
||||
type MwssClient struct {
|
||||
*WssClient
|
||||
|
||||
muxTP *smuxTransporter
|
||||
}
|
||||
|
||||
func newMWSSClient(raw *RawClient) *MWSSClient {
|
||||
dialer := &ws.Dialer{TLSConfig: mytls.DefaultTLSConfig, Timeout: constant.DialTimeOut}
|
||||
c := &MWSSClient{dialer: dialer, RawClient: raw}
|
||||
mtp := NewSmuxTransporter(raw.l.Named("mwss"), c.initNewSession)
|
||||
c.mtp = mtp
|
||||
return c
|
||||
func newMwssClient(base *baseTransporter) (*MwssClient, error) {
|
||||
wc, err := newWssClient(base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &MwssClient{WssClient: wc}
|
||||
c.muxTP = NewSmuxTransporter(c.l.Named("mwss"), c.initNewSession)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *MWSSClient) initNewSession(ctx context.Context, addr string) (*smux.Session, error) {
|
||||
func (c *MwssClient) initNewSession(ctx context.Context, addr string) (*smux.Session, error) {
|
||||
rc, _, _, err := c.dialer.Dial(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,68 +52,39 @@ func (c *MWSSClient) initNewSession(ctx context.Context, addr string) (*smux.Ses
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (s *MWSSClient) dialRemote(remote *lb.Node) (net.Conn, error) {
|
||||
func (s *MwssClient) TCPHandShake(remote *lb.Node) (net.Conn, error) {
|
||||
t1 := time.Now()
|
||||
mwssc, err := s.mtp.Dial(context.TODO(), remote.Address+"/handshake/")
|
||||
mwssc, err := s.muxTP.Dial(context.TODO(), remote.Address+"/handshake/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
latency := time.Since(t1)
|
||||
metrics.HandShakeDuration.WithLabelValues(remote.Label).Observe(float64(latency.Milliseconds()))
|
||||
remote.HandShakeDuration = latency
|
||||
return mwssc, nil
|
||||
}
|
||||
|
||||
func (s *MWSSClient) HandleTCPConn(c net.Conn, remote *lb.Node) error {
|
||||
clonedRemote := remote.Clone()
|
||||
mwsc, err := s.dialRemote(clonedRemote)
|
||||
type MwssServer struct {
|
||||
*WssServer
|
||||
*muxServerImpl
|
||||
}
|
||||
|
||||
func newMwssServer(base *baseTransporter) (*MwssServer, error) {
|
||||
wssServer, err := newWssServer(base)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
s.l.Infof("HandleTCPConn from:%s to:%s", c.LocalAddr(), remote.Address)
|
||||
relayConn := conn.NewRelayConn(s.relayLabel, c, mwsc, conn.WithHandshakeDuration(clonedRemote.HandShakeDuration))
|
||||
s.cmgr.AddConnection(relayConn)
|
||||
defer s.cmgr.RemoveConnection(relayConn)
|
||||
return relayConn.Transport(remote.Label)
|
||||
s := &MwssServer{
|
||||
WssServer: wssServer,
|
||||
muxServerImpl: newMuxServer(base.cfg.Listen, base.l.Named("mwss")),
|
||||
}
|
||||
s.e.GET("/handshake/", echo.WrapHandler(http.HandlerFunc(s.HandleRequest)))
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type MWSSServer struct {
|
||||
raw *RawClient
|
||||
httpServer *http.Server
|
||||
l *zap.SugaredLogger
|
||||
|
||||
connChan chan net.Conn
|
||||
errChan chan error
|
||||
}
|
||||
|
||||
func NewMWSSServer(listenAddr string, raw *RawClient, l *zap.SugaredLogger) *MWSSServer {
|
||||
s := &MWSSServer{
|
||||
raw: raw,
|
||||
l: l,
|
||||
errChan: make(chan error, 1),
|
||||
connChan: make(chan net.Conn, 1024),
|
||||
}
|
||||
|
||||
e := web.NewEchoServer()
|
||||
e.GET("/", echo.WrapHandler(web.MakeIndexF()))
|
||||
e.GET("/handshake/", echo.WrapHandler(http.HandlerFunc(s.HandleRequest)))
|
||||
s.httpServer = &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: e,
|
||||
TLSConfig: mytls.DefaultTLSConfig,
|
||||
ReadHeaderTimeout: 30 * time.Second,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *MWSSServer) ListenAndServe() error {
|
||||
lis, err := net.Listen("tcp", s.httpServer.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (s *MwssServer) ListenAndServe() error {
|
||||
go func() {
|
||||
s.errChan <- s.httpServer.Serve(tls.NewListener(lis, s.httpServer.TLSConfig))
|
||||
s.errChan <- s.e.StartServer(s.httpServer)
|
||||
}()
|
||||
|
||||
for {
|
||||
@@ -121,15 +93,14 @@ func (s *MWSSServer) ListenAndServe() error {
|
||||
return e
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
remote := s.raw.GetRemote()
|
||||
if err := s.raw.HandleTCPConn(c, remote); err != nil {
|
||||
s.l.Errorf("HandleTCPConn meet error from:%s to:%s err:%s", c.RemoteAddr(), remote.Address, err)
|
||||
if err := s.RelayTCPConn(c, s.relayer.TCPHandShake); err != nil {
|
||||
s.l.Errorf("RelayTCPConn error: %s", err.Error())
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MWSSServer) HandleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *MwssServer) HandleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
conn, _, _, err := ws.UpgradeHTTP(r, w)
|
||||
if err != nil {
|
||||
s.l.Error(err)
|
||||
@@ -138,44 +109,6 @@ func (s *MWSSServer) HandleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
s.mux(conn)
|
||||
}
|
||||
|
||||
func (s *MWSSServer) mux(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
cfg := smux.DefaultConfig()
|
||||
cfg.KeepAliveDisabled = true
|
||||
session, err := smux.Server(conn, cfg)
|
||||
if err != nil {
|
||||
s.l.Debugf("server err %s - %s : %s", conn.RemoteAddr(), s.httpServer.Addr, err)
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
s.l.Debugf("session init %s %s", conn.RemoteAddr(), s.httpServer.Addr)
|
||||
defer s.l.Debugf("session close %s >-< %s", conn.RemoteAddr(), s.httpServer.Addr)
|
||||
|
||||
for {
|
||||
stream, err := session.AcceptStream()
|
||||
if err != nil {
|
||||
s.l.Errorf("accept stream err: %s", err)
|
||||
break
|
||||
}
|
||||
select {
|
||||
case s.connChan <- stream:
|
||||
default:
|
||||
stream.Close()
|
||||
s.l.Infof("%s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MWSSServer) Accept() (conn net.Conn, err error) {
|
||||
select {
|
||||
case conn = <-s.connChan:
|
||||
case err = <-s.errChan:
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *MWSSServer) Close() error {
|
||||
return s.httpServer.Close()
|
||||
func (s *MwssServer) Close() error {
|
||||
return s.e.Close()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package transporter
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"github.com/Ehco1996/ehco/internal/constant"
|
||||
@@ -133,8 +133,8 @@ func (p *Proxies) ToRelayConfig(listenHost string, listenPort string, newName st
|
||||
remoteAddr := net.JoinHostPort(p.Server, p.Port)
|
||||
r := &relay_cfg.Config{
|
||||
Label: newName,
|
||||
ListenType: constant.Listen_RAW,
|
||||
TransportType: constant.Transport_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
Listen: net.JoinHostPort(listenHost, listenPort),
|
||||
TCPRemotes: []string{remoteAddr},
|
||||
}
|
||||
|
||||
@@ -56,66 +56,66 @@ func init() {
|
||||
// raw cfg
|
||||
{
|
||||
Listen: RAW_LISTEN,
|
||||
ListenType: constant.Listen_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TCPRemotes: []string{ECHO_SERVER},
|
||||
UDPRemotes: []string{ECHO_SERVER},
|
||||
TransportType: constant.Transport_RAW,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
},
|
||||
|
||||
// ws
|
||||
{
|
||||
Listen: WS_LISTEN,
|
||||
ListenType: constant.Listen_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TCPRemotes: []string{WS_REMOTE},
|
||||
TransportType: constant.Transport_WS,
|
||||
TransportType: constant.RelayTypeWS,
|
||||
},
|
||||
{
|
||||
Listen: WS_SERVER,
|
||||
ListenType: constant.Listen_WS,
|
||||
ListenType: constant.RelayTypeWS,
|
||||
TCPRemotes: []string{ECHO_SERVER},
|
||||
TransportType: constant.Transport_RAW,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
},
|
||||
|
||||
// wss
|
||||
{
|
||||
Listen: WSS_LISTEN,
|
||||
ListenType: constant.Listen_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TCPRemotes: []string{WSS_REMOTE},
|
||||
TransportType: constant.Transport_WSS,
|
||||
TransportType: constant.RelayTypeWSS,
|
||||
},
|
||||
{
|
||||
Listen: WSS_SERVER,
|
||||
ListenType: constant.Listen_WSS,
|
||||
ListenType: constant.RelayTypeWSS,
|
||||
TCPRemotes: []string{ECHO_SERVER},
|
||||
TransportType: constant.Transport_RAW,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
},
|
||||
|
||||
// mwss
|
||||
{
|
||||
Listen: MWSS_LISTEN,
|
||||
ListenType: constant.Listen_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TCPRemotes: []string{MWSS_REMOTE},
|
||||
TransportType: constant.Transport_MWSS,
|
||||
TransportType: constant.RelayTypeMWSS,
|
||||
},
|
||||
{
|
||||
Listen: MWSS_SERVER,
|
||||
ListenType: constant.Listen_MWSS,
|
||||
ListenType: constant.RelayTypeMWSS,
|
||||
TCPRemotes: []string{ECHO_SERVER},
|
||||
TransportType: constant.Transport_RAW,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
},
|
||||
|
||||
// mtcp
|
||||
{
|
||||
Listen: MTCP_LISTEN,
|
||||
ListenType: constant.Listen_RAW,
|
||||
ListenType: constant.RelayTypeRaw,
|
||||
TCPRemotes: []string{MTCP_REMOTE},
|
||||
TransportType: constant.Transport_MTCP,
|
||||
TransportType: constant.RelayTypeMTCP,
|
||||
},
|
||||
{
|
||||
Listen: MTCP_SERVER,
|
||||
ListenType: constant.Listen_MTCP,
|
||||
ListenType: constant.RelayTypeMTCP,
|
||||
TCPRemotes: []string{ECHO_SERVER},
|
||||
TransportType: constant.Transport_RAW,
|
||||
TransportType: constant.RelayTypeRaw,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user