Support default dc idx from configs

This commit is contained in:
9seconds
2018-09-21 09:47:37 +03:00
parent 8268620615
commit 1e9bbfae55
24 changed files with 187 additions and 123 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ VENDOR_FILES := $(shell find "$(ROOT_DIR)/vendor" 2>/dev/null || echo -n "vendor
CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}") CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}")
APP_DEPS := version.go $(VENDOR_FILES) APP_DEPS := version.go $(VENDOR_FILES)
GOLANGCI_LINT_VERSION := v1.9.2 GOLANGCI_LINT_VERSION := v1.10.2
COMMON_BUILD_FLAGS := -ldflags="-s -w" COMMON_BUILD_FLAGS := -ldflags="-s -w"
+2 -2
View File
@@ -30,12 +30,12 @@ func DirectInit(ctx context.Context, cancel context.CancelFunc, socket net.Conn,
return nil, nil, errors.Annotate(err, "Cannot set write buffer size of client socket") return nil, nil, errors.Annotate(err, "Cannot set write buffer size of client socket")
} }
socket.SetReadDeadline(time.Now().Add(handshakeTimeout)) // nolint: errcheck socket.SetReadDeadline(time.Now().Add(handshakeTimeout)) // nolint: errcheck, gosec
frame, err := obfuscated2.ExtractFrame(socket) frame, err := obfuscated2.ExtractFrame(socket)
if err != nil { if err != nil {
return nil, nil, errors.Annotate(err, "Cannot extract frame") return nil, nil, errors.Annotate(err, "Cannot extract frame")
} }
socket.SetReadDeadline(time.Time{}) // nolint: errcheck socket.SetReadDeadline(time.Time{}) // nolint: errcheck, gosec
conn := wrappers.NewConn(ctx, cancel, socket, connID, wrappers.ConnPurposeClient, conf.PublicIPv4, conf.PublicIPv6) conn := wrappers.NewConn(ctx, cancel, socket, connID, wrappers.ConnPurposeClient, conf.PublicIPv4, conf.PublicIPv6)
obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame) obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame)
+1 -1
View File
@@ -227,6 +227,6 @@ func printURLs(data interface{}) {
} }
func usage(msg string) { func usage(msg string) {
io.WriteString(os.Stderr, msg+"\n") // nolint: errcheck io.WriteString(os.Stderr, msg+"\n") // nolint: errcheck, gosec
os.Exit(1) os.Exit(1)
} }
+4 -4
View File
@@ -12,10 +12,10 @@ func (r *HandshakeRequest) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(len(TagHandshake) + len(HandshakeFlags) + len(HandshakeSenderPID) + len(HandshakePeerPID)) buf.Grow(len(TagHandshake) + len(HandshakeFlags) + len(HandshakeSenderPID) + len(HandshakePeerPID))
buf.Write(TagHandshake) buf.Write(TagHandshake) // nolint: gosec
buf.Write(HandshakeFlags) buf.Write(HandshakeFlags) // nolint: gosec
buf.Write(HandshakeSenderPID) buf.Write(HandshakeSenderPID) // nolint: gosec
buf.Write(HandshakePeerPID) buf.Write(HandshakePeerPID) // nolint: gosec
return buf.Bytes() return buf.Bytes()
} }
+4 -4
View File
@@ -19,10 +19,10 @@ type HandshakeResponse struct {
func (r *HandshakeResponse) Bytes() []byte { func (r *HandshakeResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Write(r.Type) buf.Write(r.Type) // nolint: gosec
buf.Write(r.Flags) buf.Write(r.Flags) // nolint: gosec
buf.Write(r.SenderPID) buf.Write(r.SenderPID) // nolint: gosec
buf.Write(r.PeerPID) buf.Write(r.PeerPID) // nolint: gosec
return buf.Bytes() return buf.Bytes()
} }
+5 -5
View File
@@ -21,11 +21,11 @@ type NonceRequest struct {
func (r *NonceRequest) Bytes() []byte { func (r *NonceRequest) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Write(TagNonce) buf.Write(TagNonce) // nolint: gosec
buf.Write(r.KeySelector) buf.Write(r.KeySelector) // nolint: gosec
buf.Write(NonceCryptoAES) buf.Write(NonceCryptoAES) // nolint: gosec
buf.Write(r.CryptoTS) buf.Write(r.CryptoTS) // nolint: gosec
buf.Write(r.Nonce) buf.Write(r.Nonce) // nolint: gosec
return buf.Bytes() return buf.Bytes()
} }
+5 -5
View File
@@ -18,11 +18,11 @@ type NonceResponse struct {
func (r *NonceResponse) Bytes() []byte { func (r *NonceResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Write(r.Type) buf.Write(r.Type) // nolint: gosec
buf.Write(r.KeySelector) buf.Write(r.KeySelector) // nolint: gosec
buf.Write(r.Crypto) buf.Write(r.Crypto) // nolint: gosec
buf.Write(r.CryptoTS) buf.Write(r.CryptoTS) // nolint: gosec
buf.Write(r.Nonce) buf.Write(r.Nonce) // nolint: gosec
return buf.Bytes() return buf.Bytes()
} }
+10 -10
View File
@@ -49,16 +49,16 @@ func (r *ProxyRequest) MakeHeader(message []byte) (*bytes.Buffer, fmt.Stringer)
flags |= proxyRequestFlagsEncrypted flags |= proxyRequestFlagsEncrypted
} }
buf.Write(TagProxyRequest) buf.Write(TagProxyRequest) // nolint: gosec
buf.Write(flags.Bytes()) buf.Write(flags.Bytes()) // nolint: gosec
buf.Write(r.ConnectionID) buf.Write(r.ConnectionID) // nolint: gosec
buf.Write(r.ClientIPPort) buf.Write(r.ClientIPPort) // nolint: gosec
buf.Write(r.OurIPPort) buf.Write(r.OurIPPort) // nolint: gosec
buf.Write(ProxyRequestExtraSize) buf.Write(ProxyRequestExtraSize) // nolint: gosec
buf.Write(ProxyRequestProxyTag) buf.Write(ProxyRequestProxyTag) // nolint: gosec
buf.WriteByte(byte(len(r.ADTag))) buf.WriteByte(byte(len(r.ADTag))) // nolint: gosec
buf.Write(r.ADTag) buf.Write(r.ADTag) // nolint: gosec
buf.Write(make([]byte, (4-buf.Len()%4)%4)) buf.Write(make([]byte, (4-buf.Len()%4)%4)) // nolint: gosec
return buf, flags return buf, flags
} }
+1 -1
View File
@@ -113,7 +113,7 @@ func generateFrame(connectionType mtproto.ConnectionType) Frame {
} }
// error has to be checked before calling this function // error has to be checked before calling this function
tag, _ := connectionType.Tag() // nolint: errcheck tag, _ := connectionType.Tag() // nolint: errcheck, gosec
copy(frame.Magic(), tag) copy(frame.Magic(), tag)
return frame return frame
+5 -5
View File
@@ -23,14 +23,14 @@ type Obfuscated2 struct {
// Beware, link above is in russian. // Beware, link above is in russian.
func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) { func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) {
decHasher := sha256.New() decHasher := sha256.New()
decHasher.Write(frame.Key()) // nolint: errcheck decHasher.Write(frame.Key()) // nolint: errcheck, gosec
decHasher.Write(secret) // nolint: errcheck decHasher.Write(secret) // nolint: errcheck, gosec
decryptor := makeStreamCipher(decHasher.Sum(nil), frame.IV()) decryptor := makeStreamCipher(decHasher.Sum(nil), frame.IV())
invertedFrame := frame.Invert() invertedFrame := frame.Invert()
encHasher := sha256.New() encHasher := sha256.New()
encHasher.Write(invertedFrame.Key()) // nolint: errcheck encHasher.Write(invertedFrame.Key()) // nolint: errcheck, gosec
encHasher.Write(secret) // nolint: errcheck encHasher.Write(secret) // nolint: errcheck, gosec
encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV()) encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV())
decryptedFrame := make(Frame, FrameLen) decryptedFrame := make(Frame, FrameLen)
@@ -76,6 +76,6 @@ func MakeTelegramObfuscated2Frame(opts *mtproto.ConnectionOpts) (*Obfuscated2, F
} }
func makeStreamCipher(key, iv []byte) cipher.Stream { func makeStreamCipher(key, iv []byte) cipher.Stream {
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(key) // nolint: gosec
return cipher.NewCTR(block, iv) return cipher.NewCTR(block, iv)
} }
+4 -4
View File
@@ -47,8 +47,8 @@ func TestObfs2Full(t *testing.T) {
clientFrame := generateFrame(mtproto.ConnectionTypeIntermediate) clientFrame := generateFrame(mtproto.ConnectionTypeIntermediate)
clientHasher := sha256.New() clientHasher := sha256.New()
clientHasher.Write(clientFrame.Key()) // nolint: errcheck clientHasher.Write(clientFrame.Key()) // nolint: errcheck, gosec
clientHasher.Write(secret) // nolint: errcheck clientHasher.Write(secret) // nolint: errcheck, gosec
clientKey := clientHasher.Sum(nil) clientKey := clientHasher.Sum(nil)
encryptor := makeStreamCipher(clientKey, clientFrame.IV()) encryptor := makeStreamCipher(clientKey, clientFrame.IV())
@@ -58,8 +58,8 @@ func TestObfs2Full(t *testing.T) {
invertedClientFrame := clientFrame.Invert() invertedClientFrame := clientFrame.Invert()
clientHasher = sha256.New() clientHasher = sha256.New()
clientHasher.Write(invertedClientFrame.Key()) // nolint: errcheck clientHasher.Write(invertedClientFrame.Key()) // nolint: errcheck, gosec
clientHasher.Write(secret) // nolint: errcheck clientHasher.Write(secret) // nolint: errcheck, gosec
invertedClientKey := clientHasher.Sum(nil) invertedClientKey := clientHasher.Sum(nil)
clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV()) clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV())
+7 -7
View File
@@ -48,7 +48,7 @@ func (p *Proxy) accept(conn net.Conn) {
defer func() { defer func() {
cancel() cancel()
conn.Close() // nolint: errcheck conn.Close() // nolint: errcheck, gosec
if err := recover(); err != nil { if err := recover(); err != nil {
stats.NewCrash() stats.NewCrash()
@@ -77,8 +77,8 @@ func (p *Proxy) accept(conn net.Conn) {
go func() { go func() {
<-ctx.Done() <-ctx.Done()
serverConn.(io.Closer).Close() serverConn.(io.Closer).Close() // nolint: gosec
clientConn.(io.Closer).Close() clientConn.(io.Closer).Close() // nolint: gosec
}() }()
wait := &sync.WaitGroup{} wait := &sync.WaitGroup{}
@@ -119,8 +119,8 @@ func (p *Proxy) getTelegramConn(ctx context.Context, cancel context.CancelFunc,
func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst io.WriteCloser, func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst io.WriteCloser,
wait *sync.WaitGroup, hacks *mtproto.Hacks) { wait *sync.WaitGroup, hacks *mtproto.Hacks) {
defer func() { defer func() {
src.Close() // nolint: errcheck src.Close() // nolint: errcheck, gosec
dst.Close() // nolint: errcheck dst.Close() // nolint: errcheck, gosec
wait.Done() wait.Done()
}() }()
@@ -143,8 +143,8 @@ func (p *Proxy) middlePipe(src wrappers.PacketReadCloser, dst io.WriteCloser,
func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst io.WriteCloser, func (p *Proxy) directPipe(src wrappers.StreamReadCloser, dst io.WriteCloser,
wait *sync.WaitGroup, bufferSize int) { wait *sync.WaitGroup, bufferSize int) {
defer func() { defer func() {
src.Close() // nolint: errcheck src.Close() // nolint: errcheck, gosec
dst.Close() // nolint: errcheck dst.Close() // nolint: errcheck, gosec
wait.Done() wait.Done()
}() }()
+1 -1
View File
@@ -49,7 +49,7 @@ func Start(conf *config.Config) error {
} }
interm := map[string]interface{}{} interm := map[string]interface{}{}
json.Unmarshal(first, &interm) // nolint: errcheck json.Unmarshal(first, &interm) // nolint: errcheck, gosec
encoder := json.NewEncoder(w) encoder := json.NewEncoder(w)
encoder.SetEscapeHTML(false) encoder.SetEscapeHTML(false)
+9 -2
View File
@@ -12,6 +12,11 @@ import (
"github.com/9seconds/mtg/wrappers" "github.com/9seconds/mtg/wrappers"
) )
const (
directV4DefaultIdx = 1
directV6DefaultIdx = 1
)
var ( var (
directV4Addresses = map[int16][]string{ directV4Addresses = map[int16][]string{
0: {"149.154.175.50:443"}, 0: {"149.154.175.50:443"},
@@ -65,8 +70,10 @@ func NewDirectTelegram(conf *config.Config) Telegram {
Dialer: net.Dialer{Timeout: telegramDialTimeout}, Dialer: net.Dialer{Timeout: telegramDialTimeout},
conf: conf, conf: conf,
}, },
v4Addresses: directV4Addresses, v4DefaultIdx: directV4DefaultIdx,
v6Addresses: directV6Addresses, v6DefaultIdx: directV6DefaultIdx,
v4Addresses: directV4Addresses,
v6Addresses: directV6Addresses,
}, },
} }
} }
+66 -29
View File
@@ -65,18 +65,20 @@ func (t *middleTelegramCaller) update() error {
return errors.Annotate(err, "Cannot get proxy secret") return errors.Annotate(err, "Cannot get proxy secret")
} }
v4Addresses, err := t.getTelegramAddresses(tgAddrProxyV4) v4Addresses, v4DefaultIdx, err := t.getTelegramAddresses(tgAddrProxyV4)
if err != nil { if err != nil {
return errors.Annotate(err, "Cannot get ipv4 addresses") return errors.Annotate(err, "Cannot get ipv4 addresses")
} }
v6Addresses, err := t.getTelegramAddresses(tgAddrProxyV6) v6Addresses, v6DefaultIdx, err := t.getTelegramAddresses(tgAddrProxyV6)
if err != nil { if err != nil {
return errors.Annotate(err, "Cannot get ipv6 addresses") return errors.Annotate(err, "Cannot get ipv6 addresses")
} }
t.dialerMutex.Lock() t.dialerMutex.Lock()
t.proxySecret = secret t.proxySecret = secret
t.v4DefaultIdx = v4DefaultIdx
t.v6DefaultIdx = v6DefaultIdx
t.v4Addresses = v4Addresses t.v4Addresses = v4Addresses
t.v6Addresses = v6Addresses t.v6Addresses = v6Addresses
t.dialerMutex.Unlock() t.dialerMutex.Unlock()
@@ -101,52 +103,87 @@ func (t *middleTelegramCaller) getTelegramProxySecret() ([]byte, error) {
return secret, nil return secret, nil
} }
func (t *middleTelegramCaller) getTelegramAddresses(url string) (map[int16][]string, error) { func (t *middleTelegramCaller) getTelegramAddresses(url string) (map[int16][]string, int16, error) { // nolint: gocyclo
resp, err := t.call(url) resp, err := t.call(url)
if err != nil { if err != nil {
return nil, errors.Annotate(err, "Cannot access telegram server") return nil, 0, errors.Annotate(err, "Cannot access telegram server")
} }
defer resp.Body.Close() // nolint: errcheck defer resp.Body.Close() // nolint: errcheck
scanner := bufio.NewScanner(resp.Body) scanner := bufio.NewScanner(resp.Body)
data := map[int16][]string{} data := map[int16][]string{}
var defaultIdx int16 = 1
for scanner.Scan() { for scanner.Scan() {
text := strings.TrimSpace(scanner.Text()) text := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(text, "#") { switch {
case strings.HasPrefix(text, "#"):
continue continue
} case strings.HasPrefix(text, "proxy_for"):
addr, idx, err2 := t.parseProxyFor(text)
chunks := middleTelegramProxyConfigSplitter.Split(text, 3) if err2 != nil {
if len(chunks) != 3 || chunks[0] != "proxy_for" { return nil, 0, errors.Annotate(err2, "Cannot parse 'proxy_for' section")
return nil, errors.Errorf("Incorrect config '%s'", text) }
} if addresses, ok := data[idx]; ok {
dcIdx64, err2 := strconv.ParseInt(chunks[1], 10, 16) data[idx] = append(addresses, addr)
if err2 != nil { } else {
return nil, errors.Errorf("Incorrect config '%s'", text) data[idx] = []string{addr}
} }
dcIdx := int16(dcIdx64) case strings.HasPrefix(text, "default"):
idx, err2 := t.parseDefault(text)
addr := strings.TrimRight(chunks[2], ";") if err2 != nil {
if _, _, err2 = net.SplitHostPort(addr); err != nil { return nil, 0, errors.Annotate(err2, "Cannot parse 'default' section")
return nil, errors.Annotatef(err2, "Incorrect config '%s'", text) }
} defaultIdx = idx
default:
if addresses, ok := data[dcIdx]; ok { return nil, 0, errors.Errorf("Unknown config string '%s'", text)
data[dcIdx] = append(addresses, addr)
} else {
data[dcIdx] = []string{addr}
} }
} }
err = scanner.Err() err = scanner.Err()
if err != nil { if err != nil {
return nil, errors.Annotate(err, "Cannot read response from the telegram") return nil, 0, errors.Annotate(err, "Cannot read response from the telegram")
} }
return data, nil return data, defaultIdx, nil
}
func (t *middleTelegramCaller) parseProxyFor(text string) (string, int16, error) {
chunks := middleTelegramProxyConfigSplitter.Split(text, 3)
if len(chunks) != 3 || chunks[0] != "proxy_for" {
return "", 0, errors.Errorf("Incorrect config '%s'", text)
}
dcIdx, err := strconv.ParseInt(chunks[1], 10, 16)
if err != nil {
return "", 0, errors.Annotatef(err, "Incorrect config '%s'", text)
}
addr := strings.TrimRight(chunks[2], ";")
if _, _, err = net.SplitHostPort(addr); err != nil {
return "", 0, errors.Annotatef(err, "Incorrect config '%s'", text)
}
return addr, int16(dcIdx), nil
}
func (t *middleTelegramCaller) parseDefault(text string) (int16, error) {
chunks := middleTelegramProxyConfigSplitter.Split(text, 2)
if len(chunks) != 2 || chunks[0] != "default" {
return 0, errors.Errorf("Incorrect config '%s'", text)
}
dcIdxString := strings.TrimRight(chunks[1], ";")
dcIdx, err := strconv.ParseInt(dcIdxString, 10, 16)
if err != nil {
return 0, errors.Annotatef(err, "Incorrect config '%s'", text)
}
return int16(dcIdx), nil
} }
func (t *middleTelegramCaller) call(url string) (*http.Response, error) { func (t *middleTelegramCaller) call(url string) (*http.Response, error) {
req, _ := http.NewRequest("GET", url, nil) req, _ := http.NewRequest("GET", url, nil) // nolint: gosec
req.Header.Set("Accept", "text/plain") req.Header.Set("Accept", "text/plain")
req.Header.Set("User-Agent", tgUserAgent) req.Header.Set("User-Agent", tgUserAgent)
+26 -6
View File
@@ -19,8 +19,10 @@ type Telegram interface {
type baseTelegram struct { type baseTelegram struct {
dialer tgDialer dialer tgDialer
v4Addresses map[int16][]string v4DefaultIdx int16
v6Addresses map[int16][]string v6DefaultIdx int16
v4Addresses map[int16][]string
v6Addresses map[int16][]string
} }
func (b *baseTelegram) dial(ctx context.Context, cancel context.CancelFunc, dcIdx int16, connID string, func (b *baseTelegram) dial(ctx context.Context, cancel context.CancelFunc, dcIdx int16, connID string,
@@ -28,13 +30,13 @@ func (b *baseTelegram) dial(ctx context.Context, cancel context.CancelFunc, dcId
addrs := make([]string, 2) addrs := make([]string, 2)
if proto&mtproto.ConnectionProtocolIPv6 != 0 { if proto&mtproto.ConnectionProtocolIPv6 != 0 {
if addr, ok := b.v6Addresses[dcIdx]; ok && len(addr) > 0 { if addr := b.chooseAddress(b.v6Addresses, dcIdx, b.v6DefaultIdx); addr != "" {
addrs = append(addrs, addr[rand.Intn(len(addr))]) addrs = append(addrs, addr)
} }
} }
if proto&mtproto.ConnectionProtocolIPv4 != 0 { if proto&mtproto.ConnectionProtocolIPv4 != 0 {
if addr, ok := b.v4Addresses[dcIdx]; ok && len(addr) > 0 { if addr := b.chooseAddress(b.v4Addresses, dcIdx, b.v4DefaultIdx); addr != "" {
addrs = append(addrs, addr[rand.Intn(len(addr))]) addrs = append(addrs, addr)
} }
} }
@@ -46,3 +48,21 @@ func (b *baseTelegram) dial(ctx context.Context, cancel context.CancelFunc, dcId
return nil, errors.New("Cannot connect to Telegram") return nil, errors.New("Cannot connect to Telegram")
} }
func (b *baseTelegram) chooseAddress(addresses map[int16][]string, idx, defaultIdx int16) string {
if addr, ok := addresses[idx]; ok {
return b.chooseRandomAddress(addr)
} else if addr, ok := addresses[defaultIdx]; ok {
return b.chooseRandomAddress(addr)
}
return ""
}
func (b *baseTelegram) chooseRandomAddress(addresses []string) string {
if len(addresses) > 0 {
return addresses[rand.Intn(len(addresses))]
}
return ""
}
+1 -1
View File
@@ -40,7 +40,7 @@ func (b *BlockCipher) Read(p []byte) (int, error) {
} }
b.decryptor.CryptBlocks(buf, buf) b.decryptor.CryptBlocks(buf, buf)
b.buf.Write(buf) b.buf.Write(buf) // nolint: gosec
return b.flush(p) return b.flush(p)
} }
+3 -3
View File
@@ -99,15 +99,15 @@ func (c *Conn) doIO(callback ioFunc, p []byte, timeout time.Duration) (int, erro
case res := <-resChan: case res := <-resChan:
timer.Stop() timer.Stop()
if res.err != nil { if res.err != nil {
c.Close() c.Close() // nolint: gosec
} }
return res.n, res.err return res.n, res.err
case <-c.ctx.Done(): case <-c.ctx.Done():
timer.Stop() timer.Stop()
c.Close() c.Close() // nolint: gosec
return 0, errors.Annotate(c.ctx.Err(), "Cannot do IO because context is closed") return 0, errors.Annotate(c.ctx.Err(), "Cannot do IO because context is closed")
case <-timer.C: case <-timer.C:
c.Close() c.Close() // nolint: gosec
return 0, errors.Annotate(c.ctx.Err(), "Timeout on IO operation") return 0, errors.Annotate(c.ctx.Err(), "Timeout on IO operation")
} }
} }
+3 -3
View File
@@ -119,9 +119,9 @@ func (m *MTProtoAbridged) Write(p []byte) (int, error) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(1 + 3 + len(p)) buf.Grow(1 + 3 + len(p))
buf.WriteByte(byte(mtprotoAbridgedSmallPacketLength)) buf.WriteByte(byte(mtprotoAbridgedSmallPacketLength)) // nolint: gosec
buf.Write(length24[:]) buf.Write(length24[:]) // nolint: gosec
buf.Write(p) buf.Write(p) // nolint: gosec
return m.conn.Write(buf.Bytes()) return m.conn.Write(buf.Bytes())
} }
+17 -17
View File
@@ -4,8 +4,8 @@ import (
"bytes" "bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/md5" // nolint: gas "crypto/md5" // nolint: gas
"crypto/sha1" "crypto/sha1" // nolint: gosec
"encoding/binary" "encoding/binary"
"net" "net"
@@ -41,9 +41,9 @@ func NewMiddleProxyCipher(conn StreamReadWriteCloser,
func deriveKeys(purpose cipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse, func deriveKeys(purpose cipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse,
client, remote *net.TCPAddr, secret []byte) ([]byte, []byte) { client, remote *net.TCPAddr, secret []byte) ([]byte, []byte) {
message := bytes.Buffer{} message := bytes.Buffer{}
message.Write(resp.Nonce) message.Write(resp.Nonce) // nolint: gosec
message.Write(req.Nonce) message.Write(req.Nonce) // nolint: gosec
message.Write(req.CryptoTS) message.Write(req.CryptoTS) // nolint: gosec
clientIPv4 := emptyIP[:] clientIPv4 := emptyIP[:]
serverIPv4 := emptyIP[:] serverIPv4 := emptyIP[:]
@@ -51,36 +51,36 @@ func deriveKeys(purpose cipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceRes
clientIPv4 = utils.ReverseBytes(client.IP.To4()) clientIPv4 = utils.ReverseBytes(client.IP.To4())
serverIPv4 = utils.ReverseBytes(remote.IP.To4()) serverIPv4 = utils.ReverseBytes(remote.IP.To4())
} }
message.Write(serverIPv4) message.Write(serverIPv4) // nolint: gosec
var port [2]byte var port [2]byte
binary.LittleEndian.PutUint16(port[:], uint16(client.Port)) binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
message.Write(port[:]) message.Write(port[:]) // nolint: gosec
switch purpose { switch purpose {
case cipherPurposeClient: case cipherPurposeClient:
message.WriteString("CLIENT") message.WriteString("CLIENT") // nolint: gosec
case cipherPurposeServer: case cipherPurposeServer:
message.WriteString("SERVER") message.WriteString("SERVER") // nolint: gosec
default: default:
panic("Unexpected cipher purpose") panic("Unexpected cipher purpose")
} }
message.Write(clientIPv4) message.Write(clientIPv4) // nolint: gosec
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port)) binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
message.Write(port[:]) message.Write(port[:]) // nolint: gosec
message.Write(secret) message.Write(secret) // nolint: gosec
message.Write(resp.Nonce) message.Write(resp.Nonce) // nolint: gosec
if client.IP.To4() == nil { if client.IP.To4() == nil {
message.Write(client.IP.To16()) message.Write(client.IP.To16()) // nolint: gosec
message.Write(remote.IP.To16()) message.Write(remote.IP.To16()) // nolint: gosec
} }
message.Write(req.Nonce) message.Write(req.Nonce) // nolint: gosec
data := message.Bytes() data := message.Bytes()
md5sum := md5.Sum(data[1:]) // nolint: gas md5sum := md5.Sum(data[1:]) // nolint: gas
sha1sum := sha1.Sum(data) sha1sum := sha1.Sum(data) // nolint: gosec
key := append(md5sum[:12], sha1sum[:]...) key := append(md5sum[:12], sha1sum[:]...)
iv := md5.Sum(data[2:]) // nolint: gas iv := md5.Sum(data[2:]) // nolint: gas
+7 -7
View File
@@ -73,12 +73,12 @@ func (m *MTProtoFrame) Read() ([]byte, error) { // nolint: gocyclo
} }
var seqNo int32 var seqNo int32
binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck binary.Read(buf, binary.LittleEndian, &seqNo) // nolint: errcheck, gosec
if seqNo != m.readSeqNo { if seqNo != m.readSeqNo {
return nil, errors.Errorf("Unexpected sequence number %d (wait for %d)", seqNo, m.readSeqNo) return nil, errors.Errorf("Unexpected sequence number %d (wait for %d)", seqNo, m.readSeqNo)
} }
data, _ := ioutil.ReadAll(buf) data, _ := ioutil.ReadAll(buf) // nolint: gosec
buf.Reset() buf.Reset()
// write to buf, not to writer. This is because we are going to fetch // write to buf, not to writer. This is because we are going to fetch
// crc32 checksum. // crc32 checksum.
@@ -109,13 +109,13 @@ func (m *MTProtoFrame) Write(p []byte) (int, error) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(messageLength + paddingLength) buf.Grow(messageLength + paddingLength)
binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck, gosec
binary.Write(buf, binary.LittleEndian, m.writeSeqNo) // nolint: errcheck binary.Write(buf, binary.LittleEndian, m.writeSeqNo) // nolint: errcheck, gosec
buf.Write(p) buf.Write(p) // nolint: gosec
checksum := crc32.ChecksumIEEE(buf.Bytes()) checksum := crc32.ChecksumIEEE(buf.Bytes())
binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck, gosec
buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) // nolint: gosec
m.logger.Debugw("Write MTProto frame", m.logger.Debugw("Write MTProto frame",
"length", len(p), "length", len(p),
+3 -3
View File
@@ -44,9 +44,9 @@ func (m *MTProtoIntermediateSecure) Write(p []byte) (int, error) {
paddingLength := rand.Intn(4) paddingLength := rand.Intn(4)
buf.Grow(4 + len(p) + paddingLength) buf.Grow(4 + len(p) + paddingLength)
binary.Write(buf, binary.LittleEndian, uint32(len(p)+paddingLength)) // nolint: errcheck binary.Write(buf, binary.LittleEndian, uint32(len(p)+paddingLength)) // nolint: errcheck, gosec
buf.Write(p) buf.Write(p) // nolint: gosec
buf.Write(make([]byte, paddingLength)) buf.Write(make([]byte, paddingLength)) // nolint: gosec
m.logger.Debugw("Write packet with padding", m.logger.Debugw("Write packet with padding",
"simple_ack", m.opts.WriteHacks.SimpleAck, "simple_ack", m.opts.WriteHacks.SimpleAck,
+1 -1
View File
@@ -120,7 +120,7 @@ func (m *MTProtoProxy) Write(p []byte) (int, error) {
zap.Stringer("flags", flags), zap.Stringer("flags", flags),
) )
} }
header.Write(p) header.Write(p) // nolint: gosec
if _, err := m.conn.Write(header.Bytes()); err != nil { if _, err := m.conn.Write(header.Bytes()); err != nil {
return 0, err return 0, err
+1 -1
View File
@@ -34,7 +34,7 @@ func (s *StreamCipher) Write(p []byte) (int, error) {
buf.Reset() buf.Reset()
buf.Grow(len(p)) buf.Grow(len(p))
buf.Write(p) buf.Write(p) // nolint: gosec
data := buf.Bytes() data := buf.Bytes()
s.encryptor.XORKeyStream(data, data) s.encryptor.XORKeyStream(data, data)