-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
127 lines (111 loc) · 3.25 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package config
import (
"crypto/tls"
"errors"
"fmt"
"strings"
)
type Config struct {
Listen []ServerConfig `json:"listen,omitempty"` // supports http, socks5, grpc and h2 protocols
Transport []ServerConfig `json:"transport,omitempty"` // supports grpc, h2 and shadowsocks protocols
// NoProxy specifies a string that contains comma-separated values
// specifying hosts that should be excluded from proxying. Each value is
// represented by an IP address (1.2.3.4), an IP address in
// CIDR notation (1.2.3.4/8), a domain name, or a special DNS label (*).
// A domain name matches that name and all subdomains.
// A single asterisk (*) indicates that no proxying should be done.
// A best effort is made to parse the string and errors are ignored.
NoProxy string `json:"no_proxy,omitempty"`
}
const (
ProtoHTTP = "http"
ProtoSOCKS5 = "socks5"
ProtoGRPC = "grpc"
ProtoHTTP2 = "h2"
ProtoShadowsocks = "ss"
)
type ServerConfig struct {
Protocol string `json:"protocol,omitempty"`
Address string `json:"address,omitempty"`
// for TLS
CertPEM []string `json:"cert_pem,omitempty"`
KeyPEM []string `json:"key_pem,omitempty"`
CAPEM []string `json:"ca_pem,omitempty"`
// for h2
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
// for shadowsocks
Cipher string `json:"cipher,omitempty"`
Secret string `json:"secret,omitempty"`
}
func mergeLine(s []string) string {
return strings.Join(s, "\n")
}
func splitLine(s string) []string {
return strings.Split(strings.TrimSpace(s), "\n")
}
func (s ServerConfig) ClientTLS() (*tls.Config, error) {
if s.CertPEM == nil {
return nil, errors.New("no certificate")
}
cert := []byte(mergeLine(s.CertPEM))
if s.KeyPEM == nil {
return nil, errors.New("no key")
}
key := []byte(mergeLine(s.KeyPEM))
if s.CAPEM == nil {
return nil, errors.New("no CA")
}
ca := []byte(mergeLine(s.CAPEM))
return newClientTLSConfig(ca, cert, key)
}
func (s ServerConfig) ServerTLS() (*tls.Config, error) {
if s.CertPEM == nil {
return nil, errors.New("no certificate")
}
cert := []byte(mergeLine(s.CertPEM))
if s.KeyPEM == nil {
return nil, errors.New("no key")
}
key := []byte(mergeLine(s.KeyPEM))
if s.CAPEM == nil {
return nil, errors.New("no CA")
}
ca := []byte(mergeLine(s.CAPEM))
return newServerTLSConfig(ca, cert, key)
}
// Generate returns a pair of client and server configuration for the given host
func Generate(host string) (cli, srv Config, err error) {
cert, err := newCert(host)
if err != nil {
return
}
proxyPort := 57175
srv = Config{
Listen: []ServerConfig{
{
Address: fmt.Sprintf("0.0.0.0:%d", proxyPort),
Protocol: ProtoGRPC,
CAPEM: splitLine(string(cert.rootCert)),
CertPEM: splitLine(string(cert.serverCert)),
KeyPEM: splitLine(string(cert.serverKey)),
},
},
}
cli = Config{
Listen: []ServerConfig{
{Protocol: ProtoHTTP, Address: "127.0.0.1:8080"},
{Protocol: ProtoSOCKS5, Address: "127.0.0.1:1080"},
},
Transport: []ServerConfig{
{
Address: fmt.Sprintf("%s:%d", host, proxyPort),
Protocol: ProtoGRPC,
CAPEM: splitLine(string(cert.rootCert)),
CertPEM: splitLine(string(cert.clientCert)),
KeyPEM: splitLine(string(cert.clientKey)),
},
},
}
return cli, srv, nil
}