-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.go
197 lines (169 loc) · 6.82 KB
/
common.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Package chained provides a chained proxy that can proxy any tcp traffic over
// any underlying transport through a remote proxy. The downstream (client) side
// of the chained setup is just a dial function. The upstream (server) side is
// just an http.Handler. The client tells the server where to connect using an
// HTTP CONNECT request.
package chained
import (
"strconv"
tls "github.com/refraction-networking/utls"
"google.golang.org/protobuf/proto"
"github.com/getlantern/common/config"
"github.com/getlantern/golog"
)
var log = golog.LoggerFor("chained")
// CopyConfigs makes a safe copy of the config to avoid any data corruption for other users of the config.
func CopyConfigs(proxies map[string]*config.ProxyConfig) map[string]*config.ProxyConfig {
proxiesCopy := make(map[string]*config.ProxyConfig)
for k, v := range proxies {
proxiesCopy[k] = CopyConfig(v)
}
return proxiesCopy
}
// CopyConfig makes a safe copy of the config to avoid any data corruption for other users of the config.
func CopyConfig(pc *config.ProxyConfig) *config.ProxyConfig {
return proto.Clone(pc).(*config.ProxyConfig)
}
func _setting(settings map[string]string, name string) string {
if settings == nil {
return ""
}
return settings[name]
}
func _settingInt(settings map[string]string, name string) int {
_val := _setting(settings, name)
if _val == "" {
return 0
}
val, err := strconv.Atoi(_val)
if err != nil {
log.Errorf("Setting %v: %v is not an int", name, _val)
return 0
}
return val
}
func _settingFloat(settings map[string]string, name string) float64 {
_val := _setting(settings, name)
if _val == "" {
return 0.0
}
val, err := strconv.ParseFloat(_val, 64)
if err != nil {
log.Errorf("Setting %v: %v is not a float", name, _val)
return 0.0
}
return val
}
func _settingBool(settings map[string]string, name string) bool {
_val := _setting(settings, name)
if _val == "" {
return false
}
val, err := strconv.ParseBool(_val)
if err != nil {
log.Errorf("Setting %v: %v is not a boolean", name, _val)
return false
}
return val
}
func ptSetting(pc *config.ProxyConfig, name string) string {
return _setting(pc.PluggableTransportSettings, name)
}
func ptSettingInt(pc *config.ProxyConfig, name string) int {
return _settingInt(pc.PluggableTransportSettings, name)
}
func ptSettingBool(pc *config.ProxyConfig, name string) bool {
return _settingBool(pc.PluggableTransportSettings, name)
}
func ptSettingFloat(pc *config.ProxyConfig, name string) float64 {
return _settingFloat(pc.PluggableTransportSettings, name)
}
func muxSetting(pc *config.ProxyConfig, name string) string {
return _setting(pc.MultiplexedSettings, name)
}
func muxSettingInt(pc *config.ProxyConfig, name string) int {
return _settingInt(pc.MultiplexedSettings, name)
}
func muxSettingBool(pc *config.ProxyConfig, name string) bool {
return _settingBool(pc.MultiplexedSettings, name)
}
func muxSettingFloat(pc *config.ProxyConfig, name string) float64 {
return _settingFloat(pc.MultiplexedSettings, name)
}
func desktopOrderedCipherSuites(pc *config.ProxyConfig) []uint16 {
return ciphersFromNames(pc.TLSDesktopOrderedCipherSuiteNames)
}
func mobileOrderedCipherSuites(pc *config.ProxyConfig) []uint16 {
return ciphersFromNames(pc.TLSMobileOrderedCipherSuiteNames)
}
func ciphersFromNames(cipherNames []string) []uint16 {
var ciphers []uint16
for _, cipherName := range cipherNames {
cipher, found := availableTLSCiphers[cipherName]
if !found {
log.Errorf("Unknown cipher: %v", cipherName)
continue
}
ciphers = append(ciphers, cipher)
}
return ciphers
}
func clientHelloID(pc *config.ProxyConfig) tls.ClientHelloID {
chid := availableClientHelloIDs[pc.TLSClientHelloID]
if chid.Client == "" {
chid = tls.HelloGolang
}
return chid
}
var availableTLSCiphers = map[string]uint16{
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
}
// helloBrowser is a special hello ID denoting that ClientHellos should be based on those used by
// the system default browser. This structure does not actually get passed to utls code. It is
// caught by tlsConfigForProxy and converted to tls.HelloCustom with a proper corresponding
// ClientHelloSpec.
var helloBrowser = tls.ClientHelloID{
Client: "Browser",
Version: "0",
}
var availableClientHelloIDs = map[string]tls.ClientHelloID{
"HelloGolang": tls.HelloGolang,
"HelloRandomized": tls.HelloRandomized,
"HelloRandomizedALPN": tls.HelloRandomizedALPN,
"HelloRandomizedNoALPN": tls.HelloRandomizedNoALPN,
"HelloFirefox_Auto": tls.HelloFirefox_Auto,
"HelloFirefox_55": tls.HelloFirefox_55,
"HelloFirefox_56": tls.HelloFirefox_56,
"HelloFirefox_105": tls.HelloFirefox_105,
"HelloChrome_Auto": tls.HelloChrome_Auto,
"HelloChrome_58": tls.HelloChrome_58,
"HelloChrome_62": tls.HelloChrome_62,
"HelloChrome_102": tls.HelloChrome_102,
"HelloChrome_106": tls.HelloChrome_106_Shuffle,
"HelloEdge_Auto": tls.HelloEdge_Auto,
"Hello360_Auto": tls.Hello360_Auto,
"HelloQQ_Auto": tls.HelloQQ_Auto,
"HelloQQ_11": tls.HelloQQ_11_1,
"HelloBrowser": helloBrowser,
}