xvzc / SpoofDPI

A simple and fast anti-censorship tool written in Go
Apache License 2.0
3.33k stars 242 forks source link

Telegram stopped working after the latest update #145

Open PoorMouse opened 4 weeks ago

PoorMouse commented 4 weeks ago

After the latest update (0.10.7) I can't use Telegram and spoof-dpi at the same time.

tgb

When I turn spoof-dpi off everything is ok.

tga_

OS: macOS 10.13.6

Version: 0.10.7

P.S. Same with 0.10.8.

xvzc commented 4 weeks ago

Same after restarting telegram?

PoorMouse commented 4 weeks ago

Yes

xvzc commented 4 weeks ago

which options did you pass to run it?

PoorMouse commented 4 weeks ago

No options. Just spoof-dpi.

xvzc commented 4 weeks ago

Can not reproduce.

LiquidTheDangerous commented 4 weeks ago

@PoorMouse run with -debug and send logs please

PoorMouse commented 4 weeks ago

Here's a part of an endless log.

sd_tg_log.txt

And a small telegram log.

tg_log.txt

LiquidTheDangerous commented 4 weeks ago

@PoorMouse

Make sure this checkbox (Try connecting through ipv6) is unchecked.

Seems to be ipv6 some issues

Снимок экрана от 2024-08-16 14-26-07

LiquidTheDangerous commented 4 weeks ago

@PoorMouse

Or You can disable proxy for telegram

PoorMouse commented 4 weeks ago

@PoorMouse

Or You can disable proxy for telegram

It works! 👍

SeJIya commented 3 weeks ago

same, this issues after https://github.com/xvzc/SpoofDPI/commit/852b789ac3f5b52288a2136102dea6408e2a55b7

just worked example (diff between v0.10.7):

diff --git a/packet/https.go b/packet/https.go
index 49abeb8..bf9467c 100644
--- a/packet/https.go
+++ b/packet/https.go
@@ -45,10 +45,12 @@ func ReadTLSMessage(r io.Reader) (*TLSMessage, error) {

        raw := make([]byte, header.PayloadLen+TLSHeaderLen) // maybe allocate only 4096

        copy(raw[0:TLSHeaderLen], rawHeader[:])
-       _, err = io.ReadFull(r, raw[TLSHeaderLen:])
+       n, err := r.Read(raw[TLSHeaderLen:])
        if err != nil {
                return nil, err
        }
+       raw = raw[:n+TLSHeaderLen]
+       header.PayloadLen = uint16(n) // maybe don't need actualize len

        hello := &TLSMessage{
                Header:     header,
diff --git a/proxy/https.go b/proxy/https.go
index c4f256e..67014ff 100644
--- a/proxy/https.go
+++ b/proxy/https.go
@@ -46,29 +46,35 @@ func (pxy *Proxy) handleHttps(lConn *net.TCPConn, exploit bool, initPkt *packet.

        // Read client hello
        m, err := packet.ReadTLSMessage(lConn)
-       if err != nil || !m.IsClientHello() {
+       if err != nil {
                log.Debug("[HTTPS] Error reading client hello from the client", err)
                return
        }
-       clientHello := m.Raw
-
-       log.Debug("[HTTPS] Client sent hello ", len(clientHello), "bytes")

        // Generate a go routine that reads from the server
        go Serve(rConn, lConn, "[HTTPS]", rConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout, pxy.bufferSize)

-       if exploit {
-               log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain())
-               chunks := splitInChunks(clientHello, pxy.windowSize)
-               if _, err := writeChunks(rConn, chunks); err != nil {
-                       log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err)
+       if !m.IsClientHello() {
+               if _, err := rConn.Write(m.Raw); err != nil {
+                       log.Debug("[HTTPS] Error writing raw data to", initPkt.Domain(), err)
                        return
                }
        } else {
-               log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain())
-               if _, err := rConn.Write(clientHello); err != nil {
-                       log.Debug("[HTTPS] Error writing plain client hello to ", initPkt.Domain(), err)
-                       return
+               log.Debug("[HTTPS] Client sent hello ", len(m.Raw), "bytes")
+
+               if exploit {
+                       log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain())
+                       chunks := splitInChunks(m.Raw, pxy.windowSize)
+                       if _, err := writeChunks(rConn, chunks); err != nil {
+                               log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err)
+                               return
+                       }
+               } else {
+                       log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain())
+                       if _, err := rConn.Write(m.Raw); err != nil {
+                               log.Debug("[HTTPS] Error writing plain client hello to ", initPkt.Domain(), err)
+                               return
+                       }
                }
        }
LiquidTheDangerous commented 3 weeks ago

@SeJIya send link to PR please

LiquidTheDangerous commented 3 weeks ago

It looks like Telegram client proxy is working in http mode. There is no request to open tunnel aka CONNECT method. I still don't understand why the http mode doesn't work

LiquidTheDangerous commented 3 weeks ago

@SeJIya telegram doesn't work also on c31fc376108be11e02daa1b09c5fedee921fd7ee

LiquidTheDangerous commented 3 weeks ago

@xvzc some issues with handling http connections

xvzc commented 3 weeks ago

I think Telegram proxy has never been worked.

xvzc commented 3 weeks ago

Maybe Telegram no longer supports HTTP Proxy because i can see that there is no option for HTTP Proxy on Telegram Desktop, and i tried to request to some endpoints that TelegramDesktop(Linux) tries to connect, but the response was 404 Not Found.

LiquidTheDangerous commented 3 weeks ago

@xvzc

I experimented a little with telegram. There are some problems with proxying http requests to telegram api. Response from api telegram was 414 Request Line too long

Also tried to use golang http client to execute request with client requests. And, it works.

LiquidTheDangerous commented 3 weeks ago

@xvzc I believe that in http mode proxy should perform single transactions, instead of tunneling, like in case of tls

SeJIya commented 3 weeks ago

@LiquidTheDangerous my case use:

Device(Mobile Android) -> Router -> SpoofDPI Proxy Device(PC) -> Router -> Direct

all mobile device trafic proxing with SpoofDPI Proxy (telegram, WhatsApp, etc..) in router level, in version 0.10.6 telegram + WhatsApp worked, starting with 0.10.7 broken

i can create PR but don't think so my sample is best way solution

LiquidTheDangerous commented 3 weeks ago

@SeJIya Send the revision number when telegram was working

SeJIya commented 3 weeks ago

@LiquidTheDangerous i tested commit per commit for find it ("broken" commit announced already in top message)

6b0547b4310b90cb1c31fc30250b380ec6245308 - still worked 852b789ac3f5b52288a2136102dea6408e2a55b7 - not worked

LiquidTheDangerous commented 2 weeks ago

@SeJIya It doesn't work for me on any of these revisions. The proxy for telegram doesn't work in HTTPS mode, it disguises itself as HTTP, I don't understand how these changes could help

same, this issues after 852b789

just worked example (diff between v0.10.7):

diff --git a/packet/https.go b/packet/https.go
index 49abeb8..bf9467c 100644
--- a/packet/https.go
+++ b/packet/https.go
@@ -45,10 +45,12 @@ func ReadTLSMessage(r io.Reader) (*TLSMessage, error) {

        raw := make([]byte, header.PayloadLen+TLSHeaderLen) // maybe allocate only 4096

        copy(raw[0:TLSHeaderLen], rawHeader[:])
-       _, err = io.ReadFull(r, raw[TLSHeaderLen:])
+       n, err := r.Read(raw[TLSHeaderLen:])
        if err != nil {
                return nil, err
        }
+       raw = raw[:n+TLSHeaderLen]
+       header.PayloadLen = uint16(n) // maybe don't need actualize len

        hello := &TLSMessage{
                Header:     header,
diff --git a/proxy/https.go b/proxy/https.go
index c4f256e..67014ff 100644
--- a/proxy/https.go
+++ b/proxy/https.go
@@ -46,29 +46,35 @@ func (pxy *Proxy) handleHttps(lConn *net.TCPConn, exploit bool, initPkt *packet.

        // Read client hello
        m, err := packet.ReadTLSMessage(lConn)
-       if err != nil || !m.IsClientHello() {
+       if err != nil {
                log.Debug("[HTTPS] Error reading client hello from the client", err)
                return
        }
-       clientHello := m.Raw
-
-       log.Debug("[HTTPS] Client sent hello ", len(clientHello), "bytes")

        // Generate a go routine that reads from the server
        go Serve(rConn, lConn, "[HTTPS]", rConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout, pxy.bufferSize)

-       if exploit {
-               log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain())
-               chunks := splitInChunks(clientHello, pxy.windowSize)
-               if _, err := writeChunks(rConn, chunks); err != nil {
-                       log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err)
+       if !m.IsClientHello() {
+               if _, err := rConn.Write(m.Raw); err != nil {
+                       log.Debug("[HTTPS] Error writing raw data to", initPkt.Domain(), err)
                        return
                }
        } else {
-               log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain())
-               if _, err := rConn.Write(clientHello); err != nil {
-                       log.Debug("[HTTPS] Error writing plain client hello to ", initPkt.Domain(), err)
-                       return
+               log.Debug("[HTTPS] Client sent hello ", len(m.Raw), "bytes")
+
+               if exploit {
+                       log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain())
+                       chunks := splitInChunks(m.Raw, pxy.windowSize)
+                       if _, err := writeChunks(rConn, chunks); err != nil {
+                               log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err)
+                               return
+                       }
+               } else {
+                       log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain())
+                       if _, err := rConn.Write(m.Raw); err != nil {
+                               log.Debug("[HTTPS] Error writing plain client hello to ", initPkt.Domain(), err)
+                               return
+                       }
                }
        }
LiquidTheDangerous commented 2 weeks ago

@SeJIya I use these settings. Spoof-dpi bind on port 1080

image

SeJIya commented 2 weeks ago

@LiquidTheDangerous im use schema: Device(Mobile Android) -> Router -> SpoofDPI Proxy (bind on 1337 port) not direct set proxy in telegram

in router settings: image

before 852b789 - reading less than or equal 4096 any bytes and proxying

after 852b789 added check for "is hello msg"

in my case maby need setup routing with netfilter/iptables. and likly it issues not software problem "SpoofDPI"