Move clienhello to faketls

This commit is contained in:
9seconds
2021-03-25 16:44:06 +03:00
parent 4a2d1df384
commit d3551aa9cc
4 changed files with 42 additions and 30 deletions
@@ -1,4 +1,4 @@
package clienthello package faketls
import ( import (
"crypto/hmac" "crypto/hmac"
@@ -16,10 +16,10 @@ type ClientHello struct {
SessionID []byte SessionID []byte
} }
func ParseHandshake(secret, handshake []byte) (ClientHello, error) { func ParseClientHello(secret, handshake []byte) (ClientHello, error) {
hello := ClientHello{} hello := ClientHello{}
if len(handshake) < MinLen { if len(handshake) < ClientHelloMinLen {
return hello, fmt.Errorf("lengh of handshake is too small: %d", len(handshake)) return hello, fmt.Errorf("lengh of handshake is too small: %d", len(handshake))
} }
@@ -27,9 +27,9 @@ func ParseHandshake(secret, handshake []byte) (ClientHello, error) {
return hello, fmt.Errorf("unknown handshake type %#x", handshake[0]) return hello, fmt.Errorf("unknown handshake type %#x", handshake[0])
} }
copy(hello.Digest[:], handshake[RandomOffset:]) copy(hello.Digest[:], handshake[ClientHelloRandomOffset:])
for i := RandomOffset; i < RandomOffset+RandomLen; i++ { for i := ClientHelloRandomOffset; i < ClientHelloRandomOffset+RandomLen; i++ {
handshake[i] = 0 handshake[i] = 0
} }
@@ -60,8 +60,8 @@ func ParseHandshake(secret, handshake []byte) (ClientHello, error) {
timestamp := int64(binary.LittleEndian.Uint32(computedDigest[RandomLen-4:])) timestamp := int64(binary.LittleEndian.Uint32(computedDigest[RandomLen-4:]))
hello.Time = time.Unix(timestamp, 0) hello.Time = time.Unix(timestamp, 0)
hello.SessionID = make([]byte, handshake[SessionIDOffset]) hello.SessionID = make([]byte, handshake[ClientHelloSessionIDOffset])
copy(hello.SessionID, handshake[SessionIDOffset+1:]) copy(hello.SessionID, handshake[ClientHelloSessionIDOffset+1:])
return hello, nil return hello, nil
} }
@@ -1,17 +0,0 @@
package clienthello
import "errors"
const (
RandomLen = 32
RandomOffset = 6
SessionIDOffset = RandomOffset + RandomLen
MinLen = SessionIDOffset + 1
HandshakeTypeClient = 0x01
)
var (
ErrBadDigest = errors.New("bad digest")
ErrAntiReplayAttack = errors.New("antireplay attack was detected")
)
+18
View File
@@ -0,0 +1,18 @@
package faketls
import "errors"
const (
RandomLen = 32
ClientHelloRandomOffset = 6
ClientHelloSessionIDOffset = ClientHelloRandomOffset + RandomLen
ClientHelloMinLen = ClientHelloSessionIDOffset + 1
HandshakeTypeClient = 0x01
)
var (
ErrBadDigest = errors.New("bad digest")
ErrAntiReplayAttack = errors.New("antireplay attack was detected")
)
+17 -6
View File
@@ -8,7 +8,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/9seconds/mtg/v2/mtglib/internal/faketls/clienthello" "github.com/9seconds/mtg/v2/mtglib/internal/faketls"
"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record" "github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
"github.com/9seconds/mtg/v2/mtglib/internal/obfuscated2" "github.com/9seconds/mtg/v2/mtglib/internal/obfuscated2"
"github.com/9seconds/mtg/v2/mtglib/internal/relay" "github.com/9seconds/mtg/v2/mtglib/internal/relay"
@@ -58,7 +58,7 @@ func (p *Proxy) ServeConn(conn net.Conn) {
ctx.logger.Info("Stream has been finished") ctx.logger.Info("Stream has been finished")
}() }()
if err := p.doFakeTLSHandshake(ctx); err != nil { if err := p.doFakeTLSHandshake(ctx, ctx.clientConn); err != nil {
p.logger.InfoError("faketls handshake is failed", err) p.logger.InfoError("faketls handshake is failed", err)
return return
@@ -121,17 +121,28 @@ func (p *Proxy) Shutdown() {
p.workerPool.Release() p.workerPool.Release()
} }
func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) error { func (p *Proxy) doFakeTLSHandshake(ctx *streamContext, conn net.Conn) error {
clientHelloRecord := record.AcquireRecord() clientHelloRecord := record.AcquireRecord()
defer record.ReleaseRecord(clientHelloRecord) defer record.ReleaseRecord(clientHelloRecord)
if err := clientHelloRecord.Read(ctx.clientConn); err != nil { if err := clientHelloRecord.Read(conn); err != nil {
return fmt.Errorf("cannot read client hello: %w", err) return fmt.Errorf("cannot read client hello: %w", err)
} }
hello, _ := clienthello.ParseHandshake(p.secret.Key[:], hello, err := faketls.ParseClientHello(p.secret.Key[:],
clientHelloRecord.Payload.Bytes()) clientHelloRecord.Payload.Bytes())
fmt.Println(hello) if err != nil {
return fmt.Errorf("cannot parse client hello: %w", err)
}
if err := p.timeAttackDetector.Valid(hello.Time); err != nil {
return fmt.Errorf("invalid time: %w", err)
}
if p.antiReplayCache.SeenBefore(hello.SessionID) {
p.logger.Warning("anti replay attack was detected")
return fmt.Errorf("anti replay attack from %s", ctx.ClientIP().String())
}
return fmt.Errorf("SUCCESS") return fmt.Errorf("SUCCESS")
} }