Skip to content

Commit 80d78aa

Browse files
committed
feat(vpn): replace buggy custom TCP/UDP bridge with robust gVisor-based FakeDNS proxy via tun2socks interceptor
1 parent f9cfdcf commit 80d78aa

7 files changed

Lines changed: 515 additions & 1169 deletions

File tree

mobile/mobile.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,34 @@ func GetListenAddress() string {
148148
return ""
149149
}
150150

151-
// StartTunBridge starts the TUN bridge with DNS interception.
151+
// StartTunBridge starts the TUN bridge with DNS interception using FakeDNS proxy.
152152
func StartTunBridge(tunFd int64, mtu int64, socksAddr string) error {
153-
return tun.StartTunBridge(int32(tunFd), int32(mtu), socksAddr)
153+
proxyAddr, err := tun.StartFakeDNSProxy(socksAddr)
154+
if err != nil {
155+
return err
156+
}
157+
158+
key := &engine.Key{
159+
Proxy: "socks5://" + proxyAddr,
160+
Device: fmt.Sprintf("fd://%d", tunFd),
161+
MTU: int(mtu),
162+
}
163+
164+
engine.Insert(key)
165+
engine.Start()
166+
167+
return nil
154168
}
155169

156170
// StopTunBridge stops the DNS-aware TUN bridge.
157171
func StopTunBridge() {
158-
tun.StopTunBridge()
172+
engine.Stop()
173+
tun.StopFakeDNSProxy()
159174
}
160175

161176
// IsTunBridgeRunning returns true if the DNS-aware TUN bridge is active.
162177
func IsTunBridgeRunning() bool {
163-
return tun.IsTunBridgeRunning()
178+
return tun.IsFakeDNSProxyRunning()
164179
}
165180

166181
// GetTunBandwidth returns upload/download counters from the TUN bridge.

mobile/tun/dns_mapper.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package tun
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"sync"
7+
"sync/atomic"
8+
)
9+
10+
type DNSMapper struct {
11+
mu sync.RWMutex
12+
hostnameToIP map[string]string
13+
ipToHostname map[string]string
14+
counter uint32
15+
}
16+
17+
func NewDNSMapper() *DNSMapper {
18+
return &DNSMapper{
19+
hostnameToIP: make(map[string]string),
20+
ipToHostname: make(map[string]string),
21+
counter: 1,
22+
}
23+
}
24+
25+
func (d *DNSMapper) GetFakeIP(hostname string) string {
26+
d.mu.Lock()
27+
defer d.mu.Unlock()
28+
29+
if ip, ok := d.hostnameToIP[hostname]; ok {
30+
return ip
31+
}
32+
33+
counter := atomic.AddUint32(&d.counter, 1)
34+
if counter > 65535 {
35+
atomic.StoreUint32(&d.counter, 1)
36+
counter = 1
37+
}
38+
39+
octet3 := byte(counter >> 8)
40+
octet4 := byte(counter & 0xFF)
41+
fakeIP := fmt.Sprintf("198.18.%d.%d", octet3, octet4)
42+
43+
d.hostnameToIP[hostname] = fakeIP
44+
d.ipToHostname[fakeIP] = hostname
45+
46+
log.Printf("[TUN-DNS] Mapped %s -> %s", hostname, fakeIP)
47+
return fakeIP
48+
}
49+
50+
func (d *DNSMapper) GetHostname(fakeIP string) (string, bool) {
51+
d.mu.RLock()
52+
defer d.mu.RUnlock()
53+
hostname, ok := d.ipToHostname[fakeIP]
54+
return hostname, ok
55+
}

0 commit comments

Comments
 (0)