@push.rocks/smartproxy 19.3.2 → 19.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/forwarding/factory/forwarding-factory.js +29 -1
  3. package/dist_ts/http/index.d.ts +1 -3
  4. package/dist_ts/http/index.js +4 -10
  5. package/dist_ts/http/models/http-types.d.ts +4 -91
  6. package/dist_ts/http/models/http-types.js +5 -60
  7. package/dist_ts/http/router/proxy-router.d.ts +1 -1
  8. package/dist_ts/http/router/route-router.d.ts +1 -1
  9. package/dist_ts/index.d.ts +9 -7
  10. package/dist_ts/index.js +10 -7
  11. package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.d.ts +2 -2
  12. package/dist_ts/proxies/{network-proxy → http-proxy}/certificate-manager.js +1 -1
  13. package/dist_ts/proxies/{network-proxy → http-proxy}/connection-pool.d.ts +2 -2
  14. package/dist_ts/proxies/http-proxy/connection-pool.js +210 -0
  15. package/dist_ts/proxies/http-proxy/context-creator.js +108 -0
  16. package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.js +1 -1
  17. package/dist_ts/proxies/http-proxy/handlers/index.d.ts +5 -0
  18. package/dist_ts/proxies/http-proxy/handlers/index.js +6 -0
  19. package/dist_ts/proxies/http-proxy/handlers/redirect-handler.d.ts +18 -0
  20. package/dist_ts/proxies/http-proxy/handlers/redirect-handler.js +78 -0
  21. package/dist_ts/proxies/http-proxy/handlers/static-handler.d.ts +19 -0
  22. package/dist_ts/proxies/http-proxy/handlers/static-handler.js +203 -0
  23. package/dist_ts/proxies/{network-proxy/network-proxy.d.ts → http-proxy/http-proxy.d.ts} +10 -9
  24. package/dist_ts/proxies/{network-proxy/network-proxy.js → http-proxy/http-proxy.js} +13 -12
  25. package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.js +1 -1
  26. package/dist_ts/proxies/http-proxy/http2-request-handler.js +201 -0
  27. package/dist_ts/proxies/{network-proxy → http-proxy}/index.d.ts +2 -2
  28. package/dist_ts/proxies/http-proxy/index.js +12 -0
  29. package/dist_ts/proxies/http-proxy/models/http-types.d.ts +119 -0
  30. package/dist_ts/proxies/http-proxy/models/http-types.js +112 -0
  31. package/dist_ts/proxies/http-proxy/models/index.d.ts +5 -0
  32. package/dist_ts/proxies/http-proxy/models/index.js +6 -0
  33. package/dist_ts/proxies/{network-proxy → http-proxy}/models/types.d.ts +2 -2
  34. package/dist_ts/proxies/http-proxy/models/types.js +276 -0
  35. package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.d.ts +3 -3
  36. package/dist_ts/proxies/{network-proxy → http-proxy}/request-handler.js +2 -2
  37. package/dist_ts/proxies/http-proxy/security-manager.js +255 -0
  38. package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.d.ts +3 -3
  39. package/dist_ts/proxies/{network-proxy → http-proxy}/websocket-handler.js +2 -2
  40. package/dist_ts/proxies/index.d.ts +5 -5
  41. package/dist_ts/proxies/index.js +5 -5
  42. package/dist_ts/proxies/smart-proxy/certificate-manager.d.ts +4 -4
  43. package/dist_ts/proxies/smart-proxy/certificate-manager.js +11 -11
  44. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +41 -0
  45. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +121 -0
  46. package/dist_ts/proxies/smart-proxy/index.d.ts +2 -1
  47. package/dist_ts/proxies/smart-proxy/index.js +4 -2
  48. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +2 -2
  49. package/dist_ts/proxies/smart-proxy/port-manager.js +3 -3
  50. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +3 -3
  51. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +24 -265
  52. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
  53. package/dist_ts/proxies/smart-proxy/smart-proxy.js +25 -25
  54. package/dist_ts/routing/index.d.ts +5 -0
  55. package/dist_ts/routing/index.js +8 -0
  56. package/dist_ts/routing/models/http-types.d.ts +6 -0
  57. package/dist_ts/routing/models/http-types.js +7 -0
  58. package/dist_ts/routing/router/index.d.ts +8 -0
  59. package/dist_ts/routing/router/index.js +7 -0
  60. package/dist_ts/{classes.router.d.ts → routing/router/proxy-router.d.ts} +14 -11
  61. package/dist_ts/{classes.router.js → routing/router/proxy-router.js} +2 -2
  62. package/dist_ts/routing/router/route-router.d.ts +108 -0
  63. package/dist_ts/routing/router/route-router.js +393 -0
  64. package/package.json +1 -1
  65. package/readme.md +12 -12
  66. package/readme.plan.md +152 -257
  67. package/ts/00_commitinfo_data.ts +1 -1
  68. package/ts/forwarding/factory/forwarding-factory.ts +28 -0
  69. package/ts/index.ts +13 -9
  70. package/ts/proxies/{network-proxy → http-proxy}/certificate-manager.ts +2 -2
  71. package/ts/proxies/{network-proxy → http-proxy}/connection-pool.ts +2 -2
  72. package/ts/proxies/http-proxy/handlers/index.ts +6 -0
  73. package/ts/proxies/http-proxy/handlers/redirect-handler.ts +105 -0
  74. package/ts/proxies/http-proxy/handlers/static-handler.ts +251 -0
  75. package/ts/proxies/{network-proxy/network-proxy.ts → http-proxy/http-proxy.ts} +15 -14
  76. package/ts/proxies/{network-proxy → http-proxy}/index.ts +3 -3
  77. package/ts/proxies/http-proxy/models/http-types.ts +165 -0
  78. package/ts/proxies/http-proxy/models/index.ts +5 -0
  79. package/ts/proxies/{network-proxy → http-proxy}/models/types.ts +2 -2
  80. package/ts/proxies/{network-proxy → http-proxy}/request-handler.ts +3 -3
  81. package/ts/proxies/{network-proxy → http-proxy}/websocket-handler.ts +3 -3
  82. package/ts/proxies/index.ts +7 -7
  83. package/ts/proxies/smart-proxy/certificate-manager.ts +10 -10
  84. package/ts/proxies/smart-proxy/{network-proxy-bridge.ts → http-proxy-bridge.ts} +44 -44
  85. package/ts/proxies/smart-proxy/index.ts +4 -1
  86. package/ts/proxies/smart-proxy/models/interfaces.ts +3 -3
  87. package/ts/proxies/smart-proxy/port-manager.ts +2 -2
  88. package/ts/proxies/smart-proxy/route-connection-handler.ts +23 -307
  89. package/ts/proxies/smart-proxy/smart-proxy.ts +25 -25
  90. package/ts/routing/index.ts +9 -0
  91. package/ts/routing/models/http-types.ts +6 -0
  92. package/ts/{http → routing}/router/proxy-router.ts +1 -1
  93. package/ts/{http → routing}/router/route-router.ts +1 -1
  94. package/dist_ts/certificate/acme/acme-factory.d.ts +0 -17
  95. package/dist_ts/certificate/acme/acme-factory.js +0 -40
  96. package/dist_ts/certificate/acme/challenge-handler.d.ts +0 -44
  97. package/dist_ts/certificate/acme/challenge-handler.js +0 -92
  98. package/dist_ts/certificate/acme/index.d.ts +0 -4
  99. package/dist_ts/certificate/acme/index.js +0 -5
  100. package/dist_ts/certificate/certificate-manager.d.ts +0 -150
  101. package/dist_ts/certificate/certificate-manager.js +0 -505
  102. package/dist_ts/certificate/events/certificate-events.d.ts +0 -33
  103. package/dist_ts/certificate/events/certificate-events.js +0 -38
  104. package/dist_ts/certificate/events/simplified-events.d.ts +0 -56
  105. package/dist_ts/certificate/events/simplified-events.js +0 -13
  106. package/dist_ts/certificate/index.d.ts +0 -30
  107. package/dist_ts/certificate/index.js +0 -37
  108. package/dist_ts/certificate/models/certificate-errors.d.ts +0 -69
  109. package/dist_ts/certificate/models/certificate-errors.js +0 -141
  110. package/dist_ts/certificate/models/certificate-strategy.d.ts +0 -60
  111. package/dist_ts/certificate/models/certificate-strategy.js +0 -73
  112. package/dist_ts/certificate/models/certificate-types.d.ts +0 -97
  113. package/dist_ts/certificate/models/certificate-types.js +0 -2
  114. package/dist_ts/certificate/providers/cert-provisioner.d.ts +0 -119
  115. package/dist_ts/certificate/providers/cert-provisioner.js +0 -422
  116. package/dist_ts/certificate/providers/index.d.ts +0 -4
  117. package/dist_ts/certificate/providers/index.js +0 -5
  118. package/dist_ts/certificate/simplified-certificate-manager.d.ts +0 -150
  119. package/dist_ts/certificate/simplified-certificate-manager.js +0 -501
  120. package/dist_ts/certificate/storage/file-storage.d.ts +0 -66
  121. package/dist_ts/certificate/storage/file-storage.js +0 -194
  122. package/dist_ts/certificate/storage/index.d.ts +0 -4
  123. package/dist_ts/certificate/storage/index.js +0 -5
  124. package/dist_ts/certificate/utils/certificate-helpers.d.ts +0 -17
  125. package/dist_ts/certificate/utils/certificate-helpers.js +0 -45
  126. package/dist_ts/classes.iptablesproxy.d.ts +0 -112
  127. package/dist_ts/classes.iptablesproxy.js +0 -765
  128. package/dist_ts/classes.networkproxy.d.ts +0 -243
  129. package/dist_ts/classes.networkproxy.js +0 -1424
  130. package/dist_ts/classes.nftablesproxy.d.ts +0 -219
  131. package/dist_ts/classes.nftablesproxy.js +0 -1542
  132. package/dist_ts/classes.port80handler.d.ts +0 -215
  133. package/dist_ts/classes.port80handler.js +0 -736
  134. package/dist_ts/classes.portproxy.d.ts +0 -171
  135. package/dist_ts/classes.portproxy.js +0 -1802
  136. package/dist_ts/classes.pp.acmemanager.d.ts +0 -34
  137. package/dist_ts/classes.pp.acmemanager.js +0 -123
  138. package/dist_ts/classes.pp.connectionhandler.d.ts +0 -39
  139. package/dist_ts/classes.pp.connectionhandler.js +0 -754
  140. package/dist_ts/classes.pp.connectionmanager.d.ts +0 -78
  141. package/dist_ts/classes.pp.connectionmanager.js +0 -378
  142. package/dist_ts/classes.pp.domainconfigmanager.d.ts +0 -55
  143. package/dist_ts/classes.pp.domainconfigmanager.js +0 -103
  144. package/dist_ts/classes.pp.interfaces.d.ts +0 -133
  145. package/dist_ts/classes.pp.interfaces.js +0 -2
  146. package/dist_ts/classes.pp.networkproxybridge.d.ts +0 -57
  147. package/dist_ts/classes.pp.networkproxybridge.js +0 -306
  148. package/dist_ts/classes.pp.portproxy.d.ts +0 -64
  149. package/dist_ts/classes.pp.portproxy.js +0 -567
  150. package/dist_ts/classes.pp.portrangemanager.d.ts +0 -56
  151. package/dist_ts/classes.pp.portrangemanager.js +0 -179
  152. package/dist_ts/classes.pp.securitymanager.d.ts +0 -47
  153. package/dist_ts/classes.pp.securitymanager.js +0 -126
  154. package/dist_ts/classes.pp.snihandler.d.ts +0 -153
  155. package/dist_ts/classes.pp.snihandler.js +0 -1053
  156. package/dist_ts/classes.pp.timeoutmanager.d.ts +0 -47
  157. package/dist_ts/classes.pp.timeoutmanager.js +0 -154
  158. package/dist_ts/classes.pp.tlsalert.d.ts +0 -149
  159. package/dist_ts/classes.pp.tlsalert.js +0 -225
  160. package/dist_ts/classes.pp.tlsmanager.d.ts +0 -57
  161. package/dist_ts/classes.pp.tlsmanager.js +0 -132
  162. package/dist_ts/classes.snihandler.d.ts +0 -198
  163. package/dist_ts/classes.snihandler.js +0 -1210
  164. package/dist_ts/classes.sslredirect.d.ts +0 -8
  165. package/dist_ts/classes.sslredirect.js +0 -28
  166. package/dist_ts/common/acmeFactory.d.ts +0 -9
  167. package/dist_ts/common/acmeFactory.js +0 -20
  168. package/dist_ts/common/port80-adapter.d.ts +0 -11
  169. package/dist_ts/common/port80-adapter.js +0 -87
  170. package/dist_ts/examples/forwarding-example.d.ts +0 -1
  171. package/dist_ts/examples/forwarding-example.js +0 -96
  172. package/dist_ts/forwarding/config/domain-config.d.ts +0 -12
  173. package/dist_ts/forwarding/config/domain-config.js +0 -12
  174. package/dist_ts/forwarding/config/domain-manager.d.ts +0 -86
  175. package/dist_ts/forwarding/config/domain-manager.js +0 -242
  176. package/dist_ts/helpers.certificates.d.ts +0 -5
  177. package/dist_ts/helpers.certificates.js +0 -23
  178. package/dist_ts/http/port80/acme-interfaces.d.ts +0 -108
  179. package/dist_ts/http/port80/acme-interfaces.js +0 -51
  180. package/dist_ts/http/port80/challenge-responder.d.ts +0 -53
  181. package/dist_ts/http/port80/challenge-responder.js +0 -203
  182. package/dist_ts/http/port80/index.d.ts +0 -6
  183. package/dist_ts/http/port80/index.js +0 -9
  184. package/dist_ts/http/port80/port80-handler.d.ts +0 -136
  185. package/dist_ts/http/port80/port80-handler.js +0 -592
  186. package/dist_ts/http/redirects/index.d.ts +0 -4
  187. package/dist_ts/http/redirects/index.js +0 -5
  188. package/dist_ts/networkproxy/classes.np.certificatemanager.d.ts +0 -77
  189. package/dist_ts/networkproxy/classes.np.certificatemanager.js +0 -372
  190. package/dist_ts/networkproxy/classes.np.connectionpool.d.ts +0 -47
  191. package/dist_ts/networkproxy/classes.np.connectionpool.js +0 -210
  192. package/dist_ts/networkproxy/classes.np.networkproxy.d.ts +0 -118
  193. package/dist_ts/networkproxy/classes.np.networkproxy.js +0 -387
  194. package/dist_ts/networkproxy/classes.np.requesthandler.d.ts +0 -56
  195. package/dist_ts/networkproxy/classes.np.requesthandler.js +0 -393
  196. package/dist_ts/networkproxy/classes.np.types.d.ts +0 -83
  197. package/dist_ts/networkproxy/classes.np.types.js +0 -35
  198. package/dist_ts/networkproxy/classes.np.websockethandler.d.ts +0 -38
  199. package/dist_ts/networkproxy/classes.np.websockethandler.js +0 -188
  200. package/dist_ts/networkproxy/index.d.ts +0 -1
  201. package/dist_ts/networkproxy/index.js +0 -4
  202. package/dist_ts/nfttablesproxy/classes.nftablesproxy.d.ts +0 -219
  203. package/dist_ts/nfttablesproxy/classes.nftablesproxy.js +0 -1542
  204. package/dist_ts/port80handler/classes.port80handler.d.ts +0 -10
  205. package/dist_ts/port80handler/classes.port80handler.js +0 -16
  206. package/dist_ts/proxies/network-proxy/connection-pool.js +0 -210
  207. package/dist_ts/proxies/network-proxy/context-creator.js +0 -108
  208. package/dist_ts/proxies/network-proxy/http2-request-handler.js +0 -201
  209. package/dist_ts/proxies/network-proxy/index.js +0 -12
  210. package/dist_ts/proxies/network-proxy/models/index.d.ts +0 -4
  211. package/dist_ts/proxies/network-proxy/models/index.js +0 -5
  212. package/dist_ts/proxies/network-proxy/models/types.js +0 -276
  213. package/dist_ts/proxies/network-proxy/security-manager.js +0 -255
  214. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.d.ts +0 -48
  215. package/dist_ts/proxies/network-proxy/simplified-certificate-bridge.js +0 -76
  216. package/dist_ts/proxies/smart-proxy/connection-handler.d.ts +0 -39
  217. package/dist_ts/proxies/smart-proxy/connection-handler.js +0 -894
  218. package/dist_ts/proxies/smart-proxy/domain-config-manager.d.ts +0 -110
  219. package/dist_ts/proxies/smart-proxy/domain-config-manager.js +0 -386
  220. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.d.ts +0 -168
  221. package/dist_ts/proxies/smart-proxy/legacy-smart-proxy.js +0 -642
  222. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.d.ts +0 -65
  223. package/dist_ts/proxies/smart-proxy/models/simplified-smartproxy-config.js +0 -31
  224. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.d.ts +0 -102
  225. package/dist_ts/proxies/smart-proxy/models/smartproxy-options.js +0 -73
  226. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +0 -41
  227. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +0 -121
  228. package/dist_ts/proxies/smart-proxy/port-range-manager.d.ts +0 -56
  229. package/dist_ts/proxies/smart-proxy/port-range-manager.js +0 -176
  230. package/dist_ts/proxies/smart-proxy/route-helpers/index.d.ts +0 -9
  231. package/dist_ts/proxies/smart-proxy/route-helpers/index.js +0 -11
  232. package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +0 -7
  233. package/dist_ts/proxies/smart-proxy/route-helpers.js +0 -9
  234. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.d.ts +0 -41
  235. package/dist_ts/proxies/smart-proxy/simplified-smart-proxy.js +0 -132
  236. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.d.ts +0 -51
  237. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.js +0 -124
  238. package/dist_ts/redirect/classes.redirect.d.ts +0 -96
  239. package/dist_ts/redirect/classes.redirect.js +0 -194
  240. package/dist_ts/smartproxy/classes.pp.certprovisioner.d.ts +0 -54
  241. package/dist_ts/smartproxy/classes.pp.certprovisioner.js +0 -179
  242. package/dist_ts/smartproxy/classes.pp.connectionhandler.d.ts +0 -39
  243. package/dist_ts/smartproxy/classes.pp.connectionhandler.js +0 -894
  244. package/dist_ts/smartproxy/classes.pp.connectionmanager.d.ts +0 -78
  245. package/dist_ts/smartproxy/classes.pp.connectionmanager.js +0 -378
  246. package/dist_ts/smartproxy/classes.pp.domainconfigmanager.d.ts +0 -94
  247. package/dist_ts/smartproxy/classes.pp.domainconfigmanager.js +0 -255
  248. package/dist_ts/smartproxy/classes.pp.interfaces.d.ts +0 -103
  249. package/dist_ts/smartproxy/classes.pp.interfaces.js +0 -2
  250. package/dist_ts/smartproxy/classes.pp.networkproxybridge.d.ts +0 -62
  251. package/dist_ts/smartproxy/classes.pp.networkproxybridge.js +0 -316
  252. package/dist_ts/smartproxy/classes.pp.portrangemanager.d.ts +0 -56
  253. package/dist_ts/smartproxy/classes.pp.portrangemanager.js +0 -176
  254. package/dist_ts/smartproxy/classes.pp.securitymanager.d.ts +0 -64
  255. package/dist_ts/smartproxy/classes.pp.securitymanager.js +0 -149
  256. package/dist_ts/smartproxy/classes.pp.snihandler.d.ts +0 -153
  257. package/dist_ts/smartproxy/classes.pp.snihandler.js +0 -1053
  258. package/dist_ts/smartproxy/classes.pp.timeoutmanager.d.ts +0 -47
  259. package/dist_ts/smartproxy/classes.pp.timeoutmanager.js +0 -154
  260. package/dist_ts/smartproxy/classes.pp.tlsalert.d.ts +0 -149
  261. package/dist_ts/smartproxy/classes.pp.tlsalert.js +0 -225
  262. package/dist_ts/smartproxy/classes.pp.tlsmanager.d.ts +0 -57
  263. package/dist_ts/smartproxy/classes.pp.tlsmanager.js +0 -132
  264. package/dist_ts/smartproxy/classes.smartproxy.d.ts +0 -63
  265. package/dist_ts/smartproxy/classes.smartproxy.js +0 -521
  266. package/dist_ts/smartproxy/forwarding/domain-config.d.ts +0 -12
  267. package/dist_ts/smartproxy/forwarding/domain-config.js +0 -12
  268. package/dist_ts/smartproxy/forwarding/domain-manager.d.ts +0 -86
  269. package/dist_ts/smartproxy/forwarding/domain-manager.js +0 -241
  270. package/dist_ts/smartproxy/forwarding/forwarding.factory.d.ts +0 -24
  271. package/dist_ts/smartproxy/forwarding/forwarding.factory.js +0 -137
  272. package/dist_ts/smartproxy/forwarding/forwarding.handler.d.ts +0 -55
  273. package/dist_ts/smartproxy/forwarding/forwarding.handler.js +0 -94
  274. package/dist_ts/smartproxy/forwarding/http.handler.d.ts +0 -25
  275. package/dist_ts/smartproxy/forwarding/http.handler.js +0 -123
  276. package/dist_ts/smartproxy/forwarding/https-passthrough.handler.d.ts +0 -24
  277. package/dist_ts/smartproxy/forwarding/https-passthrough.handler.js +0 -154
  278. package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.d.ts +0 -36
  279. package/dist_ts/smartproxy/forwarding/https-terminate-to-http.handler.js +0 -229
  280. package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.d.ts +0 -35
  281. package/dist_ts/smartproxy/forwarding/https-terminate-to-https.handler.js +0 -254
  282. package/dist_ts/smartproxy/forwarding/index.d.ts +0 -16
  283. package/dist_ts/smartproxy/forwarding/index.js +0 -23
  284. package/dist_ts/smartproxy/types/forwarding.types.d.ts +0 -104
  285. package/dist_ts/smartproxy/types/forwarding.types.js +0 -50
  286. package/dist_ts/smartproxy.classes.networkproxy.d.ts +0 -31
  287. package/dist_ts/smartproxy.classes.networkproxy.js +0 -305
  288. package/dist_ts/smartproxy.classes.router.d.ts +0 -13
  289. package/dist_ts/smartproxy.classes.router.js +0 -33
  290. package/dist_ts/smartproxy.classes.sslredirect.d.ts +0 -8
  291. package/dist_ts/smartproxy.classes.sslredirect.js +0 -28
  292. package/dist_ts/smartproxy.helpers.certificates.d.ts +0 -5
  293. package/dist_ts/smartproxy.helpers.certificates.js +0 -23
  294. package/dist_ts/smartproxy.plugins.d.ts +0 -18
  295. package/dist_ts/smartproxy.plugins.js +0 -23
  296. package/dist_ts/smartproxy.portproxy.d.ts +0 -26
  297. package/dist_ts/smartproxy.portproxy.js +0 -295
  298. package/ts/http/index.ts +0 -16
  299. package/ts/http/models/http-types.ts +0 -108
  300. package/ts/http/redirects/index.ts +0 -3
  301. package/ts/proxies/network-proxy/models/index.ts +0 -4
  302. package/ts/redirect/classes.redirect.ts +0 -295
  303. /package/dist_ts/proxies/{network-proxy → http-proxy}/context-creator.d.ts +0 -0
  304. /package/dist_ts/proxies/{network-proxy → http-proxy}/function-cache.d.ts +0 -0
  305. /package/dist_ts/proxies/{network-proxy → http-proxy}/http-request-handler.d.ts +0 -0
  306. /package/dist_ts/proxies/{network-proxy → http-proxy}/http2-request-handler.d.ts +0 -0
  307. /package/dist_ts/proxies/{network-proxy → http-proxy}/security-manager.d.ts +0 -0
  308. /package/ts/proxies/{network-proxy → http-proxy}/context-creator.ts +0 -0
  309. /package/ts/proxies/{network-proxy → http-proxy}/function-cache.ts +0 -0
  310. /package/ts/proxies/{network-proxy → http-proxy}/http-request-handler.ts +0 -0
  311. /package/ts/proxies/{network-proxy → http-proxy}/http2-request-handler.ts +0 -0
  312. /package/ts/proxies/{network-proxy → http-proxy}/security-manager.ts +0 -0
  313. /package/ts/{http → routing}/router/index.ts +0 -0
@@ -1,754 +0,0 @@
1
- import * as plugins from './plugins.js';
2
- import { ConnectionManager } from './classes.pp.connectionmanager.js';
3
- import { SecurityManager } from './classes.pp.securitymanager.js';
4
- import { DomainConfigManager } from './classes.pp.domainconfigmanager.js';
5
- import { TlsManager } from './classes.pp.tlsmanager.js';
6
- import { NetworkProxyBridge } from './classes.pp.networkproxybridge.js';
7
- import { TimeoutManager } from './classes.pp.timeoutmanager.js';
8
- import { PortRangeManager } from './classes.pp.portrangemanager.js';
9
- /**
10
- * Handles new connection processing and setup logic
11
- */
12
- export class ConnectionHandler {
13
- constructor(settings, connectionManager, securityManager, domainConfigManager, tlsManager, networkProxyBridge, timeoutManager, portRangeManager) {
14
- this.settings = settings;
15
- this.connectionManager = connectionManager;
16
- this.securityManager = securityManager;
17
- this.domainConfigManager = domainConfigManager;
18
- this.tlsManager = tlsManager;
19
- this.networkProxyBridge = networkProxyBridge;
20
- this.timeoutManager = timeoutManager;
21
- this.portRangeManager = portRangeManager;
22
- }
23
- /**
24
- * Handle a new incoming connection
25
- */
26
- handleConnection(socket) {
27
- const remoteIP = socket.remoteAddress || '';
28
- const localPort = socket.localPort || 0;
29
- // Validate IP against rate limits and connection limits
30
- const ipValidation = this.securityManager.validateIP(remoteIP);
31
- if (!ipValidation.allowed) {
32
- console.log(`Connection rejected from ${remoteIP}: ${ipValidation.reason}`);
33
- socket.end();
34
- socket.destroy();
35
- return;
36
- }
37
- // Create a new connection record
38
- const record = this.connectionManager.createConnection(socket);
39
- const connectionId = record.id;
40
- // Apply socket optimizations
41
- socket.setNoDelay(this.settings.noDelay);
42
- // Apply keep-alive settings if enabled
43
- if (this.settings.keepAlive) {
44
- socket.setKeepAlive(true, this.settings.keepAliveInitialDelay);
45
- record.hasKeepAlive = true;
46
- // Apply enhanced TCP keep-alive options if enabled
47
- if (this.settings.enableKeepAliveProbes) {
48
- try {
49
- // These are platform-specific and may not be available
50
- if ('setKeepAliveProbes' in socket) {
51
- socket.setKeepAliveProbes(10);
52
- }
53
- if ('setKeepAliveInterval' in socket) {
54
- socket.setKeepAliveInterval(1000);
55
- }
56
- }
57
- catch (err) {
58
- // Ignore errors - these are optional enhancements
59
- if (this.settings.enableDetailedLogging) {
60
- console.log(`[${connectionId}] Enhanced TCP keep-alive settings not supported: ${err}`);
61
- }
62
- }
63
- }
64
- }
65
- if (this.settings.enableDetailedLogging) {
66
- console.log(`[${connectionId}] New connection from ${remoteIP} on port ${localPort}. ` +
67
- `Keep-Alive: ${record.hasKeepAlive ? 'Enabled' : 'Disabled'}. ` +
68
- `Active connections: ${this.connectionManager.getConnectionCount()}`);
69
- }
70
- else {
71
- console.log(`New connection from ${remoteIP} on port ${localPort}. Active connections: ${this.connectionManager.getConnectionCount()}`);
72
- }
73
- // Check if this connection should be forwarded directly to NetworkProxy
74
- if (this.portRangeManager.shouldUseNetworkProxy(localPort)) {
75
- this.handleNetworkProxyConnection(socket, record);
76
- }
77
- else {
78
- // For non-NetworkProxy ports, proceed with normal processing
79
- this.handleStandardConnection(socket, record);
80
- }
81
- }
82
- /**
83
- * Handle a connection that should be forwarded to NetworkProxy
84
- */
85
- handleNetworkProxyConnection(socket, record) {
86
- const connectionId = record.id;
87
- let initialDataReceived = false;
88
- // Set an initial timeout for handshake data
89
- let initialTimeout = setTimeout(() => {
90
- if (!initialDataReceived) {
91
- console.log(`[${connectionId}] Initial data warning (${this.settings.initialDataTimeout}ms) for connection from ${record.remoteIP}`);
92
- // Add a grace period instead of immediate termination
93
- setTimeout(() => {
94
- if (!initialDataReceived) {
95
- console.log(`[${connectionId}] Final initial data timeout after grace period`);
96
- if (record.incomingTerminationReason === null) {
97
- record.incomingTerminationReason = 'initial_timeout';
98
- this.connectionManager.incrementTerminationStat('incoming', 'initial_timeout');
99
- }
100
- socket.end();
101
- this.connectionManager.cleanupConnection(record, 'initial_timeout');
102
- }
103
- }, 30000); // 30 second grace period
104
- }
105
- }, this.settings.initialDataTimeout);
106
- // Make sure timeout doesn't keep the process alive
107
- if (initialTimeout.unref) {
108
- initialTimeout.unref();
109
- }
110
- // Set up error handler
111
- socket.on('error', this.connectionManager.handleError('incoming', record));
112
- // First data handler to capture initial TLS handshake for NetworkProxy
113
- socket.once('data', (chunk) => {
114
- // Clear the initial timeout since we've received data
115
- if (initialTimeout) {
116
- clearTimeout(initialTimeout);
117
- initialTimeout = null;
118
- }
119
- initialDataReceived = true;
120
- record.hasReceivedInitialData = true;
121
- // Block non-TLS connections on port 443
122
- const localPort = record.localPort;
123
- if (!this.tlsManager.isTlsHandshake(chunk) && localPort === 443) {
124
- console.log(`[${connectionId}] Non-TLS connection detected on port 443. ` +
125
- `Terminating connection - only TLS traffic is allowed on standard HTTPS port.`);
126
- if (record.incomingTerminationReason === null) {
127
- record.incomingTerminationReason = 'non_tls_blocked';
128
- this.connectionManager.incrementTerminationStat('incoming', 'non_tls_blocked');
129
- }
130
- socket.end();
131
- this.connectionManager.cleanupConnection(record, 'non_tls_blocked');
132
- return;
133
- }
134
- // Check if this looks like a TLS handshake
135
- if (this.tlsManager.isTlsHandshake(chunk)) {
136
- record.isTLS = true;
137
- // Check for ClientHello to extract SNI - but don't enforce it for NetworkProxy
138
- if (this.tlsManager.isClientHello(chunk)) {
139
- // Create connection info for SNI extraction
140
- const connInfo = {
141
- sourceIp: record.remoteIP,
142
- sourcePort: socket.remotePort || 0,
143
- destIp: socket.localAddress || '',
144
- destPort: socket.localPort || 0,
145
- };
146
- // Extract SNI for domain-specific NetworkProxy handling if available
147
- const serverName = this.tlsManager.extractSNI(chunk, connInfo);
148
- // For NetworkProxy connections, we'll allow session tickets even without SNI
149
- // We'll only use the serverName if available to determine the specific NetworkProxy port
150
- if (serverName) {
151
- // Save domain config and SNI in connection record
152
- const domainConfig = this.domainConfigManager.findDomainConfig(serverName);
153
- record.domainConfig = domainConfig;
154
- record.lockedDomain = serverName;
155
- // Use domain-specific NetworkProxy port if configured
156
- if (domainConfig && this.domainConfigManager.shouldUseNetworkProxy(domainConfig)) {
157
- const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
158
- if (this.settings.enableDetailedLogging) {
159
- console.log(`[${connectionId}] Using domain-specific NetworkProxy for ${serverName} on port ${networkProxyPort}`);
160
- }
161
- // Forward to NetworkProxy with domain-specific port
162
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, chunk, networkProxyPort, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
163
- return;
164
- }
165
- }
166
- else if (this.settings.allowSessionTicket === false &&
167
- this.settings.enableDetailedLogging) {
168
- // Log that we're allowing a session resumption without SNI for NetworkProxy
169
- console.log(`[${connectionId}] Allowing session resumption without SNI for NetworkProxy forwarding`);
170
- }
171
- }
172
- // Forward directly to NetworkProxy without domain-specific settings
173
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, chunk, undefined, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
174
- }
175
- else {
176
- // If not TLS, use normal direct connection
177
- console.log(`[${connectionId}] Non-TLS connection on NetworkProxy port ${record.localPort}`);
178
- this.setupDirectConnection(socket, record, undefined, undefined, chunk);
179
- }
180
- });
181
- }
182
- /**
183
- * Handle a standard (non-NetworkProxy) connection
184
- */
185
- handleStandardConnection(socket, record) {
186
- const connectionId = record.id;
187
- const localPort = record.localPort;
188
- // Define helpers for rejecting connections
189
- const rejectIncomingConnection = (reason, logMessage) => {
190
- console.log(`[${connectionId}] ${logMessage}`);
191
- socket.end();
192
- if (record.incomingTerminationReason === null) {
193
- record.incomingTerminationReason = reason;
194
- this.connectionManager.incrementTerminationStat('incoming', reason);
195
- }
196
- this.connectionManager.cleanupConnection(record, reason);
197
- };
198
- let initialDataReceived = false;
199
- // Set an initial timeout for SNI data if needed
200
- let initialTimeout = null;
201
- if (this.settings.sniEnabled) {
202
- initialTimeout = setTimeout(() => {
203
- if (!initialDataReceived) {
204
- console.log(`[${connectionId}] Initial data warning (${this.settings.initialDataTimeout}ms) for connection from ${record.remoteIP}`);
205
- // Add a grace period instead of immediate termination
206
- setTimeout(() => {
207
- if (!initialDataReceived) {
208
- console.log(`[${connectionId}] Final initial data timeout after grace period`);
209
- if (record.incomingTerminationReason === null) {
210
- record.incomingTerminationReason = 'initial_timeout';
211
- this.connectionManager.incrementTerminationStat('incoming', 'initial_timeout');
212
- }
213
- socket.end();
214
- this.connectionManager.cleanupConnection(record, 'initial_timeout');
215
- }
216
- }, 30000); // 30 second grace period
217
- }
218
- }, this.settings.initialDataTimeout);
219
- // Make sure timeout doesn't keep the process alive
220
- if (initialTimeout.unref) {
221
- initialTimeout.unref();
222
- }
223
- }
224
- else {
225
- initialDataReceived = true;
226
- record.hasReceivedInitialData = true;
227
- }
228
- socket.on('error', this.connectionManager.handleError('incoming', record));
229
- // Track data for bytes counting
230
- socket.on('data', (chunk) => {
231
- record.bytesReceived += chunk.length;
232
- this.timeoutManager.updateActivity(record);
233
- // Check for TLS handshake if this is the first chunk
234
- if (!record.isTLS && this.tlsManager.isTlsHandshake(chunk)) {
235
- record.isTLS = true;
236
- if (this.settings.enableTlsDebugLogging) {
237
- console.log(`[${connectionId}] TLS handshake detected from ${record.remoteIP}, ${chunk.length} bytes`);
238
- }
239
- }
240
- });
241
- /**
242
- * Sets up the connection to the target host.
243
- */
244
- const setupConnection = (serverName, initialChunk, forcedDomain, overridePort) => {
245
- // Clear the initial timeout since we've received data
246
- if (initialTimeout) {
247
- clearTimeout(initialTimeout);
248
- initialTimeout = null;
249
- }
250
- // Mark that we've received initial data
251
- initialDataReceived = true;
252
- record.hasReceivedInitialData = true;
253
- // Check if this looks like a TLS handshake
254
- if (initialChunk && this.tlsManager.isTlsHandshake(initialChunk)) {
255
- record.isTLS = true;
256
- if (this.settings.enableTlsDebugLogging) {
257
- console.log(`[${connectionId}] TLS handshake detected in setup, ${initialChunk.length} bytes`);
258
- }
259
- }
260
- // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
261
- const domainConfig = forcedDomain
262
- ? forcedDomain
263
- : serverName
264
- ? this.domainConfigManager.findDomainConfig(serverName)
265
- : undefined;
266
- // Save domain config in connection record
267
- record.domainConfig = domainConfig;
268
- // Check if this domain should use NetworkProxy (domain-specific setting)
269
- if (domainConfig &&
270
- this.domainConfigManager.shouldUseNetworkProxy(domainConfig) &&
271
- this.networkProxyBridge.getNetworkProxy()) {
272
- if (this.settings.enableDetailedLogging) {
273
- console.log(`[${connectionId}] Domain ${serverName} is configured to use NetworkProxy`);
274
- }
275
- const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
276
- if (initialChunk && record.isTLS) {
277
- // For TLS connections with initial chunk, forward to NetworkProxy
278
- this.networkProxyBridge.forwardToNetworkProxy(connectionId, socket, record, initialChunk, networkProxyPort, (reason) => this.connectionManager.initiateCleanupOnce(record, reason));
279
- return; // Skip normal connection setup
280
- }
281
- }
282
- // IP validation
283
- if (domainConfig) {
284
- const ipRules = this.domainConfigManager.getEffectiveIPRules(domainConfig);
285
- // Skip IP validation if allowedIPs is empty
286
- if (domainConfig.allowedIPs.length > 0 &&
287
- !this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
288
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`);
289
- }
290
- }
291
- else if (this.settings.defaultAllowedIPs && this.settings.defaultAllowedIPs.length > 0) {
292
- if (!this.securityManager.isIPAuthorized(record.remoteIP, this.settings.defaultAllowedIPs, this.settings.defaultBlockedIPs || [])) {
293
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed by default allowed list`);
294
- }
295
- }
296
- // Save the initial SNI
297
- if (serverName) {
298
- record.lockedDomain = serverName;
299
- }
300
- // Set up the direct connection
301
- this.setupDirectConnection(socket, record, domainConfig, serverName, initialChunk, overridePort);
302
- };
303
- // --- PORT RANGE-BASED HANDLING ---
304
- // Only apply port-based rules if the incoming port is within one of the global port ranges.
305
- if (this.portRangeManager.isPortInGlobalRanges(localPort)) {
306
- if (this.portRangeManager.shouldUseGlobalForwarding(localPort)) {
307
- if (this.settings.defaultAllowedIPs &&
308
- this.settings.defaultAllowedIPs.length > 0 &&
309
- !this.securityManager.isIPAuthorized(record.remoteIP, this.settings.defaultAllowedIPs)) {
310
- console.log(`[${connectionId}] Connection from ${record.remoteIP} rejected: IP ${record.remoteIP} not allowed in global default allowed list.`);
311
- socket.end();
312
- return;
313
- }
314
- if (this.settings.enableDetailedLogging) {
315
- console.log(`[${connectionId}] Port-based connection from ${record.remoteIP} on port ${localPort} forwarded to global target IP ${this.settings.targetIP}.`);
316
- }
317
- setupConnection('', undefined, {
318
- domains: ['global'],
319
- allowedIPs: this.settings.defaultAllowedIPs || [],
320
- blockedIPs: this.settings.defaultBlockedIPs || [],
321
- targetIPs: [this.settings.targetIP],
322
- portRanges: [],
323
- }, localPort);
324
- return;
325
- }
326
- else {
327
- // Attempt to find a matching forced domain config based on the local port.
328
- const forcedDomain = this.domainConfigManager.findDomainConfigForPort(localPort);
329
- if (forcedDomain) {
330
- const ipRules = this.domainConfigManager.getEffectiveIPRules(forcedDomain);
331
- if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
332
- console.log(`[${connectionId}] Connection from ${record.remoteIP} rejected: IP not allowed for domain ${forcedDomain.domains.join(', ')} on port ${localPort}.`);
333
- socket.end();
334
- return;
335
- }
336
- if (this.settings.enableDetailedLogging) {
337
- console.log(`[${connectionId}] Port-based connection from ${record.remoteIP} on port ${localPort} matched domain ${forcedDomain.domains.join(', ')}.`);
338
- }
339
- setupConnection('', undefined, forcedDomain, localPort);
340
- return;
341
- }
342
- // Fall through to SNI/default handling if no forced domain config is found.
343
- }
344
- }
345
- // --- FALLBACK: SNI-BASED HANDLING (or default when SNI is disabled) ---
346
- if (this.settings.sniEnabled) {
347
- initialDataReceived = false;
348
- socket.once('data', (chunk) => {
349
- // Clear timeout immediately
350
- if (initialTimeout) {
351
- clearTimeout(initialTimeout);
352
- initialTimeout = null;
353
- }
354
- initialDataReceived = true;
355
- // Block non-TLS connections on port 443
356
- if (!this.tlsManager.isTlsHandshake(chunk) && localPort === 443) {
357
- console.log(`[${connectionId}] Non-TLS connection detected on port 443 in SNI handler. ` +
358
- `Terminating connection - only TLS traffic is allowed on standard HTTPS port.`);
359
- if (record.incomingTerminationReason === null) {
360
- record.incomingTerminationReason = 'non_tls_blocked';
361
- this.connectionManager.incrementTerminationStat('incoming', 'non_tls_blocked');
362
- }
363
- socket.end();
364
- this.connectionManager.cleanupConnection(record, 'non_tls_blocked');
365
- return;
366
- }
367
- // Try to extract SNI
368
- let serverName = '';
369
- if (this.tlsManager.isTlsHandshake(chunk)) {
370
- record.isTLS = true;
371
- if (this.settings.enableTlsDebugLogging) {
372
- console.log(`[${connectionId}] Extracting SNI from TLS handshake, ${chunk.length} bytes`);
373
- }
374
- // Create connection info object for SNI extraction
375
- const connInfo = {
376
- sourceIp: record.remoteIP,
377
- sourcePort: socket.remotePort || 0,
378
- destIp: socket.localAddress || '',
379
- destPort: socket.localPort || 0,
380
- };
381
- // Extract SNI
382
- serverName = this.tlsManager.extractSNI(chunk, connInfo) || '';
383
- // If allowSessionTicket is false and this is a ClientHello with no SNI, terminate the connection
384
- if (this.settings.allowSessionTicket === false &&
385
- this.tlsManager.isClientHello(chunk) &&
386
- !serverName) {
387
- // Block ClientHello without SNI when allowSessionTicket is false
388
- console.log(`[${connectionId}] No SNI detected in ClientHello and allowSessionTicket=false. ` +
389
- `Sending warning unrecognized_name alert to encourage immediate retry with SNI.`);
390
- // Set the termination reason first
391
- if (record.incomingTerminationReason === null) {
392
- record.incomingTerminationReason = 'session_ticket_blocked_no_sni';
393
- this.connectionManager.incrementTerminationStat('incoming', 'session_ticket_blocked_no_sni');
394
- }
395
- // Create a warning-level alert for unrecognized_name
396
- // This encourages Chrome to retry immediately with SNI
397
- const serverNameUnknownAlertData = Buffer.from([
398
- 0x15, // Alert record type
399
- 0x03,
400
- 0x03, // TLS 1.2 version
401
- 0x00,
402
- 0x02, // Length
403
- 0x01, // Warning alert level (not fatal)
404
- 0x70, // unrecognized_name alert (code 112)
405
- ]);
406
- try {
407
- // Use cork/uncork to ensure the alert is sent as a single packet
408
- socket.cork();
409
- const writeSuccessful = socket.write(serverNameUnknownAlertData);
410
- socket.uncork();
411
- socket.end();
412
- // Function to handle the clean socket termination - but more gradually
413
- const finishConnection = () => {
414
- this.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni');
415
- };
416
- if (writeSuccessful) {
417
- // Wait longer before ending connection to ensure alert is processed by client
418
- setTimeout(finishConnection, 200); // Increased from 50ms to 200ms
419
- }
420
- else {
421
- // If the kernel buffer was full, wait for the drain event
422
- socket.once('drain', () => {
423
- // Wait longer after drain as well
424
- setTimeout(finishConnection, 200);
425
- });
426
- // Safety timeout is increased too
427
- setTimeout(() => {
428
- socket.removeAllListeners('drain');
429
- finishConnection();
430
- }, 400); // Increased from 250ms to 400ms
431
- }
432
- }
433
- catch (err) {
434
- // If we can't send the alert, fall back to immediate termination
435
- console.log(`[${connectionId}] Error sending TLS alert: ${err.message}`);
436
- socket.end();
437
- this.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni');
438
- }
439
- return;
440
- }
441
- }
442
- // Lock the connection to the negotiated SNI.
443
- record.lockedDomain = serverName;
444
- if (this.settings.enableDetailedLogging) {
445
- console.log(`[${connectionId}] Received connection from ${record.remoteIP} with SNI: ${serverName || '(empty)'}`);
446
- }
447
- setupConnection(serverName, chunk);
448
- });
449
- }
450
- else {
451
- initialDataReceived = true;
452
- record.hasReceivedInitialData = true;
453
- if (this.settings.defaultAllowedIPs &&
454
- this.settings.defaultAllowedIPs.length > 0 &&
455
- !this.securityManager.isIPAuthorized(record.remoteIP, this.settings.defaultAllowedIPs)) {
456
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${record.remoteIP} not allowed for non-SNI connection`);
457
- }
458
- setupConnection('');
459
- }
460
- }
461
- /**
462
- * Sets up a direct connection to the target
463
- */
464
- setupDirectConnection(socket, record, domainConfig, serverName, initialChunk, overridePort) {
465
- const connectionId = record.id;
466
- // Determine target host
467
- const targetHost = domainConfig
468
- ? this.domainConfigManager.getTargetIP(domainConfig)
469
- : this.settings.targetIP;
470
- // Determine target port
471
- const targetPort = overridePort !== undefined ? overridePort : this.settings.toPort;
472
- // Setup connection options
473
- const connectionOptions = {
474
- host: targetHost,
475
- port: targetPort,
476
- };
477
- // Preserve source IP if configured
478
- if (this.settings.preserveSourceIP) {
479
- connectionOptions.localAddress = record.remoteIP.replace('::ffff:', '');
480
- }
481
- // Create a safe queue for incoming data
482
- const dataQueue = [];
483
- let queueSize = 0;
484
- let processingQueue = false;
485
- let drainPending = false;
486
- let pipingEstablished = false;
487
- // Pause the incoming socket to prevent buffer overflows
488
- socket.pause();
489
- // Function to safely process the data queue without losing events
490
- const processDataQueue = () => {
491
- if (processingQueue || dataQueue.length === 0 || pipingEstablished)
492
- return;
493
- processingQueue = true;
494
- try {
495
- // Process all queued chunks with the current active handler
496
- while (dataQueue.length > 0) {
497
- const chunk = dataQueue.shift();
498
- queueSize -= chunk.length;
499
- // Once piping is established, we shouldn't get here,
500
- // but just in case, pass to the outgoing socket directly
501
- if (pipingEstablished && record.outgoing) {
502
- record.outgoing.write(chunk);
503
- continue;
504
- }
505
- // Track bytes received
506
- record.bytesReceived += chunk.length;
507
- // Check for TLS handshake
508
- if (!record.isTLS && this.tlsManager.isTlsHandshake(chunk)) {
509
- record.isTLS = true;
510
- if (this.settings.enableTlsDebugLogging) {
511
- console.log(`[${connectionId}] TLS handshake detected in tempDataHandler, ${chunk.length} bytes`);
512
- }
513
- }
514
- // Check if adding this chunk would exceed the buffer limit
515
- const newSize = record.pendingDataSize + chunk.length;
516
- if (this.settings.maxPendingDataSize && newSize > this.settings.maxPendingDataSize) {
517
- console.log(`[${connectionId}] Buffer limit exceeded for connection from ${record.remoteIP}: ${newSize} bytes > ${this.settings.maxPendingDataSize} bytes`);
518
- socket.end(); // Gracefully close the socket
519
- this.connectionManager.initiateCleanupOnce(record, 'buffer_limit_exceeded');
520
- return;
521
- }
522
- // Buffer the chunk and update the size counter
523
- record.pendingData.push(Buffer.from(chunk));
524
- record.pendingDataSize = newSize;
525
- this.timeoutManager.updateActivity(record);
526
- }
527
- }
528
- finally {
529
- processingQueue = false;
530
- // If there's a pending drain and we've processed everything,
531
- // signal we're ready for more data if we haven't established piping yet
532
- if (drainPending && dataQueue.length === 0 && !pipingEstablished) {
533
- drainPending = false;
534
- socket.resume();
535
- }
536
- }
537
- };
538
- // Unified data handler that safely queues incoming data
539
- const safeDataHandler = (chunk) => {
540
- // If piping is already established, just let the pipe handle it
541
- if (pipingEstablished)
542
- return;
543
- // Add to our queue for orderly processing
544
- dataQueue.push(Buffer.from(chunk)); // Make a copy to be safe
545
- queueSize += chunk.length;
546
- // If queue is getting large, pause socket until we catch up
547
- if (this.settings.maxPendingDataSize && queueSize > this.settings.maxPendingDataSize * 0.8) {
548
- socket.pause();
549
- drainPending = true;
550
- }
551
- // Process the queue
552
- processDataQueue();
553
- };
554
- // Add our safe data handler
555
- socket.on('data', safeDataHandler);
556
- // Add initial chunk to pending data if present
557
- if (initialChunk) {
558
- record.bytesReceived += initialChunk.length;
559
- record.pendingData.push(Buffer.from(initialChunk));
560
- record.pendingDataSize = initialChunk.length;
561
- }
562
- // Create the target socket but don't set up piping immediately
563
- const targetSocket = plugins.net.connect(connectionOptions);
564
- record.outgoing = targetSocket;
565
- record.outgoingStartTime = Date.now();
566
- // Apply socket optimizations
567
- targetSocket.setNoDelay(this.settings.noDelay);
568
- // Apply keep-alive settings to the outgoing connection as well
569
- if (this.settings.keepAlive) {
570
- targetSocket.setKeepAlive(true, this.settings.keepAliveInitialDelay);
571
- // Apply enhanced TCP keep-alive options if enabled
572
- if (this.settings.enableKeepAliveProbes) {
573
- try {
574
- if ('setKeepAliveProbes' in targetSocket) {
575
- targetSocket.setKeepAliveProbes(10);
576
- }
577
- if ('setKeepAliveInterval' in targetSocket) {
578
- targetSocket.setKeepAliveInterval(1000);
579
- }
580
- }
581
- catch (err) {
582
- // Ignore errors - these are optional enhancements
583
- if (this.settings.enableDetailedLogging) {
584
- console.log(`[${connectionId}] Enhanced TCP keep-alive not supported for outgoing socket: ${err}`);
585
- }
586
- }
587
- }
588
- }
589
- // Setup specific error handler for connection phase
590
- targetSocket.once('error', (err) => {
591
- // This handler runs only once during the initial connection phase
592
- const code = err.code;
593
- console.log(`[${connectionId}] Connection setup error to ${targetHost}:${connectionOptions.port}: ${err.message} (${code})`);
594
- // Resume the incoming socket to prevent it from hanging
595
- socket.resume();
596
- if (code === 'ECONNREFUSED') {
597
- console.log(`[${connectionId}] Target ${targetHost}:${connectionOptions.port} refused connection`);
598
- }
599
- else if (code === 'ETIMEDOUT') {
600
- console.log(`[${connectionId}] Connection to ${targetHost}:${connectionOptions.port} timed out`);
601
- }
602
- else if (code === 'ECONNRESET') {
603
- console.log(`[${connectionId}] Connection to ${targetHost}:${connectionOptions.port} was reset`);
604
- }
605
- else if (code === 'EHOSTUNREACH') {
606
- console.log(`[${connectionId}] Host ${targetHost} is unreachable`);
607
- }
608
- // Clear any existing error handler after connection phase
609
- targetSocket.removeAllListeners('error');
610
- // Re-add the normal error handler for established connections
611
- targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
612
- if (record.outgoingTerminationReason === null) {
613
- record.outgoingTerminationReason = 'connection_failed';
614
- this.connectionManager.incrementTerminationStat('outgoing', 'connection_failed');
615
- }
616
- // Clean up the connection
617
- this.connectionManager.initiateCleanupOnce(record, `connection_failed_${code}`);
618
- });
619
- // Setup close handler
620
- targetSocket.on('close', this.connectionManager.handleClose('outgoing', record));
621
- socket.on('close', this.connectionManager.handleClose('incoming', record));
622
- // Handle timeouts with keep-alive awareness
623
- socket.on('timeout', () => {
624
- // For keep-alive connections, just log a warning instead of closing
625
- if (record.hasKeepAlive) {
626
- console.log(`[${connectionId}] Timeout event on incoming keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}. Connection preserved.`);
627
- return;
628
- }
629
- // For non-keep-alive connections, proceed with normal cleanup
630
- console.log(`[${connectionId}] Timeout on incoming side from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`);
631
- if (record.incomingTerminationReason === null) {
632
- record.incomingTerminationReason = 'timeout';
633
- this.connectionManager.incrementTerminationStat('incoming', 'timeout');
634
- }
635
- this.connectionManager.initiateCleanupOnce(record, 'timeout_incoming');
636
- });
637
- targetSocket.on('timeout', () => {
638
- // For keep-alive connections, just log a warning instead of closing
639
- if (record.hasKeepAlive) {
640
- console.log(`[${connectionId}] Timeout event on outgoing keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}. Connection preserved.`);
641
- return;
642
- }
643
- // For non-keep-alive connections, proceed with normal cleanup
644
- console.log(`[${connectionId}] Timeout on outgoing side from ${record.remoteIP} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`);
645
- if (record.outgoingTerminationReason === null) {
646
- record.outgoingTerminationReason = 'timeout';
647
- this.connectionManager.incrementTerminationStat('outgoing', 'timeout');
648
- }
649
- this.connectionManager.initiateCleanupOnce(record, 'timeout_outgoing');
650
- });
651
- // Apply socket timeouts
652
- this.timeoutManager.applySocketTimeouts(record);
653
- // Track outgoing data for bytes counting
654
- targetSocket.on('data', (chunk) => {
655
- record.bytesSent += chunk.length;
656
- this.timeoutManager.updateActivity(record);
657
- });
658
- // Wait for the outgoing connection to be ready before setting up piping
659
- targetSocket.once('connect', () => {
660
- // Clear the initial connection error handler
661
- targetSocket.removeAllListeners('error');
662
- // Add the normal error handler for established connections
663
- targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
664
- // Process any remaining data in the queue before switching to piping
665
- processDataQueue();
666
- // Set up piping immediately
667
- pipingEstablished = true;
668
- // Flush all pending data to target
669
- if (record.pendingData.length > 0) {
670
- const combinedData = Buffer.concat(record.pendingData);
671
- if (this.settings.enableDetailedLogging) {
672
- console.log(`[${connectionId}] Forwarding ${combinedData.length} bytes of initial data to target`);
673
- }
674
- // Write pending data immediately
675
- targetSocket.write(combinedData, (err) => {
676
- if (err) {
677
- console.log(`[${connectionId}] Error writing pending data to target: ${err.message}`);
678
- return this.connectionManager.initiateCleanupOnce(record, 'write_error');
679
- }
680
- });
681
- // Clear the buffer now that we've processed it
682
- record.pendingData = [];
683
- record.pendingDataSize = 0;
684
- }
685
- // Setup piping in both directions without any delays
686
- socket.pipe(targetSocket);
687
- targetSocket.pipe(socket);
688
- // Resume the socket to ensure data flows
689
- socket.resume();
690
- // Process any data that might be queued in the interim
691
- if (dataQueue.length > 0) {
692
- // Write any remaining queued data directly to the target socket
693
- for (const chunk of dataQueue) {
694
- targetSocket.write(chunk);
695
- }
696
- // Clear the queue
697
- dataQueue.length = 0;
698
- queueSize = 0;
699
- }
700
- if (this.settings.enableDetailedLogging) {
701
- console.log(`[${connectionId}] Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
702
- `${serverName
703
- ? ` (SNI: ${serverName})`
704
- : domainConfig
705
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
706
- : ''}` +
707
- ` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}`);
708
- }
709
- else {
710
- console.log(`Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
711
- `${serverName
712
- ? ` (SNI: ${serverName})`
713
- : domainConfig
714
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
715
- : ''}`);
716
- }
717
- // Add the renegotiation handler for SNI validation
718
- if (serverName) {
719
- // Create connection info object for the existing connection
720
- const connInfo = {
721
- sourceIp: record.remoteIP,
722
- sourcePort: record.incoming.remotePort || 0,
723
- destIp: record.incoming.localAddress || '',
724
- destPort: record.incoming.localPort || 0,
725
- };
726
- // Create a renegotiation handler function
727
- const renegotiationHandler = this.tlsManager.createRenegotiationHandler(connectionId, serverName, connInfo, (connectionId, reason) => this.connectionManager.initiateCleanupOnce(record, reason));
728
- // Store the handler in the connection record so we can remove it during cleanup
729
- record.renegotiationHandler = renegotiationHandler;
730
- // Add the handler to the socket
731
- socket.on('data', renegotiationHandler);
732
- if (this.settings.enableDetailedLogging) {
733
- console.log(`[${connectionId}] TLS renegotiation handler installed for SNI domain: ${serverName}`);
734
- if (this.settings.allowSessionTicket === false) {
735
- console.log(`[${connectionId}] Session ticket usage is disabled. Connection will be reset on reconnection attempts.`);
736
- }
737
- }
738
- }
739
- // Set connection timeout
740
- record.cleanupTimer = this.timeoutManager.setupConnectionTimeout(record, (record, reason) => {
741
- console.log(`[${connectionId}] Connection from ${record.remoteIP} exceeded max lifetime, forcing cleanup.`);
742
- this.connectionManager.initiateCleanupOnce(record, reason);
743
- });
744
- // Mark TLS handshake as complete for TLS connections
745
- if (record.isTLS) {
746
- record.tlsHandshakeComplete = true;
747
- if (this.settings.enableTlsDebugLogging) {
748
- console.log(`[${connectionId}] TLS handshake complete for connection from ${record.remoteIP}`);
749
- }
750
- }
751
- });
752
- }
753
- }
754
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcC5jb25uZWN0aW9uaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucHAuY29ubmVjdGlvbmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFNeEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDdEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN4RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDaEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFcEU7O0dBRUc7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBQzVCLFlBQ1UsUUFBNEIsRUFDNUIsaUJBQW9DLEVBQ3BDLGVBQWdDLEVBQ2hDLG1CQUF3QyxFQUN4QyxVQUFzQixFQUN0QixrQkFBc0MsRUFDdEMsY0FBOEIsRUFDOUIsZ0JBQWtDO1FBUGxDLGFBQVEsR0FBUixRQUFRLENBQW9CO1FBQzVCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQ2hDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFDeEMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0Qix1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO1FBQ3RDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO0lBQ3pDLENBQUM7SUFFSjs7T0FFRztJQUNJLGdCQUFnQixD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