Correctly process doppel conns

This commit is contained in:
9seconds
2026-03-12 19:07:11 +01:00
parent d43d6692d7
commit 7a58c74cfe
2 changed files with 34 additions and 26 deletions
+10 -9
View File
@@ -9,13 +9,13 @@ import (
) )
const ( const (
DoppelGangerMaxDurations = 4096 DoppelGangerMaxDurations = 4096
DoppelGangerScoutRaidEach = 30 * time.Minute DoppelGangerScoutRaidEach = 30 * time.Minute
DoppelGangerScoutRepeats = 10 DoppelGangerScoutRepeats = 10
) )
type gangerConnRequest struct { type gangerConnRequest struct {
ret chan Conn ret chan<- Conn
payload essentials.Conn payload essentials.Conn
} }
@@ -25,7 +25,7 @@ type Ganger struct {
logger Logger logger Logger
wg sync.WaitGroup wg sync.WaitGroup
scout Scout scout Scout
scoutRaidEach time.Duration scoutRaidEach time.Duration
scoutRaidRepeats int scoutRaidRepeats int
@@ -47,8 +47,9 @@ func (g *Ganger) Run() {
} }
func (g *Ganger) NewConn(conn essentials.Conn) (Conn, error) { func (g *Ganger) NewConn(conn essentials.Conn) (Conn, error) {
rvChan := make(chan Conn)
req := gangerConnRequest{ req := gangerConnRequest{
ret: make(chan Conn), ret: rvChan,
payload: conn, payload: conn,
} }
defer close(req.ret) defer close(req.ret)
@@ -62,7 +63,7 @@ func (g *Ganger) NewConn(conn essentials.Conn) (Conn, error) {
select { select {
case <-g.ctx.Done(): case <-g.ctx.Done():
return Conn{}, context.Cause(g.ctx) return Conn{}, context.Cause(g.ctx)
case conn := <-req.ret: case conn := <-rvChan:
return conn, nil return conn, nil
} }
} }
@@ -158,9 +159,9 @@ func NewGanger(
} }
return &Ganger{ return &Ganger{
ctx: ctx, ctx: ctx,
ctxCancel: cancel, ctxCancel: cancel,
logger: logger, logger: logger,
scoutRaidEach: scoutEach, scoutRaidEach: scoutEach,
scoutRaidRepeats: scoutRepeats, scoutRaidRepeats: scoutRepeats,
stats: &Stats{ stats: &Stats{
+24 -17
View File
@@ -78,19 +78,32 @@ func (p *Proxy) ServeConn(conn essentials.Conn) {
ctx.logger.Info("Stream has been finished") ctx.logger.Info("Stream has been finished")
}() }()
if !p.doFakeTLSHandshake(ctx) { noise, ok := p.doFakeTLSHandshake(ctx)
if !ok {
return return
} }
if err := p.doObfuscatedHandshake(ctx); err != nil { clientConn, err := p.doppelGanger.NewConn(ctx.clientConn)
p.logger.InfoError("obfuscated handshake is failed", err) if err != nil {
ctx.logger.InfoError("cannot wrap into doppelganger connection", err)
return
}
defer clientConn.Stop()
if _, err := clientConn.Write(noise); err != nil {
ctx.logger.InfoError("cannot send the first packet", err)
return
}
ctx.clientConn = clientConn
if err := p.doObfuscatedHandshake(ctx); err != nil {
ctx.logger.InfoError("obfuscated handshake is failed", err)
return return
} }
if err := p.doTelegramCall(ctx); err != nil { if err := p.doTelegramCall(ctx); err != nil {
p.logger.WarningError("cannot dial to telegram", err) ctx.logger.WarningError("cannot dial to telegram", err)
return return
} }
@@ -163,7 +176,7 @@ func (p *Proxy) Shutdown() {
p.blocklist.Shutdown() p.blocklist.Shutdown()
} }
func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) bool { func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) ([]byte, bool) {
rewind := newConnRewind(ctx.clientConn) rewind := newConnRewind(ctx.clientConn)
clientHello, err := fake.ReadClientHello( clientHello, err := fake.ReadClientHello(
@@ -175,31 +188,25 @@ func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) bool {
if err != nil { if err != nil {
p.logger.InfoError("cannot read client hello", err) p.logger.InfoError("cannot read client hello", err)
p.doDomainFronting(ctx, rewind) p.doDomainFronting(ctx, rewind)
return false return nil, false
} }
if p.antiReplayCache.SeenBefore(clientHello.SessionID) { if p.antiReplayCache.SeenBefore(clientHello.SessionID) {
p.logger.Warning("replay attack has been detected!") p.logger.Warning("replay attack has been detected!")
p.eventStream.Send(p.ctx, NewEventReplayAttack(ctx.streamID)) p.eventStream.Send(p.ctx, NewEventReplayAttack(ctx.streamID))
p.doDomainFronting(ctx, rewind) p.doDomainFronting(ctx, rewind)
return false return nil, false
} }
_, err = fake.SendServerHello(ctx.clientConn, p.secret.Key[:], clientHello) noise, err := fake.SendServerHello(ctx.clientConn, p.secret.Key[:], clientHello)
if err != nil { if err != nil {
p.logger.InfoError("cannot send welcome packet", err) p.logger.InfoError("cannot send welcome packet", err)
return false return nil, false
} }
ctx.clientConn = tls.New(ctx.clientConn, true, true) ctx.clientConn = tls.New(ctx.clientConn, true, true)
ctx.clientConn, err = p.doppelGanger.NewConn(ctx.clientConn) return noise, true
if err != nil {
p.logger.WarningError("cannot create connection", err)
return false
}
return true
} }
func (p *Proxy) doObfuscatedHandshake(ctx *streamContext) error { func (p *Proxy) doObfuscatedHandshake(ctx *streamContext) error {