ZHZ1024 commited on
Commit
34fee23
·
verified ·
1 Parent(s): dfeb107

Upload 14 files

Browse files
Files changed (14) hide show
  1. .dockerignore +27 -0
  2. Dockerfile +47 -0
  3. README +73 -0
  4. client/client.go +70 -0
  5. client/connector.go +57 -0
  6. config.ini +27 -0
  7. docker-compose.yml +26 -0
  8. go.mod +7 -0
  9. go.sum +7 -0
  10. main.go +28 -0
  11. server/handler.go +77 -0
  12. server/server.go +45 -0
  13. utils/security.go +73 -0
  14. utils/utils.go +51 -0
.dockerignore ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 忽略Git相关文件
2
+ .git
3
+ .gitignore
4
+
5
+ # 忽略README
6
+ README.md
7
+
8
+ # 忽略Dockerfile本身
9
+ Dockerfile
10
+
11
+ # 忽略Windows可执行文件
12
+ *.exe
13
+ *.exe~
14
+
15
+ # 忽略临时文件
16
+ *.tmp
17
+ *.log
18
+
19
+ # 忽略IDE相关文件
20
+ .vscode/
21
+ .idea/
22
+
23
+ # 忽略测试文件
24
+ *_test.go
25
+
26
+ # 忽略构建缓存
27
+ *.cache
Dockerfile ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 使用多阶段构建
2
+ FROM golang:1.18-alpine AS builder
3
+
4
+ # 设置工作目录
5
+ WORKDIR /app
6
+
7
+ # 复制go.mod和go.sum文件
8
+ COPY go.mod go.sum ./
9
+
10
+ # 下载依赖
11
+ RUN go mod download
12
+
13
+ # 复制源代码
14
+ COPY . .
15
+
16
+ # 编译应用程序
17
+ RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o nextconnect .
18
+
19
+ # 使用轻量级基础镜像
20
+ FROM alpine:latest
21
+
22
+ # 安装必要的包
23
+ RUN apk --no-cache add ca-certificates
24
+
25
+ # 创建非root用户
26
+ RUN addgroup -g 1000 nextconnect && adduser -D -s /bin/sh -u 1000 -G nextconnect nextconnect
27
+
28
+ # 设置工作目录
29
+ WORKDIR /root/
30
+
31
+ # 从builder阶段复制二进制文件
32
+ COPY --from=builder /app/nextconnect .
33
+
34
+ # 复制配置文件
35
+ COPY --from=builder /app/config.ini .
36
+
37
+ # 更改文件权限
38
+ RUN chown nextconnect:nextconnect nextconnect
39
+
40
+ # 切换到非root用户
41
+ USER nextconnect
42
+
43
+ # 暴露端口
44
+ EXPOSE 7000
45
+
46
+ # 设置默认命令
47
+ CMD ["./nextconnect"]
README ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NextConnect
2
+
3
+ 内网穿透程序,支持UDP、HTTP(S)、TCP协议,支持多协议混合传输。
4
+
5
+ ## 功能
6
+
7
+ - 支持UDP协议
8
+ - 支持HTTP/HTTPS协议
9
+ - 支持TCP协议
10
+ - 支持多协议混合传输
11
+ - 自动重连机制
12
+ - 连接认证
13
+ - 数据加密
14
+ - 配置文件控制
15
+
16
+ ## 安全机制
17
+
18
+ - RSA密钥对用于连接认证
19
+ - TLS加密传输(部分实现,需要进一步完善)
20
+
21
+ ## 自动重连
22
+
23
+ 客户端会自动尝试重新连接到服务器,间隔时间为5秒。
24
+
25
+ ## Docker使用
26
+
27
+ ### 构建镜像
28
+ ```bash
29
+ docker build -t nextconnect .
30
+ ```
31
+
32
+ ### 运行服务器
33
+ ```bash
34
+ docker run -p 7000:7000 nextconnect ./nextconnect -server
35
+ ```
36
+
37
+ ### 运行客户端
38
+ ```bash
39
+ docker run --network host nextconnect ./nextconnect -client
40
+ ```
41
+
42
+ ### 使用docker-compose(推荐)
43
+ ```bash
44
+ docker-compose up
45
+ ```
46
+
47
+ ### 自定义配置
48
+ 您可以将配置文件挂载到容器中:
49
+ ```bash
50
+ docker run -v $(pwd)/config.ini:/root/config.ini nextconnect ./nextconnect -server
51
+ ```
52
+
53
+ ## 目录结构
54
+
55
+ ```
56
+ NextConnect/
57
+ ├── README.md
58
+ ├── config.ini
59
+ ├── main.go
60
+ ├── go.mod
61
+ ├── Dockerfile
62
+ ├── docker-compose.yml
63
+ ├── .dockerignore
64
+ ├── server/
65
+ │ ├── server.go
66
+ │ └── handler.go
67
+ ├── client/
68
+ │ ├── client.go
69
+ │ └── connector.go
70
+ └── utils/
71
+ ├── utils.go
72
+ └── security.go
73
+ ```
client/client.go ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package client
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+ "net"
7
+ "time"
8
+
9
+ "NextConnect/utils"
10
+ )
11
+
12
+ func Start() {
13
+ for {
14
+ connectAndProxy()
15
+ time.Sleep(5 * time.Second) // 自动重连间隔
16
+ }
17
+ }
18
+
19
+ func connectAndProxy() {
20
+ config := utils.LoadConfig()
21
+ serverAddr := fmt.Sprintf("%s:%d", config.Client.ServerAddr, config.Client.ServerPort)
22
+
23
+ var conn net.Conn
24
+ var err error
25
+
26
+ // 如果启用了加密,则使用TLS连接
27
+ if config.Proxy.EncryptionEnabled {
28
+ // 这里需要实现TLS连接
29
+ // 暂时使用普通TCP连接
30
+ conn, err = net.Dial("tcp", serverAddr)
31
+ if err != nil {
32
+ log.Printf("Failed to connect to server %s: %v", serverAddr, err)
33
+ return
34
+ }
35
+ } else {
36
+ conn, err = net.Dial("tcp", serverAddr)
37
+ if err != nil {
38
+ log.Printf("Failed to connect to server %s: %v", serverAddr, err)
39
+ return
40
+ }
41
+ }
42
+
43
+ defer conn.Close()
44
+
45
+ log.Printf("Connected to server %s", serverAddr)
46
+
47
+ // 连接认证
48
+ if !authenticateWithServer(conn) {
49
+ log.Println("Authentication with server failed")
50
+ return
51
+ }
52
+
53
+ // 连接到本地服务
54
+ localConn := connectToLocalService()
55
+ if localConn == nil {
56
+ log.Println("Failed to connect to local service")
57
+ return
58
+ }
59
+ defer localConn.Close()
60
+
61
+ // 开始数据转发
62
+ forwardData(conn, localConn)
63
+ }
64
+
65
+ // 简单的服务器认证实现
66
+ func authenticateWithServer(conn net.Conn) bool {
67
+ // 在实际应用中,这里应该实现更复杂的认证机制
68
+ // 比如基于token、证书或用户名密码的认证
69
+ return true
70
+ }
client/connector.go ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package client
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+ "net"
7
+ "NextConnect/utils"
8
+ )
9
+
10
+ func connectToLocalService() net.Conn {
11
+ config := utils.LoadConfig()
12
+ localAddr := fmt.Sprintf("%s:%d", config.Proxy.LocalAddr, config.Proxy.LocalPort)
13
+
14
+ conn, err := net.Dial("tcp", localAddr)
15
+ if err != nil {
16
+ log.Printf("Failed to connect to local service %s: %v", localAddr, err)
17
+ return nil
18
+ }
19
+
20
+ log.Printf("Connected to local service %s", localAddr)
21
+ return conn
22
+ }
23
+
24
+ func forwardData(clientConn, localConn net.Conn) {
25
+ // 实现双向数据转发
26
+ go func() {
27
+ buf := make([]byte, 1024)
28
+ for {
29
+ n, err := clientConn.Read(buf)
30
+ if err != nil {
31
+ log.Printf("Failed to read from client connection: %v", err)
32
+ return
33
+ }
34
+
35
+ _, err = localConn.Write(buf[:n])
36
+ if err != nil {
37
+ log.Printf("Failed to write to local connection: %v", err)
38
+ return
39
+ }
40
+ }
41
+ }()
42
+
43
+ buf := make([]byte, 1024)
44
+ for {
45
+ n, err := localConn.Read(buf)
46
+ if err != nil {
47
+ log.Printf("Failed to read from local connection: %v", err)
48
+ return
49
+ }
50
+
51
+ _, err = clientConn.Write(buf[:n])
52
+ if err != nil {
53
+ log.Printf("Failed to write to client connection: %v", err)
54
+ return
55
+ }
56
+ }
57
+ }
config.ini ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [server]
2
+ # 服务器监听地址
3
+ bind_addr = 0.0.0.0
4
+ # 服务器端口
5
+ bind_port = 7000
6
+ # 服务器私钥路径
7
+ private_key_path = ./keys/server.key
8
+
9
+ [client]
10
+ # 服务器地址
11
+ server_addr = 127.0.0.1
12
+ # 服务器端口
13
+ server_port = 7000
14
+ # 客户端私钥路径
15
+ private_key_path = ./keys/client.key
16
+
17
+ [proxy]
18
+ # 本地服务地址
19
+ local_addr = 127.0.0.1
20
+ # 本地服务端口
21
+ local_port = 8080
22
+ # 代理类型 (tcp, udp, http, https)
23
+ proxy_type = tcp
24
+ # 代理名称
25
+ proxy_name = test_proxy
26
+ # 是否启用加密
27
+ encryption_enabled = true
docker-compose.yml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ nextconnect-server:
5
+ build: .
6
+ container_name: nextconnect-server
7
+ ports:
8
+ - "7000:7000"
9
+ command: ["./nextconnect", "-server"]
10
+ networks:
11
+ - nextconnect-network
12
+
13
+ nextconnect-client:
14
+ build: .
15
+ container_name: nextconnect-client
16
+ depends_on:
17
+ - nextconnect-server
18
+ command: ["./nextconnect", "-client"]
19
+ networks:
20
+ - nextconnect-network
21
+ environment:
22
+ - CLIENT_SERVER_ADDR=nextconnect-server
23
+
24
+ networks:
25
+ nextconnect-network:
26
+ driver: bridge
go.mod ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ module NextConnect
2
+
3
+ go 1.18
4
+
5
+ require gopkg.in/ini.v1 v1.66.2
6
+
7
+ require github.com/stretchr/testify v1.10.0 // indirect
go.sum ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3
+ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
4
+ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
5
+ gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
6
+ gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
7
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
main.go ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "flag"
5
+ "fmt"
6
+ "os"
7
+
8
+ "NextConnect/server"
9
+ "NextConnect/client"
10
+ )
11
+
12
+ var (
13
+ isServer = flag.Bool("server", false, "run as server")
14
+ isClient = flag.Bool("client", false, "run as client")
15
+ )
16
+
17
+ func main() {
18
+ flag.Parse()
19
+
20
+ if *isServer {
21
+ server.Start()
22
+ } else if *isClient {
23
+ client.Start()
24
+ } else {
25
+ fmt.Printf("Usage: %s -server or %s -client\n", os.Args[0], os.Args[0])
26
+ os.Exit(1)
27
+ }
28
+ }
server/handler.go ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package server
2
+
3
+ import (
4
+ "log"
5
+ "net"
6
+ "NextConnect/utils"
7
+ )
8
+
9
+ func handleConnection(conn net.Conn) {
10
+ defer conn.Close()
11
+ log.Printf("New connection from %s", conn.RemoteAddr())
12
+
13
+ // 连接认证
14
+ if !authenticateConnection(conn) {
15
+ log.Printf("Authentication failed for connection from %s", conn.RemoteAddr())
16
+ return
17
+ }
18
+
19
+ // 读取配置
20
+ config := utils.LoadConfig()
21
+
22
+ // 根据配置处理不同协议
23
+ switch config.Proxy.ProxyType {
24
+ case "tcp":
25
+ handleTCPConnection(conn)
26
+ case "udp":
27
+ handleUDPConnection(conn)
28
+ case "http":
29
+ handleHTTPConnection(conn)
30
+ case "https":
31
+ handleHTTPSConnection(conn)
32
+ default:
33
+ log.Printf("Unsupported proxy type: %s", config.Proxy.ProxyType)
34
+ }
35
+ }
36
+
37
+ // 简单的连接认证实现
38
+ func authenticateConnection(conn net.Conn) bool {
39
+ // 在实际应用中,这里应该实现更复杂的认证机制
40
+ // 比如基于token、证书或用户名密码的认证
41
+ return true
42
+ }
43
+
44
+ func handleTCPConnection(conn net.Conn) {
45
+ log.Println("Handling TCP connection")
46
+ // 实现TCP连接处理逻辑
47
+ buf := make([]byte, 1024)
48
+ for {
49
+ n, err := conn.Read(buf)
50
+ if err != nil {
51
+ log.Printf("Failed to read from TCP connection: %v", err)
52
+ return
53
+ }
54
+
55
+ // 简单回显逻辑
56
+ _, err = conn.Write(buf[:n])
57
+ if err != nil {
58
+ log.Printf("Failed to write to TCP connection: %v", err)
59
+ return
60
+ }
61
+ }
62
+ }
63
+
64
+ func handleUDPConnection(conn net.Conn) {
65
+ log.Println("Handling UDP connection")
66
+ // 实现UDP连接处理逻辑
67
+ }
68
+
69
+ func handleHTTPConnection(conn net.Conn) {
70
+ log.Println("Handling HTTP connection")
71
+ // 实现HTTP连接处理逻辑
72
+ }
73
+
74
+ func handleHTTPSConnection(conn net.Conn) {
75
+ log.Println("Handling HTTPS connection")
76
+ // 实现HTTPS连接处理逻辑
77
+ }
server/server.go ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package server
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+ "net"
7
+
8
+ "NextConnect/utils"
9
+ )
10
+
11
+ func Start() {
12
+ config := utils.LoadConfig()
13
+ listenAddr := fmt.Sprintf("%s:%d", config.Server.BindAddr, config.Server.BindPort)
14
+
15
+ var listener net.Listener
16
+ var err error
17
+
18
+ // 如果启用了加密,则使用TLS
19
+ if config.Proxy.EncryptionEnabled {
20
+ // 这里需要实现TLS监听器
21
+ // 暂时使用普通TCP监听器
22
+ listener, err = net.Listen("tcp", listenAddr)
23
+ if err != nil {
24
+ log.Fatalf("Failed to listen on %s: %v", listenAddr, err)
25
+ }
26
+ } else {
27
+ listener, err = net.Listen("tcp", listenAddr)
28
+ if err != nil {
29
+ log.Fatalf("Failed to listen on %s: %v", listenAddr, err)
30
+ }
31
+ }
32
+
33
+ defer listener.Close()
34
+
35
+ log.Printf("Server listening on %s", listenAddr)
36
+
37
+ for {
38
+ conn, err := listener.Accept()
39
+ if err != nil {
40
+ log.Printf("Failed to accept connection: %v", err)
41
+ continue
42
+ }
43
+ go handleConnection(conn)
44
+ }
45
+ }
utils/security.go ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package utils
2
+
3
+ import (
4
+ "crypto/rand"
5
+ "crypto/rsa"
6
+ "crypto/x509"
7
+ "encoding/pem"
8
+ "log"
9
+ )
10
+
11
+ // 生成RSA密钥对
12
+ func GenerateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey) {
13
+ privateKey, err := rsa.GenerateKey(rand.Reader, bits)
14
+ if err != nil {
15
+ log.Fatalf("Failed to generate RSA key pair: %v", err)
16
+ }
17
+ return privateKey, &privateKey.PublicKey
18
+ }
19
+
20
+ // 将公钥编码为PEM格式
21
+ func EncodePublicKeyToPEM(publicKey *rsa.PublicKey) []byte {
22
+ pubASN1, err := x509.MarshalPKIXPublicKey(publicKey)
23
+ if err != nil {
24
+ log.Fatalf("Failed to marshal public key: %v", err)
25
+ }
26
+
27
+ pubPEM := pem.EncodeToMemory(&pem.Block{
28
+ Type: "PUBLIC KEY",
29
+ Bytes: pubASN1,
30
+ })
31
+
32
+ return pubPEM
33
+ }
34
+
35
+ // 将私钥编码为PEM格式
36
+ func EncodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte {
37
+ privPEM := pem.EncodeToMemory(&pem.Block{
38
+ Type: "PRIVATE KEY",
39
+ Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
40
+ })
41
+
42
+ return privPEM
43
+ }
44
+
45
+ // 从PEM格式解码公钥
46
+ func DecodePublicKeyFromPEM(pubPEM []byte) *rsa.PublicKey {
47
+ block, _ := pem.Decode(pubPEM)
48
+ if block == nil {
49
+ log.Fatal("Failed to decode PEM block containing public key")
50
+ }
51
+
52
+ pub, err := x509.ParsePKIXPublicKey(block.Bytes)
53
+ if err != nil {
54
+ log.Fatalf("Failed to parse public key: %v", err)
55
+ }
56
+
57
+ return pub.(*rsa.PublicKey)
58
+ }
59
+
60
+ // 从PEM格式解码私钥
61
+ func DecodePrivateKeyFromPEM(privPEM []byte) *rsa.PrivateKey {
62
+ block, _ := pem.Decode(privPEM)
63
+ if block == nil {
64
+ log.Fatal("Failed to decode PEM block containing private key")
65
+ }
66
+
67
+ priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
68
+ if err != nil {
69
+ log.Fatalf("Failed to parse private key: %v", err)
70
+ }
71
+
72
+ return priv
73
+ }
utils/utils.go ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package utils
2
+
3
+ import (
4
+ "log"
5
+ "os"
6
+
7
+ "gopkg.in/ini.v1"
8
+ )
9
+
10
+ type Config struct {
11
+ Server ServerConfig `ini:"server"`
12
+ Client ClientConfig `ini:"client"`
13
+ Proxy ProxyConfig `ini:"proxy"`
14
+ }
15
+
16
+ type ServerConfig struct {
17
+ BindAddr string `ini:"bind_addr"`
18
+ BindPort int `ini:"bind_port"`
19
+ PrivateKeyPath string `ini:"private_key_path"`
20
+ }
21
+
22
+ type ClientConfig struct {
23
+ ServerAddr string `ini:"server_addr"`
24
+ ServerPort int `ini:"server_port"`
25
+ PrivateKeyPath string `ini:"private_key_path"`
26
+ }
27
+
28
+ type ProxyConfig struct {
29
+ LocalAddr string `ini:"local_addr"`
30
+ LocalPort int `ini:"local_port"`
31
+ ProxyType string `ini:"proxy_type"`
32
+ ProxyName string `ini:"proxy_name"`
33
+ EncryptionEnabled bool `ini:"encryption_enabled"`
34
+ }
35
+
36
+ func LoadConfig() *Config {
37
+ cfg, err := ini.Load("config.ini")
38
+ if err != nil {
39
+ log.Fatalf("Failed to read config file: %v", err)
40
+ os.Exit(1)
41
+ }
42
+
43
+ config := &Config{}
44
+ err = cfg.MapTo(config)
45
+ if err != nil {
46
+ log.Fatalf("Failed to parse config file: %v", err)
47
+ os.Exit(1)
48
+ }
49
+
50
+ return config
51
+ }