You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
2.3 KiB
Go

4 years ago
package proxy
import (
"bytes"
"io"
4 years ago
"os"
"strings"
"sync"
_log "github.com/sirupsen/logrus"
4 years ago
)
4 years ago
var NormalErrMsgs []string = []string{
"read: connection reset by peer",
"write: broken pipe",
"i/o timeout",
"net/http: TLS handshake timeout",
"io: read/write on closed pipe",
"connect: connection refused",
"connect: connection reset by peer",
}
// 仅打印预料之外的错误信息
func LogErr(log *_log.Entry, err error) (loged bool) {
msg := err.Error()
for _, str := range NormalErrMsgs {
if strings.Contains(msg, str) {
log.Debug(err)
return
}
}
log.Error(err)
loged = true
return
}
// 转发流量
// Read a => Write b
// Read b => Write a
4 years ago
func Transfer(log *_log.Entry, a, b io.ReadWriteCloser) {
4 years ago
done := make(chan struct{})
defer close(done)
4 years ago
forward := func(dst io.WriteCloser, src io.Reader, ec chan<- error) {
4 years ago
_, err := io.Copy(dst, src)
4 years ago
if err != nil {
select {
case <-done:
return
case ec <- err:
return
}
4 years ago
}
4 years ago
err = dst.Close()
4 years ago
select {
case <-done:
return
case ec <- err:
4 years ago
return
4 years ago
}
}
errChan := make(chan error)
go forward(a, b, errChan)
go forward(b, a, errChan)
for i := 0; i < 2; i++ {
if err := <-errChan; err != nil {
LogErr(log, err)
return // 如果有错误,直接返回
}
}
}
4 years ago
// 尝试将 Reader 读取至 buffer 中
4 years ago
// 如果未达到 limit则成功读取进入 buffer
// 否则 buffer 返回 nil且返回新 Reader状态为未读取前
4 years ago
func ReaderToBuffer(r io.Reader, limit int64) ([]byte, io.Reader, error) {
buf := bytes.NewBuffer(make([]byte, 0))
lr := io.LimitReader(r, limit)
_, err := io.Copy(buf, lr)
if err != nil {
return nil, nil, err
}
// 达到上限
if int64(buf.Len()) == limit {
// 返回新的 Reader
return nil, io.MultiReader(bytes.NewBuffer(buf.Bytes()), r), nil
}
// 返回 buffer
return buf.Bytes(), nil, nil
}
4 years ago
// Wireshark 解析 https 设置
var tlsKeyLogWriter io.Writer
var tlsKeyLogOnce sync.Once
func GetTlsKeyLogWriter() io.Writer {
tlsKeyLogOnce.Do(func() {
logfile := os.Getenv("SSLKEYLOGFILE")
if logfile == "" {
return
}
writer, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.WithField("in", "GetTlsKeyLogWriter").Debug(err)
return
}
tlsKeyLogWriter = writer
})
return tlsKeyLogWriter
}