Bugfix rpc handshake

This commit is contained in:
9seconds
2018-07-04 11:28:08 +03:00
parent ffa7ef7a0a
commit 90c10519ee
17 changed files with 129 additions and 62 deletions
+1 -2
View File
@@ -32,9 +32,8 @@ func DirectInit(conn net.Conn, conf *config.Config) (*mtproto.ConnectionOpts, wr
return nil, nil, errors.Annotate(err, "Cannot parse obfuscated frame") return nil, nil, errors.Annotate(err, "Cannot parse obfuscated frame")
} }
connOpts.ConnectionProto = mtproto.ConnectionProtocolAny connOpts.ConnectionProto = mtproto.ConnectionProtocolAny
connOpts.ClientAddr = conn.RemoteAddr().(*net.TCPAddr)
socket := wrappers.NewTimeoutRWC(conn) socket := wrappers.NewTimeoutRWC(conn, conf.PublicIPv4, conf.PublicIPv6)
socket = wrappers.NewStreamCipherRWC(socket, obfs2.Encryptor, obfs2.Decryptor) socket = wrappers.NewStreamCipherRWC(socket, obfs2.Encryptor, obfs2.Decryptor)
return connOpts, socket, nil return connOpts, socket, nil
+14 -21
View File
@@ -59,16 +59,6 @@ func (c *Config) BindAddr() string {
return getAddr(c.BindIP, c.BindPort) return getAddr(c.BindIP, c.BindPort)
} }
// IPv4Addr returns connection string to ipv6 for mtproto proxy.
func (c *Config) IPv4Addr() string {
return getAddr(c.PublicIPv4, c.PublicIPv4Port)
}
// IPv6Addr returns connection string to ipv6 for mtproto proxy.
func (c *Config) IPv6Addr() string {
return getAddr(c.PublicIPv6, c.PublicIPv6Port)
}
// StatAddr returns connection string to the stats API. // StatAddr returns connection string to the stats API.
func (c *Config) StatAddr() string { func (c *Config) StatAddr() string {
return getAddr(c.StatsIP, c.StatsPort) return getAddr(c.StatsIP, c.StatsPort)
@@ -76,10 +66,15 @@ func (c *Config) StatAddr() string {
// GetURLs returns configured IPURLs instance with links to this server. // GetURLs returns configured IPURLs instance with links to this server.
func (c *Config) GetURLs() IPURLs { func (c *Config) GetURLs() IPURLs {
return IPURLs{ urls := IPURLs{}
IPv4: getURLs(c.PublicIPv4, c.PublicIPv4Port, c.Secret), if c.PublicIPv4 != nil {
IPv6: getURLs(c.PublicIPv6, c.PublicIPv6Port, c.Secret), urls.IPv4 = getURLs(c.PublicIPv4, c.PublicIPv4Port, c.Secret)
} }
if c.PublicIPv6 != nil {
urls.IPv6 = getURLs(c.PublicIPv6, c.PublicIPv6Port, c.Secret)
}
return urls
} }
func getAddr(host fmt.Stringer, port uint16) string { func getAddr(host fmt.Stringer, port uint16) string {
@@ -106,12 +101,11 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
if publicIPv4 == nil { if publicIPv4 == nil {
publicIPv4, err = getGlobalIPv4() publicIPv4, err = getGlobalIPv4()
if err != nil { if err != nil {
return nil, errors.Errorf("Cannot get public IP") publicIPv4 = nil
} else if publicIPv4.To4() == nil {
return nil, errors.Errorf("IP %s is not IPv4", publicIPv4.String())
} }
} }
if publicIPv4.To4() == nil {
return nil, errors.Errorf("IP %s is not IPv4", publicIPv4.String())
}
if PublicIPv4Port == 0 { if PublicIPv4Port == 0 {
PublicIPv4Port = bindPort PublicIPv4Port = bindPort
} }
@@ -119,12 +113,11 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
if publicIPv6 == nil { if publicIPv6 == nil {
publicIPv6, err = getGlobalIPv6() publicIPv6, err = getGlobalIPv6()
if err != nil { if err != nil {
publicIPv6 = publicIPv4 publicIPv6 = nil
} else if publicIPv6.To4() != nil {
return nil, errors.Errorf("IP %s is not IPv6", publicIPv6.String())
} }
} }
if publicIPv6.To16() == nil {
return nil, errors.Errorf("IP %s is not IPv6", publicIPv6.String())
}
if publicIPv6Port == 0 { if publicIPv6Port == 0 {
publicIPv6Port = bindPort publicIPv6Port = bindPort
} }
+25 -9
View File
@@ -4,6 +4,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"math/rand" "math/rand"
"os" "os"
@@ -15,7 +16,8 @@ import (
kingpin "gopkg.in/alecthomas/kingpin.v2" kingpin "gopkg.in/alecthomas/kingpin.v2"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/proxy" "github.com/9seconds/mtg/mtproto"
"github.com/9seconds/mtg/telegram"
"github.com/juju/errors" "github.com/juju/errors"
) )
@@ -112,15 +114,29 @@ func main() {
atom, atom,
)).Sugar() )).Sugar()
stat := proxy.NewStats(conf) tg := telegram.NewMiddleTelegram(conf, logger)
go stat.Serve() connOpts := &mtproto.ConnectionOpts{
DC: int16(1),
srv := proxy.NewServer(conf, logger, stat) ConnectionType: mtproto.ConnectionTypeAbridged,
printURLs(conf.GetURLs()) ConnectionProto: mtproto.ConnectionProtocolIPv4,
if err := srv.Serve(); err != nil {
logger.Fatal(err.Error())
} }
sock, err := tg.Dial(connOpts)
if err != nil {
panic(err)
}
_, err = tg.Init(connOpts, sock)
fmt.Println(err)
// stat := proxy.NewStats(conf)
// go stat.Serve()
// srv := proxy.NewServer(conf, logger, stat)
// printURLs(conf.GetURLs())
// if err := srv.Serve(); err != nil {
// logger.Fatal(err.Error())
// }
} }
func setRLimit() (err error) { func setRLimit() (err error) {
+2 -2
View File
@@ -2,7 +2,6 @@ package mtproto
import ( import (
"bytes" "bytes"
"net"
"github.com/juju/errors" "github.com/juju/errors"
) )
@@ -19,7 +18,8 @@ type ConnectionOpts struct {
DC int16 DC int16
ConnectionType ConnectionType ConnectionType ConnectionType
ConnectionProto ConnectionProtocol ConnectionProto ConnectionProtocol
ClientAddr *net.TCPAddr QuickAck bool
SimpleAck bool
} }
// Different connection types which user requests from Telegram. // Different connection types which user requests from Telegram.
+3 -1
View File
@@ -1,6 +1,8 @@
package rpc package rpc
import "bytes" import (
"bytes"
)
const ( const (
rpcHandshakeTagLength = 4 rpcHandshakeTagLength = 4
+6 -5
View File
@@ -22,11 +22,12 @@ const (
var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00} var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
func NewMiddleProxyCipherRWC(conn wrappers.ReadWriteCloserWithAddr, req *rpc.RPCNonceRequest, func NewMiddleProxyCipherRWC(conn wrappers.ReadWriteCloserWithAddr, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse, secret []byte) wrappers.ReadWriteCloserWithAddr {
resp *rpc.RPCNonceResponse, client *net.TCPAddr, secret []byte) wrappers.ReadWriteCloserWithAddr { localAddr := conn.LocalAddr()
remote := conn.Addr() remoteAddr := conn.RemoteAddr()
encKey, encIV := makeKeys(CipherPurposeClient, req, resp, client, remote, secret)
decKey, decIV := makeKeys(CipherPurposeServer, req, resp, client, remote, secret) encKey, encIV := makeKeys(CipherPurposeClient, req, resp, localAddr, remoteAddr, secret)
decKey, decIV := makeKeys(CipherPurposeServer, req, resp, localAddr, remoteAddr, secret)
enc, _ := makeEncrypterDecrypter(encKey, encIV) enc, _ := makeEncrypterDecrypter(encKey, encIV)
_, dec := makeEncrypterDecrypter(decKey, decIV) _, dec := makeEncrypterDecrypter(decKey, decIV)
+6 -2
View File
@@ -112,8 +112,12 @@ func (f *FrameRWC) Close() error {
return f.conn.Close() return f.conn.Close()
} }
func (f *FrameRWC) Addr() *net.TCPAddr { func (f *FrameRWC) LocalAddr() *net.TCPAddr {
return f.conn.Addr() return f.conn.LocalAddr()
}
func (f *FrameRWC) RemoteAddr() *net.TCPAddr {
return f.conn.RemoteAddr()
} }
func NewFrameRWC(conn wrappers.ReadWriteCloserWithAddr, seqNo int32) wrappers.ReadWriteCloserWithAddr { func NewFrameRWC(conn wrappers.ReadWriteCloserWithAddr, seqNo int32) wrappers.ReadWriteCloserWithAddr {
+3 -1
View File
@@ -14,6 +14,8 @@ const telegramDialTimeout = 10 * time.Second
type tgDialer struct { type tgDialer struct {
net.Dialer net.Dialer
conf *config.Config
} }
func (t *tgDialer) dial(addr string) (net.Conn, error) { func (t *tgDialer) dial(addr string) (net.Conn, error) {
@@ -34,5 +36,5 @@ func (t *tgDialer) dialRWC(addr string) (wrappers.ReadWriteCloserWithAddr, error
return nil, err return nil, err
} }
return wrappers.NewTimeoutRWC(conn), nil return wrappers.NewTimeoutRWC(conn, t.conf.PublicIPv4, t.conf.PublicIPv6), nil
} }
+4 -1
View File
@@ -57,7 +57,10 @@ func (t *directTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.Re
// to Telegram bypassing middleproxies. // to Telegram bypassing middleproxies.
func NewDirectTelegram(conf *config.Config) Telegram { func NewDirectTelegram(conf *config.Config) Telegram {
return &directTelegram{baseTelegram{ return &directTelegram{baseTelegram{
dialer: tgDialer{net.Dialer{Timeout: telegramDialTimeout}}, dialer: tgDialer{
Dialer: net.Dialer{Timeout: telegramDialTimeout},
conf: conf,
},
v4Addresses: directV4Addresses, v4Addresses: directV4Addresses,
v6Addresses: directV6Addresses, v6Addresses: directV6Addresses,
}} }}
+7 -3
View File
@@ -1,6 +1,7 @@
package telegram package telegram
import ( import (
"fmt"
"io" "io"
"net" "net"
"net/http" "net/http"
@@ -24,7 +25,10 @@ func NewMiddleTelegram(conf *config.Config, logger *zap.SugaredLogger) Telegram
tg := &middleTelegram{ tg := &middleTelegram{
middleTelegramCaller: middleTelegramCaller{ middleTelegramCaller: middleTelegramCaller{
baseTelegram: baseTelegram{ baseTelegram: baseTelegram{
dialer: tgDialer{net.Dialer{Timeout: telegramDialTimeout}}, dialer: tgDialer{
Dialer: net.Dialer{Timeout: telegramDialTimeout},
conf: conf,
},
}, },
logger: logger, logger: logger,
httpClient: &http.Client{ httpClient: &http.Client{
@@ -54,8 +58,7 @@ func (t *middleTelegram) Init(connOpts *mtproto.ConnectionOpts, conn wrappers.Re
return nil, err return nil, err
} }
secureConn := mtwrappers.NewMiddleProxyCipherRWC(conn, rpcNonceReq, secureConn := mtwrappers.NewMiddleProxyCipherRWC(conn, rpcNonceReq, rpcNonceResp, t.proxySecret)
rpcNonceResp, connOpts.ClientAddr, t.proxySecret)
secureConn = mtwrappers.NewFrameRWC(secureConn, rpc.RPCHandshakeSeqNo) secureConn = mtwrappers.NewFrameRWC(secureConn, rpc.RPCHandshakeSeqNo)
rpcHandshakeReq, err := t.sendRPCHandshakeRequest(secureConn) rpcHandshakeReq, err := t.sendRPCHandshakeRequest(secureConn)
@@ -123,6 +126,7 @@ func (t *middleTelegram) receiveRPCHandshakeResponse(conn io.Reader, req *rpc.RP
if err = rpcHandshakeResp.Valid(req); err != nil { if err = rpcHandshakeResp.Valid(req); err != nil {
return nil, errors.Annotate(err, "Invalid RPC handshake response") return nil, errors.Annotate(err, "Invalid RPC handshake response")
} }
fmt.Println("VICTORY")
return rpcHandshakeResp, nil return rpcHandshakeResp, nil
} }
+7 -2
View File
@@ -25,6 +25,7 @@ func (c *BlockCipherReadWriteCloserWithAddr) Read(p []byte) (int, error) {
return errors.Annotate(err, "Cannot read from socket") return errors.Annotate(err, "Cannot read from socket")
} }
c.Buffer.Write(p[:n]) c.Buffer.Write(p[:n])
bufferLength = c.Buffer.Len()
} }
c.decryptor.CryptBlocks(c.Buffer.Bytes(), c.Buffer.Bytes()) c.decryptor.CryptBlocks(c.Buffer.Bytes(), c.Buffer.Bytes())
@@ -47,8 +48,12 @@ func (c *BlockCipherReadWriteCloserWithAddr) Close() error {
return c.conn.Close() return c.conn.Close()
} }
func (c *BlockCipherReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (c *BlockCipherReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return c.conn.Addr() return c.conn.LocalAddr()
}
func (c *BlockCipherReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return c.conn.RemoteAddr()
} }
func NewBlockCipherRWC(conn ReadWriteCloserWithAddr, encryptor, decryptor cipher.BlockMode) ReadWriteCloserWithAddr { func NewBlockCipherRWC(conn ReadWriteCloserWithAddr, encryptor, decryptor cipher.BlockMode) ReadWriteCloserWithAddr {
+6 -2
View File
@@ -48,8 +48,12 @@ func (c *CtxReadWriteCloserWithAddr) Close() error {
return c.conn.Close() return c.conn.Close()
} }
func (c *CtxReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (c *CtxReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return c.conn.Addr() return c.conn.LocalAddr()
}
func (c *CtxReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return c.conn.RemoteAddr()
} }
// NewCtxRWC returns ReadWriteCloser which respects given context, // NewCtxRWC returns ReadWriteCloser which respects given context,
+6 -2
View File
@@ -36,8 +36,12 @@ func (l *LogReadWriteCloserWithAddr) Close() error {
return err return err
} }
func (l *LogReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (l *LogReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return l.conn.Addr() return l.conn.LocalAddr()
}
func (l *LogReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return l.conn.RemoteAddr()
} }
// NewLogRWC wraps ReadWriteCloser with logger calls. // NewLogRWC wraps ReadWriteCloser with logger calls.
+2 -1
View File
@@ -8,5 +8,6 @@ import (
type ReadWriteCloserWithAddr interface { type ReadWriteCloserWithAddr interface {
io.ReadWriteCloser io.ReadWriteCloser
Addr() *net.TCPAddr LocalAddr() *net.TCPAddr
RemoteAddr() *net.TCPAddr
} }
+6 -2
View File
@@ -43,8 +43,12 @@ func (c *StreamCipherReadWriteCloserWithAddr) Close() error {
return c.conn.Close() return c.conn.Close()
} }
func (c *StreamCipherReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (c *StreamCipherReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return c.conn.Addr() return c.conn.LocalAddr()
}
func (c *StreamCipherReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return c.conn.RemoteAddr()
} }
// NewStreamCipherRWC returns wrapper which transparently // NewStreamCipherRWC returns wrapper which transparently
+25 -4
View File
@@ -8,7 +8,9 @@ import (
) )
type TimeoutReadWriteCloserWithAddr struct { type TimeoutReadWriteCloserWithAddr struct {
conn net.Conn conn net.Conn
publicIPv4 net.IP
publicIPv6 net.IP
} }
func (t *TimeoutReadWriteCloserWithAddr) Read(p []byte) (int, error) { func (t *TimeoutReadWriteCloserWithAddr) Read(p []byte) (int, error) {
@@ -25,10 +27,29 @@ func (t *TimeoutReadWriteCloserWithAddr) Close() error {
return t.conn.Close() return t.conn.Close()
} }
func (t *TimeoutReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (t *TimeoutReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return t.conn.RemoteAddr().(*net.TCPAddr) return t.conn.RemoteAddr().(*net.TCPAddr)
} }
func NewTimeoutRWC(conn net.Conn) ReadWriteCloserWithAddr { func (t *TimeoutReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return &TimeoutReadWriteCloserWithAddr{conn} addr := t.conn.LocalAddr().(*net.TCPAddr)
newAddr := *addr
if t.RemoteAddr().IP.To4() != nil {
if t.publicIPv4 != nil {
newAddr.IP = t.publicIPv4
}
} else if t.publicIPv6 != nil {
newAddr.IP = t.publicIPv6
}
return &newAddr
}
func NewTimeoutRWC(conn net.Conn, ipv4, ipv6 net.IP) ReadWriteCloserWithAddr {
return &TimeoutReadWriteCloserWithAddr{
conn: conn,
publicIPv4: ipv4,
publicIPv6: ipv6,
}
} }
+6 -2
View File
@@ -29,8 +29,12 @@ func (t *TrafficReadWriteCloserWithAddr) Close() error {
return t.conn.Close() return t.conn.Close()
} }
func (t *TrafficReadWriteCloserWithAddr) Addr() *net.TCPAddr { func (t *TrafficReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
return t.conn.Addr() return t.conn.LocalAddr()
}
func (t *TrafficReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
return t.conn.RemoteAddr()
} }
// NewTrafficRWC wraps ReadWriteCloser to have read/write callbacks. // NewTrafficRWC wraps ReadWriteCloser to have read/write callbacks.