This repository has been archived by the owner on Mar 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 106
/
iics.go
308 lines (236 loc) · 8.39 KB
/
iics.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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
package v2ray_simple
import (
"bytes"
"math/rand"
"net"
"net/http"
"sync"
"github.com/e1732a364fed/v2ray_simple/httpLayer"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/tlsLayer"
"github.com/e1732a364fed/v2ray_simple/utils"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var iicsZapWriterPool = sync.Pool{
New: func() interface{} {
return &iicsZapWriter{
assignedFields: make([]zapcore.Field, 1, 4),
}
},
}
// 专用于 iics的结构
type iicsZapWriter struct {
ce *zapcore.CheckedEntry
assignedFields []zapcore.Field //始终保持 有且只有 一项
id uint32
}
func (zw *iicsZapWriter) setid(id uint32) {
zw.assignedFields[0] = zap.Uint32("connid", id)
zw.id = id
}
// 只能调用Write一次,调用之后,zw 便不再可用。
func (zw *iicsZapWriter) Write(fields ...zapcore.Field) {
if len(fields) > 0 {
realFields := append(zw.assignedFields, fields...)
zw.ce.Write(realFields...)
} else {
zw.ce.Write(zw.assignedFields...)
}
iicsZapWriterPool.Put(zw)
}
// 一个贯穿转发流程的关键结构,简称iics
type incomingInserverConnState struct {
id uint32 //十进制固定6位随机数, 用于标识每一个连接.
GlobalInfo *GlobalInfo
// 在多路复用的情况下, 可能产生多个 IncomingInserverConnState,
// 共用一个 baseLocalConn, 但是 wrappedConn 各不相同。
// 所以一般我们不使用 指针传递 iics.
baseLocalConn net.Conn // baseLocalConn 是来自客户端的原始传输层链接
wrappedConn net.Conn // wrappedConn 是层层握手后,代理层握手前 包装的链接,一般为tls层/高级层;
inServer proxy.Server //可为 nil
defaultClient proxy.Client
isInner bool
inTag string //在inServer为nil时,可用此项确定 inTag。比如tproxy就属于这种情况
useSniffing bool //在inServer为nil时,可用此项确定 是否使用sniffing
cachedRemoteAddr string
inServerTlsConn tlsLayer.Conn
inServerTlsRawReadRecorder *tlsLayer.Recorder
isFallbackH2 bool
fallbackRequestPath string
fallbackH2Request *http.Request
fallbackRW http.ResponseWriter
fallbackFirstBuffer *bytes.Buffer
fallbackXver int //若大于等于0,则证明该进项已经被确定需要进行fallback。
firstPayload []byte
udpFirstTarget netLayer.Addr
isTlsLazyServerEnd bool //比如 listen 是 tls + vless 这种情况
shouldCloseInSerBaseConnWhenFinish bool
routedToDirect bool
routingEnv *proxy.RoutingEnv //used in passToOutClient
heapObj *heapObj
}
type heapObj struct {
headerPass bool
wholeBuffer *bytes.Buffer
}
// 每个iics使用之前,必须调用 genID
func (iics *incomingInserverConnState) genID() {
const low = 100000
const hi = low*10 - 1
iics.id = uint32(low + rand.Intn(hi-low))
}
// 在调用 passToOutClient前遇到err时调用, 若找出了buf,设置iics,并返回true
func (iics *incomingInserverConnState) extractFirstBufFromErr(err error) bool {
var hasHeader = iics.inServer.HasHeader() != nil
var canFallback = iics.inServer.CanFallback() || hasHeader
if !canFallback {
if iics.wrappedConn != nil {
iics.wrappedConn.Close()
}
return false
}
//通过err找出 并赋值给 iics.theFallbackFirstBuffer
{
be, ok := err.(*utils.ErrBuffer)
if !ok {
if iics.heapObj != nil {
if iics.heapObj.headerPass && iics.heapObj.wholeBuffer != nil {
//http header通过了但是后面出错,有可能是类似 vmess+http 的情况,收到了一个正常的Get请求,后面的vmess读取不到数据导致了 read timeout,此时依然可以回落.
iics.fallbackFirstBuffer = iics.heapObj.wholeBuffer
iics.heapObj = nil
return true
}
}
// 能fallback 但是返回的 err却不是fallback err,证明遇到了更大问题,可能是底层read问题,所以也不用继续fallback了
if iics.wrappedConn != nil {
iics.wrappedConn.Close()
}
return false
}
if firstbuffer := be.Buf; firstbuffer == nil {
//不应该,至少能读到1字节的。
if ce := utils.CanLogErr("No FirstBuffer"); ce != nil {
ce.Write(
zap.Any("params", be.Buf),
)
}
panic("No FirstBuffer")
} else {
iics.fallbackFirstBuffer = firstbuffer
}
}
return true
}
// 查看当前配置 是否支持fallback, 并获得回落地址。
// 被 passToOutClient 调用. 若 无fallback则 result < 0, 否则返回所使用的 PROXY protocol 版本, 0 表示 回落但是不用 PROXY protocol.
//
// 本方法不会修改 iics的任何内容.
func (iics *incomingInserverConnState) checkfallback() (targetAddr netLayer.Addr, result int) {
//先检查 mainFallback,如果mainFallback中各项都不满足 or根本没有 mainFallback 再检查 defaultFallback
//一般情况下 iics.RoutingEnv 都会给出,但是 如果是 热加载、tproxy、go test、单独自定义 调用 ListenSer 不给出env 等情况的话, iics.RoutingEnv 都是空值
if iics.routingEnv != nil {
if mf := iics.routingEnv.Fallback; mf != nil {
var thisFallbackType byte
theRequestPath := iics.fallbackRequestPath
if iics.fallbackFirstBuffer != nil && theRequestPath == "" {
var failreason int
_, _, theRequestPath, _, failreason = httpLayer.ParseH1Request(iics.fallbackFirstBuffer.Bytes(), false)
if failreason != 0 {
theRequestPath = ""
}
}
fallback_params := make([]string, 0, 4)
if theRequestPath != "" {
fallback_params = append(fallback_params, theRequestPath)
thisFallbackType |= httpLayer.Fallback_path
}
if inServerTlsConn := iics.inServerTlsConn; inServerTlsConn != nil {
alpn := inServerTlsConn.GetAlpn()
if alpn != "" {
fallback_params = append(fallback_params, alpn)
thisFallbackType |= httpLayer.Fallback_alpn
}
//默认似乎默认tls不会给出sni项?获得的是空值,也许是因为我用了自签名+insecure,所以导致server并不会设置连接好后所协商的ServerName
sni := inServerTlsConn.GetSni()
if sni != "" {
fallback_params = append(fallback_params, sni)
thisFallbackType |= httpLayer.Fallback_sni
}
}
{
fromTag := iics.inServer.GetTag()
fbResult := mf.GetFallback(fromTag, thisFallbackType, fallback_params...)
if fbResult == nil {
fbResult = mf.GetFallback("", thisFallbackType, fallback_params...)
}
if ce := utils.CanLogDebug("Fallback to"); ce != nil {
if fbResult != nil {
ce.Write(
zap.String("addr", fbResult.Addr.String()),
zap.Any("params", fallback_params),
)
}
}
if fbResult != nil {
targetAddr = fbResult.Addr
result = fbResult.Xver
return
}
}
}
} //if iics.routingEnv != nil {
//默认回落, 每个listen配置 都 有一个自己独享的默认回落配置 (fallback = 80 这种)
if defaultFallbackAddr := iics.inServer.GetFallback(); defaultFallbackAddr != nil {
if ce := utils.CanLogDebug("Fallback to default setting"); ce != nil {
ce.Write(
zap.String("addr", defaultFallbackAddr.String()),
)
}
targetAddr = *defaultFallbackAddr
result = 0
} else {
result = -1
}
return
}
func (iics *incomingInserverConnState) CanLogInfo(msg string) *iicsZapWriter {
return iics.CanLogLevel(utils.Log_info, msg)
}
func (iics *incomingInserverConnState) CanLogErr(msg string) *iicsZapWriter {
return iics.CanLogLevel(utils.Log_error, msg)
}
func (iics *incomingInserverConnState) CanLogDebug(msg string) *iicsZapWriter {
return iics.CanLogLevel(utils.Log_debug, msg)
}
func (iics *incomingInserverConnState) CanLogWarn(msg string) *iicsZapWriter {
return iics.CanLogLevel(utils.Log_warning, msg)
}
func (iics *incomingInserverConnState) CanLogLevel(level int, msg string) *iicsZapWriter {
if iics.id == 0 {
iics.genID()
}
if ce := utils.CanLogLevel(level, msg); ce != nil {
zw := iicsZapWriterPool.Get().(*iicsZapWriter)
zw.ce = ce
if zw.id != iics.id {
zw.setid(iics.id)
}
return zw
} else {
return nil
}
}
func (iics *incomingInserverConnState) getRealRAddr() (raddr string) {
raddr = iics.cachedRemoteAddr
if iics.wrappedConn != nil {
if realRA := iics.wrappedConn.RemoteAddr(); realRA != nil {
//大部分情况下,realRA.String() == iics.cachedRemoteAddr
// 但是在 ws/grpc 下,我们的代码 会读取 X-Forwarded-For, 来试图找出反代之前的客户端真实ip
//此时 RemoteAddr就 不相等了
raddr = realRA.String()
}
}
return
}