Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

service_linux.go 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. //go:build linux
  2. package desync
  3. import (
  4. "encoding/binary"
  5. "fmt"
  6. "io"
  7. "sync"
  8. "time"
  9. "golang.org/x/sys/unix"
  10. )
  11. const (
  12. tcpFlagFin = 0x01
  13. tcpFlagSyn = 0x02
  14. tcpFlagPsh = 0x08
  15. tcpFlagAck = 0x10
  16. desyncStateTTL = 30 * time.Second
  17. desyncCleanupEvery = time.Second
  18. ethernetHeaderLen = 14
  19. vlanHeaderLen = 4
  20. ipv4HeaderLen = 20
  21. tcpHeaderLen = 20
  22. )
  23. var fakeTLSAlert = []byte{0x15, 0x03, 0x03, 0x00, 0x02, 0x02, 0x28}
  24. type runner struct {
  25. port uint16
  26. packetFD int
  27. rawFD int
  28. wg sync.WaitGroup
  29. closeOnce sync.Once
  30. state map[connKey]*connState
  31. ident uint16
  32. cleanup time.Time
  33. }
  34. type connKey struct {
  35. clientIP [4]byte
  36. localIP [4]byte
  37. clientPort uint16
  38. }
  39. type connState struct {
  40. clientSeq uint32
  41. serverSeq uint32
  42. expiresAt time.Time
  43. sentMask uint8
  44. }
  45. type tcpPacket struct {
  46. srcIP [4]byte
  47. dstIP [4]byte
  48. srcPort uint16
  49. dstPort uint16
  50. seq uint32
  51. ack uint32
  52. flags byte
  53. }
  54. func Start(port int) (io.Closer, error) {
  55. if port <= 0 || port > 65535 {
  56. return nil, fmt.Errorf("invalid desync port: %d", port)
  57. }
  58. packetFD, err := unix.Socket(unix.AF_PACKET, unix.SOCK_RAW|unix.SOCK_CLOEXEC, int(htons(unix.ETH_P_IP)))
  59. if err != nil {
  60. return nil, fmt.Errorf("cannot open packet socket: %w", err)
  61. }
  62. rawFD, err := unix.Socket(unix.AF_INET, unix.SOCK_RAW|unix.SOCK_CLOEXEC, unix.IPPROTO_RAW)
  63. if err != nil {
  64. unix.Close(packetFD) //nolint: errcheck
  65. return nil, fmt.Errorf("cannot open raw ipv4 socket: %w", err)
  66. }
  67. if err := unix.SetsockoptInt(rawFD, unix.IPPROTO_IP, unix.IP_HDRINCL, 1); err != nil {
  68. unix.Close(packetFD) //nolint: errcheck
  69. unix.Close(rawFD) //nolint: errcheck
  70. return nil, fmt.Errorf("cannot enable IP_HDRINCL: %w", err)
  71. }
  72. r := &runner{
  73. port: uint16(port),
  74. packetFD: packetFD,
  75. rawFD: rawFD,
  76. state: map[connKey]*connState{},
  77. }
  78. r.wg.Add(1)
  79. go r.loop()
  80. return r, nil
  81. }
  82. func (r *runner) Close() error {
  83. r.closeOnce.Do(func() {
  84. unix.Close(r.packetFD) //nolint: errcheck
  85. unix.Close(r.rawFD) //nolint: errcheck
  86. r.wg.Wait()
  87. })
  88. return nil
  89. }
  90. func (r *runner) loop() {
  91. defer r.wg.Done()
  92. buf := make([]byte, 64*1024)
  93. for {
  94. n, _, err := unix.Recvfrom(r.packetFD, buf, 0)
  95. if err != nil {
  96. if err == unix.EBADF || err == unix.EINVAL {
  97. return
  98. }
  99. continue
  100. }
  101. packet, ok := parseIPv4TCP(buf[:n])
  102. if !ok {
  103. continue
  104. }
  105. switch {
  106. case packet.dstPort == r.port:
  107. r.handleInbound(packet)
  108. case packet.srcPort == r.port:
  109. r.handleOutbound(packet)
  110. }
  111. }
  112. }
  113. func (r *runner) handleInbound(packet tcpPacket) {
  114. key := connKey{
  115. clientIP: packet.srcIP,
  116. localIP: packet.dstIP,
  117. clientPort: packet.srcPort,
  118. }
  119. now := time.Now()
  120. r.cleanupExpired(now)
  121. state := r.state[key]
  122. if packet.flags&tcpFlagSyn != 0 && packet.flags&tcpFlagAck == 0 {
  123. if state == nil {
  124. state = &connState{}
  125. r.state[key] = state
  126. }
  127. state.clientSeq = packet.seq
  128. state.expiresAt = now.Add(desyncStateTTL)
  129. return
  130. }
  131. if state == nil {
  132. return
  133. }
  134. state.expiresAt = now.Add(desyncStateTTL)
  135. if packet.flags&tcpFlagFin != 0 {
  136. delete(r.state, key)
  137. return
  138. }
  139. if packet.flags&tcpFlagAck != 0 &&
  140. state.clientSeq != 0 &&
  141. state.serverSeq != 0 &&
  142. packet.seq == state.clientSeq+1 &&
  143. packet.ack == state.serverSeq+1 {
  144. r.sendFake(key, state, 1)
  145. delete(r.state, key)
  146. }
  147. }
  148. func (r *runner) handleOutbound(packet tcpPacket) {
  149. if packet.flags&tcpFlagSyn == 0 || packet.flags&tcpFlagAck == 0 {
  150. return
  151. }
  152. key := connKey{
  153. clientIP: packet.dstIP,
  154. localIP: packet.srcIP,
  155. clientPort: packet.dstPort,
  156. }
  157. now := time.Now()
  158. r.cleanupExpired(now)
  159. state := r.state[key]
  160. if state == nil {
  161. state = &connState{}
  162. r.state[key] = state
  163. }
  164. state.serverSeq = packet.seq
  165. state.expiresAt = now.Add(desyncStateTTL)
  166. if state.clientSeq != 0 {
  167. r.sendFake(key, state, 0)
  168. }
  169. }
  170. func (r *runner) sendFake(key connKey, state *connState, phase uint8) {
  171. mask := uint8(1) << phase
  172. if state.sentMask&mask != 0 {
  173. return
  174. }
  175. state.sentMask |= mask
  176. r.ident++
  177. packet := buildIPv4TCPPacket(key.localIP, key.clientIP,
  178. r.port, key.clientPort, state.serverSeq+1, state.clientSeq+1, r.ident)
  179. unix.Sendto(r.rawFD, packet, 0, &unix.SockaddrInet4{Addr: key.clientIP}) //nolint: errcheck
  180. }
  181. func (r *runner) cleanupExpired(now time.Time) {
  182. if now.Before(r.cleanup) {
  183. return
  184. }
  185. r.cleanup = now.Add(desyncCleanupEvery)
  186. for key, state := range r.state {
  187. if now.After(state.expiresAt) {
  188. delete(r.state, key)
  189. }
  190. }
  191. }
  192. func parseIPv4TCP(frame []byte) (tcpPacket, bool) {
  193. if len(frame) < ethernetHeaderLen {
  194. return tcpPacket{}, false
  195. }
  196. etherType := binary.BigEndian.Uint16(frame[12:14])
  197. ipOffset := ethernetHeaderLen
  198. if etherType == 0x8100 || etherType == 0x88a8 {
  199. if len(frame) < ethernetHeaderLen+vlanHeaderLen {
  200. return tcpPacket{}, false
  201. }
  202. etherType = binary.BigEndian.Uint16(frame[16:18])
  203. ipOffset += vlanHeaderLen
  204. }
  205. if etherType != unix.ETH_P_IP {
  206. return tcpPacket{}, false
  207. }
  208. if len(frame) < ipOffset+ipv4HeaderLen {
  209. return tcpPacket{}, false
  210. }
  211. ip := frame[ipOffset:]
  212. ihl := int(ip[0]&0x0f) * 4
  213. if ihl < ipv4HeaderLen || len(ip) < ihl+tcpHeaderLen {
  214. return tcpPacket{}, false
  215. }
  216. if ip[0]>>4 != 4 || ip[9] != unix.IPPROTO_TCP {
  217. return tcpPacket{}, false
  218. }
  219. fragment := binary.BigEndian.Uint16(ip[6:8])
  220. if fragment&0x1fff != 0 {
  221. return tcpPacket{}, false
  222. }
  223. totalLen := int(binary.BigEndian.Uint16(ip[2:4]))
  224. if totalLen < ihl+tcpHeaderLen || totalLen > len(ip) {
  225. return tcpPacket{}, false
  226. }
  227. tcp := ip[ihl:totalLen]
  228. dataOffset := int(tcp[12]>>4) * 4
  229. if dataOffset < tcpHeaderLen || len(tcp) < dataOffset {
  230. return tcpPacket{}, false
  231. }
  232. var packet tcpPacket
  233. copy(packet.srcIP[:], ip[12:16])
  234. copy(packet.dstIP[:], ip[16:20])
  235. packet.srcPort = binary.BigEndian.Uint16(tcp[0:2])
  236. packet.dstPort = binary.BigEndian.Uint16(tcp[2:4])
  237. packet.seq = binary.BigEndian.Uint32(tcp[4:8])
  238. packet.ack = binary.BigEndian.Uint32(tcp[8:12])
  239. packet.flags = tcp[13]
  240. return packet, true
  241. }
  242. func buildIPv4TCPPacket(
  243. srcIP [4]byte,
  244. dstIP [4]byte,
  245. srcPort uint16,
  246. dstPort uint16,
  247. seq uint32,
  248. ack uint32,
  249. ident uint16,
  250. ) []byte {
  251. packet := make([]byte, ipv4HeaderLen+tcpHeaderLen+len(fakeTLSAlert))
  252. ip := packet[:ipv4HeaderLen]
  253. tcp := packet[ipv4HeaderLen : ipv4HeaderLen+tcpHeaderLen]
  254. ip[0] = 0x45
  255. binary.BigEndian.PutUint16(ip[2:4], uint16(len(packet)))
  256. binary.BigEndian.PutUint16(ip[4:6], ident)
  257. binary.BigEndian.PutUint16(ip[6:8], 0x4000)
  258. ip[8] = 64
  259. ip[9] = unix.IPPROTO_TCP
  260. copy(ip[12:16], srcIP[:])
  261. copy(ip[16:20], dstIP[:])
  262. binary.BigEndian.PutUint16(ip[10:12], checksum(ip))
  263. binary.BigEndian.PutUint16(tcp[0:2], srcPort)
  264. binary.BigEndian.PutUint16(tcp[2:4], dstPort)
  265. binary.BigEndian.PutUint32(tcp[4:8], seq)
  266. binary.BigEndian.PutUint32(tcp[8:12], ack)
  267. tcp[12] = 5 << 4
  268. tcp[13] = tcpFlagPsh | tcpFlagAck
  269. binary.BigEndian.PutUint16(tcp[14:16], 65535)
  270. copy(packet[ipv4HeaderLen+tcpHeaderLen:], fakeTLSAlert)
  271. // The checksum is deliberately invalid: DPI can still inspect the fake TLS
  272. // alert, but the client TCP stack should drop it.
  273. sum := tcpChecksum(srcIP, dstIP, tcp) ^ 0xffff
  274. if sum == 0 {
  275. sum = 0xffff
  276. }
  277. binary.BigEndian.PutUint16(tcp[16:18], sum)
  278. return packet
  279. }
  280. func tcpChecksum(srcIP, dstIP [4]byte, tcp []byte) uint16 {
  281. pseudo := make([]byte, 12+len(tcp)+len(fakeTLSAlert))
  282. copy(pseudo[0:4], srcIP[:])
  283. copy(pseudo[4:8], dstIP[:])
  284. pseudo[9] = unix.IPPROTO_TCP
  285. binary.BigEndian.PutUint16(pseudo[10:12], uint16(len(tcp)+len(fakeTLSAlert)))
  286. copy(pseudo[12:], tcp)
  287. copy(pseudo[12+len(tcp):], fakeTLSAlert)
  288. return checksum(pseudo)
  289. }
  290. func checksum(data []byte) uint16 {
  291. var sum uint32
  292. for len(data) >= 2 {
  293. sum += uint32(binary.BigEndian.Uint16(data[:2]))
  294. data = data[2:]
  295. }
  296. if len(data) == 1 {
  297. sum += uint32(data[0]) << 8
  298. }
  299. for sum>>16 != 0 {
  300. sum = (sum & 0xffff) + (sum >> 16)
  301. }
  302. return ^uint16(sum)
  303. }
  304. func htons(value uint16) uint16 {
  305. return (value << 8) | (value >> 8)
  306. }